hickory_proto/rr/domain/
name.rs

1// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! domain name, aka labels, implementation
9
10#[cfg(feature = "serde")]
11use alloc::string::ToString;
12use alloc::{string::String, vec::Vec};
13use core::char;
14use core::cmp::{Ordering, PartialEq};
15use core::fmt::{self, Write};
16use core::hash::{Hash, Hasher};
17#[cfg(not(feature = "std"))]
18use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
19use core::str::FromStr;
20#[cfg(feature = "std")]
21use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
22
23use ipnet::{IpNet, Ipv4Net, Ipv6Net};
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
26use tinyvec::TinyVec;
27
28use crate::error::{ProtoError, ProtoErrorKind, ProtoResult};
29use crate::rr::domain::label::{CaseInsensitive, CaseSensitive, IntoLabel, Label, LabelCmp};
30use crate::rr::domain::usage::LOCALHOST as LOCALHOST_usage;
31use crate::serialize::binary::{
32    BinDecodable, BinDecoder, BinEncodable, BinEncoder, DecodeError, Restrict,
33};
34
35/// A domain name
36#[derive(Clone, Default, Eq)]
37pub struct Name {
38    is_fqdn: bool,
39    label_data: TinyVec<[u8; 32]>,
40    // This 24 is chosen because TinyVec accommodates an inline buffer up to 24 bytes without
41    // increasing its stack footprint
42    label_ends: TinyVec<[u8; 24]>,
43}
44
45impl Name {
46    /// Maximum legal length of a domain name
47    pub const MAX_LENGTH: usize = 255;
48
49    /// Create a new domain::Name, i.e. label
50    pub fn new() -> Self {
51        Self::default()
52    }
53
54    /// Returns the root label, i.e. no labels, can probably make this better in the future.
55    pub fn root() -> Self {
56        let mut this = Self::new();
57        this.is_fqdn = true;
58        this
59    }
60
61    /// Extend the name with the offered label, and ensure maximum name length is not exceeded.
62    fn extend_name(&mut self, label: &[u8]) -> Result<(), ProtoError> {
63        let new_len = self.encoded_len() + label.len() + 1;
64
65        if new_len > Self::MAX_LENGTH {
66            return Err(ProtoErrorKind::DomainNameTooLong(new_len).into());
67        };
68
69        self.label_data.extend_from_slice(label);
70        self.label_ends.push(self.label_data.len() as u8);
71
72        Ok(())
73    }
74
75    /// Randomize the case of ASCII alpha characters in a name
76    #[cfg(feature = "std")]
77    pub fn randomize_label_case(&mut self) {
78        // Generate randomness 32 bits at a time, because this is the smallest unit on which the
79        // `rand` crate operates. One RNG call should be enough for most queries.
80        let mut rand_bits: u32 = 0;
81
82        for (i, b) in self.label_data.iter_mut().enumerate() {
83            // Generate fresh random bits on the zeroth and then every 32nd iteration.
84            if i % 32 == 0 {
85                rand_bits = rand::random();
86            }
87
88            let flip_case = rand_bits & 1 == 1;
89
90            if b.is_ascii_alphabetic() && flip_case {
91                *b ^= 0x20; // toggle the case bit (0x20)
92            }
93
94            rand_bits >>= 1;
95        }
96    }
97
98    /// Returns true if there are no labels, i.e. it's empty.
99    ///
100    /// In DNS the root is represented by `.`
101    ///
102    /// # Examples
103    ///
104    /// ```
105    /// use hickory_proto::rr::domain::Name;
106    ///
107    /// let root = Name::root();
108    /// assert_eq!(&root.to_string(), ".");
109    /// ```
110    pub fn is_root(&self) -> bool {
111        self.label_ends.is_empty() && self.is_fqdn()
112    }
113
114    /// Returns true if the name is a fully qualified domain name.
115    ///
116    /// If this is true, it has effects like only querying for this single name, as opposed to building
117    ///  up a search list in resolvers.
118    ///
119    /// *warning: this interface is unstable and may change in the future*
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use std::str::FromStr;
125    /// use hickory_proto::rr::domain::Name;
126    ///
127    /// let name = Name::from_str("www").unwrap();
128    /// assert!(!name.is_fqdn());
129    ///
130    /// let name = Name::from_str("www.example.com").unwrap();
131    /// assert!(!name.is_fqdn());
132    ///
133    /// let name = Name::from_str("www.example.com.").unwrap();
134    /// assert!(name.is_fqdn());
135    /// ```
136    pub fn is_fqdn(&self) -> bool {
137        self.is_fqdn
138    }
139
140    /// Specifies this name is a fully qualified domain name
141    ///
142    /// *warning: this interface is unstable and may change in the future*
143    pub fn set_fqdn(&mut self, val: bool) {
144        self.is_fqdn = val
145    }
146
147    /// Returns an iterator over the labels
148    pub fn iter(&self) -> LabelIter<'_> {
149        LabelIter {
150            name: self,
151            start: 0,
152            end: self.label_ends.len() as u8,
153        }
154    }
155
156    /// Appends the label to the end of this name
157    ///
158    /// # Example
159    ///
160    /// ```rust
161    /// use std::str::FromStr;
162    /// use hickory_proto::rr::domain::Name;
163    ///
164    /// let name = Name::from_str("www.example").unwrap();
165    /// let name = name.append_label("com").unwrap();
166    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
167    /// ```
168    pub fn append_label<L: IntoLabel>(mut self, label: L) -> ProtoResult<Self> {
169        self.extend_name(label.into_label()?.as_bytes())?;
170        Ok(self)
171    }
172
173    /// Prepends the label to the beginning of this name
174    ///
175    /// # Example
176    ///
177    /// ```rust
178    /// use std::str::FromStr;
179    /// use hickory_proto::rr::domain::Name;
180    ///
181    /// let name = Name::from_str("example.com").unwrap();
182    /// let name = name.prepend_label("www").unwrap();
183    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
184    /// ```
185    pub fn prepend_label<L: IntoLabel>(&self, label: L) -> ProtoResult<Self> {
186        let mut name = Self::new().append_label(label)?;
187
188        for label in self.into_iter() {
189            name.extend_name(label)?;
190        }
191
192        name.set_fqdn(self.is_fqdn);
193
194        Ok(name)
195    }
196
197    /// Creates a new Name from the specified labels
198    ///
199    /// # Arguments
200    ///
201    /// * `labels` - vector of items which will be stored as Strings.
202    ///
203    /// # Examples
204    ///
205    /// ```rust
206    /// use std::str::FromStr;
207    /// use hickory_proto::rr::domain::Name;
208    ///
209    /// // From strings, uses utf8 conversion
210    /// let from_labels = Name::from_labels(vec!["www", "example", "com"]).unwrap();
211    /// assert_eq!(from_labels, Name::from_str("www.example.com.").unwrap());
212    ///
213    /// // Force a set of bytes into labels (this is none-standard and potentially dangerous)
214    /// let from_labels = Name::from_labels(vec!["bad chars".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
215    /// assert_eq!(from_labels.iter().next(), Some(&b"bad chars"[..]));
216    ///
217    /// let root = Name::from_labels(Vec::<&str>::new()).unwrap();
218    /// assert!(root.is_root());
219    /// ```
220    pub fn from_labels<I, L>(labels: I) -> ProtoResult<Self>
221    where
222        I: IntoIterator<Item = L>,
223        L: IntoLabel,
224    {
225        let (labels, errors): (Vec<_>, Vec<_>) = labels
226            .into_iter()
227            .map(IntoLabel::into_label)
228            .partition(Result::is_ok);
229        let labels: Vec<_> = labels.into_iter().map(Result::unwrap).collect();
230        let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
231
232        if labels.len() > 255 {
233            return Err(ProtoErrorKind::DomainNameTooLong(labels.len()).into());
234        };
235        if !errors.is_empty() {
236            return Err(format!("error converting some labels: {errors:?}").into());
237        };
238
239        let mut name = Self {
240            is_fqdn: true,
241            ..Self::default()
242        };
243        for label in labels {
244            name = name.append_label(label)?;
245        }
246
247        Ok(name)
248    }
249
250    /// Appends `other` to `self`, returning a new `Name`
251    ///
252    /// Carries forward `is_fqdn` from `other`.
253    ///
254    /// # Examples
255    ///
256    /// ```rust
257    /// use std::str::FromStr;
258    /// use hickory_proto::rr::domain::Name;
259    ///
260    /// let local = Name::from_str("www").unwrap();
261    /// let domain = Name::from_str("example.com").unwrap();
262    /// assert!(!domain.is_fqdn());
263    ///
264    /// let name = local.clone().append_name(&domain).unwrap();
265    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
266    /// assert!(!name.is_fqdn());
267    ///
268    /// // see also `Name::append_domain`
269    /// let domain = Name::from_str("example.com.").unwrap();
270    /// assert!(domain.is_fqdn());
271    /// let name = local.append_name(&domain).unwrap();
272    /// assert_eq!(name, Name::from_str("www.example.com.").unwrap());
273    /// assert!(name.is_fqdn());
274    /// ```
275    pub fn append_name(mut self, other: &Self) -> Result<Self, ProtoError> {
276        for label in other.iter() {
277            self.extend_name(label)?;
278        }
279
280        self.is_fqdn = other.is_fqdn;
281        Ok(self)
282    }
283
284    /// Appends the `domain` to `self`, making the new `Name` an FQDN
285    ///
286    /// This is an alias for `append_name` with the added effect of marking the new `Name` as
287    /// a fully-qualified-domain-name.
288    ///
289    /// # Examples
290    ///
291    /// ```rust
292    /// use std::str::FromStr;
293    /// use hickory_proto::rr::domain::Name;
294    ///
295    /// let local = Name::from_str("www").unwrap();
296    /// let domain = Name::from_str("example.com").unwrap();
297    /// let name = local.append_domain(&domain).unwrap();
298    /// assert_eq!(name, Name::from_str("www.example.com.").unwrap());
299    /// assert!(name.is_fqdn())
300    /// ```
301    pub fn append_domain(self, domain: &Self) -> Result<Self, ProtoError> {
302        let mut this = self.append_name(domain)?;
303        this.set_fqdn(true);
304        Ok(this)
305    }
306
307    /// Creates a new Name with all labels lowercased
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// use std::cmp::Ordering;
313    /// use std::str::FromStr;
314    ///
315    /// use hickory_proto::rr::domain::{Label, Name};
316    ///
317    /// let example_com = Name::from_ascii("Example.Com").unwrap();
318    /// assert_eq!(example_com.cmp_case(&Name::from_str("example.com").unwrap()), Ordering::Less);
319    /// assert!(example_com.to_lowercase().eq_case(&Name::from_str("example.com").unwrap()));
320    /// ```
321    pub fn to_lowercase(&self) -> Self {
322        let new_label_data = self
323            .label_data
324            .iter()
325            .map(|c| c.to_ascii_lowercase())
326            .collect();
327        Self {
328            is_fqdn: self.is_fqdn,
329            label_data: new_label_data,
330            label_ends: self.label_ends.clone(),
331        }
332    }
333
334    /// Trims off the first part of the name, to help with searching for the domain piece
335    ///
336    /// # Examples
337    ///
338    /// ```
339    /// use std::str::FromStr;
340    /// use hickory_proto::rr::domain::Name;
341    ///
342    /// let example_com = Name::from_str("example.com.").unwrap();
343    /// assert_eq!(example_com.base_name(), Name::from_str("com.").unwrap());
344    /// assert_eq!(Name::from_str("com.").unwrap().base_name(), Name::root());
345    /// assert_eq!(Name::root().base_name(), Name::root());
346    /// ```
347    pub fn base_name(&self) -> Self {
348        let length = self.label_ends.len();
349        if length > 0 {
350            return self.trim_to(length - 1);
351        }
352        self.clone()
353    }
354
355    /// Trims to the number of labels specified
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// use std::str::FromStr;
361    /// use hickory_proto::rr::domain::Name;
362    ///
363    /// let example_com = Name::from_str("example.com.").unwrap();
364    /// assert_eq!(example_com.trim_to(2), Name::from_str("example.com.").unwrap());
365    /// assert_eq!(example_com.trim_to(1), Name::from_str("com.").unwrap());
366    /// assert_eq!(example_com.trim_to(0), Name::root());
367    /// assert_eq!(example_com.trim_to(3), Name::from_str("example.com.").unwrap());
368    /// ```
369    pub fn trim_to(&self, num_labels: usize) -> Self {
370        if num_labels > self.label_ends.len() {
371            self.clone()
372        } else {
373            Self::from_labels(self.iter().skip(self.label_ends.len() - num_labels)).unwrap()
374        }
375    }
376
377    /// same as `zone_of` allows for case sensitive call
378    pub fn zone_of_case(&self, name: &Self) -> bool {
379        let self_len = self.label_ends.len();
380        let name_len = name.label_ends.len();
381        if self_len == 0 {
382            return true;
383        }
384        if name_len == 0 {
385            // self_len != 0
386            return false;
387        }
388        if self_len > name_len {
389            return false;
390        }
391
392        let self_iter = self.iter().rev();
393        let name_iter = name.iter().rev();
394
395        let zip_iter = self_iter.zip(name_iter);
396
397        for (self_label, name_label) in zip_iter {
398            if self_label != name_label {
399                return false;
400            }
401        }
402
403        true
404    }
405
406    /// returns true if the name components of self are all present at the end of name
407    ///
408    /// # Example
409    ///
410    /// ```rust
411    /// use std::str::FromStr;
412    /// use hickory_proto::rr::domain::Name;
413    ///
414    /// let name = Name::from_str("www.example.com").unwrap();
415    /// let zone = Name::from_str("example.com").unwrap();
416    /// let another = Name::from_str("example.net").unwrap();
417    /// assert!(zone.zone_of(&name));
418    /// assert!(!name.zone_of(&zone));
419    /// assert!(!another.zone_of(&name));
420    /// ```
421    pub fn zone_of(&self, name: &Self) -> bool {
422        let self_lower = self.to_lowercase();
423        let name_lower = name.to_lowercase();
424
425        self_lower.zone_of_case(&name_lower)
426    }
427
428    /// Returns the number of labels in the name, discounting `*`.
429    ///
430    /// # Examples
431    ///
432    /// ```
433    /// use std::str::FromStr;
434    /// use hickory_proto::rr::domain::Name;
435    ///
436    /// let root = Name::root();
437    /// assert_eq!(root.num_labels(), 0);
438    ///
439    /// let example_com = Name::from_str("example.com").unwrap();
440    /// assert_eq!(example_com.num_labels(), 2);
441    ///
442    /// let star_example_com = Name::from_str("*.example.com.").unwrap();
443    /// assert_eq!(star_example_com.num_labels(), 2);
444    /// ```
445    pub fn num_labels(&self) -> u8 {
446        // it is illegal to have more than 256 labels.
447
448        let num = self.label_ends.len() as u8;
449
450        self.iter()
451            .next()
452            .map(|l| if l == b"*" { num - 1 } else { num })
453            .unwrap_or(num)
454    }
455
456    /// returns the length in bytes of the labels. '.' counts as 1
457    ///
458    /// This can be used as an estimate, when serializing labels, though
459    /// escaping may cause the exact length to be different.
460    ///
461    /// # Examples
462    ///
463    /// ```
464    /// use std::str::FromStr;
465    /// use hickory_proto::rr::domain::Name;
466    ///
467    /// assert_eq!(Name::from_str("www.example.com.").unwrap().len(), 16);
468    /// assert_eq!(Name::from_str(".").unwrap().len(), 1);
469    /// assert_eq!(Name::root().len(), 1);
470    /// ```
471    pub fn len(&self) -> usize {
472        let dots = if !self.label_ends.is_empty() {
473            self.label_ends.len()
474        } else {
475            1
476        };
477        dots + self.label_data.len()
478    }
479
480    /// Returns the encoded length of this name, ignoring compression.
481    ///
482    /// The `is_fqdn` flag is ignored, and the root label at the end is assumed to always be
483    /// present, since it terminates the name in the DNS message format.
484    fn encoded_len(&self) -> usize {
485        self.label_ends.len() + self.label_data.len() + 1
486    }
487
488    /// Returns whether the length of the labels, in bytes is 0. In practice, since '.' counts as
489    /// 1, this is never the case so the method returns false.
490    pub fn is_empty(&self) -> bool {
491        false
492    }
493
494    /// attempts to parse a name such as `"example.com."` or `"subdomain.example.com."`
495    ///
496    /// # Examples
497    ///
498    /// ```rust
499    /// use std::str::FromStr;
500    /// use hickory_proto::rr::domain::Name;
501    ///
502    /// let name = Name::from_str("example.com.").unwrap();
503    /// assert_eq!(name.base_name(), Name::from_str("com.").unwrap());
504    /// assert_eq!(name.iter().next(), Some(&b"example"[..]));
505    /// ```
506    pub fn parse(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
507        Self::from_encoded_str::<LabelEncUtf8>(local, origin)
508    }
509
510    /// Will convert the string to a name only allowing ascii as valid input
511    ///
512    /// This method will also preserve the case of the name where that's desirable
513    ///
514    /// # Examples
515    ///
516    /// ```
517    /// use hickory_proto::rr::Name;
518    ///
519    /// let bytes_name = Name::from_labels(vec!["WWW".as_bytes(), "example".as_bytes(), "COM".as_bytes()]).unwrap();
520    /// let ascii_name = Name::from_ascii("WWW.example.COM.").unwrap();
521    /// let lower_name = Name::from_ascii("www.example.com.").unwrap();
522    ///
523    /// assert!(bytes_name.eq_case(&ascii_name));
524    /// assert!(!lower_name.eq_case(&ascii_name));
525    ///
526    /// // escaped values
527    /// let bytes_name = Name::from_labels(vec!["email.name".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
528    /// let name = Name::from_ascii("email\\.name.example.com.").unwrap();
529    ///
530    /// assert_eq!(bytes_name, name);
531    ///
532    /// let bytes_name = Name::from_labels(vec!["bad.char".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
533    /// let name = Name::from_ascii("bad\\056char.example.com.").unwrap();
534    ///
535    /// assert_eq!(bytes_name, name);
536    /// ```
537    pub fn from_ascii<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
538        Self::from_encoded_str::<LabelEncAscii>(name.as_ref(), None)
539    }
540
541    // TODO: currently reserved to be private to the crate, due to confusion of IDNA vs. utf8 in https://tools.ietf.org/html/rfc6762#appendix-F
542    /// Will convert the string to a name using IDNA, punycode, to encode the UTF8 as necessary
543    ///
544    /// When making names IDNA compatible, there is a side-effect of lowercasing the name.
545    ///
546    /// # Examples
547    ///
548    /// ```
549    /// use std::str::FromStr;
550    /// use hickory_proto::rr::Name;
551    ///
552    /// let bytes_name = Name::from_labels(vec!["WWW".as_bytes(), "example".as_bytes(), "COM".as_bytes()]).unwrap();
553    ///
554    /// // from_str calls through to from_utf8
555    /// let utf8_name = Name::from_str("WWW.example.COM.").unwrap();
556    /// let lower_name = Name::from_str("www.example.com.").unwrap();
557    ///
558    /// assert!(!bytes_name.eq_case(&utf8_name));
559    /// assert!(lower_name.eq_case(&utf8_name));
560    /// ```
561    pub fn from_utf8<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
562        Self::from_encoded_str::<LabelEncUtf8>(name.as_ref(), None)
563    }
564
565    /// First attempts to decode via `from_utf8`, if that fails IDNA checks, then falls back to
566    /// ascii decoding.
567    ///
568    /// # Examples
569    ///
570    /// ```
571    /// use std::str::FromStr;
572    /// use hickory_proto::rr::Name;
573    ///
574    /// // Ok, underscore in the beginning of a name
575    /// assert!(Name::from_utf8("_allows.example.com.").is_ok());
576    ///
577    /// // Error, underscore in the end
578    /// assert!(Name::from_utf8("dis_allowed.example.com.").is_err());
579    ///
580    /// // Ok, relaxed mode
581    /// assert!(Name::from_str_relaxed("allow_in_.example.com.").is_ok());
582    /// ```
583    pub fn from_str_relaxed<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
584        let name = name.as_ref();
585        Self::from_utf8(name).or_else(|_| Self::from_ascii(name))
586    }
587
588    fn from_encoded_str<E: LabelEnc>(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
589        let mut name = Self::new();
590        let mut label = String::new();
591
592        let mut state = ParseState::Label;
593
594        // short circuit root parse
595        if local == "." {
596            name.set_fqdn(true);
597            return Ok(name);
598        }
599
600        // TODO: it would be nice to relocate this to Label, but that is hard because the label boundary can only be detected after processing escapes...
601        // evaluate all characters
602        for ch in local.chars() {
603            match state {
604                ParseState::Label => match ch {
605                    '.' => {
606                        name = name.append_label(E::to_label(&label)?)?;
607                        label.clear();
608                    }
609                    '\\' => state = ParseState::Escape1,
610                    ch if !ch.is_control() && !ch.is_whitespace() => label.push(ch),
611                    _ => return Err(format!("unrecognized char: {ch}").into()),
612                },
613                ParseState::Escape1 => {
614                    if ch.is_numeric() {
615                        state = ParseState::Escape2(
616                            ch.to_digit(8)
617                                .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?,
618                        );
619                    } else {
620                        // it's a single escaped char
621                        label.push(ch);
622                        state = ParseState::Label;
623                    }
624                }
625                ParseState::Escape2(i) => {
626                    if ch.is_numeric() {
627                        state = ParseState::Escape3(
628                            i,
629                            ch.to_digit(8)
630                                .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?,
631                        );
632                    } else {
633                        return Err(ProtoError::from(format!("unrecognized char: {ch}")));
634                    }
635                }
636                ParseState::Escape3(i, ii) => {
637                    if ch.is_numeric() {
638                        // octal conversion
639                        let val: u32 = (i * 8 * 8)
640                            + (ii * 8)
641                            + ch.to_digit(8)
642                                .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?;
643                        let new: char = char::from_u32(val)
644                            .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?;
645                        label.push(new);
646                        state = ParseState::Label;
647                    } else {
648                        return Err(format!("unrecognized char: {ch}").into());
649                    }
650                }
651            }
652        }
653
654        if !label.is_empty() {
655            name = name.append_label(E::to_label(&label)?)?;
656        }
657
658        // Check if the last character processed was an unescaped `.`
659        if label.is_empty() && !local.is_empty() {
660            name.set_fqdn(true);
661        } else if let Some(other) = origin {
662            return name.append_domain(other);
663        }
664
665        Ok(name)
666    }
667
668    /// Emits the canonical version of the name to the encoder.
669    ///
670    /// In canonical form, there will be no pointers written to the encoder (i.e. no compression).
671    pub fn emit_as_canonical(
672        &self,
673        encoder: &mut BinEncoder<'_>,
674        canonical: bool,
675    ) -> ProtoResult<()> {
676        let buf_len = encoder.len(); // lazily assert the size is less than 255...
677        // lookup the label in the BinEncoder
678        // if it exists, write the Pointer
679        let labels = self.iter();
680
681        // start index of each label
682        let mut labels_written = Vec::with_capacity(self.label_ends.len());
683        // we're going to write out each label, tracking the indexes of the start to each label
684        //   then we'll look to see if we can remove them and recapture the capacity in the buffer...
685        for label in labels {
686            if label.len() > 63 {
687                return Err(ProtoErrorKind::LabelBytesTooLong(label.len()).into());
688            }
689
690            labels_written.push(encoder.offset());
691            encoder.emit_character_data(label)?;
692        }
693        let last_index = encoder.offset();
694        // now search for other labels already stored matching from the beginning label, strip then to the end
695        //   if it's not found, then store this as a new label
696        for label_idx in &labels_written {
697            match encoder.get_label_pointer(*label_idx, last_index) {
698                // if writing canonical and already found, continue
699                Some(_) if canonical => continue,
700                Some(loc) if !canonical => {
701                    // reset back to the beginning of this label, and then write the pointer...
702                    encoder.set_offset(*label_idx);
703                    encoder.trim();
704
705                    // write out the pointer marker
706                    //  or'd with the location which shouldn't be larger than this 2^14 or 16k
707                    encoder.emit_u16(0xC000u16 | (loc & 0x3FFFu16))?;
708
709                    // we found a pointer don't write more, break
710                    return Ok(());
711                }
712                _ => {
713                    // no existing label exists, store this new one.
714                    encoder.store_label_pointer(*label_idx, last_index);
715                }
716            }
717        }
718
719        // if we're getting here, then we didn't write out a pointer and are ending the name
720        // the end of the list of names
721        encoder.emit(0)?;
722
723        // the entire name needs to be less than 256.
724        let length = encoder.len() - buf_len;
725        if length > 255 {
726            return Err(ProtoErrorKind::DomainNameTooLong(length).into());
727        }
728
729        Ok(())
730    }
731
732    /// Writes the labels, as lower case, to the encoder
733    ///
734    /// # Arguments
735    ///
736    /// * `encoder` - encoder for writing this name
737    /// * `lowercase` - if true the name will be lowercased, otherwise it will not be changed when writing
738    pub fn emit_with_lowercase(
739        &self,
740        encoder: &mut BinEncoder<'_>,
741        lowercase: bool,
742    ) -> ProtoResult<()> {
743        let is_canonical_names = encoder.is_canonical_names();
744        if lowercase {
745            self.to_lowercase()
746                .emit_as_canonical(encoder, is_canonical_names)
747        } else {
748            self.emit_as_canonical(encoder, is_canonical_names)
749        }
750    }
751
752    /// compares with the other label, ignoring case
753    fn cmp_with_f<F: LabelCmp>(&self, other: &Self) -> Ordering {
754        match (self.is_fqdn(), other.is_fqdn()) {
755            (false, true) => Ordering::Less,
756            (true, false) => Ordering::Greater,
757            _ => self.cmp_labels::<F>(other),
758        }
759    }
760
761    /// Compare two Names, not considering FQDN-ness.
762    fn cmp_labels<F: LabelCmp>(&self, other: &Self) -> Ordering {
763        if self.label_ends.is_empty() && other.label_ends.is_empty() {
764            return Ordering::Equal;
765        }
766
767        // we reverse the iters so that we are comparing from the root/domain to the local...
768        let self_labels = self.iter().rev();
769        let other_labels = other.iter().rev();
770
771        for (l, r) in self_labels.zip(other_labels) {
772            let l = Label::from_raw_bytes(l).unwrap();
773            let r = Label::from_raw_bytes(r).unwrap();
774            match l.cmp_with_f::<F>(&r) {
775                Ordering::Equal => continue,
776                not_eq => return not_eq,
777            }
778        }
779
780        self.label_ends.len().cmp(&other.label_ends.len())
781    }
782
783    /// Case sensitive comparison
784    pub fn cmp_case(&self, other: &Self) -> Ordering {
785        self.cmp_with_f::<CaseSensitive>(other)
786    }
787
788    /// Compares the Names, in a case sensitive manner
789    pub fn eq_case(&self, other: &Self) -> bool {
790        self.cmp_with_f::<CaseSensitive>(other) == Ordering::Equal
791    }
792
793    /// Non-FQDN-aware case-insensitive comparison
794    ///
795    /// This will return true if names are equal, or if an otherwise equal relative and
796    /// non-relative name are compared.
797    ///
798    /// # Examples
799    ///
800    /// ```
801    /// use std::str::FromStr;
802    /// use hickory_proto::rr::domain::Name;
803    ///
804    /// let name1 = Name::from_str("a.com.").unwrap();
805    /// let name2 = name1.clone();
806    /// assert_eq!(&name1, &name2);
807    /// assert!(name1.eq_ignore_root(&name2));
808    ///
809    /// // Make name2 uppercase.
810    /// let name2 = Name::from_str("A.CoM.").unwrap();
811    /// assert_eq!(&name1, &name2);
812    /// assert!(name1.eq_ignore_root(&name2));
813    ///
814    /// // Make name2 a relative name.
815    /// // Note that standard equality testing now returns false.
816    /// let name2 = Name::from_str("a.com").unwrap();
817    /// assert!(&name1 != &name2);
818    /// assert!(name1.eq_ignore_root(&name2));
819    ///
820    /// // Make name2 a completely unrelated name.
821    /// let name2 = Name::from_str("b.com.").unwrap();
822    /// assert!(&name1 != &name2);
823    /// assert!(!name1.eq_ignore_root(&name2));
824    ///
825    /// ```
826    pub fn eq_ignore_root(&self, other: &Self) -> bool {
827        self.cmp_labels::<CaseInsensitive>(other) == Ordering::Equal
828    }
829
830    /// Non-FQDN-aware case-sensitive comparison
831    ///
832    /// This will return true if names are equal, or if an otherwise equal relative and
833    /// non-relative name are compared.
834    ///
835    /// # Examples
836    ///
837    /// ```
838    /// use std::str::FromStr;
839    /// use hickory_proto::rr::domain::Name;
840    ///
841    /// let name1 = Name::from_str("a.com.").unwrap();
842    /// let name2 = Name::from_ascii("A.CoM.").unwrap();
843    /// let name3 = Name::from_ascii("A.CoM").unwrap();
844    ///
845    /// assert_eq!(&name1, &name2);
846    /// assert!(name1.eq_ignore_root(&name2));
847    /// assert!(!name1.eq_ignore_root_case(&name2));
848    /// assert!(name2.eq_ignore_root_case(&name3));
849    ///
850    /// ```
851    pub fn eq_ignore_root_case(&self, other: &Self) -> bool {
852        self.cmp_labels::<CaseSensitive>(other) == Ordering::Equal
853    }
854
855    /// Converts this name into an ascii safe string.
856    ///
857    /// If the name is an IDNA name, then the name labels will be returned with the `xn--` prefix.
858    ///  see `to_utf8` or the `Display` impl for methods which convert labels to utf8.
859    pub fn to_ascii(&self) -> String {
860        let mut s = String::with_capacity(self.len());
861        self.write_labels::<String, LabelEncAscii>(&mut s)
862            .expect("string conversion of name should not fail");
863        s
864    }
865
866    /// Converts the Name labels to the utf8 String form.
867    ///
868    /// This converts the name to an unescaped format, that could be used with parse. If, the name is
869    ///  is followed by the final `.`, e.g. as in `www.example.com.`, which represents a fully
870    ///  qualified Name.
871    pub fn to_utf8(&self) -> String {
872        format!("{self}")
873    }
874
875    /// Converts a *.arpa Name in a PTR record back into an IpNet if possible.
876    pub fn parse_arpa_name(&self) -> Result<IpNet, ProtoError> {
877        if !self.is_fqdn() {
878            return Err("PQDN cannot be valid arpa name".into());
879        }
880        let mut iter = self.iter().rev();
881        let first = iter
882            .next()
883            .ok_or_else(|| ProtoError::from("not an arpa address"))?;
884        if !"arpa".eq_ignore_ascii_case(core::str::from_utf8(first)?) {
885            return Err("not an arpa address".into());
886        }
887        let second = iter
888            .next()
889            .ok_or_else(|| ProtoError::from("invalid arpa address"))?;
890        let mut prefix_len: u8 = 0;
891        match &core::str::from_utf8(second)?.to_ascii_lowercase()[..] {
892            "in-addr" => {
893                let mut octets: [u8; 4] = [0; 4];
894                for octet in octets.iter_mut() {
895                    match iter.next() {
896                        Some(label) => *octet = core::str::from_utf8(label)?.parse()?,
897                        None => break,
898                    }
899                    prefix_len += 8;
900                }
901                if iter.next().is_some() {
902                    return Err("unrecognized in-addr.arpa.".into());
903                }
904                Ok(IpNet::V4(
905                    Ipv4Net::new(octets.into(), prefix_len).expect("Ipv4Net::new"),
906                ))
907            }
908            "ip6" => {
909                let mut address: u128 = 0;
910                while prefix_len < 128 {
911                    match iter.next() {
912                        Some(label) => {
913                            if label.len() == 1 {
914                                prefix_len += 4;
915                                let hex = u8::from_str_radix(core::str::from_utf8(label)?, 16)?;
916                                address |= u128::from(hex) << (128 - prefix_len);
917                            } else {
918                                return Err("invalid label length for ip6.arpa".into());
919                            }
920                        }
921                        None => break,
922                    }
923                }
924                if iter.next().is_some() {
925                    return Err("unrecognized ip6.arpa.".into());
926                }
927                Ok(IpNet::V6(
928                    Ipv6Net::new(address.into(), prefix_len).expect("Ipv6Net::new"),
929                ))
930            }
931            _ => Err("unrecognized arpa address".into()),
932        }
933    }
934
935    fn write_labels<W: Write, E: LabelEnc>(&self, f: &mut W) -> Result<(), fmt::Error> {
936        let mut iter = self.iter().map(|b| Label::from_raw_bytes(b).unwrap());
937        if let Some(label) = iter.next() {
938            E::write_label(f, &label)?;
939        }
940
941        for label in iter {
942            write!(f, ".")?;
943            E::write_label(f, &label)?;
944        }
945
946        // if it was the root name
947        if self.is_root() || self.is_fqdn() {
948            write!(f, ".")?;
949        }
950        Ok(())
951    }
952
953    /// Returns true if the `Name` is either localhost or in the localhost zone.
954    ///
955    /// # Example
956    ///
957    /// ```
958    /// use std::str::FromStr;
959    /// use hickory_proto::rr::Name;
960    ///
961    /// let name = Name::from_str("localhost").unwrap();
962    /// assert!(name.is_localhost());
963    ///
964    /// let name = Name::from_str("localhost.").unwrap();
965    /// assert!(name.is_localhost());
966    ///
967    /// let name = Name::from_str("my.localhost.").unwrap();
968    /// assert!(name.is_localhost());
969    /// ```
970    pub fn is_localhost(&self) -> bool {
971        LOCALHOST_usage.zone_of(self)
972    }
973
974    /// True if the first label of this name is the wildcard, i.e. '*'
975    ///
976    /// # Example
977    ///
978    /// ```
979    /// use std::str::FromStr;
980    /// use hickory_proto::rr::Name;
981    ///
982    /// let name = Name::from_str("www.example.com").unwrap();
983    /// assert!(!name.is_wildcard());
984    ///
985    /// let name = Name::from_str("*.example.com").unwrap();
986    /// assert!(name.is_wildcard());
987    ///
988    /// let name = Name::root();
989    /// assert!(!name.is_wildcard());
990    /// ```
991    pub fn is_wildcard(&self) -> bool {
992        self.iter().next().is_some_and(|l| l == b"*")
993    }
994
995    /// Converts a name to a wildcard, by replacing the first label with `*`
996    ///
997    /// # Example
998    ///
999    /// ```
1000    /// use std::str::FromStr;
1001    /// use hickory_proto::rr::Name;
1002    ///
1003    /// let name = Name::from_str("www.example.com.").unwrap().into_wildcard();
1004    /// assert_eq!(name, Name::from_str("*.example.com.").unwrap());
1005    ///
1006    /// // does nothing if the root
1007    /// let name = Name::root().into_wildcard();
1008    /// assert_eq!(name, Name::root());
1009    /// ```
1010    pub fn into_wildcard(self) -> Self {
1011        if self.label_ends.is_empty() {
1012            return Self::root();
1013        }
1014        let mut label_data = TinyVec::new();
1015        label_data.push(b'*');
1016        let mut label_ends = TinyVec::new();
1017        label_ends.push(1);
1018
1019        // this is not using the Name::extend_name function as it should always be shorter than the original name, so length check is unnecessary
1020        for label in self.iter().skip(1) {
1021            label_data.extend_from_slice(label);
1022            label_ends.push(label_data.len() as u8);
1023        }
1024        Self {
1025            label_data,
1026            label_ends,
1027            is_fqdn: self.is_fqdn,
1028        }
1029    }
1030}
1031
1032impl core::fmt::Debug for Name {
1033    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1034        f.write_str("Name(\"")?;
1035        self.write_labels::<_, LabelEncUtf8>(f)?;
1036        f.write_str("\")")
1037    }
1038}
1039
1040trait LabelEnc {
1041    #[allow(clippy::wrong_self_convention)]
1042    fn to_label(name: &str) -> ProtoResult<Label>;
1043    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error>;
1044}
1045
1046struct LabelEncAscii;
1047
1048impl LabelEnc for LabelEncAscii {
1049    #[allow(clippy::wrong_self_convention)]
1050    fn to_label(name: &str) -> ProtoResult<Label> {
1051        Label::from_ascii(name)
1052    }
1053
1054    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
1055        label.write_ascii(f)
1056    }
1057}
1058
1059struct LabelEncUtf8;
1060
1061impl LabelEnc for LabelEncUtf8 {
1062    #[allow(clippy::wrong_self_convention)]
1063    fn to_label(name: &str) -> ProtoResult<Label> {
1064        Label::from_utf8(name)
1065    }
1066
1067    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
1068        write!(f, "{label}")
1069    }
1070}
1071
1072/// An iterator over labels in a name
1073pub struct LabelIter<'a> {
1074    name: &'a Name,
1075    start: u8,
1076    end: u8,
1077}
1078
1079impl<'a> Iterator for LabelIter<'a> {
1080    type Item = &'a [u8];
1081
1082    fn next(&mut self) -> Option<Self::Item> {
1083        if self.start >= self.end {
1084            return None;
1085        }
1086
1087        let end = *self.name.label_ends.get(self.start as usize)?;
1088        let start = match self.start {
1089            0 => 0,
1090            _ => self.name.label_ends[(self.start - 1) as usize],
1091        };
1092        self.start += 1;
1093        Some(&self.name.label_data[start as usize..end as usize])
1094    }
1095
1096    fn size_hint(&self) -> (usize, Option<usize>) {
1097        let len = self.end.saturating_sub(self.start) as usize;
1098        (len, Some(len))
1099    }
1100}
1101
1102impl ExactSizeIterator for LabelIter<'_> {}
1103
1104impl DoubleEndedIterator for LabelIter<'_> {
1105    fn next_back(&mut self) -> Option<Self::Item> {
1106        if self.end <= self.start {
1107            return None;
1108        }
1109
1110        self.end -= 1;
1111
1112        let end = *self.name.label_ends.get(self.end as usize)?;
1113        let start = match self.end {
1114            0 => 0,
1115            _ => self.name.label_ends[(self.end - 1) as usize],
1116        };
1117
1118        Some(&self.name.label_data[start as usize..end as usize])
1119    }
1120}
1121
1122impl<'a> IntoIterator for &'a Name {
1123    type Item = &'a [u8];
1124    type IntoIter = LabelIter<'a>;
1125
1126    fn into_iter(self) -> Self::IntoIter {
1127        self.iter()
1128    }
1129}
1130
1131impl From<IpAddr> for Name {
1132    fn from(addr: IpAddr) -> Self {
1133        match addr {
1134            IpAddr::V4(ip) => ip.into(),
1135            IpAddr::V6(ip) => ip.into(),
1136        }
1137    }
1138}
1139
1140impl From<Ipv4Addr> for Name {
1141    fn from(addr: Ipv4Addr) -> Self {
1142        let octets = addr.octets();
1143
1144        let mut labels =
1145            octets
1146                .iter()
1147                .rev()
1148                .fold(Vec::<Label>::with_capacity(6), |mut labels, o| {
1149                    let label: Label = format!("{o}")
1150                        .as_bytes()
1151                        .into_label()
1152                        .expect("IP octet to label should never fail");
1153                    labels.push(label);
1154                    labels
1155                });
1156
1157        labels.push(
1158            b"in-addr"
1159                .into_label()
1160                .expect("simple name should never fail"),
1161        );
1162        labels.push(b"arpa".into_label().expect("simple name should never fail"));
1163
1164        Self::from_labels(labels).expect("a translation of Ipv4Addr should never fail")
1165    }
1166}
1167
1168impl From<Ipv6Addr> for Name {
1169    fn from(addr: Ipv6Addr) -> Self {
1170        let segments = addr.segments();
1171
1172        let mut labels =
1173            segments
1174                .iter()
1175                .rev()
1176                .fold(Vec::<Label>::with_capacity(34), |mut labels, o| {
1177                    labels.push(
1178                        format!("{:x}", (*o & 0x000F) as u8)
1179                            .as_bytes()
1180                            .into_label()
1181                            .expect("IP octet to label should never fail"),
1182                    );
1183                    labels.push(
1184                        format!("{:x}", ((*o >> 4) & 0x000F) as u8)
1185                            .as_bytes()
1186                            .into_label()
1187                            .expect("IP octet to label should never fail"),
1188                    );
1189                    labels.push(
1190                        format!("{:x}", ((*o >> 8) & 0x000F) as u8)
1191                            .as_bytes()
1192                            .into_label()
1193                            .expect("IP octet to label should never fail"),
1194                    );
1195                    labels.push(
1196                        format!("{:x}", ((*o >> 12) & 0x000F) as u8)
1197                            .as_bytes()
1198                            .into_label()
1199                            .expect("IP octet to label should never fail"),
1200                    );
1201                    labels
1202                });
1203
1204        labels.push(b"ip6".into_label().expect("simple name should never fail"));
1205        labels.push(b"arpa".into_label().expect("simple name should never fail"));
1206
1207        Self::from_labels(labels).expect("a translation of Ipv6Addr should never fail")
1208    }
1209}
1210
1211impl PartialEq<Self> for Name {
1212    fn eq(&self, other: &Self) -> bool {
1213        match self.is_fqdn == other.is_fqdn {
1214            true => self.cmp_with_f::<CaseInsensitive>(other) == Ordering::Equal,
1215            false => false,
1216        }
1217    }
1218}
1219
1220impl Hash for Name {
1221    fn hash<H: Hasher>(&self, state: &mut H) {
1222        self.is_fqdn.hash(state);
1223
1224        // this needs to be CaseInsensitive like PartialEq
1225        for l in self
1226            .iter()
1227            .map(|l| Label::from_raw_bytes(l).unwrap().to_lowercase())
1228        {
1229            l.hash(state);
1230        }
1231    }
1232}
1233
1234enum ParseState {
1235    Label,
1236    Escape1,
1237    Escape2(u32),
1238    Escape3(u32, u32),
1239}
1240
1241impl BinEncodable for Name {
1242    fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
1243        let is_canonical_names = encoder.is_canonical_names();
1244        self.emit_as_canonical(encoder, is_canonical_names)
1245    }
1246}
1247
1248impl<'r> BinDecodable<'r> for Name {
1249    /// parses the chain of labels
1250    ///  this has a max of 255 octets, with each label being less than 63.
1251    ///  all names will be stored lowercase internally.
1252    /// This will consume the portions of the `Vec` which it is reading...
1253    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
1254        let mut name = Self::default();
1255        read_inner(decoder, &mut name, None)?;
1256        Ok(name)
1257    }
1258}
1259
1260fn read_inner(
1261    decoder: &mut BinDecoder<'_>,
1262    name: &mut Name,
1263    max_idx: Option<usize>,
1264) -> Result<(), DecodeError> {
1265    let mut state: LabelParseState = LabelParseState::LabelLengthOrPointer;
1266    let name_start = decoder.index();
1267
1268    // assume all chars are utf-8. We're doing byte-by-byte operations, no endianness issues...
1269    // reserved: (1000 0000 aka 0800) && (0100 0000 aka 0400)
1270    // pointer: (slice == 1100 0000 aka C0) & C0 == true, then 03FF & slice = offset
1271    // label: 03FF & slice = length; slice.next(length) = label
1272    // root: 0000
1273    loop {
1274        // this protects against overlapping labels
1275        if let Some(max_idx) = max_idx {
1276            if decoder.index() >= max_idx {
1277                return Err(DecodeError::LabelOverlapsWithOther {
1278                    label: name_start,
1279                    other: max_idx,
1280                });
1281            }
1282        }
1283
1284        state = match state {
1285            LabelParseState::LabelLengthOrPointer => {
1286                // determine what the next label is
1287                match decoder
1288                    .peek()
1289                    .map(Restrict::unverified /*verified in this usage*/)
1290                {
1291                    Some(0) => {
1292                        // RFC 1035 Section 3.1 - Name space definitions
1293                        //
1294                        // Domain names in messages are expressed in terms of a sequence of labels.
1295                        // Each label is represented as a one octet length field followed by that
1296                        // number of octets.  **Since every domain name ends with the null label of
1297                        // the root, a domain name is terminated by a length byte of zero.**  The
1298                        // high order two bits of every length octet must be zero, and the
1299                        // remaining six bits of the length field limit the label to 63 octets or
1300                        // less.
1301                        name.set_fqdn(true);
1302                        LabelParseState::Root
1303                    }
1304                    None => {
1305                        // Valid names on the wire should end in a 0-octet, signifying the end of
1306                        // the name. If the last byte wasn't 00, the name is invalid.
1307                        return Err(DecodeError::InsufficientBytes);
1308                    }
1309                    Some(byte) if byte & 0b1100_0000 == 0b1100_0000 => LabelParseState::Pointer,
1310                    Some(byte) if byte & 0b1100_0000 == 0b0000_0000 => LabelParseState::Label,
1311                    Some(byte) => return Err(DecodeError::UnrecognizedLabelCode(byte)),
1312                }
1313            }
1314            // labels must have a maximum length of 63
1315            LabelParseState::Label => {
1316                let label = decoder
1317                    .read_character_data()?
1318                    .verify_unwrap(|l| l.len() <= 63)
1319                    .map_err(|l| DecodeError::LabelBytesTooLong(l.len()))?;
1320
1321                name.extend_name(label)
1322                    .map_err(|_| DecodeError::DomainNameTooLong(label.len()))?;
1323
1324                // reset to collect more data
1325                LabelParseState::LabelLengthOrPointer
1326            }
1327            //         4.1.4. Message compression
1328            //
1329            // In order to reduce the size of messages, the domain system utilizes a
1330            // compression scheme which eliminates the repetition of domain names in a
1331            // message.  In this scheme, an entire domain name or a list of labels at
1332            // the end of a domain name is replaced with a pointer to a prior occurrence
1333            // of the same name.
1334            //
1335            // The pointer takes the form of a two octet sequence:
1336            //
1337            //     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1338            //     | 1  1|                OFFSET                   |
1339            //     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1340            //
1341            // The first two bits are ones.  This allows a pointer to be distinguished
1342            // from a label, since the label must begin with two zero bits because
1343            // labels are restricted to 63 octets or less.  (The 10 and 01 combinations
1344            // are reserved for future use.)  The OFFSET field specifies an offset from
1345            // the start of the message (i.e., the first octet of the ID field in the
1346            // domain header).  A zero offset specifies the first byte of the ID field,
1347            // etc.
1348            LabelParseState::Pointer => {
1349                let pointer_location = decoder.index();
1350                let location = decoder
1351                    .read_u16()?
1352                    .map(|u| {
1353                        // get rid of the two high order bits, they are markers for length or pointers
1354                        u & 0x3FFF
1355                    })
1356                    .verify_unwrap(|ptr| {
1357                        // all labels must appear "prior" to this Name
1358                        (*ptr as usize) < name_start
1359                    })
1360                    .map_err(|e| DecodeError::PointerNotPriorToLabel {
1361                        idx: pointer_location,
1362                        ptr: e,
1363                    })?;
1364
1365                let mut pointer = decoder.clone(location);
1366                read_inner(&mut pointer, name, Some(name_start))?;
1367
1368                // Pointers always finish the name, break like Root.
1369                break;
1370            }
1371            LabelParseState::Root => {
1372                // need to pop() the 0 off the stack...
1373                decoder.pop()?;
1374                break;
1375            }
1376        }
1377    }
1378
1379    // TODO: should we consider checking this while the name is parsed?
1380    let len = name.len();
1381    if len >= 255 {
1382        return Err(DecodeError::DomainNameTooLong(len));
1383    }
1384
1385    Ok(())
1386}
1387
1388impl fmt::Display for Name {
1389    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1390        self.write_labels::<fmt::Formatter<'_>, LabelEncUtf8>(f)
1391    }
1392}
1393
1394impl PartialOrd<Self> for Name {
1395    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1396        Some(self.cmp(other))
1397    }
1398}
1399
1400impl Ord for Name {
1401    /// Case insensitive comparison, see [`Name::cmp_case`] for case sensitive comparisons
1402    ///
1403    /// RFC 4034                DNSSEC Resource Records               March 2005
1404    ///
1405    /// ```text
1406    /// 6.1.  Canonical DNS Name Order
1407    ///
1408    ///  For the purposes of DNS security, owner names are ordered by treating
1409    ///  individual labels as unsigned left-justified octet strings.  The
1410    ///  absence of a octet sorts before a zero value octet, and uppercase
1411    ///  US-ASCII letters are treated as if they were lowercase US-ASCII
1412    ///  letters.
1413    ///
1414    ///  To compute the canonical ordering of a set of DNS names, start by
1415    ///  sorting the names according to their most significant (rightmost)
1416    ///  labels.  For names in which the most significant label is identical,
1417    ///  continue sorting according to their next most significant label, and
1418    ///  so forth.
1419    ///
1420    ///  For example, the following names are sorted in canonical DNS name
1421    ///  order.  The most significant label is "example".  At this level,
1422    ///  "example" sorts first, followed by names ending in "a.example", then
1423    ///  by names ending "z.example".  The names within each level are sorted
1424    ///  in the same way.
1425    ///
1426    ///            example
1427    ///            a.example
1428    ///            yljkjljk.a.example
1429    ///            Z.a.example
1430    ///            zABC.a.EXAMPLE
1431    ///            z.example
1432    ///            \001.z.example
1433    ///            *.z.example
1434    ///            \200.z.example
1435    /// ```
1436    fn cmp(&self, other: &Self) -> Ordering {
1437        self.cmp_with_f::<CaseInsensitive>(other)
1438    }
1439}
1440
1441/// This is the list of states for the label parsing state machine
1442enum LabelParseState {
1443    LabelLengthOrPointer, // basically the start of the FSM
1444    Label,                // storing length of the label, must be < 63
1445    Pointer,              // location of pointer in slice,
1446    Root,                 // root is the end of the labels list for an FQDN
1447}
1448
1449impl FromStr for Name {
1450    type Err = ProtoError;
1451
1452    /// Uses the Name::from_utf8 conversion on this string, see [Name::from_ascii] for ascii only, or for preserving case
1453    fn from_str(s: &str) -> Result<Self, Self::Err> {
1454        Self::from_str_relaxed(s)
1455    }
1456}
1457
1458/// Conversion into a Name
1459pub trait IntoName: Sized {
1460    /// Convert this into Name
1461    fn into_name(self) -> ProtoResult<Name>;
1462
1463    /// Check if this value is a valid IP address
1464    fn to_ip(&self) -> Option<IpAddr>;
1465}
1466
1467impl IntoName for &str {
1468    /// Performs a utf8, IDNA or punycode, translation of the `str` into `Name`
1469    fn into_name(self) -> ProtoResult<Name> {
1470        Name::from_utf8(self)
1471    }
1472
1473    fn to_ip(&self) -> Option<IpAddr> {
1474        IpAddr::from_str(self).ok()
1475    }
1476}
1477
1478impl IntoName for String {
1479    /// Performs a utf8, IDNA or punycode, translation of the `String` into `Name`
1480    fn into_name(self) -> ProtoResult<Name> {
1481        Name::from_utf8(self)
1482    }
1483
1484    fn to_ip(&self) -> Option<IpAddr> {
1485        IpAddr::from_str(self).ok()
1486    }
1487}
1488
1489impl IntoName for &String {
1490    /// Performs a utf8, IDNA or punycode, translation of the `&String` into `Name`
1491    fn into_name(self) -> ProtoResult<Name> {
1492        Name::from_utf8(self)
1493    }
1494
1495    fn to_ip(&self) -> Option<IpAddr> {
1496        IpAddr::from_str(self).ok()
1497    }
1498}
1499
1500impl<T> IntoName for T
1501where
1502    T: Into<Name>,
1503{
1504    fn into_name(self) -> ProtoResult<Name> {
1505        Ok(self.into())
1506    }
1507
1508    fn to_ip(&self) -> Option<IpAddr> {
1509        None
1510    }
1511}
1512
1513#[cfg(feature = "serde")]
1514impl Serialize for Name {
1515    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1516    where
1517        S: Serializer,
1518    {
1519        serializer.serialize_str(&self.to_string())
1520    }
1521}
1522
1523#[cfg(feature = "serde")]
1524impl<'de> Deserialize<'de> for Name {
1525    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1526    where
1527        D: Deserializer<'de>,
1528    {
1529        let s = String::deserialize(deserializer)?;
1530        FromStr::from_str(&s).map_err(de::Error::custom)
1531    }
1532}
1533
1534#[cfg(test)]
1535mod tests {
1536    #![allow(clippy::dbg_macro, clippy::print_stdout)]
1537
1538    use alloc::string::ToString;
1539    use core::cmp::Ordering;
1540    use core::iter;
1541    #[cfg(feature = "std")]
1542    use std::{collections::hash_map::DefaultHasher, println};
1543
1544    use super::*;
1545
1546    use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
1547    #[allow(clippy::useless_attribute)]
1548    #[allow(unused)]
1549    use crate::serialize::binary::*;
1550
1551    fn get_data() -> Vec<(Name, Vec<u8>)> {
1552        vec![
1553            (Name::from_str(".").unwrap(), vec![0]), // base case, only the root
1554            (Name::from_str("a.").unwrap(), vec![1, b'a', 0]), // a single 'a' label
1555            (
1556                Name::from_str("a.bc.").unwrap(),
1557                vec![1, b'a', 2, b'b', b'c', 0],
1558            ), // two labels, 'a.bc'
1559            (
1560                Name::from_str("a.♥.").unwrap(),
1561                vec![1, b'a', 7, b'x', b'n', b'-', b'-', b'g', b'6', b'h', 0],
1562            ), // two labels utf8, 'a.♥'
1563        ]
1564    }
1565
1566    #[test]
1567    fn test_num_labels() {
1568        assert_eq!(Name::from_str("*").unwrap().num_labels(), 0);
1569        assert_eq!(Name::from_str("a").unwrap().num_labels(), 1);
1570        assert_eq!(Name::from_str("*.b").unwrap().num_labels(), 1);
1571        assert_eq!(Name::from_str("a.b").unwrap().num_labels(), 2);
1572        assert_eq!(Name::from_str("*.b.c").unwrap().num_labels(), 2);
1573        assert_eq!(Name::from_str("a.b.c").unwrap().num_labels(), 3);
1574    }
1575
1576    #[test]
1577    fn test_read() {
1578        test_read_data_set(get_data(), |mut d| Name::read(&mut d));
1579    }
1580
1581    #[test]
1582    fn test_write_to() {
1583        test_emit_data_set(get_data(), |e, n| n.emit(e));
1584    }
1585
1586    #[test]
1587    fn test_pointer() {
1588        let mut bytes = Vec::with_capacity(512);
1589
1590        let first = Name::from_str("ra.rb.rc.").unwrap();
1591        let second = Name::from_str("rb.rc.").unwrap();
1592        let third = Name::from_str("rc.").unwrap();
1593        let fourth = Name::from_str("z.ra.rb.rc.").unwrap();
1594
1595        {
1596            let mut e = BinEncoder::new(&mut bytes);
1597
1598            first.emit(&mut e).unwrap();
1599            assert_eq!(e.len(), 10); // should be 7 u8s...
1600
1601            second.emit(&mut e).unwrap();
1602            // if this wrote the entire thing, then it would be +5... but a pointer should be +2
1603            assert_eq!(e.len(), 12);
1604
1605            third.emit(&mut e).unwrap();
1606            assert_eq!(e.len(), 14);
1607
1608            fourth.emit(&mut e).unwrap();
1609            assert_eq!(e.len(), 18);
1610        }
1611
1612        // now read them back
1613        let mut d = BinDecoder::new(&bytes);
1614
1615        let r_test = Name::read(&mut d).unwrap();
1616        assert_eq!(first, r_test);
1617
1618        let r_test = Name::read(&mut d).unwrap();
1619        assert_eq!(second, r_test);
1620
1621        let r_test = Name::read(&mut d).unwrap();
1622        assert_eq!(third, r_test);
1623
1624        let r_test = Name::read(&mut d).unwrap();
1625        assert_eq!(fourth, r_test);
1626    }
1627
1628    #[test]
1629    fn test_pointer_with_pointer_ending_labels() {
1630        let mut bytes: Vec<u8> = Vec::with_capacity(512);
1631
1632        let first = Name::from_str("ra.rb.rc.").unwrap();
1633        let second = Name::from_str("ra.rc.").unwrap();
1634        let third = Name::from_str("ra.rc.").unwrap();
1635
1636        {
1637            let mut e = BinEncoder::new(&mut bytes);
1638
1639            first.emit(&mut e).unwrap();
1640            assert_eq!(e.len(), 10);
1641
1642            second.emit(&mut e).unwrap();
1643            // +5 with the first +3 being the text form of "ra" and +2 for the pointer to "rc".
1644            assert_eq!(e.len(), 15);
1645
1646            // +2 with the pointer to "ra.rc" as previously seen.
1647            third.emit(&mut e).unwrap();
1648            assert_eq!(e.len(), 17);
1649        }
1650
1651        // now read them back
1652        let mut d = BinDecoder::new(&bytes);
1653
1654        let r_test = Name::read(&mut d).unwrap();
1655        assert_eq!(first, r_test);
1656
1657        let r_test = Name::read(&mut d).unwrap();
1658        assert_eq!(second, r_test);
1659
1660        let r_test = Name::read(&mut d).unwrap();
1661        assert_eq!(third, r_test);
1662    }
1663
1664    #[test]
1665    fn test_recursive_pointer() {
1666        // points to an invalid beginning label marker
1667        let bytes = vec![0xC0, 0x01];
1668        let mut d = BinDecoder::new(&bytes);
1669
1670        assert!(Name::read(&mut d).is_err());
1671
1672        // formerly a stack overflow, recursing back on itself
1673        let bytes = vec![0xC0, 0x00];
1674        let mut d = BinDecoder::new(&bytes);
1675
1676        assert!(Name::read(&mut d).is_err());
1677
1678        // formerly a stack overflow, recursing back on itself
1679        let bytes = vec![0x01, 0x41, 0xC0, 0x00];
1680        let mut d = BinDecoder::new(&bytes);
1681
1682        assert!(Name::read(&mut d).is_err());
1683
1684        // formerly a stack overflow, recursing by going past the end, then back to the beginning.
1685        //   this is disallowed based on the rule that all labels must be "prior" to the current label.
1686        let bytes = vec![0xC0, 0x02, 0xC0, 0x00];
1687        let mut d = BinDecoder::new(&bytes);
1688
1689        assert!(Name::read(&mut d).is_err());
1690    }
1691
1692    #[test]
1693    fn test_bin_overlap_enforced() {
1694        let mut bytes: Vec<u8> = Vec::with_capacity(512);
1695        let n: u8 = 31;
1696        for _ in 0..=5 {
1697            bytes.extend(iter::repeat(n).take(n as usize));
1698        }
1699        bytes.push(n + 1);
1700        for b in 0..n {
1701            bytes.push(1 + n + b);
1702        }
1703        bytes.extend_from_slice(&[1, 0]);
1704        for b in 0..n {
1705            bytes.extend_from_slice(&[0xC0, b]);
1706        }
1707        let mut d = BinDecoder::new(&bytes);
1708        d.read_slice(n as usize).unwrap();
1709        assert!(Name::read(&mut d).is_err());
1710    }
1711
1712    #[test]
1713    fn test_bin_max_octets() {
1714        let mut bytes = Vec::with_capacity(512);
1715        for _ in 0..256 {
1716            bytes.extend_from_slice(&[1, b'a']);
1717        }
1718        bytes.push(0);
1719
1720        let mut d = BinDecoder::new(&bytes);
1721        assert!(Name::read(&mut d).is_err());
1722    }
1723
1724    #[test]
1725    fn test_base_name() {
1726        let zone = Name::from_str("example.com.").unwrap();
1727
1728        assert_eq!(zone.base_name(), Name::from_str("com.").unwrap());
1729        assert!(zone.base_name().base_name().is_root());
1730        assert!(zone.base_name().base_name().base_name().is_root());
1731    }
1732
1733    #[test]
1734    fn test_zone_of() {
1735        let zone = Name::from_str("example.com").unwrap();
1736        let www = Name::from_str("www.example.com").unwrap();
1737        let none = Name::from_str("none.com").unwrap();
1738        let root = Name::root();
1739
1740        assert!(zone.zone_of(&zone));
1741        assert!(zone.zone_of(&www));
1742        assert!(!zone.zone_of(&none));
1743        assert!(root.zone_of(&zone));
1744        assert!(!zone.zone_of(&root));
1745    }
1746
1747    #[test]
1748    fn test_zone_of_case() {
1749        let zone = Name::from_ascii("examplE.cOm").unwrap();
1750        let www = Name::from_str("www.example.com").unwrap();
1751        let none = Name::from_str("none.com").unwrap();
1752
1753        assert!(zone.zone_of(&zone));
1754        assert!(zone.zone_of(&www));
1755        assert!(!zone.zone_of(&none))
1756    }
1757
1758    #[test]
1759    fn test_partial_cmp_eq() {
1760        let root = Some(Name::from_labels(Vec::<&str>::new()).unwrap());
1761        let comparisons: Vec<(Name, Name)> = vec![
1762            (root.clone().unwrap(), root.clone().unwrap()),
1763            (
1764                Name::parse("example.", root.as_ref()).unwrap(),
1765                Name::parse("example", root.as_ref()).unwrap(),
1766            ),
1767        ];
1768
1769        for (left, right) in comparisons {
1770            #[cfg(feature = "std")]
1771            println!("left: {left}, right: {right}");
1772            assert_eq!(left.partial_cmp(&right), Some(Ordering::Equal));
1773        }
1774    }
1775
1776    #[test]
1777    fn test_partial_cmp() {
1778        let comparisons: Vec<(Name, Name)> = vec![
1779            (
1780                Name::from_str("example.").unwrap(),
1781                Name::from_str("a.example.").unwrap(),
1782            ),
1783            (
1784                Name::from_str("a.example.").unwrap(),
1785                Name::from_str("yljkjljk.a.example.").unwrap(),
1786            ),
1787            (
1788                Name::from_str("yljkjljk.a.example.").unwrap(),
1789                Name::from_ascii("Z.a.example.").unwrap(),
1790            ),
1791            (
1792                Name::from_ascii("Z.a.example").unwrap(),
1793                Name::from_ascii("zABC.a.EXAMPLE.").unwrap(),
1794            ),
1795            (
1796                Name::from_ascii("zABC.a.EXAMPLE.").unwrap(),
1797                Name::from_str("z.example.").unwrap(),
1798            ),
1799            (
1800                Name::from_str("z.example").unwrap(),
1801                Name::from_labels(vec![&[1u8] as &[u8], b"z", b"example."]).unwrap(),
1802            ),
1803            (
1804                Name::from_labels(vec![&[1u8] as &[u8], b"z", b"example"]).unwrap(),
1805                Name::from_str("*.z.example.").unwrap(),
1806            ),
1807            (
1808                Name::from_str("*.z.example").unwrap(),
1809                Name::from_labels(vec![&[200u8] as &[u8], b"z", b"example."]).unwrap(),
1810            ),
1811        ];
1812
1813        for (left, right) in comparisons {
1814            #[cfg(feature = "std")]
1815            println!("left: {left}, right: {right}");
1816            assert_eq!(left.cmp(&right), Ordering::Less);
1817        }
1818    }
1819
1820    #[test]
1821    fn test_cmp_ignore_case() {
1822        let comparisons: Vec<(Name, Name)> = vec![
1823            (
1824                Name::from_ascii("ExAmPle.").unwrap(),
1825                Name::from_ascii("example.").unwrap(),
1826            ),
1827            (
1828                Name::from_ascii("A.example.").unwrap(),
1829                Name::from_ascii("a.example.").unwrap(),
1830            ),
1831        ];
1832
1833        for (left, right) in comparisons {
1834            #[cfg(feature = "std")]
1835            println!("left: {left}, right: {right}");
1836            assert_eq!(left, right);
1837        }
1838    }
1839
1840    #[test]
1841    fn test_from_ipv4() {
1842        let ip = IpAddr::V4(Ipv4Addr::new(26, 3, 0, 103));
1843        let name = Name::from_str("103.0.3.26.in-addr.arpa.").unwrap();
1844
1845        assert_eq!(Into::<Name>::into(ip), name);
1846    }
1847
1848    #[test]
1849    fn test_from_ipv6() {
1850        let ip = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x1));
1851        let name = Name::from_str(
1852            "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.",
1853        )
1854        .unwrap();
1855
1856        assert_eq!(Into::<Name>::into(ip), name);
1857    }
1858
1859    #[test]
1860    fn test_from_str() {
1861        assert_eq!(
1862            Name::from_str("www.example.com.").unwrap(),
1863            Name::from_labels(vec![b"www" as &[u8], b"example", b"com"]).unwrap()
1864        );
1865        assert_eq!(
1866            Name::from_str(".").unwrap(),
1867            Name::from_labels(Vec::<&str>::new()).unwrap()
1868        );
1869    }
1870
1871    #[test]
1872    fn test_fqdn() {
1873        assert!(Name::root().is_fqdn());
1874        assert!(Name::from_str(".").unwrap().is_fqdn());
1875        assert!(Name::from_str("www.example.com.").unwrap().is_fqdn());
1876        assert!(
1877            Name::from_labels(vec![b"www" as &[u8], b"example", b"com"])
1878                .unwrap()
1879                .is_fqdn()
1880        );
1881
1882        assert!(!Name::new().is_fqdn());
1883        assert!(!Name::from_str("www.example.com").unwrap().is_fqdn());
1884        assert!(!Name::from_str("www.example").unwrap().is_fqdn());
1885        assert!(!Name::from_str("www").unwrap().is_fqdn());
1886    }
1887
1888    #[test]
1889    fn test_to_string() {
1890        assert_eq!(
1891            Name::from_str("www.example.com.").unwrap().to_string(),
1892            "www.example.com."
1893        );
1894        assert_eq!(
1895            Name::from_str("www.example.com").unwrap().to_string(),
1896            "www.example.com"
1897        );
1898    }
1899
1900    #[test]
1901    fn test_from_ascii() {
1902        let bytes_name = Name::from_labels(vec![b"WWW" as &[u8], b"example", b"COM"]).unwrap();
1903        let ascii_name = Name::from_ascii("WWW.example.COM.").unwrap();
1904        let lower_name = Name::from_ascii("www.example.com.").unwrap();
1905
1906        assert!(bytes_name.eq_case(&ascii_name));
1907        assert!(!lower_name.eq_case(&ascii_name));
1908    }
1909
1910    #[test]
1911    fn test_from_utf8() {
1912        let bytes_name = Name::from_labels(vec![b"WWW" as &[u8], b"example", b"COM"]).unwrap();
1913        let utf8_name = Name::from_utf8("WWW.example.COM.").unwrap();
1914        let lower_name = Name::from_utf8("www.example.com.").unwrap();
1915
1916        assert!(!bytes_name.eq_case(&utf8_name));
1917        assert!(lower_name.eq_case(&utf8_name));
1918    }
1919
1920    #[test]
1921    fn test_into_name() {
1922        let name = Name::from_utf8("www.example.com").unwrap();
1923        assert_eq!(Name::from_utf8("www.example.com").unwrap(), name);
1924        assert_eq!(
1925            Name::from_utf8("www.example.com").unwrap(),
1926            Name::from_utf8("www.example.com")
1927                .unwrap()
1928                .into_name()
1929                .unwrap()
1930        );
1931        assert_eq!(
1932            Name::from_utf8("www.example.com").unwrap(),
1933            "www.example.com".into_name().unwrap()
1934        );
1935        assert_eq!(
1936            Name::from_utf8("www.example.com").unwrap(),
1937            "www.example.com".to_string().into_name().unwrap()
1938        );
1939    }
1940
1941    #[test]
1942    fn test_encoding() {
1943        assert_eq!(
1944            Name::from_ascii("WWW.example.COM.").unwrap().to_ascii(),
1945            "WWW.example.COM."
1946        );
1947        assert_eq!(
1948            Name::from_utf8("WWW.example.COM.").unwrap().to_ascii(),
1949            "www.example.com."
1950        );
1951        assert_eq!(
1952            Name::from_ascii("WWW.example.COM.").unwrap().to_utf8(),
1953            "WWW.example.COM."
1954        );
1955    }
1956
1957    #[test]
1958    fn test_excessive_encoding_len() {
1959        use crate::error::ProtoErrorKind;
1960
1961        // u16 max value is where issues start being tickled...
1962        let mut buf = Vec::with_capacity(u16::MAX as usize);
1963        let mut encoder = BinEncoder::new(&mut buf);
1964
1965        let mut result = Ok(());
1966        for i in 0..10000 {
1967            let name = Name::from_ascii(format!("name{i}.example.com.")).unwrap();
1968            result = name.emit(&mut encoder);
1969            if result.is_err() {
1970                break;
1971            }
1972        }
1973
1974        assert!(result.is_err());
1975        match result.unwrap_err().kind() {
1976            ProtoErrorKind::MaxBufferSizeExceeded(_) => (),
1977            _ => panic!(),
1978        }
1979    }
1980
1981    #[test]
1982    fn test_underscore() {
1983        Name::from_str("_begin.example.com").expect("failed at beginning");
1984        Name::from_str_relaxed("mid_dle.example.com").expect("failed in the middle");
1985        Name::from_str_relaxed("end_.example.com").expect("failed at the end");
1986    }
1987
1988    #[test]
1989    fn test_parse_arpa_name() {
1990        assert!(
1991            Name::from_ascii("168.192.in-addr.arpa")
1992                .unwrap()
1993                .parse_arpa_name()
1994                .is_err()
1995        );
1996        assert!(
1997            Name::from_ascii("host.example.com.")
1998                .unwrap()
1999                .parse_arpa_name()
2000                .is_err()
2001        );
2002        assert!(
2003            Name::from_ascii("caffee.ip6.arpa.")
2004                .unwrap()
2005                .parse_arpa_name()
2006                .is_err()
2007        );
2008        assert!(
2009            Name::from_ascii(
2010                "1.4.3.3.7.0.7.3.0.E.2.A.8.9.1.3.1.3.D.8.0.3.A.5.8.8.B.D.0.1.0.0.2.ip6.arpa."
2011            )
2012            .unwrap()
2013            .parse_arpa_name()
2014            .is_err()
2015        );
2016        assert!(
2017            Name::from_ascii("caffee.in-addr.arpa.")
2018                .unwrap()
2019                .parse_arpa_name()
2020                .is_err()
2021        );
2022        assert!(
2023            Name::from_ascii("1.2.3.4.5.in-addr.arpa.")
2024                .unwrap()
2025                .parse_arpa_name()
2026                .is_err()
2027        );
2028        assert!(
2029            Name::from_ascii("1.2.3.4.home.arpa.")
2030                .unwrap()
2031                .parse_arpa_name()
2032                .is_err()
2033        );
2034        assert_eq!(
2035            Name::from_ascii("168.192.in-addr.arpa.")
2036                .unwrap()
2037                .parse_arpa_name()
2038                .unwrap(),
2039            IpNet::V4(Ipv4Net::new("192.168.0.0".parse().unwrap(), 16).unwrap())
2040        );
2041        assert_eq!(
2042            Name::from_ascii("1.0.168.192.in-addr.arpa.")
2043                .unwrap()
2044                .parse_arpa_name()
2045                .unwrap(),
2046            IpNet::V4(Ipv4Net::new("192.168.0.1".parse().unwrap(), 32).unwrap())
2047        );
2048        assert_eq!(
2049            Name::from_ascii("0.1.0.0.2.ip6.arpa.")
2050                .unwrap()
2051                .parse_arpa_name()
2052                .unwrap(),
2053            IpNet::V6(Ipv6Net::new("2001::".parse().unwrap(), 20).unwrap())
2054        );
2055        assert_eq!(
2056            Name::from_ascii("D.0.1.0.0.2.ip6.arpa.")
2057                .unwrap()
2058                .parse_arpa_name()
2059                .unwrap(),
2060            IpNet::V6(Ipv6Net::new("2001:d00::".parse().unwrap(), 24).unwrap())
2061        );
2062        assert_eq!(
2063            Name::from_ascii("B.D.0.1.0.0.2.ip6.arpa.")
2064                .unwrap()
2065                .parse_arpa_name()
2066                .unwrap(),
2067            IpNet::V6(Ipv6Net::new("2001:db0::".parse().unwrap(), 28).unwrap())
2068        );
2069        assert_eq!(
2070            Name::from_ascii("8.B.D.0.1.0.0.2.ip6.arpa.")
2071                .unwrap()
2072                .parse_arpa_name()
2073                .unwrap(),
2074            IpNet::V6(Ipv6Net::new("2001:db8::".parse().unwrap(), 32).unwrap())
2075        );
2076        assert_eq!(
2077            Name::from_ascii(
2078                "4.3.3.7.0.7.3.0.E.2.A.8.9.1.3.1.3.D.8.0.3.A.5.8.8.B.D.0.1.0.0.2.ip6.arpa."
2079            )
2080            .unwrap()
2081            .parse_arpa_name()
2082            .unwrap(),
2083            IpNet::V6(
2084                Ipv6Net::new("2001:db8:85a3:8d3:1319:8a2e:370:7334".parse().unwrap(), 128).unwrap()
2085            )
2086        );
2087    }
2088
2089    #[test]
2090    fn test_prepend_label() {
2091        for name in ["foo.com", "foo.com."] {
2092            let name = Name::from_ascii(name).unwrap();
2093
2094            for label in ["bar", "baz", "quux"] {
2095                let sub = name.clone().prepend_label(label).unwrap();
2096                let expected = Name::from_ascii(format!("{label}.{name}")).unwrap();
2097                assert_eq!(expected, sub);
2098            }
2099        }
2100
2101        for name in ["", "."] {
2102            let name = Name::from_ascii(name).unwrap();
2103
2104            for label in ["bar", "baz", "quux"] {
2105                let sub = name.clone().prepend_label(label).unwrap();
2106                let expected = Name::from_ascii(format!("{label}{name}")).unwrap();
2107                assert_eq!(expected, sub);
2108            }
2109        }
2110    }
2111
2112    #[test]
2113    fn test_name_too_long_with_prepend() {
2114        let n = Name::from_ascii("Llocainvannnnnnaxgtezqzqznnnnnn1na.nnntnninvannnnnnaxgtezqzqznnnnnn1na.nnntnnnnnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.innnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.in").unwrap();
2115        let sfx = "xxxxxxx.yyyyy.zzz";
2116
2117        let error = n
2118            .prepend_label(sfx)
2119            .expect_err("should have errored, too long");
2120
2121        match error.kind() {
2122            ProtoErrorKind::DomainNameTooLong(_) => (),
2123            _ => panic!("expected too long message"),
2124        }
2125    }
2126
2127    #[test]
2128    fn test_name_too_long_with_append() {
2129        // from https://github.com/hickory-dns/hickory-dns/issues/1447
2130        let n = Name::from_ascii("Llocainvannnnnnaxgtezqzqznnnnnn1na.nnntnninvannnnnnaxgtezqzqznnnnnn1na.nnntnnnnnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.innnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.in").unwrap();
2131        let sfx = Name::from_ascii("xxxxxxx.yyyyy.zzz").unwrap();
2132
2133        let error = n
2134            .append_domain(&sfx)
2135            .expect_err("should have errored, too long");
2136
2137        match error.kind() {
2138            ProtoErrorKind::DomainNameTooLong(_) => (),
2139            _ => panic!("expected too long message"),
2140        }
2141    }
2142
2143    #[test]
2144    fn test_encoded_len() {
2145        for name in [
2146            // FQDN
2147            Name::parse("www.example.com.", None).unwrap(),
2148            // Non-FQDN
2149            Name::parse("www", None).unwrap(),
2150            // Root (FQDN)
2151            Name::root(),
2152            // Empty (non-FQDN)
2153            Name::new(),
2154        ] {
2155            let mut buffer = Vec::new();
2156            let mut encoder = BinEncoder::new(&mut buffer);
2157            name.emit(&mut encoder).unwrap();
2158
2159            assert_eq!(
2160                name.encoded_len(),
2161                buffer.len(),
2162                "encoded_len() was incorrect for {name:?}"
2163            );
2164        }
2165    }
2166
2167    #[test]
2168    fn test_length_limits() {
2169        // Labels are limited to 63 bytes, and names are limited to 255 bytes.
2170        // This name is composed of three labels of length 63, a label of length 61, and a label of
2171        // length 0 for the root zone. There are a total of five length bytes. Thus, the total
2172        // length is 63 + 63 + 63 + 61 + 5 = 255.
2173        let encoded_name_255_bytes: [u8; 255] = [
2174            63, b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2175            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2176            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2177            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2178            b'a', b'a', b'a', b'a', b'a', b'a', b'a', 63, b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2179            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2180            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2181            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2182            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', 63,
2183            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2184            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2185            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2186            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2187            b'a', b'a', b'a', b'a', b'a', b'a', b'a', 61, b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2188            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2189            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2190            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a',
2191            b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', b'a', 0,
2192        ];
2193        let expected_name_str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.\
2194        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.\
2195        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.\
2196        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.";
2197
2198        let mut decoder = BinDecoder::new(&encoded_name_255_bytes);
2199        let decoded_name = Name::read(&mut decoder).unwrap();
2200        assert!(decoder.is_empty());
2201
2202        assert_eq!(decoded_name.to_string(), expected_name_str);
2203
2204        // Should not be able to construct a longer name from a string.
2205        let long_label_error = Name::parse(&format!("a{expected_name_str}"), None).unwrap_err();
2206        assert!(matches!(
2207            long_label_error.kind(),
2208            ProtoErrorKind::LabelBytesTooLong(64)
2209        ));
2210        let long_name_error =
2211            Name::parse(&format!("a.{}", &expected_name_str[1..]), None).unwrap_err();
2212        assert!(matches!(
2213            long_name_error.kind(),
2214            ProtoErrorKind::DomainNameTooLong(256)
2215        ))
2216    }
2217
2218    #[test]
2219    fn test_double_ended_iterator() {
2220        let name = Name::from_ascii("www.example.com").unwrap();
2221        let mut iter = name.iter();
2222
2223        assert_eq!(iter.next().unwrap(), b"www");
2224        assert_eq!(iter.next_back().unwrap(), b"com");
2225        assert_eq!(iter.next().unwrap(), b"example");
2226        assert!(iter.next_back().is_none());
2227        assert!(iter.next().is_none());
2228    }
2229
2230    #[test]
2231    fn test_size_hint() {
2232        let name = Name::from_ascii("www.example.com").unwrap();
2233        let mut iter = name.iter();
2234
2235        assert_eq!(iter.size_hint().0, 3);
2236        assert_eq!(iter.next().unwrap(), b"www");
2237        assert_eq!(iter.size_hint().0, 2);
2238        assert_eq!(iter.next_back().unwrap(), b"com");
2239        assert_eq!(iter.size_hint().0, 1);
2240        assert_eq!(iter.next().unwrap(), b"example");
2241        assert_eq!(iter.size_hint().0, 0);
2242        assert!(iter.next_back().is_none());
2243        assert_eq!(iter.size_hint().0, 0);
2244        assert!(iter.next().is_none());
2245        assert_eq!(iter.size_hint().0, 0);
2246    }
2247
2248    #[test]
2249    #[cfg(feature = "std")]
2250    fn test_label_randomization() {
2251        let mut name = Name::root();
2252        name.randomize_label_case();
2253        assert!(name.eq_case(&Name::root()));
2254
2255        for qname in [
2256            "x",
2257            "0",
2258            "aaaaaaaaaaaaaaaa",
2259            "AAAAAAAAAAAAAAAA",
2260            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.",
2261            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.",
2262            "abcdefghijklmnopqrstuvwxyz0123456789A.",
2263            "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.",
2264            "www01.example-site.com",
2265            "1234567890.e-1204089_043820-5.com.",
2266        ] {
2267            let mut name = Name::from_ascii(qname).unwrap();
2268            let name2 = name.clone();
2269            name.randomize_label_case();
2270            assert_eq!(name, name2);
2271            println!("{name2} == {name}: {}", name == name2);
2272        }
2273
2274        // 50k iterations gets us very close to a 50/50 uppercase/lowercase distribution in testing
2275        // without a long test runtime.
2276        let iterations = 50_000;
2277
2278        // This is a max length name (255 bytes) with the maximum number of possible flippable bytes
2279        // (nominal label length 63, except the last, with all label characters ASCII alpha)
2280        let test_str = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.lmnopqrstuvwxyzabcdefghjijklmnopqrstuvwxyzabcdefghijklmnopqrstu.vwxyzABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF.GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO";
2281        let mut name = Name::from_ascii(test_str).unwrap();
2282        let name2 = name.clone();
2283
2284        let len = name.label_data.len();
2285        let mut cap_table: [u32; 255] = [0; 255];
2286        let mut lower_table: [u32; 255] = [0; 255];
2287        let mut mean_table: [f64; 255] = [0.0; 255];
2288
2289        for _ in 0..iterations {
2290            name.randomize_label_case();
2291            assert_eq!(name, name2);
2292
2293            for (j, &cbyte) in name.label_data.iter().enumerate() {
2294                if cbyte.is_ascii_lowercase() {
2295                    lower_table[j] += 1;
2296                } else if cbyte.is_ascii_uppercase() {
2297                    cap_table[j] += 1;
2298                }
2299            }
2300            name = Name::from_ascii(test_str).unwrap();
2301        }
2302
2303        println!("Distribution of lower case values by label offset");
2304        println!("-------------------------------------------------");
2305        for i in 0..len {
2306            let cap_ratio = cap_table[i] as f64 / iterations as f64;
2307            let lower_ratio = lower_table[i] as f64 / iterations as f64;
2308            let total_ratio = cap_ratio + lower_ratio;
2309            mean_table[i] = lower_ratio;
2310            println!(
2311                "{i:03} {:.3}% {:.3}% {:.3}%",
2312                cap_ratio * 100.0,
2313                lower_ratio * 100.0,
2314                total_ratio * 100.0,
2315            );
2316        }
2317        println!("-------------------------------------------------");
2318
2319        let data_mean = mean_table.iter().sum::<f64>() / len as f64;
2320        let data_std_deviation = std_deviation(data_mean, &mean_table);
2321
2322        let mut max_zscore = 0.0;
2323        for elem in mean_table.iter() {
2324            let zscore = (elem - data_mean) / data_std_deviation;
2325
2326            if zscore > max_zscore {
2327                max_zscore = zscore;
2328            }
2329        }
2330
2331        println!("μ: {data_mean:.4} σ: {data_std_deviation:.4}, max variance: {max_zscore:.4}σ");
2332
2333        // These levels are from observed test behavior; typical values for 50k iterations are:
2334        //
2335        //   mean: ~ 50% (this is the % of test iterations where the value is lower case)
2336        //   standard deviation: ~ 0.063
2337        //   largest z-score: ~ 0.10 (i.e., around 1/10 of a standard deviation)
2338        //
2339        // The values below are designed to avoid random CI test failures, but alert on any
2340        // significant variation from the observed randomization behavior during test development.
2341        //
2342        // Specifically, this test will fail if there is a single bit hole in the random bit stream
2343        assert!(data_mean > 0.485 && data_mean < 0.515);
2344        assert!(data_std_deviation < 0.18);
2345        assert!(max_zscore < 0.33);
2346    }
2347
2348    #[cfg(feature = "std")]
2349    fn std_deviation(mean: f64, data: &[f64]) -> f64 {
2350        match (mean, data.len()) {
2351            (data_mean, count) if count > 0 => {
2352                let variance = data
2353                    .iter()
2354                    .map(|value| {
2355                        let diff = data_mean - *value;
2356
2357                        diff * diff
2358                    })
2359                    .sum::<f64>()
2360                    / count as f64;
2361
2362                variance.sqrt()
2363            }
2364            _ => 0.0,
2365        }
2366    }
2367
2368    #[test]
2369    fn test_fqdn_escaped_dot() {
2370        let name = Name::from_utf8("test.").unwrap();
2371        assert!(name.is_fqdn());
2372
2373        let name = Name::from_utf8("test\\.").unwrap();
2374        assert!(!name.is_fqdn());
2375
2376        let name = Name::from_utf8("").unwrap();
2377        assert!(!name.is_fqdn());
2378
2379        let name = Name::from_utf8(".").unwrap();
2380        assert!(name.is_fqdn());
2381    }
2382
2383    #[test]
2384    #[allow(clippy::nonminimal_bool)]
2385    fn test_name_partialeq_constraints() {
2386        let example_fqdn = Name::from_utf8("example.com.").unwrap();
2387        let example_nonfqdn = Name::from_utf8("example.com").unwrap();
2388        let other_fqdn = Name::from_utf8("otherdomain.com.").unwrap();
2389
2390        assert_eq!(example_fqdn, example_fqdn);
2391        assert_eq!(example_nonfqdn, example_nonfqdn);
2392        assert!(example_fqdn != example_nonfqdn);
2393
2394        // a != b if and only if !(a == b).
2395        assert!(example_fqdn != example_nonfqdn && !(example_fqdn == example_nonfqdn));
2396        assert!(example_nonfqdn != example_fqdn && !(example_nonfqdn == example_fqdn));
2397        assert!(example_fqdn != other_fqdn && !(example_fqdn == other_fqdn));
2398        assert!(example_nonfqdn != other_fqdn && !(example_nonfqdn == other_fqdn));
2399    }
2400
2401    #[test]
2402    fn test_name_partialord_constraints() {
2403        use core::cmp::Ordering::*;
2404
2405        let example_fqdn = Name::from_utf8("example.com.").unwrap();
2406        let foo_example_fqdn = Name::from_utf8("foo.example.com.").unwrap();
2407        let example_nonfqdn = Name::from_utf8("example.com").unwrap();
2408        let foo_example_nonfqdn = Name::from_utf8("foo.example.com").unwrap();
2409
2410        // 1. a == b if and only if partial_cmp(a, b) == Some(Equal).
2411        assert_eq!(example_fqdn.partial_cmp(&example_fqdn), Some(Equal),);
2412        assert!(example_fqdn.partial_cmp(&example_nonfqdn) != Some(Equal));
2413
2414        // 2. a < b if and only if partial_cmp(a, b) == Some(Less)
2415        assert!(
2416            example_nonfqdn < example_fqdn
2417                && example_nonfqdn.partial_cmp(&example_fqdn) == Some(Less)
2418        );
2419
2420        assert!(
2421            example_fqdn < foo_example_fqdn
2422                && example_fqdn.partial_cmp(&foo_example_fqdn) == Some(Less)
2423        );
2424
2425        assert!(
2426            example_nonfqdn < foo_example_nonfqdn
2427                && example_nonfqdn.partial_cmp(&foo_example_nonfqdn) == Some(Less)
2428        );
2429
2430        // 3. a > b) if and only if partial_cmp(a, b) == Some(Greater)
2431        assert!(
2432            example_fqdn > example_nonfqdn
2433                && example_fqdn.partial_cmp(&example_nonfqdn) == Some(Greater)
2434        );
2435
2436        assert!(
2437            foo_example_fqdn > example_fqdn
2438                && foo_example_fqdn.partial_cmp(&example_fqdn) == Some(Greater)
2439        );
2440
2441        assert!(
2442            foo_example_nonfqdn > example_nonfqdn
2443                && foo_example_nonfqdn.partial_cmp(&example_nonfqdn) == Some(Greater)
2444        );
2445
2446        // 4. a <= b if and only if a < b || a == b
2447        assert!(example_nonfqdn <= example_fqdn);
2448        assert!(example_nonfqdn <= example_nonfqdn);
2449        assert!(example_fqdn <= example_fqdn);
2450        assert!(example_nonfqdn <= foo_example_nonfqdn);
2451        assert!(example_fqdn <= foo_example_fqdn);
2452        assert!(foo_example_nonfqdn <= foo_example_nonfqdn);
2453        assert!(foo_example_fqdn <= foo_example_fqdn);
2454
2455        // 5. a >= b if and only if a > b || a == b
2456        assert!(example_fqdn >= example_nonfqdn);
2457        assert!(example_nonfqdn >= example_nonfqdn);
2458        assert!(example_fqdn >= example_fqdn);
2459        assert!(foo_example_nonfqdn >= example_nonfqdn);
2460        assert!(foo_example_fqdn >= example_fqdn);
2461        assert!(foo_example_nonfqdn >= foo_example_nonfqdn);
2462        assert!(foo_example_fqdn >= foo_example_fqdn);
2463
2464        // 6. a != b if and only if !(a == b). -- Tested in test_name_partialeq_constraints.
2465    }
2466
2467    #[test]
2468    fn test_name_ord_constraints() {
2469        use core::cmp;
2470
2471        let example_fqdn = Name::from_utf8("example.com.").unwrap();
2472        let foo_example_fqdn = Name::from_utf8("foo.example.com.").unwrap();
2473        let example_nonfqdn = Name::from_utf8("example.com").unwrap();
2474        let foo_example_nonfqdn = Name::from_utf8("foo.example.com").unwrap();
2475
2476        // These are consistency checks between Ord and PartialOrd; therefore
2477        // we don't really care about picking the individual mappings and want
2478        // to test on all possible combinations.
2479        for pair in [
2480            (&example_fqdn, &example_fqdn),
2481            (&example_fqdn, &example_nonfqdn),
2482            (&example_fqdn, &foo_example_fqdn),
2483            (&example_fqdn, &foo_example_nonfqdn),
2484            (&example_nonfqdn, &example_nonfqdn),
2485            (&example_nonfqdn, &example_fqdn),
2486            (&example_nonfqdn, &foo_example_fqdn),
2487            (&example_nonfqdn, &foo_example_nonfqdn),
2488            (&foo_example_fqdn, &example_nonfqdn),
2489            (&foo_example_fqdn, &example_fqdn),
2490            (&foo_example_fqdn, &foo_example_fqdn),
2491            (&foo_example_fqdn, &foo_example_nonfqdn),
2492            (&foo_example_fqdn, &example_nonfqdn),
2493            (&foo_example_fqdn, &example_fqdn),
2494            (&foo_example_fqdn, &foo_example_fqdn),
2495            (&foo_example_fqdn, &foo_example_nonfqdn),
2496        ] {
2497            let name1 = pair.0;
2498            let name2 = pair.1;
2499
2500            // 1. partial_cmp(a, b) == Some(cmp(a, b)).
2501            assert_eq!(name1.partial_cmp(name2), Some(name1.cmp(name2)));
2502
2503            // 2. max(a, b) == max_by(a, b, cmp) (ensured by the default implementation).
2504            assert_eq!(
2505                name1.clone().max(name2.clone()),
2506                cmp::max_by(name1.clone(), name2.clone(), |x: &Name, y: &Name| x.cmp(y)),
2507            );
2508
2509            // 3. min(a, b) == min_by(a, b, cmp) (ensured by the default implementation).
2510            assert_eq!(
2511                name1.clone().min(name2.clone()),
2512                cmp::min_by(name1.clone(), name2.clone(), |x: &Name, y: &Name| x.cmp(y)),
2513            );
2514        }
2515
2516        // 4. For a.clamp(min, max), see the method docs (ensured by the default implementation).
2517        //
2518        // Restrict a value to a certain interval.
2519        // Returns max if self is greater than max, and min if self is less than min.
2520        // Otherwise this returns self.
2521        //
2522        // Panics if min > max -- tested in test_ord_clamp_panic
2523        let min_name = Name::from_utf8("com").unwrap();
2524        let max_name = Name::from_utf8("max.example.com.").unwrap();
2525
2526        assert_eq!(
2527            min_name
2528                .clone()
2529                .clamp(min_name.clone(), example_nonfqdn.clone()),
2530            min_name.clone(),
2531        );
2532
2533        assert_eq!(
2534            max_name
2535                .clone()
2536                .clamp(example_nonfqdn.clone(), example_fqdn.clone()),
2537            example_fqdn.clone(),
2538        );
2539
2540        assert_eq!(
2541            max_name
2542                .clone()
2543                .clamp(example_nonfqdn.clone(), max_name.clone()),
2544            max_name.clone(),
2545        );
2546
2547        // Transitivity tests
2548        // if A < B and B < C then A < C
2549        // if A > B and B > C then A > C
2550        let most_min_name = Name::from_utf8("").unwrap();
2551        let most_max_name = Name::from_utf8("most.max.example.com.").unwrap();
2552        assert_eq!(min_name.cmp(&example_nonfqdn), Ordering::Less);
2553        assert_eq!(most_min_name.cmp(&min_name), Ordering::Less);
2554        assert_eq!(most_min_name.cmp(&example_nonfqdn), Ordering::Less);
2555        assert_eq!(max_name.cmp(&example_fqdn), Ordering::Greater);
2556        assert_eq!(most_max_name.cmp(&max_name), Ordering::Greater);
2557        assert_eq!(most_max_name.cmp(&example_fqdn), Ordering::Greater);
2558    }
2559
2560    #[test]
2561    #[should_panic]
2562    fn test_ord_clamp_panic() {
2563        let min_name = Name::from_utf8("com").unwrap();
2564        let max_name = Name::from_utf8("max.example.com.").unwrap();
2565
2566        // this should panic since min > max
2567        let _ = min_name.clone().clamp(max_name, min_name);
2568    }
2569
2570    #[test]
2571    #[cfg(feature = "std")]
2572    fn test_hash() {
2573        // verify that two identical names with and without the trailing dot hashes to the same value
2574        let mut hasher = DefaultHasher::new();
2575        let with_dot = Name::from_utf8("com.").unwrap();
2576        with_dot.hash(&mut hasher);
2577        let hash_with_dot = hasher.finish();
2578
2579        let mut hasher = DefaultHasher::new();
2580        let without_dot = Name::from_utf8("com").unwrap();
2581        without_dot.hash(&mut hasher);
2582        let hash_without_dot = hasher.finish();
2583        assert_ne!(with_dot, without_dot);
2584        assert_ne!(hash_with_dot, hash_without_dot);
2585    }
2586
2587    #[test]
2588    fn eq_ignore_root_tests() {
2589        let fqdn_name = Name::from_utf8("host.example.com.").unwrap();
2590        let relative_name = Name::from_utf8("host.example.com").unwrap();
2591        let upper_relative_name = Name::from_ascii("HOST.EXAMPLE.COM").unwrap();
2592
2593        assert_ne!(fqdn_name, relative_name);
2594        assert!(fqdn_name.eq_ignore_root(&relative_name));
2595        assert!(!fqdn_name.eq_ignore_root_case(&upper_relative_name));
2596        assert!(fqdn_name.eq_ignore_root(&upper_relative_name));
2597    }
2598
2599    #[test]
2600    fn rfc4034_canonical_ordering_example() {
2601        // From section 6.1 of RFC 4034
2602        let names = Vec::from([
2603            Name::from_labels::<_, &[u8]>([b"example".as_slice()]).unwrap(),
2604            Name::from_labels::<_, &[u8]>([b"a".as_slice(), b"example".as_slice()]).unwrap(),
2605            Name::from_labels::<_, &[u8]>([
2606                b"yljkjljk".as_slice(),
2607                b"a".as_slice(),
2608                b"example".as_slice(),
2609            ])
2610            .unwrap(),
2611            Name::from_labels::<_, &[u8]>([
2612                b"Z".as_slice(),
2613                b"a".as_slice(),
2614                b"example".as_slice(),
2615            ])
2616            .unwrap(),
2617            Name::from_labels::<_, &[u8]>([
2618                b"zABC".as_slice(),
2619                b"a".as_slice(),
2620                b"EXAMPLE".as_slice(),
2621            ])
2622            .unwrap(),
2623            Name::from_labels::<_, &[u8]>([b"z".as_slice(), b"example".as_slice()]).unwrap(),
2624            Name::from_labels::<_, &[u8]>([
2625                b"\x01".as_slice(),
2626                b"z".as_slice(),
2627                b"example".as_slice(),
2628            ])
2629            .unwrap(),
2630            Name::from_labels::<_, &[u8]>([
2631                b"*".as_slice(),
2632                b"z".as_slice(),
2633                b"example".as_slice(),
2634            ])
2635            .unwrap(),
2636            Name::from_labels::<_, &[u8]>([
2637                b"\x80".as_slice(),
2638                b"z".as_slice(),
2639                b"example".as_slice(),
2640            ])
2641            .unwrap(),
2642        ]);
2643        let mut sorted = names.clone();
2644        sorted.sort();
2645        assert_eq!(names, sorted);
2646    }
2647}