Reference

std/dns/name

std/dns/src/name.trb

DomainName: a name of the DNS as a sequence of labels, read from what a person writes (IDNA, docs/design/DNS.md section 3), from the presentation format of a zone file, or from the labels of a message - and compared the way the DNS compares names, without regard to the case of ASCII letters (RFC 4343).

type DomainName

type DomainName with Show, Equals, Hash, TryFrom<String, DnsError>

A domain name: its labels, most specific first, each one to 63 bytes, 255 bytes at most on the wire. The root is the name without labels. A label may hold any byte (RFC 2181 section 11); DomainName.tryFrom builds only host names, whose labels are letters, digits and hyphens, with Unicode written as A-labels.

Two names are equal when their labels are equal with the ASCII letters compared without their case, and the hash agrees (RFC 4343). The case a name was written in is kept, and show() writes it back.

Examples

const name = DomainName.tryFrom("Bücher.Example")?
print name
print name.unicodeText()

Related

const root

static root = DomainName([])

The root, .: the name without labels.

fn tryFrom

static fn tryFrom(text: String): Result<Self, DnsError>

A host name as a person writes it, after the lookup processing of UTS #46 as far as this package covers it (docs/design/DNS.md section 3): Unicode is mapped, lower cased and written as A-labels, so Bücher.example and xn--bcher-kva.example are one name, shown as the second. One trailing dot is allowed and changes nothing, and . is the root.

A label is letters, digits and hyphens and does not start or end with a hyphen (RFC 1123 section 2.1); a label that starts with xn-- has to be an A-label whose U-label this package would have produced itself. An underscore, as in _sip._tcp.example.test, and a * are not part of a host name: DomainName.ofPresentation reads those.

Errors

  • DnsError.InvalidName for an empty text, an empty label, a character that is neither a letter, a digit nor a hyphen, a character this package cannot map, a broken A-label, a label longer than 63 bytes as an A-label, and a name longer than 255 bytes on the wire.

fn ofPresentation

static fn ofPresentation(text: String): Result<Self, DnsError>

The presentation format of RFC 1035 section 5.1: labels separated by dots, any byte in a label, \. for a dot and \\ for a backslash inside of one, and \DDD for the byte of the decimal number DDD. No IDNA and no change of case: this is the form show() writes, and the one for names that are not host names - _sip._tcp.example.test, *.example.test.

Errors

  • DnsError.InvalidName for an empty text, an empty label, a character that is not ASCII (a Unicode name is DomainName.tryFrom's), a broken escape, a label longer than 63 bytes and a name longer than 255 bytes.

fn ofLabels

static fn ofLabels(labels: List<Bytes>): Result<Self, DnsError>

The name of these labels, most specific first, each any bytes: what a message holds. The root is [].

Errors

  • DnsError.InvalidName for an empty label, a label longer than 63 bytes and a name longer than 255 bytes.

fn labels

fn labels(): List<Bytes>

The labels, most specific first, as bytes. The root has none.

fn labelCount

fn labelCount(): Int

How many labels the name has: 2 for example.test, 0 for the root.

fn isRoot

fn isRoot(): Bool

The root, .. root() would collide with DomainName.root.

fn isHostName

fn isHostName(): Bool

Every label is letters, digits and hyphens and none starts or ends with a hyphen (RFC 1123 section 2.1): what DomainName.tryFrom builds. The root is one.

fn parent

fn parent(): Self?

The name without its first label: example.test for www.example.test, and None for the root.

fn isSubdomain

fn isSubdomain(of: DomainName): Bool

The name is of or lies below it: www.example.test is a subdomain of example.test and of itself.

fn wireLength

fn wireLength(): Int

The bytes of the name on the wire without compression: each label and its length, and the zero of the root.

fn show

fn show(): String

The presentation format, in A-labels and without the dot of the root: xn--bcher-kva.example, and . for the root. A dot or a backslash inside of a label is escaped with a backslash, and a byte that is not printable ASCII is written \DDD, so DomainName.ofPresentation reads every shown name back.

fn unicodeText

fn unicodeText(): String

The name for a person to read: every A-label as the U-label it stands for, bücher.example, and every other label as show() writes it. Where a label that starts with xn-- is no valid A-label, it stays as it is.

Pitfalls

A U-label is where homographs live - аpple.test with a Cyrillic а. A program that shows names to a person decides under a policy of its own when to show this form, as browsers do; show() is the form for a log.

fn equals

fn equals(other: DomainName): Bool

Label by label, with the ASCII letters compared without their case (RFC 4343).

fn hash

fn hash(): Int

The hash of the lower-cased presentation, so two names that are equal hash alike.