Search results

There are no results.

std.net.ip.Ipv6Address

Value
type pub copy Ipv6Address

An IPv6 address.

Static methods

new

Show source code
Hide 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 code
Hide 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 code
Hide source code
fn pub !=(other: ref Self) -> Bool {
  (self == other).false?
}
fn pub !=(other: ref Self) -> Bool

Returns true if self and the given object are not equal to each other.

==

Show source code
Hide source code
fn pub inline ==(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 inline ==(other: 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 code
Hide source code
fn pub inline clone -> Ipv6Address {
  Ipv6Address(a: @a, b: @b, c: @c, d: @d, e: @e, f: @f, g: @g, h: @h)
}
fn pub inline clone -> Ipv6Address

Creates a clone of self.

The returned value is an owned value that is the same type as the receiver of this method. For example, cloning a ref Array[Int] results in a Array[Int], not another ref Array[Int].

documentation?

Show source code
Hide 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 code
Hide 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 code
Hide 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 code
Hide 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 code
Hide 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 code
Hide 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 code
Hide 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 code
Hide 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 {
        if index > 0 { buffer.push(':') }

        buffer.push(hextet.format(format))
      } else if index == compression_start {
        buffer.push('::')
      } else if index >= compression_end {
        if index > compression_end { 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 code
Hide 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

std.clone.

Clone

impl Clone for Ipv6Address
std.cmp.

Equal

impl Equal for Ipv6Address
std.fmt.

Format

impl Format for Ipv6Address
std.string.

IntoString

impl IntoString for Ipv6Address
std.string.

ToString

impl ToString for Ipv6Address