std/ip
IPv4, IPv6, socket addresses and subnets as values, read from text and shown as text, with no natives and no capability - std/network and std/uri both use them.
The generated reference of std/ip has every public construct with its signature, its doc comment and its examples.
std/ip holds the addresses of the Internet Protocol as values: an IPv4 address, an IPv6 address, an address of either
version, a socket address - an address and a port - and a subnet, a network as address/prefix. It touches nothing: it has no natives and needs no capability,
so a package that only names an address - a URI whose host is an IP literal, a configuration file - does not claim the
network by importing it. std/network connects to these addresses and re-exports every name of this
package, so use SocketAddress from "std/network" and use SocketAddress from "std/ip" name the same type (see
docs/design/URI.md section 8a). It is not in the prelude.
Import#
use IpAddress, Ipv4Address, Ipv6Address, SocketAddress, Subnet, AddressError from "std/ip"use IpAddress, Ipv6Address, SocketAddress, Subnet from "std/ip"
const local = SocketAddress IpAddress.loopback, 8080
print local
match Subnet.tryFrom("10.0.0.0/8") {
Ok(network) => print network.contains(IpAddress.loopback)
Fail(problem) => print problem
}
match Ipv6Address.tryFrom("2001:DB8:0:0:0:0:0:1") {
Ok(address) => print address
Fail(problem) => print problem
}Declarations#
type Ipv4Address with Show, Equals, Hash, Compare, TryFrom<String, AddressError> {
static loopback = Self 2130706433
static unspecified = Self 0
static fn of(first: UInt8, second: UInt8, third: UInt8, fourth: UInt8): Self
fn number(): Int
fn octets(): List<Int>
fn isLoopback(): Bool
fn isUnspecified(): Bool
fn isPrivate(): Bool
fn isLinkLocal(): Bool
fn isMulticast(): Bool
fn show(): String
fn compare(other: Self): Ordering
static fn tryFrom(text: String): Result<Self, AddressError>
}
type Ipv6Address with Show, Equals, Hash, Compare, TryFrom<String, AddressError> {
static loopback = Self 0, 1
static unspecified = Self 0, 0
static fn of(segments: List<Int>): Result<Self, AddressError>
static fn ofHalves(high: Int, low: Int): Self
fn high(): Int
fn low(): Int
fn segments(): List<Int>
fn isLoopback(): Bool
fn isUnspecified(): Bool
fn isLinkLocal(): Bool
fn isUniqueLocal(): Bool
fn isMulticast(): Bool
fn mappedVersion4(): Ipv4Address?
fn show(): String
fn compare(other: Self): Ordering
static fn tryFrom(text: String): Result<Self, AddressError>
}
type IpAddress with Show, Equals, Hash, Compare, TryFrom<String, AddressError> {
case Version4(address: Ipv4Address)
case Version6(address: Ipv6Address)
static loopback = Self.Version4 Ipv4Address.loopback
fn isLoopback(): Bool
fn isUnspecified(): Bool
fn version(): Int
fn show(): String
fn compare(other: Self): Ordering
static fn tryFrom(text: String): Result<Self, AddressError>
}
type SocketAddress with Show, Equals, Hash, TryFrom<String, AddressError> {
address: IpAddress
port: Int
fn show(): String
static fn tryFrom(text: String): Result<Self, AddressError>
}
type Subnet with Show, Equals, Hash, TryFrom<String, AddressError> {
static fn of(address: IpAddress, prefixLength: Int): Result<Self, AddressError>
fn address(): IpAddress
fn prefixLength(): Int
fn contains(address: IpAddress): Bool
fn show(): String
static fn tryFrom(text: String): Result<Self, AddressError>
}
type AddressError with Show, Error {
text: String
reason: String
fn show(): String
}Values like any other, read from text with tryFrom and shown as text. An IPv4 address is four decimal parts from 0 to
255; a part with a leading zero is refused, because some systems read 010 as octal. An IPv6 address shows in the RFC
5952 form: lower case, no leading zeros, the longest run of zero segments collapsed to ::, and an IPv4-mapped
address with its IPv4 part (::ffff:192.0.2.1). A zone (fe80::1%eth0) is not part of an address and is refused.
Ipv4Address.loopback, Ipv6Address.loopback, IpAddress.loopback and the unspecified addresses are constants, and
isLoopback(), isPrivate(), isLinkLocal(), isMulticast() answer what they say. A SocketAddress shows as
127.0.0.1:8080 or [::1]:8080. IpAddress orders every IPv4 address before every IPv6 address.
A Subnet is a network, 10.0.0.0/8 or fe80::/64: the address of its first host and the number of leading bits
every address in it shares. It is always a network - the bits of the address after the prefix are zero - so
192.168.1.23/24 is refused instead of being rounded down, and 192.168.1.0/24 is the value. Subnet is a
capsule: its fields are private, so no Subnet can hold a prefix the address
does not fit or host bits that are set; Subnet.of and tryFrom are the ways in, and address() and prefixLength()
the two reads. Both refuse a prefix outside 0..32 (version 4) or 0..128 (version 6) and an address with host bits
set; tryFrom also refuses a missing /, a prefix that is empty, signed, has a leading zero or is not a number, and a
zone on the address, like it is for an IpAddress. show() is the address in its own text form, a / and the prefix,
and tryFrom(show()) gives the value back.
contains(address) is true for every address that shares the prefix, the first and the last of the network included.
/0 holds every address of its own version and none of the other, /32 and /128 exactly one. An address of the other
version is never in a subnet, and an IPv4-mapped IPv6 address is not matched against a version 4 subnet either: map it
with mappedVersion4() first if that is what you mean.
use AddressError, IpAddress, Subnet from "std/ip"
fn main(): Result<Void, AddressError> {
const office = Subnet.tryFrom("192.168.1.0/24")?
print office.contains(IpAddress.tryFrom("192.168.1.255")?)
print office.contains(IpAddress.tryFrom("192.168.2.0")?)
match Subnet.tryFrom("192.168.1.23/24") {
Ok(network) => print network
Fail(problem) => print problem
}
Ok void
}Related#
- std/network - resolving names into these addresses, and connecting to them.
- std/uri - a URI whose host is an IP literal holds one of these, and answers a
SocketAddress. - The standard library - the other packages.