1use super::super::wire::ParseError;
6use super::builder::{DnameBuilder, FromStrError, PushError};
7use super::chain::{Chain, LongChainError};
8use super::dname::Dname;
9use super::label::{Label, LabelTypeError, SplitLabelError};
10use super::traits::{ToLabelIter, ToRelativeDname};
11#[cfg(feature = "bytes")]
12use bytes::Bytes;
13use core::cmp::Ordering;
14use core::ops::{Bound, RangeBounds};
15use core::str::FromStr;
16use core::{cmp, fmt, hash};
17use octseq::builder::{
18 EmptyBuilder, FreezeBuilder, FromBuilder, IntoBuilder, Truncate,
19};
20use octseq::octets::{Octets, OctetsFrom};
21#[cfg(feature = "serde")]
22use octseq::serde::{DeserializeOctets, SerializeOctets};
23#[cfg(feature = "std")]
24use std::vec::Vec;
25
26#[derive(Clone)]
44pub struct RelativeDname<Octs: ?Sized>(Octs);
45
46impl<Octs> RelativeDname<Octs> {
49 pub const unsafe fn from_octets_unchecked(octets: Octs) -> Self {
60 RelativeDname(octets)
61 }
62
63 pub fn from_octets(octets: Octs) -> Result<Self, RelativeDnameError>
68 where
69 Octs: AsRef<[u8]>,
70 {
71 RelativeDname::check_slice(octets.as_ref())?;
72 Ok(unsafe { RelativeDname::from_octets_unchecked(octets) })
73 }
74
75 #[must_use]
77 pub fn empty() -> Self
78 where
79 Octs: From<&'static [u8]>,
80 {
81 unsafe { RelativeDname::from_octets_unchecked(b"".as_ref().into()) }
82 }
83
84 #[must_use]
91 pub fn wildcard() -> Self
92 where
93 Octs: From<&'static [u8]>,
94 {
95 unsafe {
96 RelativeDname::from_octets_unchecked(b"\x01*".as_ref().into())
97 }
98 }
99
100 pub fn from_chars<C>(chars: C) -> Result<Self, RelativeFromStrError>
112 where
113 Octs: FromBuilder,
114 <Octs as FromBuilder>::Builder: EmptyBuilder
115 + FreezeBuilder<Octets = Octs>
116 + AsRef<[u8]>
117 + AsMut<[u8]>,
118 C: IntoIterator<Item = char>,
119 {
120 let mut builder = DnameBuilder::<Octs::Builder>::new();
121 builder.append_chars(chars)?;
122 if builder.in_label() || builder.is_empty() {
123 Ok(builder.finish())
124 } else {
125 Err(RelativeFromStrError::AbsoluteName)
126 }
127 }
128}
129
130impl RelativeDname<[u8]> {
131 pub(super) unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
137 &*(slice as *const [u8] as *const RelativeDname<[u8]>)
138 }
139
140 pub fn from_slice(slice: &[u8]) -> Result<&Self, RelativeDnameError> {
151 Self::check_slice(slice)?;
152 Ok(unsafe { Self::from_slice_unchecked(slice) })
153 }
154
155 #[must_use]
157 pub fn empty_slice() -> &'static Self {
158 unsafe { Self::from_slice_unchecked(b"") }
159 }
160
161 #[must_use]
162 pub fn wildcard_slice() -> &'static Self {
163 unsafe { Self::from_slice_unchecked(b"\x01*") }
164 }
165
166 pub(super) fn check_slice(
168 mut slice: &[u8],
169 ) -> Result<(), RelativeDnameError> {
170 if slice.len() > 254 {
171 return Err(RelativeDnameError::LongName);
172 }
173 while !slice.is_empty() {
174 let (label, tail) = Label::split_from(slice)?;
175 if label.is_root() {
176 return Err(RelativeDnameError::AbsoluteName);
177 }
178 slice = tail;
179 }
180 Ok(())
181 }
182}
183
184impl RelativeDname<&'static [u8]> {
185 #[must_use]
187 pub fn empty_ref() -> Self {
188 Self::empty()
189 }
190
191 #[must_use]
193 pub fn wildcard_ref() -> Self {
194 Self::wildcard()
195 }
196}
197
198#[cfg(feature = "std")]
199impl RelativeDname<Vec<u8>> {
200 #[must_use]
202 pub fn empty_vec() -> Self {
203 Self::empty()
204 }
205
206 #[must_use]
208 pub fn wildcard_vec() -> Self {
209 Self::wildcard()
210 }
211
212 pub fn vec_from_str(s: &str) -> Result<Self, RelativeFromStrError> {
214 FromStr::from_str(s)
215 }
216}
217
218#[cfg(feature = "bytes")]
219impl RelativeDname<Bytes> {
220 pub fn empty_bytes() -> Self {
222 Self::empty()
223 }
224
225 pub fn wildcard_bytes() -> Self {
227 Self::wildcard()
228 }
229
230 pub fn bytes_from_str(s: &str) -> Result<Self, RelativeFromStrError> {
232 FromStr::from_str(s)
233 }
234}
235
236impl<Octs: ?Sized> RelativeDname<Octs> {
239 pub fn as_octets(&self) -> &Octs {
241 &self.0
242 }
243
244 pub fn into_octets(self) -> Octs
246 where
247 Octs: Sized,
248 {
249 self.0
250 }
251
252 pub fn for_ref(&self) -> RelativeDname<&Octs> {
254 unsafe { RelativeDname::from_octets_unchecked(&self.0) }
255 }
256
257 pub fn as_slice(&self) -> &[u8]
259 where
260 Octs: AsRef<[u8]>,
261 {
262 self.0.as_ref()
263 }
264
265 pub fn for_slice(&self) -> &RelativeDname<[u8]>
267 where
268 Octs: AsRef<[u8]>,
269 {
270 unsafe { RelativeDname::from_slice_unchecked(self.0.as_ref()) }
271 }
272
273 pub fn make_canonical(&mut self)
275 where
276 Octs: AsMut<[u8]>,
277 {
278 Label::make_slice_canonical(self.0.as_mut());
279 }
280}
281
282impl<Octs> RelativeDname<Octs> {
283 pub fn into_builder(self) -> DnameBuilder<<Octs as IntoBuilder>::Builder>
288 where
289 Octs: IntoBuilder,
290 {
291 unsafe { DnameBuilder::from_builder_unchecked(self.0.into_builder()) }
292 }
293
294 pub fn into_absolute(self) -> Result<Dname<Octs>, PushError>
302 where
303 Octs: IntoBuilder,
304 <Octs as IntoBuilder>::Builder:
305 FreezeBuilder<Octets = Octs> + AsRef<[u8]> + AsMut<[u8]>,
306 {
307 self.into_builder().into_dname()
308 }
309
310 pub fn chain<N: ToLabelIter>(
320 self,
321 other: N,
322 ) -> Result<Chain<Self, N>, LongChainError>
323 where
324 Octs: AsRef<[u8]>,
325 {
326 Chain::new(self, other)
327 }
328
329 pub fn chain_root(self) -> Chain<Self, Dname<&'static [u8]>>
331 where
332 Octs: AsRef<[u8]>,
333 {
334 self.chain(Dname::root()).unwrap()
335 }
336}
337
338impl<Octs: AsRef<[u8]> + ?Sized> RelativeDname<Octs> {
341 pub fn len(&self) -> usize {
343 self.0.as_ref().len()
344 }
345
346 pub fn is_empty(&self) -> bool {
348 self.0.as_ref().is_empty()
349 }
350}
351
352impl<Octs: AsRef<[u8]> + ?Sized> RelativeDname<Octs> {
355 pub fn iter(&self) -> DnameIter {
357 DnameIter::new(self.0.as_ref())
358 }
359
360 pub fn label_count(&self) -> usize {
362 self.iter().count()
363 }
364
365 pub fn first(&self) -> Option<&Label> {
367 self.iter().next()
368 }
369
370 pub fn last(&self) -> Option<&Label> {
372 self.iter().next_back()
373 }
374
375 pub fn ndots(&self) -> usize {
380 if self.0.as_ref().is_empty() {
381 0
382 } else {
383 self.label_count() - 1
384 }
385 }
386
387 pub fn starts_with<N: ToLabelIter>(&self, base: &N) -> bool {
389 <Self as ToLabelIter>::starts_with(self, base)
390 }
391
392 pub fn ends_with<N: ToLabelIter>(&self, base: &N) -> bool {
394 <Self as ToLabelIter>::ends_with(self, base)
395 }
396
397 pub fn is_label_start(&self, mut index: usize) -> bool {
399 if index == 0 {
400 return true;
401 }
402 let mut tmp = self.as_slice();
403 while !tmp.is_empty() {
404 let (label, tail) = Label::split_from(tmp).unwrap();
405 let len = label.len() + 1;
406 match index.cmp(&len) {
407 Ordering::Less => return false,
408 Ordering::Equal => return true,
409 _ => {}
410 }
411 index -= len;
412 tmp = tail;
413 }
414 false
415 }
416
417 fn check_index(&self, index: usize) {
419 if !self.is_label_start(index) {
420 panic!("index not at start of a label");
421 }
422 }
423
424 fn check_bounds(&self, bounds: &impl RangeBounds<usize>) {
425 match bounds.start_bound().cloned() {
426 Bound::Included(idx) => self.check_index(idx),
427 Bound::Excluded(_) => {
428 panic!("excluded lower bounds not supported");
429 }
430 Bound::Unbounded => {}
431 }
432 match bounds.end_bound().cloned() {
433 Bound::Included(idx) => self
434 .check_index(idx.checked_add(1).expect("end bound too big")),
435 Bound::Excluded(idx) => self.check_index(idx),
436 Bound::Unbounded => {}
437 }
438 }
439
440 pub fn slice(
457 &self,
458 range: impl RangeBounds<usize>,
459 ) -> &RelativeDname<[u8]> {
460 self.check_bounds(&range);
461 unsafe {
462 RelativeDname::from_slice_unchecked(self.0.as_ref().range(range))
463 }
464 }
465
466 pub fn range(
477 &self,
478 range: impl RangeBounds<usize>,
479 ) -> RelativeDname<<Octs as Octets>::Range<'_>>
480 where
481 Octs: Octets,
482 {
483 self.check_bounds(&range);
484 unsafe { RelativeDname::from_octets_unchecked(self.0.range(range)) }
485 }
486}
487
488impl<Octs: AsRef<[u8]> + ?Sized> RelativeDname<Octs> {
489 pub fn split(
498 &self,
499 mid: usize,
500 ) -> (
501 RelativeDname<Octs::Range<'_>>,
502 RelativeDname<Octs::Range<'_>>,
503 )
504 where
505 Octs: Octets,
506 {
507 self.check_index(mid);
508 unsafe {
509 (
510 RelativeDname::from_octets_unchecked(self.0.range(..mid)),
511 RelativeDname::from_octets_unchecked(self.0.range(mid..)),
512 )
513 }
514 }
515
516 pub fn truncate(&mut self, len: usize)
523 where
524 Octs: Truncate,
525 {
526 self.check_index(len);
527 self.0.truncate(len);
528 }
529
530 pub fn split_first(
537 &self,
538 ) -> Option<(&Label, RelativeDname<Octs::Range<'_>>)>
539 where
540 Octs: Octets,
541 {
542 if self.is_empty() {
543 return None;
544 }
545 let label = self.iter().next()?;
546 Some((label, self.split(label.len() + 1).1))
547 }
548
549 pub fn parent(&self) -> Option<RelativeDname<Octs::Range<'_>>>
553 where
554 Octs: Octets,
555 {
556 self.split_first().map(|(_, parent)| parent)
557 }
558
559 pub fn strip_suffix<N: ToRelativeDname>(
566 &mut self,
567 base: &N,
568 ) -> Result<(), StripSuffixError>
569 where
570 Octs: Truncate,
571 {
572 if self.ends_with(base) {
573 let idx = self.0.as_ref().len() - usize::from(base.compose_len());
574 self.0.truncate(idx);
575 Ok(())
576 } else {
577 Err(StripSuffixError)
578 }
579 }
580}
581
582impl<Octs> AsRef<Octs> for RelativeDname<Octs> {
585 fn as_ref(&self) -> &Octs {
586 &self.0
587 }
588}
589
590impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for RelativeDname<Octs> {
591 fn as_ref(&self) -> &[u8] {
592 self.0.as_ref()
593 }
594}
595
596impl<Octs, SrcOcts> OctetsFrom<RelativeDname<SrcOcts>> for RelativeDname<Octs>
599where
600 Octs: OctetsFrom<SrcOcts>,
601{
602 type Error = Octs::Error;
603
604 fn try_octets_from(
605 source: RelativeDname<SrcOcts>,
606 ) -> Result<Self, Self::Error> {
607 Octs::try_octets_from(source.0)
608 .map(|octets| unsafe { Self::from_octets_unchecked(octets) })
609 }
610}
611
612impl<Octs> FromStr for RelativeDname<Octs>
615where
616 Octs: FromBuilder,
617 <Octs as FromBuilder>::Builder: EmptyBuilder
618 + FreezeBuilder<Octets = Octs>
619 + AsRef<[u8]>
620 + AsMut<[u8]>,
621{
622 type Err = RelativeFromStrError;
623
624 fn from_str(s: &str) -> Result<Self, Self::Err> {
634 Self::from_chars(s.chars())
635 }
636}
637
638impl<Octs> ToLabelIter for RelativeDname<Octs>
641where
642 Octs: AsRef<[u8]> + ?Sized,
643{
644 type LabelIter<'a> = DnameIter<'a> where Octs: 'a;
645
646 fn iter_labels(&self) -> Self::LabelIter<'_> {
647 self.iter()
648 }
649
650 fn compose_len(&self) -> u16 {
651 u16::try_from(self.0.as_ref().len()).expect("long domain name")
652 }
653}
654
655impl<Octs: AsRef<[u8]> + ?Sized> ToRelativeDname for RelativeDname<Octs> {
656 fn as_flat_slice(&self) -> Option<&[u8]> {
657 Some(self.0.as_ref())
658 }
659
660 fn is_empty(&self) -> bool {
661 self.0.as_ref().is_empty()
662 }
663}
664
665impl<'a, Octs> IntoIterator for &'a RelativeDname<Octs>
668where
669 Octs: AsRef<[u8]> + ?Sized,
670{
671 type Item = &'a Label;
672 type IntoIter = DnameIter<'a>;
673
674 fn into_iter(self) -> Self::IntoIter {
675 self.iter()
676 }
677}
678
679impl<Octs, N> PartialEq<N> for RelativeDname<Octs>
682where
683 Octs: AsRef<[u8]> + ?Sized,
684 N: ToRelativeDname + ?Sized,
685{
686 fn eq(&self, other: &N) -> bool {
687 self.name_eq(other)
688 }
689}
690
691impl<Octs: AsRef<[u8]> + ?Sized> Eq for RelativeDname<Octs> {}
692
693impl<Octs, N> PartialOrd<N> for RelativeDname<Octs>
696where
697 Octs: AsRef<[u8]> + ?Sized,
698 N: ToRelativeDname + ?Sized,
699{
700 fn partial_cmp(&self, other: &N) -> Option<cmp::Ordering> {
701 Some(self.name_cmp(other))
702 }
703}
704
705impl<Octs: AsRef<[u8]> + ?Sized> Ord for RelativeDname<Octs> {
706 fn cmp(&self, other: &Self) -> cmp::Ordering {
707 self.name_cmp(other)
708 }
709}
710
711impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for RelativeDname<Octs> {
714 fn hash<H: hash::Hasher>(&self, state: &mut H) {
715 for item in self.iter() {
716 item.hash(state)
717 }
718 }
719}
720
721impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for RelativeDname<Octs> {
724 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
725 let mut iter = self.iter();
726 match iter.next() {
727 Some(label) => label.fmt(f)?,
728 None => return Ok(()),
729 }
730 for label in iter {
731 f.write_str(".")?;
732 label.fmt(f)?;
733 }
734 Ok(())
735 }
736}
737
738impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for RelativeDname<Octs> {
739 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
740 write!(f, "RelativeDname({})", self)
741 }
742}
743
744#[cfg(feature = "serde")]
747impl<Octs> serde::Serialize for RelativeDname<Octs>
748where
749 Octs: AsRef<[u8]> + SerializeOctets + ?Sized,
750{
751 fn serialize<S: serde::Serializer>(
752 &self,
753 serializer: S,
754 ) -> Result<S::Ok, S::Error> {
755 if serializer.is_human_readable() {
756 serializer.serialize_newtype_struct(
757 "RelativeDname",
758 &format_args!("{}", self),
759 )
760 } else {
761 serializer.serialize_newtype_struct(
762 "RelativeDname",
763 &self.0.as_serialized_octets(),
764 )
765 }
766 }
767}
768
769#[cfg(feature = "serde")]
770impl<'de, Octs> serde::Deserialize<'de> for RelativeDname<Octs>
771where
772 Octs: FromBuilder + DeserializeOctets<'de>,
773 <Octs as FromBuilder>::Builder: FreezeBuilder<Octets = Octs>
774 + EmptyBuilder
775 + AsRef<[u8]>
776 + AsMut<[u8]>,
777{
778 fn deserialize<D: serde::Deserializer<'de>>(
779 deserializer: D,
780 ) -> Result<Self, D::Error> {
781 use core::marker::PhantomData;
782
783 struct InnerVisitor<'de, T: DeserializeOctets<'de>>(T::Visitor);
784
785 impl<'de, Octs> serde::de::Visitor<'de> for InnerVisitor<'de, Octs>
786 where
787 Octs: FromBuilder + DeserializeOctets<'de>,
788 <Octs as FromBuilder>::Builder: FreezeBuilder<Octets = Octs>
789 + EmptyBuilder
790 + AsRef<[u8]>
791 + AsMut<[u8]>,
792 {
793 type Value = RelativeDname<Octs>;
794
795 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
796 f.write_str("a relative domain name")
797 }
798
799 fn visit_str<E: serde::de::Error>(
800 self,
801 v: &str,
802 ) -> Result<Self::Value, E> {
803 let mut builder = DnameBuilder::<Octs::Builder>::new();
804 builder.append_chars(v.chars()).map_err(E::custom)?;
805 Ok(builder.finish())
806 }
807
808 fn visit_borrowed_bytes<E: serde::de::Error>(
809 self,
810 value: &'de [u8],
811 ) -> Result<Self::Value, E> {
812 self.0.visit_borrowed_bytes(value).and_then(|octets| {
813 RelativeDname::from_octets(octets).map_err(E::custom)
814 })
815 }
816
817 #[cfg(feature = "std")]
818 fn visit_byte_buf<E: serde::de::Error>(
819 self,
820 value: std::vec::Vec<u8>,
821 ) -> Result<Self::Value, E> {
822 self.0.visit_byte_buf(value).and_then(|octets| {
823 RelativeDname::from_octets(octets).map_err(E::custom)
824 })
825 }
826 }
827
828 struct NewtypeVisitor<T>(PhantomData<T>);
829
830 impl<'de, Octs> serde::de::Visitor<'de> for NewtypeVisitor<Octs>
831 where
832 Octs: FromBuilder + DeserializeOctets<'de>,
833 <Octs as FromBuilder>::Builder: FreezeBuilder<Octets = Octs>
834 + EmptyBuilder
835 + AsRef<[u8]>
836 + AsMut<[u8]>,
837 {
838 type Value = RelativeDname<Octs>;
839
840 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
841 f.write_str("a relative domain name")
842 }
843
844 fn visit_newtype_struct<D: serde::Deserializer<'de>>(
845 self,
846 deserializer: D,
847 ) -> Result<Self::Value, D::Error> {
848 if deserializer.is_human_readable() {
849 deserializer
850 .deserialize_str(InnerVisitor(Octs::visitor()))
851 } else {
852 Octs::deserialize_with_visitor(
853 deserializer,
854 InnerVisitor(Octs::visitor()),
855 )
856 }
857 }
858 }
859
860 deserializer.deserialize_newtype_struct(
861 "RelativeDname",
862 NewtypeVisitor(PhantomData),
863 )
864 }
865}
866
867#[derive(Clone, Debug)]
871pub struct DnameIter<'a> {
872 slice: &'a [u8],
873}
874
875impl<'a> DnameIter<'a> {
876 pub(super) fn new(slice: &'a [u8]) -> Self {
877 DnameIter { slice }
878 }
879}
880
881impl<'a> Iterator for DnameIter<'a> {
882 type Item = &'a Label;
883
884 fn next(&mut self) -> Option<Self::Item> {
885 let (label, tail) = match Label::split_from(self.slice) {
886 Ok(res) => res,
887 Err(_) => return None,
888 };
889 self.slice = tail;
890 Some(label)
891 }
892}
893
894impl<'a> DoubleEndedIterator for DnameIter<'a> {
895 fn next_back(&mut self) -> Option<Self::Item> {
896 if self.slice.is_empty() {
897 return None;
898 }
899 let mut tmp = self.slice;
900 loop {
901 let (label, tail) = Label::split_from(tmp).unwrap();
902 if tail.is_empty() {
903 let end = self.slice.len() - (label.len() + 1);
904 self.slice = &self.slice[..end];
905 return Some(label);
906 } else {
907 tmp = tail
908 }
909 }
910 }
911}
912
913#[derive(Clone, Copy, Debug, Eq, PartialEq)]
919pub enum RelativeDnameError {
920 BadLabel(LabelTypeError),
922
923 CompressedName,
925
926 ShortInput,
928
929 LongName,
931
932 AbsoluteName,
934}
935
936impl From<LabelTypeError> for RelativeDnameError {
939 fn from(err: LabelTypeError) -> Self {
940 RelativeDnameError::BadLabel(err)
941 }
942}
943
944impl From<SplitLabelError> for RelativeDnameError {
945 fn from(err: SplitLabelError) -> Self {
946 match err {
947 SplitLabelError::Pointer(_) => RelativeDnameError::CompressedName,
948 SplitLabelError::BadType(t) => RelativeDnameError::BadLabel(t),
949 SplitLabelError::ShortInput => RelativeDnameError::ShortInput,
950 }
951 }
952}
953
954impl fmt::Display for RelativeDnameError {
957 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
958 match *self {
959 RelativeDnameError::BadLabel(err) => err.fmt(f),
960 RelativeDnameError::CompressedName => {
961 f.write_str("compressed domain name")
962 }
963 RelativeDnameError::ShortInput => ParseError::ShortInput.fmt(f),
964 RelativeDnameError::LongName => f.write_str("long domain name"),
965 RelativeDnameError::AbsoluteName => {
966 f.write_str("absolute domain name")
967 }
968 }
969 }
970}
971
972#[cfg(feature = "std")]
973impl std::error::Error for RelativeDnameError {}
974
975#[derive(Clone, Copy, Debug, Eq, PartialEq)]
978#[non_exhaustive]
979pub enum RelativeFromStrError {
980 FromStr(FromStrError),
982
983 AbsoluteName,
985}
986
987impl From<FromStrError> for RelativeFromStrError {
990 fn from(src: FromStrError) -> Self {
991 Self::FromStr(src)
992 }
993}
994
995impl fmt::Display for RelativeFromStrError {
998 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
999 match self {
1000 RelativeFromStrError::FromStr(err) => err.fmt(f),
1001 RelativeFromStrError::AbsoluteName => {
1002 f.write_str("absolute domain name")
1003 }
1004 }
1005 }
1006}
1007
1008#[cfg(feature = "std")]
1009impl std::error::Error for RelativeFromStrError {}
1010
1011#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1015pub struct StripSuffixError;
1016
1017impl fmt::Display for StripSuffixError {
1020 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1021 f.write_str("suffix not found")
1022 }
1023}
1024
1025#[cfg(feature = "std")]
1026impl std::error::Error for StripSuffixError {}
1027
1028#[cfg(test)]
1031mod test {
1032 use super::*;
1033
1034 #[cfg(feature = "std")]
1035 macro_rules! assert_panic {
1036 ( $cond:expr ) => {{
1037 let result = std::panic::catch_unwind(|| $cond);
1038 assert!(result.is_err());
1039 }};
1040 }
1041
1042 #[test]
1043 #[cfg(feature = "std")]
1044 fn impls() {
1045 fn assert_to_relative_dname<T: ToRelativeDname + ?Sized>(_: &T) {}
1046
1047 assert_to_relative_dname(
1048 RelativeDname::from_slice(b"\x03www".as_ref()).unwrap(),
1049 );
1050 assert_to_relative_dname(
1051 &RelativeDname::from_octets(b"\x03www").unwrap(),
1052 );
1053 assert_to_relative_dname(
1054 &RelativeDname::from_octets(b"\x03www".as_ref()).unwrap(),
1055 );
1056 assert_to_relative_dname(
1057 &RelativeDname::from_octets(Vec::from(b"\x03www".as_ref()))
1058 .unwrap(),
1059 );
1060 }
1061
1062 #[cfg(feature = "bytes")]
1063 #[test]
1064 fn impl_bytes() {
1065 fn assert_to_relative_dname<T: ToRelativeDname + ?Sized>(_: &T) {}
1066
1067 assert_to_relative_dname(
1068 &RelativeDname::from_octets(Bytes::from(b"\x03www".as_ref()))
1069 .unwrap(),
1070 );
1071 }
1072
1073 #[test]
1074 fn empty() {
1075 assert_eq!(RelativeDname::empty_slice().as_slice(), b"");
1076 assert_eq!(RelativeDname::empty_ref().as_slice(), b"");
1077
1078 #[cfg(feature = "std")]
1079 {
1080 assert_eq!(RelativeDname::empty_vec().as_slice(), b"");
1081 }
1082 }
1083
1084 #[test]
1085 fn wildcard() {
1086 assert_eq!(RelativeDname::wildcard_slice().as_slice(), b"\x01*");
1087 assert_eq!(RelativeDname::wildcard_ref().as_slice(), b"\x01*");
1088
1089 #[cfg(feature = "std")]
1090 {
1091 assert_eq!(RelativeDname::wildcard_vec().as_slice(), b"\x01*");
1092 }
1093 }
1094
1095 #[cfg(feature = "bytes")]
1096 #[test]
1097 fn literals_bytes() {
1098 assert_eq!(RelativeDname::empty_bytes().as_slice(), b"");
1099 assert_eq!(RelativeDname::wildcard_bytes().as_slice(), b"\x01*");
1100 }
1101
1102 #[test]
1103 #[cfg(feature = "std")]
1104 fn from_slice() {
1105 assert_eq!(RelativeDname::from_slice(b"").unwrap().as_slice(), b"");
1107 assert_eq!(
1108 RelativeDname::from_slice(b"\x03www").unwrap().as_slice(),
1109 b"\x03www"
1110 );
1111 assert_eq!(
1112 RelativeDname::from_slice(b"\x03www\x07example")
1113 .unwrap()
1114 .as_slice(),
1115 b"\x03www\x07example"
1116 );
1117
1118 assert_eq!(
1120 RelativeDname::from_slice(b"\x03www\x07example\x03com\0"),
1121 Err(RelativeDnameError::AbsoluteName)
1122 );
1123 assert_eq!(
1124 RelativeDname::from_slice(b"\0"),
1125 Err(RelativeDnameError::AbsoluteName)
1126 );
1127
1128 assert_eq!(
1130 RelativeDname::from_slice(b"\x03www\x07exa"),
1131 Err(RelativeDnameError::ShortInput)
1132 );
1133
1134 let mut slice = [0u8; 64];
1136 slice[0] = 63;
1137 assert!(RelativeDname::from_slice(&slice[..]).is_ok());
1138 let mut slice = [0u8; 65];
1139 slice[0] = 64;
1140 assert!(RelativeDname::from_slice(&slice[..]).is_err());
1141
1142 let mut buf = Vec::new();
1144 for _ in 0..25 {
1145 buf.extend_from_slice(b"\x09123456789");
1146 }
1147 assert_eq!(buf.len(), 250);
1148 let mut tmp = buf.clone();
1149 tmp.extend_from_slice(b"\x03123");
1150 assert_eq!(RelativeDname::from_slice(&tmp).map(|_| ()), Ok(()));
1151 buf.extend_from_slice(b"\x041234");
1152 assert!(RelativeDname::from_slice(&buf).is_err());
1153
1154 assert_eq!(
1156 RelativeDname::from_slice(b"\xa2asdasds"),
1157 Err(LabelTypeError::Undefined.into())
1158 );
1159 assert_eq!(
1160 RelativeDname::from_slice(b"\x62asdasds"),
1161 Err(LabelTypeError::Extended(0x62).into())
1162 );
1163 assert_eq!(
1164 RelativeDname::from_slice(b"\xccasdasds"),
1165 Err(RelativeDnameError::CompressedName)
1166 );
1167 }
1168
1169 #[test]
1170 #[cfg(feature = "std")]
1171 fn from_str() {
1172 assert_eq!(RelativeDname::vec_from_str("").unwrap().as_slice(), b"");
1174
1175 assert_eq!(
1177 RelativeDname::vec_from_str("www.example")
1178 .unwrap()
1179 .as_slice(),
1180 b"\x03www\x07example"
1181 );
1182
1183 assert!(RelativeDname::vec_from_str("www.example.com.").is_err());
1185 }
1186
1187 #[test]
1188 #[cfg(feature = "std")]
1189 fn into_absolute() {
1190 assert_eq!(
1191 RelativeDname::from_octets(Vec::from(
1192 b"\x03www\x07example\x03com".as_ref()
1193 ))
1194 .unwrap()
1195 .into_absolute()
1196 .unwrap()
1197 .as_slice(),
1198 b"\x03www\x07example\x03com\0"
1199 );
1200
1201 let mut buf = Vec::new();
1203 for _ in 0..25 {
1204 buf.extend_from_slice(b"\x09123456789");
1205 }
1206 assert_eq!(buf.len(), 250);
1207 let mut tmp = buf.clone();
1208 tmp.extend_from_slice(b"\x03123");
1209 RelativeDname::from_octets(tmp)
1210 .unwrap()
1211 .into_absolute()
1212 .unwrap();
1213 }
1214
1215 #[test]
1216 #[cfg(feature = "std")]
1217 fn make_canonical() {
1218 let mut name = Dname::vec_from_str("wWw.exAmpLE.coM.").unwrap();
1219 name.make_canonical();
1220 assert_eq!(
1221 name,
1222 Dname::from_octets(b"\x03www\x07example\x03com\0").unwrap()
1223 );
1224 }
1225
1226 #[test]
1229 fn chain_root() {
1230 assert_eq!(
1231 Dname::from_octets(b"\x03www\x07example\x03com\0").unwrap(),
1232 RelativeDname::from_octets(b"\x03www\x07example\x03com")
1233 .unwrap()
1234 .chain_root()
1235 );
1236 }
1237
1238 #[test]
1239 fn iter() {
1240 use crate::base::name::dname::test::cmp_iter;
1241
1242 cmp_iter(RelativeDname::empty_ref().iter(), &[]);
1243 cmp_iter(RelativeDname::wildcard_ref().iter(), &[b"*"]);
1244 cmp_iter(
1245 RelativeDname::from_slice(b"\x03www\x07example\x03com")
1246 .unwrap()
1247 .iter(),
1248 &[b"www", b"example", b"com"],
1249 );
1250 }
1251
1252 #[test]
1253 fn iter_back() {
1254 use crate::base::name::dname::test::cmp_iter_back;
1255
1256 cmp_iter_back(RelativeDname::empty_ref().iter(), &[]);
1257 cmp_iter_back(RelativeDname::wildcard_ref().iter(), &[b"*"]);
1258 cmp_iter_back(
1259 RelativeDname::from_slice(b"\x03www\x07example\x03com")
1260 .unwrap()
1261 .iter(),
1262 &[b"com", b"example", b"www"],
1263 );
1264 }
1265
1266 #[test]
1267 fn label_count() {
1268 assert_eq!(RelativeDname::empty_ref().label_count(), 0);
1269 assert_eq!(RelativeDname::wildcard_slice().label_count(), 1);
1270 assert_eq!(
1271 RelativeDname::from_slice(b"\x03www\x07example\x03com")
1272 .unwrap()
1273 .label_count(),
1274 3
1275 );
1276 }
1277
1278 #[test]
1279 fn first() {
1280 assert_eq!(RelativeDname::empty_slice().first(), None);
1281 assert_eq!(
1282 RelativeDname::from_slice(b"\x03www")
1283 .unwrap()
1284 .first()
1285 .unwrap()
1286 .as_slice(),
1287 b"www"
1288 );
1289 assert_eq!(
1290 RelativeDname::from_slice(b"\x03www\x07example")
1291 .unwrap()
1292 .first()
1293 .unwrap()
1294 .as_slice(),
1295 b"www"
1296 );
1297 }
1298
1299 #[test]
1300 fn last() {
1301 assert_eq!(RelativeDname::empty_slice().last(), None);
1302 assert_eq!(
1303 RelativeDname::from_slice(b"\x03www")
1304 .unwrap()
1305 .last()
1306 .unwrap()
1307 .as_slice(),
1308 b"www"
1309 );
1310 assert_eq!(
1311 RelativeDname::from_slice(b"\x03www\x07example")
1312 .unwrap()
1313 .last()
1314 .unwrap()
1315 .as_slice(),
1316 b"example"
1317 );
1318 }
1319
1320 #[test]
1321 fn ndots() {
1322 assert_eq!(RelativeDname::empty_slice().ndots(), 0);
1323 assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap().ndots(), 0);
1324 assert_eq!(
1325 RelativeDname::from_slice(b"\x03www\x07example")
1326 .unwrap()
1327 .ndots(),
1328 1
1329 );
1330 }
1331
1332 #[test]
1333 fn starts_with() {
1334 let matrix = [
1335 (
1336 RelativeDname::empty_slice(),
1337 [true, false, false, false, false, false],
1338 ),
1339 (
1340 RelativeDname::from_slice(b"\x03www").unwrap(),
1341 [true, true, false, false, false, false],
1342 ),
1343 (
1344 RelativeDname::from_slice(b"\x03www\x07example").unwrap(),
1345 [true, true, true, false, false, false],
1346 ),
1347 (
1348 RelativeDname::from_slice(b"\x03www\x07example\x03com")
1349 .unwrap(),
1350 [true, true, true, true, false, false],
1351 ),
1352 (
1353 RelativeDname::from_slice(b"\x07example\x03com").unwrap(),
1354 [true, false, false, false, true, false],
1355 ),
1356 (
1357 RelativeDname::from_slice(b"\x03com").unwrap(),
1358 [true, false, false, false, false, true],
1359 ),
1360 ];
1361 for i in 0..6 {
1362 for j in 0..6 {
1363 assert_eq!(
1364 matrix[i].0.starts_with(&matrix[j].0),
1365 matrix[i].1[j],
1366 "i={}, j={}",
1367 i,
1368 j
1369 )
1370 }
1371 }
1372 }
1373
1374 #[test]
1375 fn ends_with() {
1376 let matrix = [
1377 (
1378 RelativeDname::empty_slice(),
1379 [true, false, false, false, false, false],
1380 ),
1381 (
1382 RelativeDname::from_slice(b"\x03www").unwrap(),
1383 [true, true, false, false, false, false],
1384 ),
1385 (
1386 RelativeDname::from_slice(b"\x03www\x07example").unwrap(),
1387 [true, false, true, false, false, false],
1388 ),
1389 (
1390 RelativeDname::from_slice(b"\x03www\x07example\x03com")
1391 .unwrap(),
1392 [true, false, false, true, true, true],
1393 ),
1394 (
1395 RelativeDname::from_slice(b"\x07example\x03com").unwrap(),
1396 [true, false, false, false, true, true],
1397 ),
1398 (
1399 RelativeDname::from_slice(b"\x03com").unwrap(),
1400 [true, false, false, false, false, true],
1401 ),
1402 ];
1403 for i in 0..matrix.len() {
1404 for j in 0..matrix.len() {
1405 assert_eq!(
1406 matrix[i].0.ends_with(&matrix[j].0),
1407 matrix[i].1[j],
1408 "i={}, j={}",
1409 i,
1410 j
1411 )
1412 }
1413 }
1414 }
1415
1416 #[test]
1417 fn is_label_start() {
1418 let wec =
1419 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap();
1420
1421 assert!(wec.is_label_start(0)); assert!(!wec.is_label_start(1)); assert!(!wec.is_label_start(2)); assert!(!wec.is_label_start(3)); assert!(wec.is_label_start(4)); assert!(!wec.is_label_start(5)); assert!(!wec.is_label_start(6)); assert!(!wec.is_label_start(7)); assert!(!wec.is_label_start(8)); assert!(!wec.is_label_start(9)); assert!(!wec.is_label_start(10)); assert!(!wec.is_label_start(11)); assert!(wec.is_label_start(12)); assert!(!wec.is_label_start(13)); assert!(!wec.is_label_start(14)); assert!(!wec.is_label_start(15)); assert!(wec.is_label_start(16)); assert!(!wec.is_label_start(17)); }
1440
1441 #[test]
1442 #[cfg(feature = "std")]
1443 fn slice() {
1444 let wec =
1445 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap();
1446 assert_eq!(wec.slice(0..4).as_slice(), b"\x03www");
1447 assert_eq!(wec.slice(0..12).as_slice(), b"\x03www\x07example");
1448 assert_eq!(wec.slice(4..12).as_slice(), b"\x07example");
1449 assert_eq!(wec.slice(4..16).as_slice(), b"\x07example\x03com");
1450
1451 assert_panic!(wec.slice(0..3));
1452 assert_panic!(wec.slice(1..4));
1453 assert_panic!(wec.slice(0..11));
1454 assert_panic!(wec.slice(1..12));
1455 assert_panic!(wec.slice(0..17));
1456 assert_panic!(wec.slice(4..17));
1457 assert_panic!(wec.slice(0..18));
1458 }
1459
1460 #[test]
1461 #[cfg(feature = "std")]
1462 fn range() {
1463 let wec =
1464 RelativeDname::from_octets(b"\x03www\x07example\x03com".as_ref())
1465 .unwrap();
1466 assert_eq!(wec.range(0..4).as_slice(), b"\x03www");
1467 assert_eq!(wec.range(0..12).as_slice(), b"\x03www\x07example");
1468 assert_eq!(wec.range(4..12).as_slice(), b"\x07example");
1469 assert_eq!(wec.range(4..16).as_slice(), b"\x07example\x03com");
1470
1471 assert_panic!(wec.range(0..3));
1472 assert_panic!(wec.range(1..4));
1473 assert_panic!(wec.range(0..11));
1474 assert_panic!(wec.range(1..12));
1475 assert_panic!(wec.range(0..17));
1476 assert_panic!(wec.range(4..17));
1477 assert_panic!(wec.range(0..18));
1478 }
1479
1480 #[test]
1481 #[cfg(feature = "std")]
1482 fn split() {
1483 let wec =
1484 RelativeDname::from_octets(b"\x03www\x07example\x03com".as_ref())
1485 .unwrap();
1486
1487 let (left, right) = wec.split(0);
1488 assert_eq!(left.as_slice(), b"");
1489 assert_eq!(right.as_slice(), b"\x03www\x07example\x03com");
1490
1491 let (left, right) = wec.split(4);
1492 assert_eq!(left.as_slice(), b"\x03www");
1493 assert_eq!(right.as_slice(), b"\x07example\x03com");
1494
1495 let (left, right) = wec.split(12);
1496 assert_eq!(left.as_slice(), b"\x03www\x07example");
1497 assert_eq!(right.as_slice(), b"\x03com");
1498
1499 let (left, right) = wec.split(16);
1500 assert_eq!(left.as_slice(), b"\x03www\x07example\x03com");
1501 assert_eq!(right.as_slice(), b"");
1502
1503 assert_panic!(wec.split(1));
1504 assert_panic!(wec.split(14));
1505 assert_panic!(wec.split(17));
1506 assert_panic!(wec.split(18));
1507 }
1508
1509 #[test]
1510 #[cfg(feature = "std")]
1511 fn truncate() {
1512 let wec =
1513 RelativeDname::from_octets(b"\x03www\x07example\x03com".as_ref())
1514 .unwrap();
1515
1516 let mut tmp = wec.clone();
1517 tmp.truncate(0);
1518 assert_eq!(tmp.as_slice(), b"");
1519
1520 let mut tmp = wec.clone();
1521 tmp.truncate(4);
1522 assert_eq!(tmp.as_slice(), b"\x03www");
1523
1524 let mut tmp = wec.clone();
1525 tmp.truncate(12);
1526 assert_eq!(tmp.as_slice(), b"\x03www\x07example");
1527
1528 let mut tmp = wec.clone();
1529 tmp.truncate(16);
1530 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
1531
1532 assert_panic!(wec.clone().truncate(1));
1533 assert_panic!(wec.clone().truncate(14));
1534 assert_panic!(wec.clone().truncate(17));
1535 assert_panic!(wec.clone().truncate(18));
1536 }
1537
1538 #[test]
1539 fn split_first() {
1540 let wec =
1541 RelativeDname::from_octets(b"\x03www\x07example\x03com".as_ref())
1542 .unwrap();
1543
1544 let (label, wec) = wec.split_first().unwrap();
1545 assert_eq!(label.as_slice(), b"www");
1546 assert_eq!(wec.as_slice(), b"\x07example\x03com");
1547
1548 let (label, wec) = wec.split_first().unwrap();
1549 assert_eq!(label.as_slice(), b"example");
1550 assert_eq!(wec.as_slice(), b"\x03com");
1551
1552 let (label, wec) = wec.split_first().unwrap();
1553 assert_eq!(label.as_slice(), b"com");
1554 assert_eq!(wec.as_slice(), b"");
1555 assert!(wec.split_first().is_none());
1556 }
1557
1558 #[test]
1559 fn parent() {
1560 let wec =
1561 RelativeDname::from_octets(b"\x03www\x07example\x03com".as_ref())
1562 .unwrap();
1563
1564 let wec = wec.parent().unwrap();
1565 assert_eq!(wec.as_slice(), b"\x07example\x03com");
1566
1567 let wec = wec.parent().unwrap();
1568 assert_eq!(wec.as_slice(), b"\x03com");
1569
1570 let wec = wec.parent().unwrap();
1571 assert_eq!(wec.as_slice(), b"");
1572
1573 assert!(wec.parent().is_none());
1574 }
1575
1576 #[test]
1577 fn strip_suffix() {
1578 let wec =
1579 RelativeDname::from_octets(b"\x03www\x07example\x03com".as_ref())
1580 .unwrap();
1581 let ec = RelativeDname::from_octets(b"\x07example\x03com".as_ref())
1582 .unwrap();
1583 let c = RelativeDname::from_octets(b"\x03com".as_ref()).unwrap();
1584 let wen =
1585 RelativeDname::from_octets(b"\x03www\x07example\x03net".as_ref())
1586 .unwrap();
1587 let en = RelativeDname::from_octets(b"\x07example\x03net".as_ref())
1588 .unwrap();
1589 let n = RelativeDname::from_slice(b"\x03net".as_ref()).unwrap();
1590
1591 let mut tmp = wec.clone();
1592 assert_eq!(tmp.strip_suffix(&wec), Ok(()));
1593 assert_eq!(tmp.as_slice(), b"");
1594
1595 let mut tmp = wec.clone();
1596 assert_eq!(tmp.strip_suffix(&ec), Ok(()));
1597 assert_eq!(tmp.as_slice(), b"\x03www");
1598
1599 let mut tmp = wec.clone();
1600 assert_eq!(tmp.strip_suffix(&c), Ok(()));
1601 assert_eq!(tmp.as_slice(), b"\x03www\x07example");
1602
1603 let mut tmp = wec.clone();
1604 assert_eq!(tmp.strip_suffix(&RelativeDname::empty_ref()), Ok(()));
1605 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
1606
1607 assert_eq!(wec.clone().strip_suffix(&wen), Err(StripSuffixError));
1608 assert_eq!(wec.clone().strip_suffix(&en), Err(StripSuffixError));
1609 assert_eq!(wec.clone().strip_suffix(&n), Err(StripSuffixError));
1610 }
1611
1612 #[test]
1615 fn eq() {
1616 assert_eq!(
1617 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1618 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap()
1619 );
1620 assert_eq!(
1621 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1622 RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap()
1623 );
1624 assert_eq!(
1625 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1626 &RelativeDname::from_octets(b"\x03www")
1627 .unwrap()
1628 .chain(
1629 RelativeDname::from_octets(b"\x07example\x03com")
1630 .unwrap()
1631 )
1632 .unwrap()
1633 );
1634 assert_eq!(
1635 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1636 &RelativeDname::from_octets(b"\x03wWw")
1637 .unwrap()
1638 .chain(
1639 RelativeDname::from_octets(b"\x07eXAMple\x03coM")
1640 .unwrap()
1641 )
1642 .unwrap()
1643 );
1644
1645 assert_ne!(
1646 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1647 RelativeDname::from_slice(b"\x03ww4\x07example\x03com").unwrap()
1648 );
1649 assert_ne!(
1650 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1651 &RelativeDname::from_octets(b"\x03www")
1652 .unwrap()
1653 .chain(
1654 RelativeDname::from_octets(b"\x073xample\x03com")
1655 .unwrap()
1656 )
1657 .unwrap()
1658 );
1659 }
1660
1661 #[test]
1662 fn cmp() {
1663 use core::cmp::Ordering;
1664
1665 let names = [
1667 RelativeDname::from_slice(b"\x07example").unwrap(),
1668 RelativeDname::from_slice(b"\x01a\x07example").unwrap(),
1669 RelativeDname::from_slice(b"\x08yljkjljk\x01a\x07example")
1670 .unwrap(),
1671 RelativeDname::from_slice(b"\x01Z\x01a\x07example").unwrap(),
1672 RelativeDname::from_slice(b"\x04zABC\x01a\x07example").unwrap(),
1673 RelativeDname::from_slice(b"\x01z\x07example").unwrap(),
1674 RelativeDname::from_slice(b"\x01\x01\x01z\x07example").unwrap(),
1675 RelativeDname::from_slice(b"\x01*\x01z\x07example").unwrap(),
1676 RelativeDname::from_slice(b"\x01\xc8\x01z\x07example").unwrap(),
1677 ];
1678 for i in 0..names.len() {
1679 for j in 0..names.len() {
1680 let ord = i.cmp(&j);
1681 assert_eq!(names[i].partial_cmp(names[j]), Some(ord));
1682 assert_eq!(names[i].cmp(names[j]), ord);
1683 }
1684 }
1685
1686 let n1 =
1687 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap();
1688 let n2 =
1689 RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap();
1690 assert_eq!(n1.partial_cmp(n2), Some(Ordering::Equal));
1691 assert_eq!(n1.cmp(n2), Ordering::Equal);
1692 }
1693
1694 #[test]
1695 #[cfg(feature = "std")]
1696 fn hash() {
1697 use std::collections::hash_map::DefaultHasher;
1698 use std::hash::{Hash, Hasher};
1699
1700 let mut s1 = DefaultHasher::new();
1701 let mut s2 = DefaultHasher::new();
1702 RelativeDname::from_slice(b"\x03www\x07example\x03com")
1703 .unwrap()
1704 .hash(&mut s1);
1705 RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com")
1706 .unwrap()
1707 .hash(&mut s2);
1708 assert_eq!(s1.finish(), s2.finish());
1709 }
1710
1711 #[cfg(all(feature = "serde", feature = "std"))]
1714 #[test]
1715 fn ser_de() {
1716 use serde_test::{assert_tokens, Configure, Token};
1717
1718 let name = RelativeDname::from_octets(Vec::from(
1719 b"\x03www\x07example\x03com".as_ref(),
1720 ))
1721 .unwrap();
1722 assert_tokens(
1723 &name.clone().compact(),
1724 &[
1725 Token::NewtypeStruct {
1726 name: "RelativeDname",
1727 },
1728 Token::ByteBuf(b"\x03www\x07example\x03com"),
1729 ],
1730 );
1731 assert_tokens(
1732 &name.readable(),
1733 &[
1734 Token::NewtypeStruct {
1735 name: "RelativeDname",
1736 },
1737 Token::Str("www.example.com"),
1738 ],
1739 );
1740 }
1741}