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) const unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
137 mem::transmute(slice)
139 }
140
141 pub const fn from_slice(
152 slice: &[u8],
153 ) -> Result<&Self, RelativeNameError> {
154 match Self::check_slice(slice) {
155 Ok(()) => Ok(unsafe { Self::from_slice_unchecked(slice) }),
156 Err(err) => Err(err),
157 }
158 }
159
160 #[must_use]
162 pub fn empty_slice() -> &'static Self {
163 unsafe { Self::from_slice_unchecked(b"") }
164 }
165
166 #[must_use]
167 pub fn wildcard_slice() -> &'static Self {
168 unsafe { Self::from_slice_unchecked(b"\x01*") }
169 }
170
171 pub(super) const fn check_slice(
173 mut slice: &[u8],
174 ) -> Result<(), RelativeNameError> {
175 if slice.len() > 254 {
176 return Err(RelativeNameError(RelativeNameErrorEnum::LongName));
177 }
178 while !slice.is_empty() {
179 let (label, tail) = match Label::split_from(slice) {
180 Ok((label, tail)) => (label, tail),
181 Err(err) => {
182 return Err(RelativeNameError(match err {
183 SplitLabelError::Pointer(_) => {
184 RelativeNameErrorEnum::CompressedName
185 }
186 SplitLabelError::BadType(t) => {
187 RelativeNameErrorEnum::BadLabel(t)
188 }
189 SplitLabelError::ShortInput => {
190 RelativeNameErrorEnum::ShortInput
191 }
192 }));
193 }
194 };
195 if label.is_root() {
196 return Err(RelativeNameError(
197 RelativeNameErrorEnum::AbsoluteName,
198 ));
199 }
200 slice = tail;
201 }
202 Ok(())
203 }
204}
205
206impl RelativeName<&'static [u8]> {
207 #[must_use]
209 pub fn empty_ref() -> Self {
210 Self::empty()
211 }
212
213 #[must_use]
215 pub fn wildcard_ref() -> Self {
216 Self::wildcard()
217 }
218}
219
220#[cfg(feature = "std")]
221impl RelativeName<Vec<u8>> {
222 #[must_use]
224 pub fn empty_vec() -> Self {
225 Self::empty()
226 }
227
228 #[must_use]
230 pub fn wildcard_vec() -> Self {
231 Self::wildcard()
232 }
233
234 pub fn vec_from_str(s: &str) -> Result<Self, RelativeFromStrError> {
236 FromStr::from_str(s)
237 }
238}
239
240#[cfg(feature = "bytes")]
241impl RelativeName<Bytes> {
242 pub fn empty_bytes() -> Self {
244 Self::empty()
245 }
246
247 pub fn wildcard_bytes() -> Self {
249 Self::wildcard()
250 }
251
252 pub fn bytes_from_str(s: &str) -> Result<Self, RelativeFromStrError> {
254 FromStr::from_str(s)
255 }
256}
257
258impl<Octs: ?Sized> RelativeName<Octs> {
261 pub fn as_octets(&self) -> &Octs {
263 &self.0
264 }
265
266 pub fn into_octets(self) -> Octs
268 where
269 Octs: Sized,
270 {
271 self.0
272 }
273
274 pub fn for_ref(&self) -> RelativeName<&Octs> {
276 unsafe { RelativeName::from_octets_unchecked(&self.0) }
277 }
278
279 pub fn as_slice(&self) -> &[u8]
281 where
282 Octs: AsRef<[u8]>,
283 {
284 self.0.as_ref()
285 }
286
287 pub fn for_slice(&self) -> &RelativeName<[u8]>
289 where
290 Octs: AsRef<[u8]>,
291 {
292 unsafe { RelativeName::from_slice_unchecked(self.0.as_ref()) }
293 }
294
295 pub fn make_canonical(&mut self)
297 where
298 Octs: AsMut<[u8]>,
299 {
300 Label::make_slice_canonical(self.0.as_mut());
301 }
302}
303
304impl<Octs> RelativeName<Octs> {
305 pub fn into_builder(self) -> NameBuilder<<Octs as IntoBuilder>::Builder>
310 where
311 Octs: IntoBuilder,
312 {
313 unsafe { NameBuilder::from_builder_unchecked(self.0.into_builder()) }
314 }
315
316 pub fn into_absolute(self) -> Result<Name<Octs>, PushError>
322 where
323 Octs: IntoBuilder,
324 <Octs as IntoBuilder>::Builder:
325 FreezeBuilder<Octets = Octs> + AsRef<[u8]> + AsMut<[u8]>,
326 {
327 self.into_builder().into_name()
328 }
329
330 pub fn chain<N: ToLabelIter>(
340 self,
341 other: N,
342 ) -> Result<Chain<Self, N>, LongChainError>
343 where
344 Octs: AsRef<[u8]>,
345 {
346 Chain::new(self, other)
347 }
348
349 pub fn chain_root(self) -> Chain<Self, Name<&'static [u8]>>
351 where
352 Octs: AsRef<[u8]>,
353 {
354 self.chain(Name::root()).unwrap()
355 }
356}
357
358impl<Octs: AsRef<[u8]> + ?Sized> RelativeName<Octs> {
361 pub fn len(&self) -> usize {
363 self.0.as_ref().len()
364 }
365
366 pub fn is_empty(&self) -> bool {
368 self.0.as_ref().is_empty()
369 }
370}
371
372impl<Octs: AsRef<[u8]> + ?Sized> RelativeName<Octs> {
375 pub fn iter(&self) -> NameIter<'_> {
377 NameIter::new(self.0.as_ref())
378 }
379
380 pub fn label_count(&self) -> usize {
382 self.iter().count()
383 }
384
385 pub fn first(&self) -> Option<&Label> {
387 self.iter().next()
388 }
389
390 pub fn last(&self) -> Option<&Label> {
392 self.iter().next_back()
393 }
394
395 pub fn ndots(&self) -> usize {
400 if self.0.as_ref().is_empty() {
401 0
402 } else {
403 self.label_count() - 1
404 }
405 }
406
407 pub fn starts_with<N: ToLabelIter>(&self, base: &N) -> bool {
409 <Self as ToLabelIter>::starts_with(self, base)
410 }
411
412 pub fn ends_with<N: ToLabelIter>(&self, base: &N) -> bool {
414 <Self as ToLabelIter>::ends_with(self, base)
415 }
416
417 pub fn is_label_start(&self, mut index: usize) -> bool {
419 if index == 0 {
420 return true;
421 }
422 let mut tmp = self.as_slice();
423 while !tmp.is_empty() {
424 let (label, tail) = Label::split_from(tmp).unwrap();
425 let len = label.len() + 1;
426 match index.cmp(&len) {
427 Ordering::Less => return false,
428 Ordering::Equal => return true,
429 _ => {}
430 }
431 index -= len;
432 tmp = tail;
433 }
434 false
435 }
436
437 fn check_index(&self, index: usize) {
439 if !self.is_label_start(index) {
440 panic!("index not at start of a label");
441 }
442 }
443
444 fn check_bounds(&self, bounds: &impl RangeBounds<usize>) {
445 match bounds.start_bound().cloned() {
446 Bound::Included(idx) => self.check_index(idx),
447 Bound::Excluded(_) => {
448 panic!("excluded lower bounds not supported");
449 }
450 Bound::Unbounded => {}
451 }
452 match bounds.end_bound().cloned() {
453 Bound::Included(idx) => self
454 .check_index(idx.checked_add(1).expect("end bound too big")),
455 Bound::Excluded(idx) => self.check_index(idx),
456 Bound::Unbounded => {}
457 }
458 }
459
460 pub fn slice(
477 &self,
478 range: impl RangeBounds<usize>,
479 ) -> &RelativeName<[u8]> {
480 self.check_bounds(&range);
481 unsafe {
482 RelativeName::from_slice_unchecked(self.0.as_ref().range(range))
483 }
484 }
485
486 pub fn range(
497 &self,
498 range: impl RangeBounds<usize>,
499 ) -> RelativeName<<Octs as Octets>::Range<'_>>
500 where
501 Octs: Octets,
502 {
503 self.check_bounds(&range);
504 unsafe { RelativeName::from_octets_unchecked(self.0.range(range)) }
505 }
506}
507
508impl<Octs: AsRef<[u8]> + ?Sized> RelativeName<Octs> {
509 pub fn split(
518 &self,
519 mid: usize,
520 ) -> (RelativeName<Octs::Range<'_>>, RelativeName<Octs::Range<'_>>)
521 where
522 Octs: Octets,
523 {
524 self.check_index(mid);
525 unsafe {
526 (
527 RelativeName::from_octets_unchecked(self.0.range(..mid)),
528 RelativeName::from_octets_unchecked(self.0.range(mid..)),
529 )
530 }
531 }
532
533 pub fn truncate(&mut self, len: usize)
540 where
541 Octs: Truncate,
542 {
543 self.check_index(len);
544 self.0.truncate(len);
545 }
546
547 pub fn split_first(
554 &self,
555 ) -> Option<(&Label, RelativeName<Octs::Range<'_>>)>
556 where
557 Octs: Octets,
558 {
559 if self.is_empty() {
560 return None;
561 }
562 let label = self.iter().next()?;
563 Some((label, self.split(label.len() + 1).1))
564 }
565
566 pub fn parent(&self) -> Option<RelativeName<Octs::Range<'_>>>
570 where
571 Octs: Octets,
572 {
573 self.split_first().map(|(_, parent)| parent)
574 }
575
576 pub fn strip_suffix<N: ToRelativeName>(
583 &mut self,
584 base: &N,
585 ) -> Result<(), StripSuffixError>
586 where
587 Octs: Truncate,
588 {
589 if self.ends_with(base) {
590 let idx = self.0.as_ref().len() - usize::from(base.compose_len());
591 self.0.truncate(idx);
592 Ok(())
593 } else {
594 Err(StripSuffixError(()))
595 }
596 }
597}
598
599impl<Octs> AsRef<Octs> for RelativeName<Octs> {
602 fn as_ref(&self) -> &Octs {
603 &self.0
604 }
605}
606
607impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for RelativeName<Octs> {
608 fn as_ref(&self) -> &[u8] {
609 self.0.as_ref()
610 }
611}
612
613impl<Octs, SrcOcts> OctetsFrom<RelativeName<SrcOcts>> for RelativeName<Octs>
616where
617 Octs: OctetsFrom<SrcOcts>,
618{
619 type Error = Octs::Error;
620
621 fn try_octets_from(
622 source: RelativeName<SrcOcts>,
623 ) -> Result<Self, Self::Error> {
624 Octs::try_octets_from(source.0)
625 .map(|octets| unsafe { Self::from_octets_unchecked(octets) })
626 }
627}
628
629impl<Octs> FromStr for RelativeName<Octs>
632where
633 Octs: FromBuilder,
634 <Octs as FromBuilder>::Builder: EmptyBuilder
635 + FreezeBuilder<Octets = Octs>
636 + AsRef<[u8]>
637 + AsMut<[u8]>,
638{
639 type Err = RelativeFromStrError;
640
641 fn from_str(s: &str) -> Result<Self, Self::Err> {
651 Self::from_chars(s.chars())
652 }
653}
654
655impl<Octs> ToLabelIter for RelativeName<Octs>
658where
659 Octs: AsRef<[u8]> + ?Sized,
660{
661 type LabelIter<'a>
662 = NameIter<'a>
663 where
664 Octs: 'a;
665
666 fn iter_labels(&self) -> Self::LabelIter<'_> {
667 self.iter()
668 }
669
670 fn compose_len(&self) -> u16 {
671 u16::try_from(self.0.as_ref().len()).expect("long domain name")
672 }
673}
674
675impl<Octs: AsRef<[u8]> + ?Sized> ToRelativeName for RelativeName<Octs> {
676 fn as_flat_slice(&self) -> Option<&[u8]> {
677 Some(self.0.as_ref())
678 }
679
680 fn is_empty(&self) -> bool {
681 self.0.as_ref().is_empty()
682 }
683}
684
685impl<'a, Octs> IntoIterator for &'a RelativeName<Octs>
688where
689 Octs: AsRef<[u8]> + ?Sized,
690{
691 type Item = &'a Label;
692 type IntoIter = NameIter<'a>;
693
694 fn into_iter(self) -> Self::IntoIter {
695 self.iter()
696 }
697}
698
699impl<Octs, N> PartialEq<N> for RelativeName<Octs>
702where
703 Octs: AsRef<[u8]> + ?Sized,
704 N: ToRelativeName + ?Sized,
705{
706 fn eq(&self, other: &N) -> bool {
707 self.name_eq(other)
708 }
709}
710
711impl<Octs: AsRef<[u8]> + ?Sized> Eq for RelativeName<Octs> {}
712
713impl<Octs, N> PartialOrd<N> for RelativeName<Octs>
716where
717 Octs: AsRef<[u8]> + ?Sized,
718 N: ToRelativeName + ?Sized,
719{
720 fn partial_cmp(&self, other: &N) -> Option<cmp::Ordering> {
721 Some(self.name_cmp(other))
722 }
723}
724
725impl<Octs: AsRef<[u8]> + ?Sized> Ord for RelativeName<Octs> {
726 fn cmp(&self, other: &Self) -> cmp::Ordering {
727 self.name_cmp(other)
728 }
729}
730
731impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for RelativeName<Octs> {
734 fn hash<H: hash::Hasher>(&self, state: &mut H) {
735 for item in self.iter() {
736 item.hash(state)
737 }
738 }
739}
740
741impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for RelativeName<Octs> {
744 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
745 let mut iter = self.iter();
746 match iter.next() {
747 Some(label) => label.fmt(f)?,
748 None => return Ok(()),
749 }
750 for label in iter {
751 f.write_str(".")?;
752 label.fmt(f)?;
753 }
754 Ok(())
755 }
756}
757
758impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for RelativeName<Octs> {
759 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
760 write!(f, "RelativeName({})", self)
761 }
762}
763
764impl<Octs> AsRef<RelativeName<[u8]>> for RelativeName<Octs>
767where
768 Octs: AsRef<[u8]> + ?Sized,
769{
770 fn as_ref(&self) -> &RelativeName<[u8]> {
771 self.for_slice()
772 }
773}
774
775impl<Octs> borrow::Borrow<RelativeName<[u8]>> for RelativeName<Octs>
795where
796 Octs: AsRef<[u8]>,
797{
798 fn borrow(&self) -> &RelativeName<[u8]> {
799 self.for_slice()
800 }
801}
802
803#[cfg(feature = "serde")]
806impl<Octs> serde::Serialize for RelativeName<Octs>
807where
808 Octs: AsRef<[u8]> + SerializeOctets + ?Sized,
809{
810 fn serialize<S: serde::Serializer>(
811 &self,
812 serializer: S,
813 ) -> Result<S::Ok, S::Error> {
814 if serializer.is_human_readable() {
815 serializer.serialize_newtype_struct(
816 "RelativeName",
817 &format_args!("{}", self),
818 )
819 } else {
820 serializer.serialize_newtype_struct(
821 "RelativeName",
822 &self.0.as_serialized_octets(),
823 )
824 }
825 }
826}
827
828#[cfg(feature = "serde")]
829impl<'de, Octs> serde::Deserialize<'de> for RelativeName<Octs>
830where
831 Octs: FromBuilder + DeserializeOctets<'de>,
832 <Octs as FromBuilder>::Builder: FreezeBuilder<Octets = Octs>
833 + EmptyBuilder
834 + AsRef<[u8]>
835 + AsMut<[u8]>,
836{
837 fn deserialize<D: serde::Deserializer<'de>>(
838 deserializer: D,
839 ) -> Result<Self, D::Error> {
840 use core::marker::PhantomData;
841
842 struct InnerVisitor<'de, T: DeserializeOctets<'de>>(T::Visitor);
843
844 impl<'de, Octs> serde::de::Visitor<'de> for InnerVisitor<'de, Octs>
845 where
846 Octs: FromBuilder + DeserializeOctets<'de>,
847 <Octs as FromBuilder>::Builder: FreezeBuilder<Octets = Octs>
848 + EmptyBuilder
849 + AsRef<[u8]>
850 + AsMut<[u8]>,
851 {
852 type Value = RelativeName<Octs>;
853
854 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
855 f.write_str("a relative domain name")
856 }
857
858 fn visit_str<E: serde::de::Error>(
859 self,
860 v: &str,
861 ) -> Result<Self::Value, E> {
862 let mut builder = NameBuilder::<Octs::Builder>::new();
863 builder.append_chars(v.chars()).map_err(E::custom)?;
864 Ok(builder.finish())
865 }
866
867 fn visit_borrowed_bytes<E: serde::de::Error>(
868 self,
869 value: &'de [u8],
870 ) -> Result<Self::Value, E> {
871 self.0.visit_borrowed_bytes(value).and_then(|octets| {
872 RelativeName::from_octets(octets).map_err(E::custom)
873 })
874 }
875
876 #[cfg(feature = "std")]
877 fn visit_byte_buf<E: serde::de::Error>(
878 self,
879 value: std::vec::Vec<u8>,
880 ) -> Result<Self::Value, E> {
881 self.0.visit_byte_buf(value).and_then(|octets| {
882 RelativeName::from_octets(octets).map_err(E::custom)
883 })
884 }
885 }
886
887 struct NewtypeVisitor<T>(PhantomData<T>);
888
889 impl<'de, Octs> serde::de::Visitor<'de> for NewtypeVisitor<Octs>
890 where
891 Octs: FromBuilder + DeserializeOctets<'de>,
892 <Octs as FromBuilder>::Builder: FreezeBuilder<Octets = Octs>
893 + EmptyBuilder
894 + AsRef<[u8]>
895 + AsMut<[u8]>,
896 {
897 type Value = RelativeName<Octs>;
898
899 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
900 f.write_str("a relative domain name")
901 }
902
903 fn visit_newtype_struct<D: serde::Deserializer<'de>>(
904 self,
905 deserializer: D,
906 ) -> Result<Self::Value, D::Error> {
907 if deserializer.is_human_readable() {
908 deserializer
909 .deserialize_str(InnerVisitor(Octs::visitor()))
910 } else {
911 Octs::deserialize_with_visitor(
912 deserializer,
913 InnerVisitor(Octs::visitor()),
914 )
915 }
916 }
917 }
918
919 deserializer.deserialize_newtype_struct(
920 "RelativeName",
921 NewtypeVisitor(PhantomData),
922 )
923 }
924}
925
926#[derive(Clone, Debug)]
930pub struct NameIter<'a> {
931 slice: &'a [u8],
932}
933
934impl<'a> NameIter<'a> {
935 pub(super) fn new(slice: &'a [u8]) -> Self {
936 NameIter { slice }
937 }
938}
939
940impl<'a> Iterator for NameIter<'a> {
941 type Item = &'a Label;
942
943 fn next(&mut self) -> Option<Self::Item> {
944 let (label, tail) = match Label::split_from(self.slice) {
945 Ok(res) => res,
946 Err(_) => return None,
947 };
948 self.slice = tail;
949 Some(label)
950 }
951}
952
953impl DoubleEndedIterator for NameIter<'_> {
954 fn next_back(&mut self) -> Option<Self::Item> {
955 if self.slice.is_empty() {
956 return None;
957 }
958 let mut tmp = self.slice;
959 loop {
960 let (label, tail) = Label::split_from(tmp).unwrap();
961 if tail.is_empty() {
962 let end = self.slice.len() - (label.len() + 1);
963 self.slice = &self.slice[..end];
964 return Some(label);
965 } else {
966 tmp = tail
967 }
968 }
969 }
970}
971
972#[derive(Clone, Copy, Debug, Eq, PartialEq)]
978pub struct RelativeNameError(RelativeNameErrorEnum);
979
980#[derive(Clone, Copy, Debug, Eq, PartialEq)]
981enum RelativeNameErrorEnum {
982 BadLabel(LabelTypeError),
984
985 CompressedName,
987
988 ShortInput,
990
991 LongName,
993
994 AbsoluteName,
996}
997
998impl From<LabelTypeError> for RelativeNameError {
1001 fn from(err: LabelTypeError) -> Self {
1002 Self(RelativeNameErrorEnum::BadLabel(err))
1003 }
1004}
1005
1006impl From<SplitLabelError> for RelativeNameError {
1007 fn from(err: SplitLabelError) -> Self {
1008 Self(match err {
1009 SplitLabelError::Pointer(_) => {
1010 RelativeNameErrorEnum::CompressedName
1011 }
1012 SplitLabelError::BadType(t) => RelativeNameErrorEnum::BadLabel(t),
1013 SplitLabelError::ShortInput => RelativeNameErrorEnum::ShortInput,
1014 })
1015 }
1016}
1017
1018impl From<RelativeNameErrorEnum> for RelativeNameError {
1019 fn from(err: RelativeNameErrorEnum) -> Self {
1020 Self(err)
1021 }
1022}
1023
1024impl fmt::Display for RelativeNameError {
1027 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1028 match self.0 {
1029 RelativeNameErrorEnum::BadLabel(err) => err.fmt(f),
1030 RelativeNameErrorEnum::CompressedName => {
1031 f.write_str("compressed domain name")
1032 }
1033 RelativeNameErrorEnum::ShortInput => {
1034 ParseError::ShortInput.fmt(f)
1035 }
1036 RelativeNameErrorEnum::LongName => {
1037 f.write_str("long domain name")
1038 }
1039 RelativeNameErrorEnum::AbsoluteName => {
1040 f.write_str("absolute domain name")
1041 }
1042 }
1043 }
1044}
1045
1046impl core::error::Error for RelativeNameError {}
1047
1048#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1051#[non_exhaustive]
1052pub enum RelativeFromStrError {
1053 FromStr(FromStrError),
1055
1056 AbsoluteName,
1058}
1059
1060impl From<FromStrError> for RelativeFromStrError {
1063 fn from(src: FromStrError) -> Self {
1064 Self::FromStr(src)
1065 }
1066}
1067
1068impl fmt::Display for RelativeFromStrError {
1071 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1072 match self {
1073 RelativeFromStrError::FromStr(err) => err.fmt(f),
1074 RelativeFromStrError::AbsoluteName => {
1075 f.write_str("absolute domain name")
1076 }
1077 }
1078 }
1079}
1080
1081impl core::error::Error for RelativeFromStrError {}
1082
1083#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1087pub struct StripSuffixError(());
1088
1089impl fmt::Display for StripSuffixError {
1092 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1093 f.write_str("suffix not found")
1094 }
1095}
1096
1097impl core::error::Error for StripSuffixError {}
1098
1099#[cfg(test)]
1102mod test {
1103 use super::*;
1104
1105 #[cfg(feature = "std")]
1106 macro_rules! assert_panic {
1107 ( $cond:expr ) => {{
1108 let result = std::panic::catch_unwind(|| $cond);
1109 assert!(result.is_err());
1110 }};
1111 }
1112
1113 #[test]
1114 #[cfg(feature = "std")]
1115 fn impls() {
1116 fn assert_to_relative_name<T: ToRelativeName + ?Sized>(_: &T) {}
1117
1118 assert_to_relative_name(
1119 RelativeName::from_slice(b"\x03www".as_ref()).unwrap(),
1120 );
1121 assert_to_relative_name(
1122 &RelativeName::from_octets(b"\x03www").unwrap(),
1123 );
1124 assert_to_relative_name(
1125 &RelativeName::from_octets(b"\x03www".as_ref()).unwrap(),
1126 );
1127 assert_to_relative_name(
1128 &RelativeName::from_octets(Vec::from(b"\x03www".as_ref()))
1129 .unwrap(),
1130 );
1131 }
1132
1133 #[cfg(feature = "bytes")]
1134 #[test]
1135 fn impl_bytes() {
1136 fn assert_to_relative_name<T: ToRelativeName + ?Sized>(_: &T) {}
1137
1138 assert_to_relative_name(
1139 &RelativeName::from_octets(Bytes::from(b"\x03www".as_ref()))
1140 .unwrap(),
1141 );
1142 }
1143
1144 #[test]
1145 fn empty() {
1146 assert_eq!(RelativeName::empty_slice().as_slice(), b"");
1147 assert_eq!(RelativeName::empty_ref().as_slice(), b"");
1148
1149 #[cfg(feature = "std")]
1150 {
1151 assert_eq!(RelativeName::empty_vec().as_slice(), b"");
1152 }
1153 }
1154
1155 #[test]
1156 fn wildcard() {
1157 assert_eq!(RelativeName::wildcard_slice().as_slice(), b"\x01*");
1158 assert_eq!(RelativeName::wildcard_ref().as_slice(), b"\x01*");
1159
1160 #[cfg(feature = "std")]
1161 {
1162 assert_eq!(RelativeName::wildcard_vec().as_slice(), b"\x01*");
1163 }
1164 }
1165
1166 #[cfg(feature = "bytes")]
1167 #[test]
1168 fn literals_bytes() {
1169 assert_eq!(RelativeName::empty_bytes().as_slice(), b"");
1170 assert_eq!(RelativeName::wildcard_bytes().as_slice(), b"\x01*");
1171 }
1172
1173 #[test]
1174 #[cfg(feature = "std")]
1175 fn from_slice() {
1176 assert_eq!(RelativeName::from_slice(b"").unwrap().as_slice(), b"");
1178 assert_eq!(
1179 RelativeName::from_slice(b"\x03www").unwrap().as_slice(),
1180 b"\x03www"
1181 );
1182 assert_eq!(
1183 RelativeName::from_slice(b"\x03www\x07example")
1184 .unwrap()
1185 .as_slice(),
1186 b"\x03www\x07example"
1187 );
1188
1189 assert_eq!(
1191 RelativeName::from_slice(b"\x03www\x07example\x03com\0"),
1192 Err(RelativeNameError(RelativeNameErrorEnum::AbsoluteName))
1193 );
1194 assert_eq!(
1195 RelativeName::from_slice(b"\0"),
1196 Err(RelativeNameError(RelativeNameErrorEnum::AbsoluteName))
1197 );
1198
1199 assert_eq!(
1201 RelativeName::from_slice(b"\x03www\x07exa"),
1202 Err(RelativeNameError(RelativeNameErrorEnum::ShortInput))
1203 );
1204
1205 let mut slice = [0u8; 64];
1207 slice[0] = 63;
1208 assert!(RelativeName::from_slice(&slice[..]).is_ok());
1209 let mut slice = [0u8; 65];
1210 slice[0] = 64;
1211 assert!(RelativeName::from_slice(&slice[..]).is_err());
1212
1213 let mut buf = Vec::new();
1215 for _ in 0..25 {
1216 buf.extend_from_slice(b"\x09123456789");
1217 }
1218 assert_eq!(buf.len(), 250);
1219 let mut tmp = buf.clone();
1220 tmp.extend_from_slice(b"\x03123");
1221 assert_eq!(RelativeName::from_slice(&tmp).map(|_| ()), Ok(()));
1222 buf.extend_from_slice(b"\x041234");
1223 assert!(RelativeName::from_slice(&buf).is_err());
1224
1225 assert_eq!(
1227 RelativeName::from_slice(b"\xa2asdasds"),
1228 Err(LabelTypeError::Undefined.into())
1229 );
1230 assert_eq!(
1231 RelativeName::from_slice(b"\x62asdasds"),
1232 Err(LabelTypeError::Extended(0x62).into())
1233 );
1234 assert_eq!(
1235 RelativeName::from_slice(b"\xccasdasds"),
1236 Err(RelativeNameError(RelativeNameErrorEnum::CompressedName))
1237 );
1238 }
1239
1240 #[test]
1241 #[cfg(feature = "std")]
1242 fn from_str() {
1243 assert_eq!(RelativeName::vec_from_str("").unwrap().as_slice(), b"");
1245
1246 assert_eq!(
1248 RelativeName::vec_from_str("www.example")
1249 .unwrap()
1250 .as_slice(),
1251 b"\x03www\x07example"
1252 );
1253
1254 assert!(RelativeName::vec_from_str("www.example.com.").is_err());
1256 }
1257
1258 #[test]
1259 #[cfg(feature = "std")]
1260 fn into_absolute() {
1261 assert_eq!(
1262 RelativeName::from_octets(Vec::from(
1263 b"\x03www\x07example\x03com".as_ref()
1264 ))
1265 .unwrap()
1266 .into_absolute()
1267 .unwrap()
1268 .as_slice(),
1269 b"\x03www\x07example\x03com\0"
1270 );
1271
1272 let mut buf = Vec::new();
1274 for _ in 0..25 {
1275 buf.extend_from_slice(b"\x09123456789");
1276 }
1277 assert_eq!(buf.len(), 250);
1278 let mut tmp = buf.clone();
1279 tmp.extend_from_slice(b"\x03123");
1280 RelativeName::from_octets(tmp)
1281 .unwrap()
1282 .into_absolute()
1283 .unwrap();
1284 }
1285
1286 #[test]
1287 #[cfg(feature = "std")]
1288 fn make_canonical() {
1289 let mut name = Name::vec_from_str("wWw.exAmpLE.coM.").unwrap();
1290 name.make_canonical();
1291 assert_eq!(
1292 name,
1293 Name::from_octets(b"\x03www\x07example\x03com\0").unwrap()
1294 );
1295 }
1296
1297 #[test]
1300 fn chain_root() {
1301 assert_eq!(
1302 Name::from_octets(b"\x03www\x07example\x03com\0").unwrap(),
1303 RelativeName::from_octets(b"\x03www\x07example\x03com")
1304 .unwrap()
1305 .chain_root()
1306 );
1307 }
1308
1309 #[test]
1310 fn iter() {
1311 use crate::base::name::absolute::test::cmp_iter;
1312
1313 cmp_iter(RelativeName::empty_ref().iter(), &[]);
1314 cmp_iter(RelativeName::wildcard_ref().iter(), &[b"*"]);
1315 cmp_iter(
1316 RelativeName::from_slice(b"\x03www\x07example\x03com")
1317 .unwrap()
1318 .iter(),
1319 &[b"www", b"example", b"com"],
1320 );
1321 }
1322
1323 #[test]
1324 fn iter_back() {
1325 use crate::base::name::absolute::test::cmp_iter_back;
1326
1327 cmp_iter_back(RelativeName::empty_ref().iter(), &[]);
1328 cmp_iter_back(RelativeName::wildcard_ref().iter(), &[b"*"]);
1329 cmp_iter_back(
1330 RelativeName::from_slice(b"\x03www\x07example\x03com")
1331 .unwrap()
1332 .iter(),
1333 &[b"com", b"example", b"www"],
1334 );
1335 }
1336
1337 #[test]
1338 fn label_count() {
1339 assert_eq!(RelativeName::empty_ref().label_count(), 0);
1340 assert_eq!(RelativeName::wildcard_slice().label_count(), 1);
1341 assert_eq!(
1342 RelativeName::from_slice(b"\x03www\x07example\x03com")
1343 .unwrap()
1344 .label_count(),
1345 3
1346 );
1347 }
1348
1349 #[test]
1350 fn first() {
1351 assert_eq!(RelativeName::empty_slice().first(), None);
1352 assert_eq!(
1353 RelativeName::from_slice(b"\x03www")
1354 .unwrap()
1355 .first()
1356 .unwrap()
1357 .as_slice(),
1358 b"www"
1359 );
1360 assert_eq!(
1361 RelativeName::from_slice(b"\x03www\x07example")
1362 .unwrap()
1363 .first()
1364 .unwrap()
1365 .as_slice(),
1366 b"www"
1367 );
1368 }
1369
1370 #[test]
1371 fn last() {
1372 assert_eq!(RelativeName::empty_slice().last(), None);
1373 assert_eq!(
1374 RelativeName::from_slice(b"\x03www")
1375 .unwrap()
1376 .last()
1377 .unwrap()
1378 .as_slice(),
1379 b"www"
1380 );
1381 assert_eq!(
1382 RelativeName::from_slice(b"\x03www\x07example")
1383 .unwrap()
1384 .last()
1385 .unwrap()
1386 .as_slice(),
1387 b"example"
1388 );
1389 }
1390
1391 #[test]
1392 fn ndots() {
1393 assert_eq!(RelativeName::empty_slice().ndots(), 0);
1394 assert_eq!(RelativeName::from_slice(b"\x03www").unwrap().ndots(), 0);
1395 assert_eq!(
1396 RelativeName::from_slice(b"\x03www\x07example")
1397 .unwrap()
1398 .ndots(),
1399 1
1400 );
1401 }
1402
1403 #[test]
1404 fn starts_with() {
1405 let matrix = [
1406 (
1407 RelativeName::empty_slice(),
1408 [true, false, false, false, false, false],
1409 ),
1410 (
1411 RelativeName::from_slice(b"\x03www").unwrap(),
1412 [true, true, false, false, false, false],
1413 ),
1414 (
1415 RelativeName::from_slice(b"\x03www\x07example").unwrap(),
1416 [true, true, true, false, false, false],
1417 ),
1418 (
1419 RelativeName::from_slice(b"\x03www\x07example\x03com")
1420 .unwrap(),
1421 [true, true, true, true, false, false],
1422 ),
1423 (
1424 RelativeName::from_slice(b"\x07example\x03com").unwrap(),
1425 [true, false, false, false, true, false],
1426 ),
1427 (
1428 RelativeName::from_slice(b"\x03com").unwrap(),
1429 [true, false, false, false, false, true],
1430 ),
1431 ];
1432 for i in 0..6 {
1433 for j in 0..6 {
1434 assert_eq!(
1435 matrix[i].0.starts_with(&matrix[j].0),
1436 matrix[i].1[j],
1437 "i={}, j={}",
1438 i,
1439 j
1440 )
1441 }
1442 }
1443 }
1444
1445 #[test]
1446 fn ends_with() {
1447 let matrix = [
1448 (
1449 RelativeName::empty_slice(),
1450 [true, false, false, false, false, false],
1451 ),
1452 (
1453 RelativeName::from_slice(b"\x03www").unwrap(),
1454 [true, true, false, false, false, false],
1455 ),
1456 (
1457 RelativeName::from_slice(b"\x03www\x07example").unwrap(),
1458 [true, false, true, false, false, false],
1459 ),
1460 (
1461 RelativeName::from_slice(b"\x03www\x07example\x03com")
1462 .unwrap(),
1463 [true, false, false, true, true, true],
1464 ),
1465 (
1466 RelativeName::from_slice(b"\x07example\x03com").unwrap(),
1467 [true, false, false, false, true, true],
1468 ),
1469 (
1470 RelativeName::from_slice(b"\x03com").unwrap(),
1471 [true, false, false, false, false, true],
1472 ),
1473 ];
1474 for i in 0..matrix.len() {
1475 for j in 0..matrix.len() {
1476 assert_eq!(
1477 matrix[i].0.ends_with(&matrix[j].0),
1478 matrix[i].1[j],
1479 "i={}, j={}",
1480 i,
1481 j
1482 )
1483 }
1484 }
1485 }
1486
1487 #[test]
1488 fn is_label_start() {
1489 let wec =
1490 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap();
1491
1492 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)); }
1511
1512 #[test]
1513 #[cfg(feature = "std")]
1514 fn slice() {
1515 let wec =
1516 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap();
1517 assert_eq!(wec.slice(0..4).as_slice(), b"\x03www");
1518 assert_eq!(wec.slice(0..12).as_slice(), b"\x03www\x07example");
1519 assert_eq!(wec.slice(4..12).as_slice(), b"\x07example");
1520 assert_eq!(wec.slice(4..16).as_slice(), b"\x07example\x03com");
1521
1522 assert_panic!(wec.slice(0..3));
1523 assert_panic!(wec.slice(1..4));
1524 assert_panic!(wec.slice(0..11));
1525 assert_panic!(wec.slice(1..12));
1526 assert_panic!(wec.slice(0..17));
1527 assert_panic!(wec.slice(4..17));
1528 assert_panic!(wec.slice(0..18));
1529 }
1530
1531 #[test]
1532 #[cfg(feature = "std")]
1533 fn range() {
1534 let wec =
1535 RelativeName::from_octets(b"\x03www\x07example\x03com".as_ref())
1536 .unwrap();
1537 assert_eq!(wec.range(0..4).as_slice(), b"\x03www");
1538 assert_eq!(wec.range(0..12).as_slice(), b"\x03www\x07example");
1539 assert_eq!(wec.range(4..12).as_slice(), b"\x07example");
1540 assert_eq!(wec.range(4..16).as_slice(), b"\x07example\x03com");
1541
1542 assert_panic!(wec.range(0..3));
1543 assert_panic!(wec.range(1..4));
1544 assert_panic!(wec.range(0..11));
1545 assert_panic!(wec.range(1..12));
1546 assert_panic!(wec.range(0..17));
1547 assert_panic!(wec.range(4..17));
1548 assert_panic!(wec.range(0..18));
1549 }
1550
1551 #[test]
1552 #[cfg(feature = "std")]
1553 fn split() {
1554 let wec =
1555 RelativeName::from_octets(b"\x03www\x07example\x03com".as_ref())
1556 .unwrap();
1557
1558 let (left, right) = wec.split(0);
1559 assert_eq!(left.as_slice(), b"");
1560 assert_eq!(right.as_slice(), b"\x03www\x07example\x03com");
1561
1562 let (left, right) = wec.split(4);
1563 assert_eq!(left.as_slice(), b"\x03www");
1564 assert_eq!(right.as_slice(), b"\x07example\x03com");
1565
1566 let (left, right) = wec.split(12);
1567 assert_eq!(left.as_slice(), b"\x03www\x07example");
1568 assert_eq!(right.as_slice(), b"\x03com");
1569
1570 let (left, right) = wec.split(16);
1571 assert_eq!(left.as_slice(), b"\x03www\x07example\x03com");
1572 assert_eq!(right.as_slice(), b"");
1573
1574 assert_panic!(wec.split(1));
1575 assert_panic!(wec.split(14));
1576 assert_panic!(wec.split(17));
1577 assert_panic!(wec.split(18));
1578 }
1579
1580 #[test]
1581 #[cfg(feature = "std")]
1582 fn truncate() {
1583 let wec =
1584 RelativeName::from_octets(b"\x03www\x07example\x03com".as_ref())
1585 .unwrap();
1586
1587 let mut tmp = wec.clone();
1588 tmp.truncate(0);
1589 assert_eq!(tmp.as_slice(), b"");
1590
1591 let mut tmp = wec.clone();
1592 tmp.truncate(4);
1593 assert_eq!(tmp.as_slice(), b"\x03www");
1594
1595 let mut tmp = wec.clone();
1596 tmp.truncate(12);
1597 assert_eq!(tmp.as_slice(), b"\x03www\x07example");
1598
1599 let mut tmp = wec.clone();
1600 tmp.truncate(16);
1601 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
1602
1603 assert_panic!(wec.clone().truncate(1));
1604 assert_panic!(wec.clone().truncate(14));
1605 assert_panic!(wec.clone().truncate(17));
1606 assert_panic!(wec.clone().truncate(18));
1607 }
1608
1609 #[test]
1610 fn split_first() {
1611 let wec =
1612 RelativeName::from_octets(b"\x03www\x07example\x03com".as_ref())
1613 .unwrap();
1614
1615 let (label, wec) = wec.split_first().unwrap();
1616 assert_eq!(label.as_slice(), b"www");
1617 assert_eq!(wec.as_slice(), b"\x07example\x03com");
1618
1619 let (label, wec) = wec.split_first().unwrap();
1620 assert_eq!(label.as_slice(), b"example");
1621 assert_eq!(wec.as_slice(), b"\x03com");
1622
1623 let (label, wec) = wec.split_first().unwrap();
1624 assert_eq!(label.as_slice(), b"com");
1625 assert_eq!(wec.as_slice(), b"");
1626 assert!(wec.split_first().is_none());
1627 }
1628
1629 #[test]
1630 fn parent() {
1631 let wec =
1632 RelativeName::from_octets(b"\x03www\x07example\x03com".as_ref())
1633 .unwrap();
1634
1635 let wec = wec.parent().unwrap();
1636 assert_eq!(wec.as_slice(), b"\x07example\x03com");
1637
1638 let wec = wec.parent().unwrap();
1639 assert_eq!(wec.as_slice(), b"\x03com");
1640
1641 let wec = wec.parent().unwrap();
1642 assert_eq!(wec.as_slice(), b"");
1643
1644 assert!(wec.parent().is_none());
1645 }
1646
1647 #[test]
1648 fn strip_suffix() {
1649 let wec =
1650 RelativeName::from_octets(b"\x03www\x07example\x03com".as_ref())
1651 .unwrap();
1652 let ec = RelativeName::from_octets(b"\x07example\x03com".as_ref())
1653 .unwrap();
1654 let c = RelativeName::from_octets(b"\x03com".as_ref()).unwrap();
1655 let wen =
1656 RelativeName::from_octets(b"\x03www\x07example\x03net".as_ref())
1657 .unwrap();
1658 let en = RelativeName::from_octets(b"\x07example\x03net".as_ref())
1659 .unwrap();
1660 let n = RelativeName::from_slice(b"\x03net".as_ref()).unwrap();
1661
1662 let mut tmp = wec.clone();
1663 assert_eq!(tmp.strip_suffix(&wec), Ok(()));
1664 assert_eq!(tmp.as_slice(), b"");
1665
1666 let mut tmp = wec.clone();
1667 assert_eq!(tmp.strip_suffix(&ec), Ok(()));
1668 assert_eq!(tmp.as_slice(), b"\x03www");
1669
1670 let mut tmp = wec.clone();
1671 assert_eq!(tmp.strip_suffix(&c), Ok(()));
1672 assert_eq!(tmp.as_slice(), b"\x03www\x07example");
1673
1674 let mut tmp = wec.clone();
1675 assert_eq!(tmp.strip_suffix(&RelativeName::empty_ref()), Ok(()));
1676 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
1677
1678 assert!(wec.clone().strip_suffix(&wen).is_err());
1679 assert!(wec.clone().strip_suffix(&en).is_err());
1680 assert!(wec.clone().strip_suffix(&n).is_err());
1681 }
1682
1683 #[test]
1686 fn eq() {
1687 assert_eq!(
1688 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap(),
1689 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap()
1690 );
1691 assert_eq!(
1692 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap(),
1693 RelativeName::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap()
1694 );
1695 assert_eq!(
1696 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap(),
1697 &RelativeName::from_octets(b"\x03www")
1698 .unwrap()
1699 .chain(
1700 RelativeName::from_octets(b"\x07example\x03com").unwrap()
1701 )
1702 .unwrap()
1703 );
1704 assert_eq!(
1705 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap(),
1706 &RelativeName::from_octets(b"\x03wWw")
1707 .unwrap()
1708 .chain(
1709 RelativeName::from_octets(b"\x07eXAMple\x03coM").unwrap()
1710 )
1711 .unwrap()
1712 );
1713
1714 assert_ne!(
1715 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap(),
1716 RelativeName::from_slice(b"\x03ww4\x07example\x03com").unwrap()
1717 );
1718 assert_ne!(
1719 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap(),
1720 &RelativeName::from_octets(b"\x03www")
1721 .unwrap()
1722 .chain(
1723 RelativeName::from_octets(b"\x073xample\x03com").unwrap()
1724 )
1725 .unwrap()
1726 );
1727 }
1728
1729 #[test]
1730 fn cmp() {
1731 use core::cmp::Ordering;
1732
1733 let names = [
1735 RelativeName::from_slice(b"\x07example").unwrap(),
1736 RelativeName::from_slice(b"\x01a\x07example").unwrap(),
1737 RelativeName::from_slice(b"\x08yljkjljk\x01a\x07example")
1738 .unwrap(),
1739 RelativeName::from_slice(b"\x01Z\x01a\x07example").unwrap(),
1740 RelativeName::from_slice(b"\x04zABC\x01a\x07example").unwrap(),
1741 RelativeName::from_slice(b"\x01z\x07example").unwrap(),
1742 RelativeName::from_slice(b"\x01\x01\x01z\x07example").unwrap(),
1743 RelativeName::from_slice(b"\x01*\x01z\x07example").unwrap(),
1744 RelativeName::from_slice(b"\x01\xc8\x01z\x07example").unwrap(),
1745 ];
1746 for i in 0..names.len() {
1747 for j in 0..names.len() {
1748 let ord = i.cmp(&j);
1749 assert_eq!(names[i].partial_cmp(names[j]), Some(ord));
1750 assert_eq!(names[i].cmp(names[j]), ord);
1751 }
1752 }
1753
1754 let n1 =
1755 RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap();
1756 let n2 =
1757 RelativeName::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap();
1758 assert_eq!(n1.partial_cmp(n2), Some(Ordering::Equal));
1759 assert_eq!(n1.cmp(n2), Ordering::Equal);
1760 }
1761
1762 #[test]
1763 #[cfg(feature = "std")]
1764 fn hash() {
1765 use std::collections::hash_map::DefaultHasher;
1766 use std::hash::{Hash, Hasher};
1767
1768 let mut s1 = DefaultHasher::new();
1769 let mut s2 = DefaultHasher::new();
1770 RelativeName::from_slice(b"\x03www\x07example\x03com")
1771 .unwrap()
1772 .hash(&mut s1);
1773 RelativeName::from_slice(b"\x03wWw\x07eXAMple\x03Com")
1774 .unwrap()
1775 .hash(&mut s2);
1776 assert_eq!(s1.finish(), s2.finish());
1777 }
1778
1779 #[test]
1780 #[cfg(feature = "std")]
1781 fn display() {
1782 use std::string::ToString;
1783
1784 fn cmp(bytes: &[u8], fmt: &str) {
1785 let name = RelativeName::from_octets(bytes).unwrap();
1786 assert_eq!(name.to_string(), fmt);
1787 }
1788
1789 cmp(b"", "");
1790 cmp(b"\x03com", "com");
1791 cmp(b"\x07example\x03com", "example.com");
1792 }
1793
1794 const VALID_NAME: &RelativeName<[u8]> =
1795 match RelativeName::from_slice(b"\x03www\x07example") {
1796 Ok(name) => name,
1797 Err(_) => panic!("VALID_NAME failed at compile time"),
1798 };
1799 const EMPTY_NAME: &RelativeName<[u8]> =
1800 match RelativeName::from_slice(b"") {
1801 Ok(name) => name,
1802 Err(_) => {
1803 panic!("EMPTY_NAME failed at compile time")
1804 }
1805 };
1806 const INVALID_NAME: RelativeNameError =
1807 match RelativeName::from_slice(b"\x03www\x07example\x03com\0") {
1808 Ok(_) => panic!("INVALID_NAME succeeded at compile time"),
1809 Err(err) => err,
1810 };
1811
1812 #[test]
1813 fn const_from_slice() {
1814 assert_eq!(VALID_NAME.as_slice(), b"\x03www\x07example");
1815 assert_eq!(EMPTY_NAME.as_slice(), b"");
1816 assert_eq!(INVALID_NAME, RelativeNameErrorEnum::AbsoluteName.into());
1817 }
1818
1819 #[cfg(all(feature = "serde", feature = "std"))]
1820 #[test]
1821 fn ser_de() {
1822 use serde_test::{assert_tokens, Configure, Token};
1823
1824 let name = RelativeName::from_octets(Vec::from(
1825 b"\x03www\x07example\x03com".as_ref(),
1826 ))
1827 .unwrap();
1828 assert_tokens(
1829 &name.clone().compact(),
1830 &[
1831 Token::NewtypeStruct {
1832 name: "RelativeName",
1833 },
1834 Token::ByteBuf(b"\x03www\x07example\x03com"),
1835 ],
1836 );
1837 assert_tokens(
1838 &name.readable(),
1839 &[
1840 Token::NewtypeStruct {
1841 name: "RelativeName",
1842 },
1843 Token::Str("www.example.com"),
1844 ],
1845 );
1846 }
1847}