std.net.ip.Ipv6Address
class pub Ipv6Address
An IPv6 address.
Static methods
new
Show source codeHide source code
fn pub static new(
a: Int,
b: Int,
c: Int,
d: Int,
e: Int,
f: Int,
g: Int,
h: Int,
) -> Ipv6Address {
Ipv6Address(a: a, b: b, c: c, d: d, e: e, f: f, g: g, h: h)
}
fn pub static new(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int, g: Int, h: Int) -> Ipv6Address
Returns a new IPv6 address using the given hextets.
parse
Show source codeHide source code
fn pub static parse(input: String) -> Option[Ipv6Address] {
let bytes = input.to_byte_array
let mut cursor = 0
let max = bytes.size
let segments = []
let ipv4_segments = []
let segment_bytes = ByteArray.new
let mut compressed = false
let mut ipv4_mode = false
let mut max_hextet_value = IPV6_HEXTET_MAXIMUM
let mut format = Format.Hex
# No point in parsing the input if we're certain it's not a valid address.
if max > IPV6_STRING_MAXIMUM_LENGTH { return Option.None }
while cursor < max {
# IPv6 addresses can embed IPv4 addresses, so instead of reading until we
# encounter a ":" we will also stop reading when running into a ".".
while
cursor < max
and bytes.get(cursor) != COLON_BYTE
and bytes.get(cursor) != DOT_BYTE
{
segment_bytes.push(bytes.get(cursor))
cursor += 1
}
# The moment we encounter a dot we'll enter IPv4 mode, and remain in this
# mode until we reach the end of the input, as embedded IPv4 addresses
# must be at the end of an IPv6 address.
if ipv4_mode.false? and cursor < max and bytes.get(cursor) == DOT_BYTE {
ipv4_mode = true
format = Format.Decimal
max_hextet_value = IPV4_OCTET_MAXIMUM
}
# When the IP starts with a "::" we won't be able to read input, so the
# byte buffer is empty.
if segment_bytes.size > 0 {
let int = try Int.parse(segment_bytes, format)
segment_bytes.clear
if int < IP_MINIMUM_VALUE or int > max_hextet_value {
return Option.None
}
if ipv4_mode { ipv4_segments.push(int) } else { segments.push(int) }
}
cursor += 1
# We have reached another ":", which is used to compress one or more empty
# groups together.
if cursor < max and bytes.get(cursor) == COLON_BYTE {
# Zero compression can only be applied once.
if compressed { return Option.None }
compressed = true
let mut pad = IPV6_HEXTETS - segments.size
let mut pad_cursor = cursor
let mut ipv4_padded = false
let look_ahead = cursor + 1 < max
# Scan ahead in the input to determine how many empty hextets we need to
# add, based on the remaining number of hextets.
#
# When the compression is at the end of the input (e.g. "1::") there is
# no point in looking ahead, so we don't.
while pad_cursor < max and look_ahead {
let byte = bytes.get(pad_cursor)
if byte == COLON_BYTE { pad -= 1 }
# Two IPv4 octets can be stored in a single IPv6 hextet, meaning we'd
# have to reduce padding by two. Since we already skip padding for the
# ":" that preceeds the IPv4 address, we only reduce the padding by
# one.
if ipv4_padded.false? and byte == DOT_BYTE {
ipv4_padded = true
pad -= 1
}
pad_cursor += 1
}
while pad > 0 {
segments.push(0)
pad -= 1
}
cursor += 1
}
}
if ipv4_segments.size == IPV4_OCTETS {
segments.push(
octets_to_hextet(ipv4_segments.get(0), ipv4_segments.get(1)),
)
segments.push(
octets_to_hextet(ipv4_segments.get(2), ipv4_segments.get(3)),
)
}
if segments.size != IPV6_HEXTETS { return Option.None }
Option.Some(
Ipv6Address.new(
segments.get(0),
segments.get(1),
segments.get(2),
segments.get(3),
segments.get(4),
segments.get(5),
segments.get(6),
segments.get(7),
),
)
}
fn pub static parse(input: String) -> Option[Ipv6Address]
Parses an IPv6 address literal.
This method only supports IPv6 addresses. Port numbers, zones, and CIDR masks are not supported.
Examples
Parsing an IPv6 address:
import std.net.ip (Ipv6Address)
Ipv6Address.parse('::1').get.v6? # => true
Instance methods
!=
Show source codeHide source code
fn pub !=(other: T) -> Bool {
(self == other).false?
}
fn pub !=(other: T) -> Bool
Returns true
if self
and the given object are not equal to each other.
==
Show source codeHide source code
fn pub ==(other: ref Ipv6Address) -> Bool {
@a == other.a
and @b == other.b
and @c == other.c
and @d == other.d
and @e == other.e
and @f == other.f
and @g == other.g
and @h == other.h
}
fn pub ==(other: ref Ipv6Address) -> Bool
Returns true
if self
and the given IP address are the same.
Examples
Comparing two IPv6 addresses:
import std.net.ip (Ipv6Address)
let addr1 = Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 1)
let addr2 = Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 1)
let addr3 = Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 2)
addr1 == addr2 # => true
addr1 == addr3 # => false
clone
Show source codeHide source code
fn pub clone -> Ipv6Address {
Ipv6Address(a: @a, b: @b, c: @c, d: @d, e: @e, f: @f, g: @g, h: @h)
}
fn pub clone -> Ipv6Address
Creates a clone of self
.
documentation?
Show source codeHide source code
fn pub documentation? -> Bool {
@a == 0x2001 and @b == 0xdb8
}
fn pub documentation? -> Bool
Returns true
if self
is in a range designated for documentation.
All addresses in the range 2001:db8::/32 are designated for documentation.
Examples
Checking if an IPv6 address is a documentation address:
import std.net.ip (Ipv6Address)
Ipv6Address.new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).documentation # => true
fmt
Show source codeHide source code
fn pub fmt(formatter: mut Formatter) {
formatter.write(to_string)
}
fn pub fmt(formatter: mut Formatter)
Formats self
in a human-readable format for debugging purposes.
into_string
Show source codeHide source code
fn pub move into_string -> String {
to_string
}
fn pub move into_string -> String
Moves self
into a String
.
ipv4_compatible?
Show source codeHide source code
fn pub ipv4_compatible? -> Bool {
@a == 0 and @b == 0 and @c == 0 and @d == 0 and @e == 0 and @f == 0
}
fn pub ipv4_compatible? -> Bool
Returns true
if self
is an IPv4-compatible IPv6 address.
Examples
Checking if an IPv6 address is an IPv4-compatible IPv6 address:
import std.net.ip (Ipv6Address)
Ipv6Address.new(0, 0, 0, 0, 0, 0, 1, 1).ipv4_compatible? # => true
ipv4_mapped?
Show source codeHide source code
fn pub ipv4_mapped? -> Bool {
@a == 0
and @b == 0
and @c == 0
and @d == 0
and @e == 0
and @f == IPV6_HEXTET_MAXIMUM
}
fn pub ipv4_mapped? -> Bool
Returns true
if self
is an IPv4-mapped IPv6 address.
Examples
Checking if an IPv6 address is an IPv4-mapped IPv6 address:
import std.net.ip (Ipv6Address)
Ipv6Address.new(0, 0, 0, 0, 0, 0xffff, 1, 1).ipv4_compatible? # => true
loopback?
Show source codeHide source code
fn pub loopback? -> Bool {
@a == 0
and @b == 0
and @c == 0
and @d == 0
and @e == 0
and @f == 0
and @g == 0
and @h == 1
}
fn pub loopback? -> Bool
Returns true
if self
is a loopback address (::1).
Examples
Checking if an address is a loopback address:
import std.net.ip (Ipv6Address)
Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 1).loopback? # => true
Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 2).loopback? # => false
multicast?
Show source codeHide source code
fn pub multicast? -> Bool {
@a & 0xff00 == 0xff00
}
fn pub multicast? -> Bool
Returns true
if self
is a multicast address (ff00::/8).
Examples
Checking if an address is a multicast address:
import std.net.ip (Ipv6Address)
Ipv6Address.new(0xff00, 0, 0, 0, 0, 0, 0, 0).multicast? # => true
Ipv6Address.new(0xff01, 0, 0, 0, 0, 0, 0, 0).multicast? # => true
Ipv6Address.new(0, 1, 0, 0, 0, 0, 0, 0).multicast? # => false
to_string
Show source codeHide source code
fn pub to_string -> String {
if unspecified? { return '::' }
if loopback? { return '::1' }
let ipv4_compatible = ipv4_compatible?
let ipv4_mapped = ipv4_mapped?
if ipv4_compatible or ipv4_mapped {
# This value (256) is used to convert a hextet to the second and fourth
# octet in an IPv4 address. For example, for a hextet 0x2ff this produces
# an octet of 255.
let hextet_to_octet_modulo = IPV4_OCTET_MAXIMUM + 1
let prefix = if ipv4_compatible { '::' } else { '::ffff:' }
let a = @g >> IPV4_TOIPV6_SHIFT
let b = @g % hextet_to_octet_modulo
let c = @h >> IPV4_TOIPV6_SHIFT
let d = @h % hextet_to_octet_modulo
return '${prefix}${a}.${b}.${c}.${d}'
}
let mut compression_start = 0
let mut compression_len = 0
let mut current_at = 0
let mut current_len = 0
let mut index = 0
let segments = [@a, @b, @c, @d, @e, @f, @g, @h]
# Find the longest sequence of empty hextets, which we will compress
# together.
while index < segments.size {
let hextet = segments.get(index)
if hextet == 0 {
if current_len == 0 { current_at = index }
current_len += 1
if current_len > compression_len {
compression_len = current_len
compression_start = current_at
}
} else {
current_at = 0
current_len = 0
}
index += 1
}
let format = Format.Hex
if compression_len > 0 {
let buffer = StringBuffer.new
let compression_end = compression_start + compression_len
segments.iter.each_with_index(fn (index, hextet) {
if index == compression_start { buffer.push(':') }
if index < compression_start or index >= compression_end {
if index > 0 { buffer.push(':') }
buffer.push(hextet.format(format))
}
})
return buffer.to_string
}
let a = @a.format(format)
let b = @b.format(format)
let c = @c.format(format)
let d = @d.format(format)
let e = @e.format(format)
let f = @f.format(format)
let g = @g.format(format)
let h = @h.format(format)
'${a}:${b}:${c}:${d}:${e}:${f}:${g}:${h}'
}
fn pub to_string -> String
Converts self
to a String
.
Zero compression is applied to the longest sequence of empty hextets, if there are any.
Examples
Converting an IPv6 address to a String
:
import std.net.ip (Ipv6Address)
Ipv6Address.new.to_string # => '::'
Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 1) # => '::1'
unspecified?
Show source codeHide source code
fn pub unspecified? -> Bool {
@a == 0
and @b == 0
and @c == 0
and @d == 0
and @e == 0
and @f == 0
and @g == 0
and @h == 0
}
fn pub unspecified? -> Bool
Returns true
if self
is the special "unspecified" address (::).
Examples
import std.net.ip (Ipv6Address)
Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 0).unspecified? # => true
Ipv6Address.new(0, 0, 0, 0, 0, 0, 0, 1).unspecified? # => false
Implemented traits
Clone
impl Clone[Ipv6Address] for Ipv6Address
Equal
impl Equal[ref Ipv6Address] for Ipv6Address
Format
impl Format for Ipv6Address
IntoString
impl IntoString for Ipv6Address
ToString
impl ToString for Ipv6Address