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