1use alloc::string::ToString;
11use alloc::{string::String, vec::Vec};
12use core::char;
13use core::cmp::{Ordering, PartialEq};
14use core::fmt::{self, Write};
15use core::hash::{Hash, Hasher};
16use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
17use core::str::FromStr;
18
19use ipnet::{IpNet, Ipv4Net, Ipv6Net};
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
22use tinyvec::TinyVec;
23
24use crate::error::{ProtoError, ProtoResult};
25use crate::rr::domain::label::{CaseInsensitive, CaseSensitive, IntoLabel, Label, LabelCmp};
26use crate::rr::domain::usage::LOCALHOST as LOCALHOST_usage;
27use crate::serialize::binary::{
28 BinDecodable, BinDecoder, BinEncodable, BinEncoder, DecodeError, NameEncoding, Restrict,
29};
30use crate::serialize::txt::ParseError;
31
32#[derive(Clone, Default, Eq)]
34pub struct Name {
35 is_fqdn: bool,
36 label_data: TinyVec<[u8; 32]>,
37 label_ends: TinyVec<[u8; 24]>,
40}
41
42impl Name {
43 pub const MAX_LENGTH: usize = 255;
45
46 pub fn new() -> Self {
48 Self::default()
49 }
50
51 pub fn root() -> Self {
53 let mut this = Self::new();
54 this.is_fqdn = true;
55 this
56 }
57
58 fn extend_name(&mut self, label: &[u8]) -> Result<(), DecodeError> {
60 let new_len = self.encoded_len() + label.len() + 1;
61
62 if new_len > Self::MAX_LENGTH {
63 return Err(DecodeError::DomainNameTooLong(new_len));
64 };
65
66 self.label_data.extend_from_slice(label);
67 self.label_ends.push(self.label_data.len() as u8);
68
69 Ok(())
70 }
71
72 #[cfg(feature = "std")]
74 pub fn randomize_label_case(&mut self) {
75 let mut rand_bits: u32 = 0;
78
79 for (i, b) in self.label_data.iter_mut().enumerate() {
80 if i % 32 == 0 {
82 rand_bits = rand::random();
83 }
84
85 let flip_case = rand_bits & 1 == 1;
86
87 if b.is_ascii_alphabetic() && flip_case {
88 *b ^= 0x20; }
90
91 rand_bits >>= 1;
92 }
93 }
94
95 pub fn is_root(&self) -> bool {
108 self.label_ends.is_empty() && self.is_fqdn()
109 }
110
111 pub fn is_fqdn(&self) -> bool {
134 self.is_fqdn
135 }
136
137 pub fn set_fqdn(&mut self, val: bool) {
141 self.is_fqdn = val
142 }
143
144 pub fn iter(&self) -> LabelIter<'_> {
146 LabelIter {
147 name: self,
148 start: 0,
149 end: self.label_ends.len() as u8,
150 }
151 }
152
153 pub fn append_label<L: IntoLabel>(mut self, label: L) -> ProtoResult<Self> {
166 self.extend_name(label.into_label()?.as_bytes())?;
167 Ok(self)
168 }
169
170 pub fn prepend_label<L: IntoLabel>(&self, label: L) -> ProtoResult<Self> {
183 let mut name = Self::new().append_label(label)?;
184
185 for label in self.into_iter() {
186 name.extend_name(label)?;
187 }
188
189 name.set_fqdn(self.is_fqdn);
190
191 Ok(name)
192 }
193
194 pub fn from_labels<I, L>(labels: I) -> ProtoResult<Self>
218 where
219 I: IntoIterator<Item = L>,
220 L: IntoLabel,
221 {
222 let (labels, errors): (Vec<_>, Vec<_>) = labels
223 .into_iter()
224 .map(IntoLabel::into_label)
225 .partition(Result::is_ok);
226 let labels: Vec<_> = labels.into_iter().map(Result::unwrap).collect();
227 let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
228
229 if labels.len() > 255 {
230 return Err(DecodeError::DomainNameTooLong(labels.len()).into());
231 };
232 if !errors.is_empty() {
233 return Err(format!("error converting some labels: {errors:?}").into());
234 };
235
236 let mut name = Self {
237 is_fqdn: true,
238 ..Self::default()
239 };
240 for label in labels {
241 name = name.append_label(label)?;
242 }
243
244 Ok(name)
245 }
246
247 pub fn append_name(mut self, other: &Self) -> Result<Self, ProtoError> {
273 for label in other.iter() {
274 self.extend_name(label)?;
275 }
276
277 self.is_fqdn = other.is_fqdn;
278 Ok(self)
279 }
280
281 pub fn append_domain(self, domain: &Self) -> Result<Self, ProtoError> {
299 let mut this = self.append_name(domain)?;
300 this.set_fqdn(true);
301 Ok(this)
302 }
303
304 pub fn to_lowercase(&self) -> Self {
319 let new_label_data = self
320 .label_data
321 .iter()
322 .map(|c| c.to_ascii_lowercase())
323 .collect();
324 Self {
325 is_fqdn: self.is_fqdn,
326 label_data: new_label_data,
327 label_ends: self.label_ends.clone(),
328 }
329 }
330
331 pub fn base_name(&self) -> Self {
345 let length = self.label_ends.len();
346 if length > 0 {
347 return self.trim_to(length - 1);
348 }
349 self.clone()
350 }
351
352 pub fn trim_to(&self, num_labels: usize) -> Self {
367 if num_labels > self.label_ends.len() {
368 self.clone()
369 } else {
370 Self::from_labels(self.iter().skip(self.label_ends.len() - num_labels)).unwrap()
371 }
372 }
373
374 pub fn zone_of_case(&self, name: &Self) -> bool {
376 self.zone_of_with(name, <[u8]>::eq)
377 }
378
379 pub fn zone_of(&self, name: &Self) -> bool {
395 self.zone_of_with(name, <[u8]>::eq_ignore_ascii_case)
396 }
397
398 fn zone_of_with(&self, name: &Self, label_eq: fn(&[u8], &[u8]) -> bool) -> bool {
399 let self_len = self.label_ends.len();
400 let name_len = name.label_ends.len();
401 match (self_len, name_len) {
402 (0, _) => return true,
403 (_, 0) => return false,
404 _ if self_len > name_len => return false,
405 _ => {}
406 }
407
408 self.iter()
409 .rev()
410 .zip(name.iter().rev())
411 .all(|(a, b)| label_eq(a, b))
412 }
413
414 pub fn num_labels(&self) -> u8 {
432 let num = self.label_ends.len() as u8;
435
436 self.iter()
437 .next()
438 .map(|l| if l == b"*" { num - 1 } else { num })
439 .unwrap_or(num)
440 }
441
442 pub fn len(&self) -> usize {
458 let dots = if !self.label_ends.is_empty() {
459 self.label_ends.len()
460 } else {
461 1
462 };
463 dots + self.label_data.len()
464 }
465
466 fn encoded_len(&self) -> usize {
471 self.label_ends.len() + self.label_data.len() + 1
472 }
473
474 pub fn is_empty(&self) -> bool {
477 false
478 }
479
480 pub(crate) fn from_tokens<'i, I: Iterator<Item = &'i str>>(
482 mut tokens: I,
483 origin: Option<&Self>,
484 ) -> Result<Self, ParseError> {
485 let name = tokens
486 .next()
487 .ok_or_else(|| ParseError::MissingToken("name".to_string()))
488 .and_then(|s| Self::parse(s, origin).map_err(ParseError::from))?;
489 Ok(name)
490 }
491
492 pub fn parse(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
505 Self::from_encoded_str::<LabelEncUtf8>(local, origin)
506 }
507
508 pub fn from_ascii<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
536 Self::from_encoded_str::<LabelEncAscii>(name.as_ref(), None)
537 }
538
539 pub fn from_utf8<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
560 Self::from_encoded_str::<LabelEncUtf8>(name.as_ref(), None)
561 }
562
563 pub fn from_str_relaxed<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
582 let name = name.as_ref();
583 Self::from_utf8(name).or_else(|_| Self::from_ascii(name))
584 }
585
586 fn from_encoded_str<E: LabelEnc>(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
587 let mut name = Self::new();
588 let mut label = String::new();
589
590 let mut state = ParseState::Label;
591
592 if local == "." {
594 name.set_fqdn(true);
595 return Ok(name);
596 }
597
598 for ch in local.chars() {
601 match state {
602 ParseState::Label => match ch {
603 '.' => {
604 name = name.append_label(E::to_label(&label)?)?;
605 label.clear();
606 }
607 '\\' => state = ParseState::Escape1,
608 ch if !ch.is_control() && !ch.is_whitespace() => label.push(ch),
609 _ => return Err(format!("unrecognized char: {ch}").into()),
610 },
611 ParseState::Escape1 => {
612 if ch.is_numeric() {
613 state = ParseState::Escape2(
614 ch.to_digit(8)
615 .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?,
616 );
617 } else {
618 label.push(ch);
620 state = ParseState::Label;
621 }
622 }
623 ParseState::Escape2(i) => {
624 if ch.is_numeric() {
625 state = ParseState::Escape3(
626 i,
627 ch.to_digit(8)
628 .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?,
629 );
630 } else {
631 return Err(ProtoError::from(format!("unrecognized char: {ch}")));
632 }
633 }
634 ParseState::Escape3(i, ii) => {
635 if ch.is_numeric() {
636 let val: u32 = (i * 8 * 8)
638 + (ii * 8)
639 + ch.to_digit(8)
640 .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?;
641 let new: char = char::from_u32(val)
642 .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?;
643 label.push(new);
644 state = ParseState::Label;
645 } else {
646 return Err(format!("unrecognized char: {ch}").into());
647 }
648 }
649 }
650 }
651
652 if !label.is_empty() {
653 name = name.append_label(E::to_label(&label)?)?;
654 }
655
656 if label.is_empty() && !local.is_empty() {
658 name.set_fqdn(true);
659 } else if let Some(other) = origin {
660 return name.append_domain(other);
661 }
662
663 Ok(name)
664 }
665
666 fn cmp_with_f<F: LabelCmp>(&self, other: &Self) -> Ordering {
668 match (self.is_fqdn(), other.is_fqdn()) {
669 (false, true) => Ordering::Less,
670 (true, false) => Ordering::Greater,
671 _ => self.cmp_labels::<F>(other),
672 }
673 }
674
675 fn cmp_labels<F: LabelCmp>(&self, other: &Self) -> Ordering {
677 for (l, r) in self.iter().rev().zip(other.iter().rev()) {
679 for (&a, &b) in l.iter().zip(r.iter()) {
680 match F::cmp_u8(a, b) {
681 Ordering::Equal => {}
682 ord => return ord,
683 }
684 }
685 match l.len().cmp(&r.len()) {
686 Ordering::Equal => {}
687 ord => return ord,
688 }
689 }
690 self.label_ends.len().cmp(&other.label_ends.len())
691 }
692
693 pub fn cmp_case(&self, other: &Self) -> Ordering {
695 self.cmp_with_f::<CaseSensitive>(other)
696 }
697
698 pub fn eq_case(&self, other: &Self) -> bool {
700 self.cmp_with_f::<CaseSensitive>(other) == Ordering::Equal
701 }
702
703 pub fn eq_ignore_root(&self, other: &Self) -> bool {
737 self.cmp_labels::<CaseInsensitive>(other) == Ordering::Equal
738 }
739
740 pub fn eq_ignore_root_case(&self, other: &Self) -> bool {
762 self.cmp_labels::<CaseSensitive>(other) == Ordering::Equal
763 }
764
765 pub fn to_ascii(&self) -> String {
770 let mut s = String::with_capacity(self.len());
771 self.write_labels::<String, LabelEncAscii>(&mut s)
772 .expect("string conversion of name should not fail");
773 s
774 }
775
776 pub fn to_utf8(&self) -> String {
782 format!("{self}")
783 }
784
785 pub fn parse_arpa_name(&self) -> Result<IpNet, ProtoError> {
787 if !self.is_fqdn() {
788 return Err("PQDN cannot be valid arpa name".into());
789 }
790 let mut iter = self.iter().rev();
791 let first = iter
792 .next()
793 .ok_or_else(|| ProtoError::from("not an arpa address"))?;
794 if !"arpa".eq_ignore_ascii_case(core::str::from_utf8(first)?) {
795 return Err("not an arpa address".into());
796 }
797 let second = iter
798 .next()
799 .ok_or_else(|| ProtoError::from("invalid arpa address"))?;
800 let mut prefix_len: u8 = 0;
801 match &core::str::from_utf8(second)?.to_ascii_lowercase()[..] {
802 "in-addr" => {
803 let mut octets: [u8; 4] = [0; 4];
804 for octet in octets.iter_mut() {
805 match iter.next() {
806 Some(label) => *octet = core::str::from_utf8(label)?.parse()?,
807 None => break,
808 }
809 prefix_len += 8;
810 }
811 if iter.next().is_some() {
812 return Err("unrecognized in-addr.arpa.".into());
813 }
814 Ok(IpNet::V4(
815 Ipv4Net::new(octets.into(), prefix_len).expect("Ipv4Net::new"),
816 ))
817 }
818 "ip6" => {
819 let mut address: u128 = 0;
820 while prefix_len < 128 {
821 match iter.next() {
822 Some(label) => {
823 if label.len() == 1 {
824 prefix_len += 4;
825 let hex = u8::from_str_radix(core::str::from_utf8(label)?, 16)?;
826 address |= u128::from(hex) << (128 - prefix_len);
827 } else {
828 return Err("invalid label length for ip6.arpa".into());
829 }
830 }
831 None => break,
832 }
833 }
834 if iter.next().is_some() {
835 return Err("unrecognized ip6.arpa.".into());
836 }
837 Ok(IpNet::V6(
838 Ipv6Net::new(address.into(), prefix_len).expect("Ipv6Net::new"),
839 ))
840 }
841 _ => Err("unrecognized arpa address".into()),
842 }
843 }
844
845 fn write_labels<W: Write, E: LabelEnc>(&self, f: &mut W) -> Result<(), fmt::Error> {
846 let mut iter = self.iter().map(|b| Label::from_raw_bytes(b).unwrap());
847 if let Some(label) = iter.next() {
848 E::write_label(f, &label)?;
849 }
850
851 for label in iter {
852 write!(f, ".")?;
853 E::write_label(f, &label)?;
854 }
855
856 if self.is_root() || self.is_fqdn() {
858 write!(f, ".")?;
859 }
860 Ok(())
861 }
862
863 pub fn is_localhost(&self) -> bool {
881 LOCALHOST_usage.zone_of(self)
882 }
883
884 pub fn is_wildcard(&self) -> bool {
902 self.iter().next().is_some_and(|l| l == b"*")
903 }
904
905 pub fn into_wildcard(self) -> Self {
921 if self.label_ends.is_empty() {
922 return Self::root();
923 }
924 let mut label_data = TinyVec::new();
925 label_data.push(b'*');
926 let mut label_ends = TinyVec::new();
927 label_ends.push(1);
928
929 for label in self.iter().skip(1) {
931 label_data.extend_from_slice(label);
932 label_ends.push(label_data.len() as u8);
933 }
934 Self {
935 label_data,
936 label_ends,
937 is_fqdn: self.is_fqdn,
938 }
939 }
940}
941
942impl fmt::Debug for Name {
943 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
944 f.write_str("Name(\"")?;
945 self.write_labels::<_, LabelEncUtf8>(f)?;
946 f.write_str("\")")
947 }
948}
949
950trait LabelEnc {
951 fn to_label(name: &str) -> ProtoResult<Label>;
952 fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error>;
953}
954
955struct LabelEncAscii;
956
957impl LabelEnc for LabelEncAscii {
958 fn to_label(name: &str) -> ProtoResult<Label> {
959 Label::from_ascii(name)
960 }
961
962 fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
963 label.write_ascii(f)
964 }
965}
966
967struct LabelEncUtf8;
968
969impl LabelEnc for LabelEncUtf8 {
970 fn to_label(name: &str) -> ProtoResult<Label> {
971 Label::from_utf8(name)
972 }
973
974 fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
975 write!(f, "{label}")
976 }
977}
978
979pub struct LabelIter<'a> {
981 name: &'a Name,
982 start: u8,
983 end: u8,
984}
985
986impl<'a> Iterator for LabelIter<'a> {
987 type Item = &'a [u8];
988
989 fn next(&mut self) -> Option<Self::Item> {
990 if self.start >= self.end {
991 return None;
992 }
993
994 let end = *self.name.label_ends.get(self.start as usize)?;
995 let start = match self.start {
996 0 => 0,
997 _ => self.name.label_ends[(self.start - 1) as usize],
998 };
999 self.start += 1;
1000 Some(&self.name.label_data[start as usize..end as usize])
1001 }
1002
1003 fn size_hint(&self) -> (usize, Option<usize>) {
1004 let len = self.end.saturating_sub(self.start) as usize;
1005 (len, Some(len))
1006 }
1007}
1008
1009impl ExactSizeIterator for LabelIter<'_> {}
1010
1011impl DoubleEndedIterator for LabelIter<'_> {
1012 fn next_back(&mut self) -> Option<Self::Item> {
1013 if self.end <= self.start {
1014 return None;
1015 }
1016
1017 self.end -= 1;
1018
1019 let end = *self.name.label_ends.get(self.end as usize)?;
1020 let start = match self.end {
1021 0 => 0,
1022 _ => self.name.label_ends[(self.end - 1) as usize],
1023 };
1024
1025 Some(&self.name.label_data[start as usize..end as usize])
1026 }
1027}
1028
1029impl<'a> IntoIterator for &'a Name {
1030 type Item = &'a [u8];
1031 type IntoIter = LabelIter<'a>;
1032
1033 fn into_iter(self) -> Self::IntoIter {
1034 self.iter()
1035 }
1036}
1037
1038impl From<IpAddr> for Name {
1039 fn from(addr: IpAddr) -> Self {
1040 match addr {
1041 IpAddr::V4(ip) => ip.into(),
1042 IpAddr::V6(ip) => ip.into(),
1043 }
1044 }
1045}
1046
1047impl From<Ipv4Addr> for Name {
1048 fn from(addr: Ipv4Addr) -> Self {
1049 let octets = addr.octets();
1050
1051 let mut labels =
1052 octets
1053 .iter()
1054 .rev()
1055 .fold(Vec::<Label>::with_capacity(6), |mut labels, o| {
1056 let label: Label = format!("{o}")
1057 .as_bytes()
1058 .into_label()
1059 .expect("IP octet to label should never fail");
1060 labels.push(label);
1061 labels
1062 });
1063
1064 labels.push(
1065 b"in-addr"
1066 .into_label()
1067 .expect("simple name should never fail"),
1068 );
1069 labels.push(b"arpa".into_label().expect("simple name should never fail"));
1070
1071 Self::from_labels(labels).expect("a translation of Ipv4Addr should never fail")
1072 }
1073}
1074
1075impl From<Ipv6Addr> for Name {
1076 fn from(addr: Ipv6Addr) -> Self {
1077 let segments = addr.segments();
1078
1079 let mut labels =
1080 segments
1081 .iter()
1082 .rev()
1083 .fold(Vec::<Label>::with_capacity(34), |mut labels, o| {
1084 labels.push(
1085 format!("{:x}", (*o & 0x000F) as u8)
1086 .as_bytes()
1087 .into_label()
1088 .expect("IP octet to label should never fail"),
1089 );
1090 labels.push(
1091 format!("{:x}", ((*o >> 4) & 0x000F) as u8)
1092 .as_bytes()
1093 .into_label()
1094 .expect("IP octet to label should never fail"),
1095 );
1096 labels.push(
1097 format!("{:x}", ((*o >> 8) & 0x000F) as u8)
1098 .as_bytes()
1099 .into_label()
1100 .expect("IP octet to label should never fail"),
1101 );
1102 labels.push(
1103 format!("{:x}", ((*o >> 12) & 0x000F) as u8)
1104 .as_bytes()
1105 .into_label()
1106 .expect("IP octet to label should never fail"),
1107 );
1108 labels
1109 });
1110
1111 labels.push(b"ip6".into_label().expect("simple name should never fail"));
1112 labels.push(b"arpa".into_label().expect("simple name should never fail"));
1113
1114 Self::from_labels(labels).expect("a translation of Ipv6Addr should never fail")
1115 }
1116}
1117
1118impl PartialEq<Self> for Name {
1119 fn eq(&self, other: &Self) -> bool {
1120 match self.is_fqdn == other.is_fqdn {
1121 true => self.cmp_with_f::<CaseInsensitive>(other) == Ordering::Equal,
1122 false => false,
1123 }
1124 }
1125}
1126
1127impl Hash for Name {
1128 fn hash<H: Hasher>(&self, state: &mut H) {
1129 self.is_fqdn.hash(state);
1130 self.label_ends.hash(state);
1131 self.iter()
1133 .flatten()
1134 .for_each(|&b| state.write_u8(b.to_ascii_lowercase()));
1135 }
1136}
1137
1138enum ParseState {
1139 Label,
1140 Escape1,
1141 Escape2(u32),
1142 Escape3(u32, u32),
1143}
1144
1145impl BinEncodable for Name {
1146 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
1147 let name;
1148 let name_ref = if matches!(encoder.name_encoding(), NameEncoding::UncompressedLowercase) {
1149 name = self.to_lowercase();
1150 &name
1151 } else {
1152 self
1153 };
1154 let compression = matches!(encoder.name_encoding(), NameEncoding::Compressed)
1155 && encoder.compressed_name_count < COMPRESSED_NAME_LIMIT;
1156
1157 let buf_len = encoder.len(); let labels = name_ref.iter();
1161
1162 let mut labels_written = Vec::with_capacity(name_ref.label_ends.len());
1164 for label in labels {
1167 if label.len() > 63 {
1168 return Err(DecodeError::LabelBytesTooLong(label.len()).into());
1169 }
1170
1171 labels_written.push(encoder.offset());
1172 encoder.emit_character_data(label)?;
1173 }
1174 let last_index = encoder.offset();
1175 if compression {
1178 encoder.compressed_name_count += 1;
1179 for label_idx in &labels_written {
1180 match encoder.get_label_pointer(*label_idx, last_index) {
1181 Some(loc) if loc & 0xC000 == 0 => {
1182 encoder.set_offset(*label_idx);
1184 encoder.trim();
1185
1186 encoder.emit_u16(0xC000u16 | loc)?;
1189
1190 return Ok(());
1192 }
1193 _ => {
1194 encoder.store_label_pointer(*label_idx, last_index);
1196 }
1197 }
1198 }
1199 } else {
1200 for label_idx in &labels_written {
1203 encoder.store_label_pointer(*label_idx, last_index);
1204 }
1205 }
1206
1207 encoder.emit(0)?;
1210
1211 let length = encoder.len() - buf_len;
1213 if length > 255 {
1214 return Err(DecodeError::DomainNameTooLong(length).into());
1215 }
1216
1217 Ok(())
1218 }
1219}
1220
1221const COMPRESSED_NAME_LIMIT: usize = 120;
1226
1227impl<'r> BinDecodable<'r> for Name {
1228 fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
1233 let mut name = Self::default();
1234 read_inner(decoder, &mut name)?;
1235 Ok(name)
1236 }
1237}
1238
1239fn read_inner(decoder: &mut BinDecoder<'_>, name: &mut Name) -> Result<(), DecodeError> {
1240 let mut state: LabelParseState = LabelParseState::LabelLengthOrPointer;
1241 let mut ptr_max_idx = None;
1242 let mut decoder_tmp;
1243 let mut decoder = &mut *decoder;
1244 let mut name_start = decoder.index();
1245
1246 loop {
1252 if let Some(max_idx) = ptr_max_idx {
1254 if decoder.index() >= max_idx {
1255 return Err(DecodeError::LabelOverlapsWithOther {
1256 label: name_start,
1257 other: max_idx,
1258 });
1259 }
1260 }
1261
1262 state = match state {
1263 LabelParseState::LabelLengthOrPointer => {
1264 match decoder
1266 .peek()
1267 .map(Restrict::unverified )
1268 {
1269 Some(0) => {
1270 name.set_fqdn(true);
1280 LabelParseState::Root
1281 }
1282 None => {
1283 return Err(DecodeError::InsufficientBytes);
1286 }
1287 Some(byte) if byte & 0b1100_0000 == 0b1100_0000 => LabelParseState::Pointer,
1288 Some(byte) if byte & 0b1100_0000 == 0b0000_0000 => LabelParseState::Label,
1289 Some(byte) => return Err(DecodeError::UnrecognizedLabelCode(byte)),
1290 }
1291 }
1292 LabelParseState::Label => {
1294 let label = decoder
1295 .read_character_data()?
1296 .verify_unwrap(|l| l.len() <= 63)
1297 .map_err(|l| DecodeError::LabelBytesTooLong(l.len()))?;
1298
1299 name.extend_name(label)
1300 .map_err(|_| DecodeError::DomainNameTooLong(label.len()))?;
1301
1302 LabelParseState::LabelLengthOrPointer
1304 }
1305 LabelParseState::Pointer => {
1327 let pointer_location = decoder.index();
1328 let location = decoder
1329 .read_u16()?
1330 .map(|u| {
1331 u & 0x3FFF
1333 })
1334 .verify_unwrap(|ptr| {
1335 (*ptr as usize) < name_start
1337 })
1338 .map_err(|e| DecodeError::PointerNotPriorToLabel {
1339 idx: pointer_location,
1340 ptr: e,
1341 })?;
1342
1343 ptr_max_idx = Some(name_start);
1345 decoder_tmp = decoder.clone(location);
1346 decoder = &mut decoder_tmp;
1347 name_start = decoder.index();
1348 LabelParseState::LabelLengthOrPointer
1349 }
1350 LabelParseState::Root => {
1351 decoder.pop()?;
1353 break;
1354 }
1355 }
1356 }
1357
1358 let len = name.len();
1360 if len >= 255 {
1361 return Err(DecodeError::DomainNameTooLong(len));
1362 }
1363
1364 Ok(())
1365}
1366
1367impl fmt::Display for Name {
1368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1369 self.write_labels::<fmt::Formatter<'_>, LabelEncUtf8>(f)
1370 }
1371}
1372
1373impl PartialOrd<Self> for Name {
1374 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1375 Some(self.cmp(other))
1376 }
1377}
1378
1379impl Ord for Name {
1380 fn cmp(&self, other: &Self) -> Ordering {
1416 self.cmp_with_f::<CaseInsensitive>(other)
1417 }
1418}
1419
1420enum LabelParseState {
1422 LabelLengthOrPointer, Label, Pointer, Root, }
1427
1428impl FromStr for Name {
1429 type Err = ProtoError;
1430
1431 fn from_str(s: &str) -> Result<Self, Self::Err> {
1433 Self::from_str_relaxed(s)
1434 }
1435}
1436
1437pub trait IntoName: Sized {
1439 fn into_name(self) -> ProtoResult<Name>;
1441
1442 fn to_ip(&self) -> Option<IpAddr>;
1444}
1445
1446impl IntoName for &str {
1447 fn into_name(self) -> ProtoResult<Name> {
1449 Name::from_utf8(self)
1450 }
1451
1452 fn to_ip(&self) -> Option<IpAddr> {
1453 IpAddr::from_str(self).ok()
1454 }
1455}
1456
1457impl IntoName for String {
1458 fn into_name(self) -> ProtoResult<Name> {
1460 Name::from_utf8(self)
1461 }
1462
1463 fn to_ip(&self) -> Option<IpAddr> {
1464 IpAddr::from_str(self).ok()
1465 }
1466}
1467
1468impl IntoName for &String {
1469 fn into_name(self) -> ProtoResult<Name> {
1471 Name::from_utf8(self)
1472 }
1473
1474 fn to_ip(&self) -> Option<IpAddr> {
1475 IpAddr::from_str(self).ok()
1476 }
1477}
1478
1479impl<T> IntoName for T
1480where
1481 T: Into<Name>,
1482{
1483 fn into_name(self) -> ProtoResult<Name> {
1484 Ok(self.into())
1485 }
1486
1487 fn to_ip(&self) -> Option<IpAddr> {
1488 None
1489 }
1490}
1491
1492#[cfg(feature = "serde")]
1493impl Serialize for Name {
1494 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1495 where
1496 S: Serializer,
1497 {
1498 serializer.serialize_str(&self.to_string())
1499 }
1500}
1501
1502#[cfg(feature = "serde")]
1503impl<'de> Deserialize<'de> for Name {
1504 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1505 where
1506 D: Deserializer<'de>,
1507 {
1508 let s = String::deserialize(deserializer)?;
1509 FromStr::from_str(&s).map_err(de::Error::custom)
1510 }
1511}
1512
1513#[cfg(test)]
1514mod tests {
1515 #![allow(clippy::dbg_macro, clippy::print_stdout)]
1516
1517 use alloc::string::ToString;
1518 use core::cmp::Ordering;
1519 #[cfg(feature = "std")]
1520 use std::{collections::hash_map::DefaultHasher, println};
1521
1522 use super::*;
1523 use crate::error::ProtoError;
1524 use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
1525
1526 fn get_data() -> Vec<(Name, Vec<u8>)> {
1527 vec![
1528 (Name::from_str(".").unwrap(), vec![0]), (Name::from_str("a.").unwrap(), vec![1, b'a', 0]), (
1531 Name::from_str("a.bc.").unwrap(),
1532 vec![1, b'a', 2, b'b', b'c', 0],
1533 ), (
1535 Name::from_str("a.♥.").unwrap(),
1536 vec![1, b'a', 7, b'x', b'n', b'-', b'-', b'g', b'6', b'h', 0],
1537 ), ]
1539 }
1540
1541 #[test]
1542 fn test_num_labels() {
1543 assert_eq!(Name::from_str("*").unwrap().num_labels(), 0);
1544 assert_eq!(Name::from_str("a").unwrap().num_labels(), 1);
1545 assert_eq!(Name::from_str("*.b").unwrap().num_labels(), 1);
1546 assert_eq!(Name::from_str("a.b").unwrap().num_labels(), 2);
1547 assert_eq!(Name::from_str("*.b.c").unwrap().num_labels(), 2);
1548 assert_eq!(Name::from_str("a.b.c").unwrap().num_labels(), 3);
1549 }
1550
1551 #[test]
1552 fn test_read() {
1553 test_read_data_set(get_data(), |mut d| Name::read(&mut d));
1554 }
1555
1556 #[test]
1557 fn test_write_to() {
1558 test_emit_data_set(get_data(), |e, n| n.emit(e));
1559 }
1560
1561 #[test]
1562 fn test_pointer() {
1563 let mut bytes = Vec::with_capacity(512);
1564
1565 let first = Name::from_str("ra.rb.rc.").unwrap();
1566 let second = Name::from_str("rb.rc.").unwrap();
1567 let third = Name::from_str("rc.").unwrap();
1568 let fourth = Name::from_str("z.ra.rb.rc.").unwrap();
1569
1570 {
1571 let mut e = BinEncoder::new(&mut bytes);
1572
1573 first.emit(&mut e).unwrap();
1574 assert_eq!(e.len(), 10); second.emit(&mut e).unwrap();
1577 assert_eq!(e.len(), 12);
1579
1580 third.emit(&mut e).unwrap();
1581 assert_eq!(e.len(), 14);
1582
1583 fourth.emit(&mut e).unwrap();
1584 assert_eq!(e.len(), 18);
1585 }
1586
1587 let mut d = BinDecoder::new(&bytes);
1589
1590 let r_test = Name::read(&mut d).unwrap();
1591 assert_eq!(first, r_test);
1592
1593 let r_test = Name::read(&mut d).unwrap();
1594 assert_eq!(second, r_test);
1595
1596 let r_test = Name::read(&mut d).unwrap();
1597 assert_eq!(third, r_test);
1598
1599 let r_test = Name::read(&mut d).unwrap();
1600 assert_eq!(fourth, r_test);
1601 }
1602
1603 #[test]
1604 fn test_pointer_with_pointer_ending_labels() {
1605 let mut bytes: Vec<u8> = Vec::with_capacity(512);
1606
1607 let first = Name::from_str("ra.rb.rc.").unwrap();
1608 let second = Name::from_str("ra.rc.").unwrap();
1609 let third = Name::from_str("ra.rc.").unwrap();
1610
1611 {
1612 let mut e = BinEncoder::new(&mut bytes);
1613
1614 first.emit(&mut e).unwrap();
1615 assert_eq!(e.len(), 10);
1616
1617 second.emit(&mut e).unwrap();
1618 assert_eq!(e.len(), 15);
1620
1621 third.emit(&mut e).unwrap();
1623 assert_eq!(e.len(), 17);
1624 }
1625
1626 let mut d = BinDecoder::new(&bytes);
1628
1629 let r_test = Name::read(&mut d).unwrap();
1630 assert_eq!(first, r_test);
1631
1632 let r_test = Name::read(&mut d).unwrap();
1633 assert_eq!(second, r_test);
1634
1635 let r_test = Name::read(&mut d).unwrap();
1636 assert_eq!(third, r_test);
1637 }
1638
1639 #[test]
1640 fn test_recursive_pointer() {
1641 let bytes = vec![0xC0, 0x01];
1643 let mut d = BinDecoder::new(&bytes);
1644
1645 assert!(Name::read(&mut d).is_err());
1646
1647 let bytes = vec![0xC0, 0x00];
1649 let mut d = BinDecoder::new(&bytes);
1650
1651 assert!(Name::read(&mut d).is_err());
1652
1653 let bytes = vec![0x01, 0x41, 0xC0, 0x00];
1655 let mut d = BinDecoder::new(&bytes);
1656
1657 assert!(Name::read(&mut d).is_err());
1658
1659 let bytes = vec![0xC0, 0x02, 0xC0, 0x00];
1662 let mut d = BinDecoder::new(&bytes);
1663
1664 assert!(Name::read(&mut d).is_err());
1665 }
1666
1667 #[test]
1668 #[cfg(feature = "std")]
1669 fn test_long_pointer_chain_small_stack() {
1670 let mut bytes = vec![0x00, 0xC0, 0x00];
1672 let mut last_ptr_offset: u16 = 1;
1673 for _ in 1..8000 {
1674 last_ptr_offset = bytes.len() as u16 - 2;
1675 bytes.extend(&u16::to_be_bytes(0xC000 | last_ptr_offset));
1676 }
1677
1678 let name = std::thread::Builder::new()
1680 .stack_size(256 * 1024)
1681 .spawn(move || {
1682 let mut decoder = BinDecoder::new(&bytes).clone(last_ptr_offset);
1683 Name::read(&mut decoder).unwrap()
1684 })
1685 .unwrap()
1686 .join()
1687 .unwrap();
1688
1689 assert_eq!(name, Name::root());
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(core::iter::repeat_n(n, 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::ProtoError;
1960
1961 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 match result.unwrap_err() {
1975 ProtoError::MaxBufferSizeExceeded(_) => (),
1976 _ => panic!(),
1977 }
1978 }
1979
1980 #[test]
1981 fn test_underscore() {
1982 Name::from_str("_begin.example.com").expect("failed at beginning");
1983 Name::from_str_relaxed("mid_dle.example.com").expect("failed in the middle");
1984 Name::from_str_relaxed("end_.example.com").expect("failed at the end");
1985 }
1986
1987 #[test]
1988 fn test_parse_arpa_name() {
1989 assert!(
1990 Name::from_ascii("168.192.in-addr.arpa")
1991 .unwrap()
1992 .parse_arpa_name()
1993 .is_err()
1994 );
1995 assert!(
1996 Name::from_ascii("host.example.com.")
1997 .unwrap()
1998 .parse_arpa_name()
1999 .is_err()
2000 );
2001 assert!(
2002 Name::from_ascii("caffee.ip6.arpa.")
2003 .unwrap()
2004 .parse_arpa_name()
2005 .is_err()
2006 );
2007 assert!(
2008 Name::from_ascii(
2009 "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."
2010 )
2011 .unwrap()
2012 .parse_arpa_name()
2013 .is_err()
2014 );
2015 assert!(
2016 Name::from_ascii("caffee.in-addr.arpa.")
2017 .unwrap()
2018 .parse_arpa_name()
2019 .is_err()
2020 );
2021 assert!(
2022 Name::from_ascii("1.2.3.4.5.in-addr.arpa.")
2023 .unwrap()
2024 .parse_arpa_name()
2025 .is_err()
2026 );
2027 assert!(
2028 Name::from_ascii("1.2.3.4.home.arpa.")
2029 .unwrap()
2030 .parse_arpa_name()
2031 .is_err()
2032 );
2033 assert_eq!(
2034 Name::from_ascii("168.192.in-addr.arpa.")
2035 .unwrap()
2036 .parse_arpa_name()
2037 .unwrap(),
2038 IpNet::V4(Ipv4Net::new("192.168.0.0".parse().unwrap(), 16).unwrap())
2039 );
2040 assert_eq!(
2041 Name::from_ascii("1.0.168.192.in-addr.arpa.")
2042 .unwrap()
2043 .parse_arpa_name()
2044 .unwrap(),
2045 IpNet::V4(Ipv4Net::new("192.168.0.1".parse().unwrap(), 32).unwrap())
2046 );
2047 assert_eq!(
2048 Name::from_ascii("0.1.0.0.2.ip6.arpa.")
2049 .unwrap()
2050 .parse_arpa_name()
2051 .unwrap(),
2052 IpNet::V6(Ipv6Net::new("2001::".parse().unwrap(), 20).unwrap())
2053 );
2054 assert_eq!(
2055 Name::from_ascii("D.0.1.0.0.2.ip6.arpa.")
2056 .unwrap()
2057 .parse_arpa_name()
2058 .unwrap(),
2059 IpNet::V6(Ipv6Net::new("2001:d00::".parse().unwrap(), 24).unwrap())
2060 );
2061 assert_eq!(
2062 Name::from_ascii("B.D.0.1.0.0.2.ip6.arpa.")
2063 .unwrap()
2064 .parse_arpa_name()
2065 .unwrap(),
2066 IpNet::V6(Ipv6Net::new("2001:db0::".parse().unwrap(), 28).unwrap())
2067 );
2068 assert_eq!(
2069 Name::from_ascii("8.B.D.0.1.0.0.2.ip6.arpa.")
2070 .unwrap()
2071 .parse_arpa_name()
2072 .unwrap(),
2073 IpNet::V6(Ipv6Net::new("2001:db8::".parse().unwrap(), 32).unwrap())
2074 );
2075 assert_eq!(
2076 Name::from_ascii(
2077 "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."
2078 )
2079 .unwrap()
2080 .parse_arpa_name()
2081 .unwrap(),
2082 IpNet::V6(
2083 Ipv6Net::new("2001:db8:85a3:8d3:1319:8a2e:370:7334".parse().unwrap(), 128).unwrap()
2084 )
2085 );
2086 }
2087
2088 #[test]
2089 fn test_prepend_label() {
2090 for name in ["foo.com", "foo.com."] {
2091 let name = Name::from_ascii(name).unwrap();
2092
2093 for label in ["bar", "baz", "quux"] {
2094 let sub = name.clone().prepend_label(label).unwrap();
2095 let expected = Name::from_ascii(format!("{label}.{name}")).unwrap();
2096 assert_eq!(expected, sub);
2097 }
2098 }
2099
2100 for name in ["", "."] {
2101 let name = Name::from_ascii(name).unwrap();
2102
2103 for label in ["bar", "baz", "quux"] {
2104 let sub = name.clone().prepend_label(label).unwrap();
2105 let expected = Name::from_ascii(format!("{label}{name}")).unwrap();
2106 assert_eq!(expected, sub);
2107 }
2108 }
2109 }
2110
2111 #[test]
2112 fn test_name_too_long_with_prepend() {
2113 let n = Name::from_ascii("Llocainvannnnnnaxgtezqzqznnnnnn1na.nnntnninvannnnnnaxgtezqzqznnnnnn1na.nnntnnnnnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.innnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.in").unwrap();
2114 let sfx = "xxxxxxx.yyyyy.zzz";
2115
2116 let error = n
2117 .prepend_label(sfx)
2118 .expect_err("should have errored, too long");
2119
2120 match error {
2121 ProtoError::Decode(DecodeError::DomainNameTooLong(_)) => (),
2122 _ => panic!("expected too long message"),
2123 }
2124 }
2125
2126 #[test]
2127 fn test_name_too_long_with_append() {
2128 let n = Name::from_ascii("Llocainvannnnnnaxgtezqzqznnnnnn1na.nnntnninvannnnnnaxgtezqzqznnnnnn1na.nnntnnnnnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.innnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.in").unwrap();
2130 let sfx = Name::from_ascii("xxxxxxx.yyyyy.zzz").unwrap();
2131
2132 let error = n
2133 .append_domain(&sfx)
2134 .expect_err("should have errored, too long");
2135
2136 match error {
2137 ProtoError::Decode(DecodeError::DomainNameTooLong(_)) => (),
2138 _ => panic!("expected too long message"),
2139 }
2140 }
2141
2142 #[test]
2143 fn test_encoded_len() {
2144 for name in [
2145 Name::parse("www.example.com.", None).unwrap(),
2147 Name::parse("www", None).unwrap(),
2149 Name::root(),
2151 Name::new(),
2153 ] {
2154 let mut buffer = Vec::new();
2155 let mut encoder = BinEncoder::new(&mut buffer);
2156 name.emit(&mut encoder).unwrap();
2157
2158 assert_eq!(
2159 name.encoded_len(),
2160 buffer.len(),
2161 "encoded_len() was incorrect for {name:?}"
2162 );
2163 }
2164 }
2165
2166 #[test]
2167 fn test_length_limits() {
2168 let encoded_name_255_bytes: [u8; 255] = [
2173 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',
2174 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', 63, 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', 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', 63,
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',
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', 61, 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', 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', 0,
2191 ];
2192 let expected_name_str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.\
2193 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.\
2194 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.\
2195 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.";
2196
2197 let mut decoder = BinDecoder::new(&encoded_name_255_bytes);
2198 let decoded_name = Name::read(&mut decoder).unwrap();
2199 assert!(decoder.is_empty());
2200
2201 assert_eq!(decoded_name.to_string(), expected_name_str);
2202
2203 let long_label_error = Name::parse(&format!("a{expected_name_str}"), None).unwrap_err();
2205 assert!(matches!(
2206 long_label_error,
2207 ProtoError::Decode(DecodeError::LabelBytesTooLong(64))
2208 ));
2209 let long_name_error =
2210 Name::parse(&format!("a.{}", &expected_name_str[1..]), None).unwrap_err();
2211 assert!(matches!(
2212 long_name_error,
2213 ProtoError::Decode(DecodeError::DomainNameTooLong(256))
2214 ))
2215 }
2216
2217 #[test]
2218 fn test_double_ended_iterator() {
2219 let name = Name::from_ascii("www.example.com").unwrap();
2220 let mut iter = name.iter();
2221
2222 assert_eq!(iter.next().unwrap(), b"www");
2223 assert_eq!(iter.next_back().unwrap(), b"com");
2224 assert_eq!(iter.next().unwrap(), b"example");
2225 assert!(iter.next_back().is_none());
2226 assert!(iter.next().is_none());
2227 }
2228
2229 #[test]
2230 fn test_size_hint() {
2231 let name = Name::from_ascii("www.example.com").unwrap();
2232 let mut iter = name.iter();
2233
2234 assert_eq!(iter.size_hint().0, 3);
2235 assert_eq!(iter.next().unwrap(), b"www");
2236 assert_eq!(iter.size_hint().0, 2);
2237 assert_eq!(iter.next_back().unwrap(), b"com");
2238 assert_eq!(iter.size_hint().0, 1);
2239 assert_eq!(iter.next().unwrap(), b"example");
2240 assert_eq!(iter.size_hint().0, 0);
2241 assert!(iter.next_back().is_none());
2242 assert_eq!(iter.size_hint().0, 0);
2243 assert!(iter.next().is_none());
2244 assert_eq!(iter.size_hint().0, 0);
2245 }
2246
2247 #[test]
2248 #[cfg(feature = "std")]
2249 fn test_label_randomization() {
2250 let mut name = Name::root();
2251 name.randomize_label_case();
2252 assert!(name.eq_case(&Name::root()));
2253
2254 for qname in [
2255 "x",
2256 "0",
2257 "aaaaaaaaaaaaaaaa",
2258 "AAAAAAAAAAAAAAAA",
2259 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.",
2260 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.",
2261 "abcdefghijklmnopqrstuvwxyz0123456789A.",
2262 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.",
2263 "www01.example-site.com",
2264 "1234567890.e-1204089_043820-5.com.",
2265 ] {
2266 let mut name = Name::from_ascii(qname).unwrap();
2267 let name2 = name.clone();
2268 name.randomize_label_case();
2269 assert_eq!(name, name2);
2270 println!("{name2} == {name}: {}", name == name2);
2271 }
2272
2273 let iterations = 50_000;
2276
2277 let test_str = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.lmnopqrstuvwxyzabcdefghjijklmnopqrstuvwxyzabcdefghijklmnopqrstu.vwxyzABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF.GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO";
2280 let mut name = Name::from_ascii(test_str).unwrap();
2281 let name2 = name.clone();
2282
2283 let len = name.label_data.len();
2284 let mut cap_table: [u32; 255] = [0; 255];
2285 let mut lower_table: [u32; 255] = [0; 255];
2286 let mut mean_table: [f64; 255] = [0.0; 255];
2287
2288 for _ in 0..iterations {
2289 name.randomize_label_case();
2290 assert_eq!(name, name2);
2291
2292 for (j, &cbyte) in name.label_data.iter().enumerate() {
2293 if cbyte.is_ascii_lowercase() {
2294 lower_table[j] += 1;
2295 } else if cbyte.is_ascii_uppercase() {
2296 cap_table[j] += 1;
2297 }
2298 }
2299 name = Name::from_ascii(test_str).unwrap();
2300 }
2301
2302 println!("Distribution of lower case values by label offset");
2303 println!("-------------------------------------------------");
2304 for i in 0..len {
2305 let cap_ratio = cap_table[i] as f64 / iterations as f64;
2306 let lower_ratio = lower_table[i] as f64 / iterations as f64;
2307 let total_ratio = cap_ratio + lower_ratio;
2308 mean_table[i] = lower_ratio;
2309 println!(
2310 "{i:03} {:.3}% {:.3}% {:.3}%",
2311 cap_ratio * 100.0,
2312 lower_ratio * 100.0,
2313 total_ratio * 100.0,
2314 );
2315 }
2316 println!("-------------------------------------------------");
2317
2318 let data_mean = mean_table.iter().sum::<f64>() / len as f64;
2319 let data_std_deviation = std_deviation(data_mean, &mean_table);
2320
2321 let mut max_zscore = 0.0;
2322 for elem in mean_table.iter() {
2323 let zscore = (elem - data_mean) / data_std_deviation;
2324
2325 if zscore > max_zscore {
2326 max_zscore = zscore;
2327 }
2328 }
2329
2330 println!("μ: {data_mean:.4} σ: {data_std_deviation:.4}, max variance: {max_zscore:.4}σ");
2331
2332 assert!(data_mean > 0.485 && data_mean < 0.515);
2343 assert!(data_std_deviation < 0.18);
2344 assert!(max_zscore < 0.33);
2345 }
2346
2347 #[cfg(feature = "std")]
2348 fn std_deviation(mean: f64, data: &[f64]) -> f64 {
2349 match (mean, data.len()) {
2350 (data_mean, count) if count > 0 => {
2351 let variance = data
2352 .iter()
2353 .map(|value| {
2354 let diff = data_mean - *value;
2355
2356 diff * diff
2357 })
2358 .sum::<f64>()
2359 / count as f64;
2360
2361 variance.sqrt()
2362 }
2363 _ => 0.0,
2364 }
2365 }
2366
2367 #[test]
2368 fn test_fqdn_escaped_dot() {
2369 let name = Name::from_utf8("test.").unwrap();
2370 assert!(name.is_fqdn());
2371
2372 let name = Name::from_utf8("test\\.").unwrap();
2373 assert!(!name.is_fqdn());
2374
2375 let name = Name::from_utf8("").unwrap();
2376 assert!(!name.is_fqdn());
2377
2378 let name = Name::from_utf8(".").unwrap();
2379 assert!(name.is_fqdn());
2380 }
2381
2382 #[test]
2383 #[allow(clippy::nonminimal_bool)]
2384 fn test_name_partialeq_constraints() {
2385 let example_fqdn = Name::from_utf8("example.com.").unwrap();
2386 let example_nonfqdn = Name::from_utf8("example.com").unwrap();
2387 let other_fqdn = Name::from_utf8("otherdomain.com.").unwrap();
2388
2389 assert_eq!(example_fqdn, example_fqdn);
2390 assert_eq!(example_nonfqdn, example_nonfqdn);
2391 assert!(example_fqdn != example_nonfqdn);
2392
2393 assert!(example_fqdn != example_nonfqdn && !(example_fqdn == example_nonfqdn));
2395 assert!(example_nonfqdn != example_fqdn && !(example_nonfqdn == example_fqdn));
2396 assert!(example_fqdn != other_fqdn && !(example_fqdn == other_fqdn));
2397 assert!(example_nonfqdn != other_fqdn && !(example_nonfqdn == other_fqdn));
2398 }
2399
2400 #[test]
2401 fn test_name_partialord_constraints() {
2402 use core::cmp::Ordering::*;
2403
2404 let example_fqdn = Name::from_utf8("example.com.").unwrap();
2405 let foo_example_fqdn = Name::from_utf8("foo.example.com.").unwrap();
2406 let example_nonfqdn = Name::from_utf8("example.com").unwrap();
2407 let foo_example_nonfqdn = Name::from_utf8("foo.example.com").unwrap();
2408
2409 assert_eq!(example_fqdn.partial_cmp(&example_fqdn), Some(Equal),);
2411 assert!(example_fqdn.partial_cmp(&example_nonfqdn) != Some(Equal));
2412
2413 assert!(
2415 example_nonfqdn < example_fqdn
2416 && example_nonfqdn.partial_cmp(&example_fqdn) == Some(Less)
2417 );
2418
2419 assert!(
2420 example_fqdn < foo_example_fqdn
2421 && example_fqdn.partial_cmp(&foo_example_fqdn) == Some(Less)
2422 );
2423
2424 assert!(
2425 example_nonfqdn < foo_example_nonfqdn
2426 && example_nonfqdn.partial_cmp(&foo_example_nonfqdn) == Some(Less)
2427 );
2428
2429 assert!(
2431 example_fqdn > example_nonfqdn
2432 && example_fqdn.partial_cmp(&example_nonfqdn) == Some(Greater)
2433 );
2434
2435 assert!(
2436 foo_example_fqdn > example_fqdn
2437 && foo_example_fqdn.partial_cmp(&example_fqdn) == Some(Greater)
2438 );
2439
2440 assert!(
2441 foo_example_nonfqdn > example_nonfqdn
2442 && foo_example_nonfqdn.partial_cmp(&example_nonfqdn) == Some(Greater)
2443 );
2444
2445 assert!(example_nonfqdn <= example_fqdn);
2447 assert!(example_nonfqdn <= example_nonfqdn);
2448 assert!(example_fqdn <= example_fqdn);
2449 assert!(example_nonfqdn <= foo_example_nonfqdn);
2450 assert!(example_fqdn <= foo_example_fqdn);
2451 assert!(foo_example_nonfqdn <= foo_example_nonfqdn);
2452 assert!(foo_example_fqdn <= foo_example_fqdn);
2453
2454 assert!(example_fqdn >= example_nonfqdn);
2456 assert!(example_nonfqdn >= example_nonfqdn);
2457 assert!(example_fqdn >= example_fqdn);
2458 assert!(foo_example_nonfqdn >= example_nonfqdn);
2459 assert!(foo_example_fqdn >= example_fqdn);
2460 assert!(foo_example_nonfqdn >= foo_example_nonfqdn);
2461 assert!(foo_example_fqdn >= foo_example_fqdn);
2462
2463 }
2465
2466 #[test]
2467 fn test_name_ord_constraints() {
2468 use core::cmp;
2469
2470 let example_fqdn = Name::from_utf8("example.com.").unwrap();
2471 let foo_example_fqdn = Name::from_utf8("foo.example.com.").unwrap();
2472 let example_nonfqdn = Name::from_utf8("example.com").unwrap();
2473 let foo_example_nonfqdn = Name::from_utf8("foo.example.com").unwrap();
2474
2475 for pair in [
2479 (&example_fqdn, &example_fqdn),
2480 (&example_fqdn, &example_nonfqdn),
2481 (&example_fqdn, &foo_example_fqdn),
2482 (&example_fqdn, &foo_example_nonfqdn),
2483 (&example_nonfqdn, &example_nonfqdn),
2484 (&example_nonfqdn, &example_fqdn),
2485 (&example_nonfqdn, &foo_example_fqdn),
2486 (&example_nonfqdn, &foo_example_nonfqdn),
2487 (&foo_example_fqdn, &example_nonfqdn),
2488 (&foo_example_fqdn, &example_fqdn),
2489 (&foo_example_fqdn, &foo_example_fqdn),
2490 (&foo_example_fqdn, &foo_example_nonfqdn),
2491 (&foo_example_fqdn, &example_nonfqdn),
2492 (&foo_example_fqdn, &example_fqdn),
2493 (&foo_example_fqdn, &foo_example_fqdn),
2494 (&foo_example_fqdn, &foo_example_nonfqdn),
2495 ] {
2496 let name1 = pair.0;
2497 let name2 = pair.1;
2498
2499 assert_eq!(name1.partial_cmp(name2), Some(name1.cmp(name2)));
2501
2502 assert_eq!(
2504 name1.clone().max(name2.clone()),
2505 cmp::max_by(name1.clone(), name2.clone(), |x: &Name, y: &Name| x.cmp(y)),
2506 );
2507
2508 assert_eq!(
2510 name1.clone().min(name2.clone()),
2511 cmp::min_by(name1.clone(), name2.clone(), |x: &Name, y: &Name| x.cmp(y)),
2512 );
2513 }
2514
2515 let min_name = Name::from_utf8("com").unwrap();
2523 let max_name = Name::from_utf8("max.example.com.").unwrap();
2524
2525 assert_eq!(
2526 min_name
2527 .clone()
2528 .clamp(min_name.clone(), example_nonfqdn.clone()),
2529 min_name.clone(),
2530 );
2531
2532 assert_eq!(
2533 max_name
2534 .clone()
2535 .clamp(example_nonfqdn.clone(), example_fqdn.clone()),
2536 example_fqdn.clone(),
2537 );
2538
2539 assert_eq!(
2540 max_name
2541 .clone()
2542 .clamp(example_nonfqdn.clone(), max_name.clone()),
2543 max_name.clone(),
2544 );
2545
2546 let most_min_name = Name::from_utf8("").unwrap();
2550 let most_max_name = Name::from_utf8("most.max.example.com.").unwrap();
2551 assert_eq!(min_name.cmp(&example_nonfqdn), Ordering::Less);
2552 assert_eq!(most_min_name.cmp(&min_name), Ordering::Less);
2553 assert_eq!(most_min_name.cmp(&example_nonfqdn), Ordering::Less);
2554 assert_eq!(max_name.cmp(&example_fqdn), Ordering::Greater);
2555 assert_eq!(most_max_name.cmp(&max_name), Ordering::Greater);
2556 assert_eq!(most_max_name.cmp(&example_fqdn), Ordering::Greater);
2557 }
2558
2559 #[test]
2560 #[should_panic]
2561 fn test_ord_clamp_panic() {
2562 let min_name = Name::from_utf8("com").unwrap();
2563 let max_name = Name::from_utf8("max.example.com.").unwrap();
2564
2565 let _ = min_name.clone().clamp(max_name, min_name);
2567 }
2568
2569 #[test]
2570 #[cfg(feature = "std")]
2571 fn test_hash() {
2572 let with_dot = Name::from_utf8("com.").unwrap();
2575 let hash_with_dot = hash(&with_dot);
2576
2577 let without_dot = Name::from_utf8("com").unwrap();
2578 let hash_without_dot = hash(&without_dot);
2579 assert_ne!(with_dot, without_dot);
2580 assert_ne!(hash_with_dot, hash_without_dot);
2581 }
2582
2583 #[test]
2584 #[cfg(feature = "std")]
2585 fn test_name_hash_label_boundaries() {
2586 let ab_c = Name::parse("ab.c.", None).unwrap();
2587 let a_bc = Name::parse("a.bc.", None).unwrap();
2588 assert_ne!(ab_c, a_bc);
2589 assert_ne!(hash(&ab_c), hash(&a_bc));
2590 }
2591
2592 #[cfg(feature = "std")]
2593 fn hash(name: &Name) -> u64 {
2594 let mut hasher = DefaultHasher::new();
2595 name.hash(&mut hasher);
2596 hasher.finish()
2597 }
2598
2599 #[test]
2600 fn eq_ignore_root_tests() {
2601 let fqdn_name = Name::from_utf8("host.example.com.").unwrap();
2602 let relative_name = Name::from_utf8("host.example.com").unwrap();
2603 let upper_relative_name = Name::from_ascii("HOST.EXAMPLE.COM").unwrap();
2604
2605 assert_ne!(fqdn_name, relative_name);
2606 assert!(fqdn_name.eq_ignore_root(&relative_name));
2607 assert!(!fqdn_name.eq_ignore_root_case(&upper_relative_name));
2608 assert!(fqdn_name.eq_ignore_root(&upper_relative_name));
2609 }
2610
2611 #[test]
2612 fn rfc4034_canonical_ordering_example() {
2613 let names = Vec::from([
2615 Name::from_labels::<_, &[u8]>([b"example".as_slice()]).unwrap(),
2616 Name::from_labels::<_, &[u8]>([b"a".as_slice(), b"example".as_slice()]).unwrap(),
2617 Name::from_labels::<_, &[u8]>([
2618 b"yljkjljk".as_slice(),
2619 b"a".as_slice(),
2620 b"example".as_slice(),
2621 ])
2622 .unwrap(),
2623 Name::from_labels::<_, &[u8]>([
2624 b"Z".as_slice(),
2625 b"a".as_slice(),
2626 b"example".as_slice(),
2627 ])
2628 .unwrap(),
2629 Name::from_labels::<_, &[u8]>([
2630 b"zABC".as_slice(),
2631 b"a".as_slice(),
2632 b"EXAMPLE".as_slice(),
2633 ])
2634 .unwrap(),
2635 Name::from_labels::<_, &[u8]>([b"z".as_slice(), b"example".as_slice()]).unwrap(),
2636 Name::from_labels::<_, &[u8]>([
2637 b"\x01".as_slice(),
2638 b"z".as_slice(),
2639 b"example".as_slice(),
2640 ])
2641 .unwrap(),
2642 Name::from_labels::<_, &[u8]>([
2643 b"*".as_slice(),
2644 b"z".as_slice(),
2645 b"example".as_slice(),
2646 ])
2647 .unwrap(),
2648 Name::from_labels::<_, &[u8]>([
2649 b"\x80".as_slice(),
2650 b"z".as_slice(),
2651 b"example".as_slice(),
2652 ])
2653 .unwrap(),
2654 ]);
2655 let mut sorted = names.clone();
2656 sorted.sort();
2657 assert_eq!(names, sorted);
2658 }
2659}