Documentation
¶
Overview ¶
Package dnsname walks domain-name labels without allocating.
The library answers every label question by materializing it: Split builds an index slice, SplitDomainName a string slice, and CompareDomainName two index slices — per call, for answers that are a handful of comparisons. In the field the two of them were 4.3% of every object the resolver allocated. The functions here give the same answers out of a single forward walk, using the library's own NextLabel for boundary and escape handling, so there is no second implementation of `\.` to get wrong.
Index ¶
- Constants
- func AppendCanonicalLabels(dst, wire []byte, offs []int) ([]byte, int, bool)
- func AppendFoldedKey(dst, wire []byte) ([]byte, bool)
- func AppendPresentation(dst, wire []byte) ([]byte, bool)
- func CanonicalCompare(a, b string) int
- func CompareSuffix(a, b string) int
- func Sub(zone, name string) bool
- func Suffixes(name string) iter.Seq[int]
- func WireLabelCount(wire []byte) (int, bool)
Constants ¶
const MaxLabels = 127
MaxLabels bounds the label count of any legal wire name: every label needs a length byte plus one octet inside the 255-octet wire bound.
const MaxPresentationLength = 61*4 + 1 + 63*4 + 1 + 63*4 + 1 + 63*4 + 1
MaxPresentationLength bounds the presentation form of any legal wire name: every octet escaping to \DDD, plus label separators. Callers size stack buffers with it.
Variables ¶
This section is empty.
Functions ¶
func AppendCanonicalLabels ¶
AppendCanonicalLabels appends the canonical spelling — the presentation form with ASCII A–Z lowered and the trailing dot kept, dns.CanonicalName's answer — and records where each label starts inside the appended region. offs needs capacity MaxLabels; the returned count says how many entries were filled, and its contents are undefined on refusal. Suffix matching against canonical zone keys then indexes a map with canon[offs[i]:] without ever building a string — a recipe that assumes an empty dst, since the offsets are relative to the appended region, not the slice.
func AppendFoldedKey ¶
AppendFoldedKey appends the lookup-key form: the presentation form with ASCII A–Z lowered and no trailing dot (the root name comes back empty). This is the spelling hostsfile keys its database with and domain metrics tracks, so a stack-buffered key indexes those maps with zero allocation.
func AppendPresentation ¶
AppendPresentation appends the presentation form of an uncompressed wire-form name to dst — byte-identical to what dns.UnpackDomainName returns for the same bytes, trailing dot included, case preserved.
func CanonicalCompare ¶
CanonicalCompare orders a and b per RFC 4034 §6.3: the canonical DNS name order — labels compared right to left as the octets they decode to, ASCII-folded, with the name that runs out of labels first sorting first. It is the ordering every NSEC coverage proof stands on.
The octets, not the spelling. A presentation label is an encoding — `\065` is the octet 0x41, the same label as `a`; `\.` inside a label is the octet 0x2E, which sorts before `0` — and the comparison this replaces ordered the escape text instead, so wire-equal names compared unequal and names around the escapes could invert. Every escape is decoded as it is read — exactly as the library's packer decodes it, wrap quirk included (see decodeOctet) — and nothing is materialized. A dangling backslash, which no valid name contains, decodes as a literal one, keeping the order total for inputs only a hand can construct.
The fold is ASCII, which is what the RFC's canonical form specifies. (The old implementation folded through strings.ToLower, whose non-ASCII case mappings have no business in DNS names.)
Rooted and unrooted spellings compare equal: labels are read without their separators, so the trailing root dot contributes nothing.
The walk is forward, in label lockstep after aligning the starts, and the verdict is the rightmost pair that differed — right-to-left order without offset arrays, so the frame stays flat instead of carrying two of them.
func CompareSuffix ¶
CompareSuffix returns how many labels a and b share, counted from the right and stopping at the first inequality — dns.CompareDomainName's answer without its two index slices.
The library's exact comparison is preserved: ASCII case folding only, the final label read to the end of the string (so a rooted and an unrooted spelling of the same name do not match on it), and every other label read through its separating dot.
func Sub ¶
Sub reports whether name sits at or below zone — dns.IsSubDomain's answer, which is CompareSuffix covering every label of the zone.
func Suffixes ¶
Suffixes yields the start offset of every label in name, in order — dns.Split's answer as an iteration instead of a slice. The root name yields nothing, exactly as Split returns nil for it.
func WireLabelCount ¶
WireLabelCount returns the number of labels in an uncompressed wire-form name — dns.CountLabel's answer without the string. The root name has zero.
Types ¶
This section is empty.