domain/base/name/
relative.rs

1//! Uncompressed, relative domain names.
2//!
3//! This is a private module. Its public types are re-exported by the parent.
4
5use 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//------------ RelativeName --------------------------------------------------
27
28/// An uncompressed, relative domain name.
29///
30/// A relative domain name is one that doesn’t end with the root label. As the
31/// name suggests, it is relative to some other domain name. This type wraps
32/// a octets sequence containing such a relative name similarly to the way
33/// [`Name`] wraps an absolute one. In fact, it behaves very similarly to
34/// [`Name`] taking into account differences when slicing and dicing names.
35///
36/// `RelativeName` guarantees that the name is at most 254 bytes long. As the
37/// length limit for a domain name is actually 255 bytes, this means that you
38/// can always safely turn a [`RelativeName`] into a [`Name`] by adding the root
39/// label (which is exactly one byte long).
40#[derive(Clone)]
41#[repr(transparent)]
42pub struct RelativeName<Octs: ?Sized>(Octs);
43
44/// # Creating Values
45///
46impl<Octs> RelativeName<Octs> {
47    /// Creates a relative domain name from octets without checking.
48    ///
49    /// Since the content of the octets sequence can be anything, really,
50    /// this is an unsafe function.
51    ///
52    /// # Safety
53    ///
54    /// The octets sequence passed via `octets` must contain a correctly
55    /// encoded relative domain name. It must be at most 254 octets long.
56    /// There must be no root labels anywhere in the name.
57    pub const unsafe fn from_octets_unchecked(octets: Octs) -> Self {
58        RelativeName(octets)
59    }
60
61    /// Creates a relative domain name from an octets sequence.
62    ///
63    /// This checks that `octets` contains a properly encoded relative domain
64    /// name and fails if it doesn’t.
65    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    /// Creates an empty relative domain name.
74    #[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    /// Creates a relative domain name representing the wildcard label.
83    ///
84    /// The wildcard label is intended to match any label. There are special
85    /// rules for names with wildcard labels. Note that the comparison traits
86    /// implemented for domain names do *not* consider wildcards and treat
87    /// them as regular labels.
88    #[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    /// Creates a domain name from a sequence of characters.
99    ///
100    /// The sequence must result in a domain name in representation format.
101    /// That is, its labels should be separated by dots.
102    /// Actual dots, white space and backslashes should be escaped by a
103    /// preceeding backslash, and any byte value that is not a printable
104    /// ASCII character should be encoded by a backslash followed by its
105    /// three digit decimal value.
106    ///
107    /// If Internationalized Domain Names are to be used, the labels already
108    /// need to be in punycode-encoded form.
109    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    /// Creates a domain name from an octet slice without checking.
130    ///
131    /// # Safety
132    ///
133    /// The same rules as for [`from_octets_unchecked`] apply.
134    ///
135    /// [`from_octets_unchecked`]: RelativeName::from_octets_unchecked
136    pub(super) unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
137        // SAFETY: RelativeName has repr(transparent)
138        mem::transmute(slice)
139    }
140
141    /// Creates a relative domain name from an octet slice.
142    ///
143    /// Note that the input must be in wire format, as shown below.
144    ///
145    /// # Example
146    ///
147    /// ```
148    /// use domain::base::name::RelativeName;
149    /// RelativeName::from_slice(b"\x0c_submissions\x04_tcp");
150    /// ```
151    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    /// Returns an empty relative name atop a unsized slice.
157    #[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    /// Checks whether an octet slice contains a correctly encoded name.
168    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    /// Creates an empty relative name atop a slice reference.
187    #[must_use]
188    pub fn empty_ref() -> Self {
189        Self::empty()
190    }
191
192    /// Creates a wildcard relative name atop a slice reference.
193    #[must_use]
194    pub fn wildcard_ref() -> Self {
195        Self::wildcard()
196    }
197}
198
199#[cfg(feature = "std")]
200impl RelativeName<Vec<u8>> {
201    /// Creates an empty relative name atop a `Vec<u8>`.
202    #[must_use]
203    pub fn empty_vec() -> Self {
204        Self::empty()
205    }
206
207    /// Creates a wildcard relative name atop a `Vec<u8>`.
208    #[must_use]
209    pub fn wildcard_vec() -> Self {
210        Self::wildcard()
211    }
212
213    /// Parses a string into a relative name atop a `Vec<u8>`.
214    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    /// Creates an empty relative name atop a bytes value.
222    pub fn empty_bytes() -> Self {
223        Self::empty()
224    }
225
226    /// Creates a wildcard relative name atop a bytes value.
227    pub fn wildcard_bytes() -> Self {
228        Self::wildcard()
229    }
230
231    /// Parses a string into a relative name atop a `Bytes`.
232    pub fn bytes_from_str(s: &str) -> Result<Self, RelativeFromStrError> {
233        FromStr::from_str(s)
234    }
235}
236
237/// # Conversions
238///
239impl<Octs: ?Sized> RelativeName<Octs> {
240    /// Returns a reference to the underlying octets.
241    pub fn as_octets(&self) -> &Octs {
242        &self.0
243    }
244
245    /// Converts the name into the underlying octets.
246    pub fn into_octets(self) -> Octs
247    where
248        Octs: Sized,
249    {
250        self.0
251    }
252
253    /// Returns a domain name using a reference to the octets.
254    pub fn for_ref(&self) -> RelativeName<&Octs> {
255        unsafe { RelativeName::from_octets_unchecked(&self.0) }
256    }
257
258    /// Returns a reference to an octets slice with the content of the name.
259    pub fn as_slice(&self) -> &[u8]
260    where
261        Octs: AsRef<[u8]>,
262    {
263        self.0.as_ref()
264    }
265
266    /// Returns a domain name for the octets slice of the content.
267    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    /// Converts the name into its canonical form.
275    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    /// Converts the name into a domain name builder for appending data.
285    ///
286    /// This method is only available for octets sequences that have an
287    /// associated octets builder such as `Vec<u8>` or `Bytes`.
288    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    /// Converts the name into an absolute name by appending the root label.
296    ///
297    /// This manipulates the name itself and thus is only available for
298    /// octets sequences that can be converted into an octets builder and back
299    /// such as `Vec<u8>`.
300    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    /// Chains another name to the end of this name.
310    ///
311    /// Depending on whether `other` is an absolute or relative domain name,
312    /// the resulting name will behave like an absolute or relative name.
313    ///
314    /// The method will fail if the combined length of the two names is
315    /// greater than the size limit of 255. Note that in this case you will
316    /// loose both `self` and `other`, so it might be worthwhile to check
317    /// first.
318    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    /// Creates an absolute name by chaining the root label to it.
329    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
337/// # Properties
338///
339impl<Octs: AsRef<[u8]> + ?Sized> RelativeName<Octs> {
340    /// Returns the length of the name.
341    pub fn len(&self) -> usize {
342        self.0.as_ref().len()
343    }
344
345    /// Returns whether the name is empty.
346    pub fn is_empty(&self) -> bool {
347        self.0.as_ref().is_empty()
348    }
349}
350
351/// # Working with Labels
352///
353impl<Octs: AsRef<[u8]> + ?Sized> RelativeName<Octs> {
354    /// Returns an iterator over the labels of the domain name.
355    pub fn iter(&self) -> NameIter {
356        NameIter::new(self.0.as_ref())
357    }
358
359    /// Returns the number of labels in the name.
360    pub fn label_count(&self) -> usize {
361        self.iter().count()
362    }
363
364    /// Returns a reference to the first label if the name isn’t empty.
365    pub fn first(&self) -> Option<&Label> {
366        self.iter().next()
367    }
368
369    /// Returns a reference to the last label if the name isn’t empty.
370    pub fn last(&self) -> Option<&Label> {
371        self.iter().next_back()
372    }
373
374    /// Returns the number of dots in the string representation of the name.
375    ///
376    /// Specifically, returns a value equal to the number of labels minus one,
377    /// except for an empty name where it returns a zero, also.
378    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    /// Determines whether `base` is a prefix of `self`.
387    pub fn starts_with<N: ToLabelIter>(&self, base: &N) -> bool {
388        <Self as ToLabelIter>::starts_with(self, base)
389    }
390
391    /// Determines whether `base` is a suffix of `self`.
392    pub fn ends_with<N: ToLabelIter>(&self, base: &N) -> bool {
393        <Self as ToLabelIter>::ends_with(self, base)
394    }
395
396    /// Returns whether an index points to the first octet of a label.
397    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    /// Like `is_label_start` but panics if it isn’t.
417    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    /// Returns a part of the name indicated by start and end positions.
440    ///
441    /// The returned name will start at position `begin` and end right before
442    /// position `end`. Both positions are given as indexes into the
443    /// underlying octets sequence and must point to the begining of a label.
444    ///
445    /// The method returns a reference to an unsized relative domain name and
446    /// is thus best suited for temporary referencing. If you want to keep the
447    /// part of the name around, [`range`] is likely a better choice.
448    ///
449    /// # Panics
450    ///
451    /// The method panics if either position is not the beginning of a label
452    /// or is out of bounds.
453    ///
454    /// [`range`]: RelativeName::range
455    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    /// Returns a part of the name indicated by start and end positions.
466    ///
467    /// The returned name will start at position `begin` and end right before
468    /// position `end`. Both positions are given as indexes into the
469    /// underlying octets sequence and must point to the begining of a label.
470    ///
471    /// # Panics
472    ///
473    /// The method panics if either position is not the beginning of a label
474    /// or is out of bounds.
475    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    /// Splits the name into two at the given position.
489    ///
490    /// Returns a pair of the left and right part of the split name.
491    ///
492    /// # Panics
493    ///
494    /// The method panics if the position is not the beginning of a label
495    /// or is beyond the end of the name.
496    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    /// Truncates the name to the given length.
513    ///
514    /// # Panics
515    ///
516    /// The method panics if the position is not the beginning of a label
517    /// or is beyond the end of the name.
518    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    /// Splits off the first label.
527    ///
528    /// If there is at least one label in the name, returns the first label
529    /// as a relative domain name with exactly one label and makes `self`
530    /// contain the domain name starting after that first label. If the name
531    /// is empty, returns `None`.
532    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    /// Returns the parent name.
546    ///
547    /// Returns `None` if the name was empty.
548    pub fn parent(&self) -> Option<RelativeName<Octs::Range<'_>>>
549    where
550        Octs: Octets,
551    {
552        self.split_first().map(|(_, parent)| parent)
553    }
554
555    /// Strips the suffix `base` from the domain name.
556    ///
557    /// This will fail if `base` isn’t actually a suffix, i.e., if
558    /// [`ends_with`] doesn’t return `true`.
559    ///
560    /// [`ends_with`]: RelativeName::ends_with
561    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
578//--- AsRef
579
580impl<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
592//--- OctetsFrom
593
594impl<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
608//--- FromStr
609
610impl<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    /// Parses a string into an absolute domain name.
621    ///
622    /// The name needs to be formatted in representation format, i.e., as a
623    /// sequence of labels separated by dots. If Internationalized Domain
624    /// Name (IDN) labels are to be used, these need to be given in punycode
625    /// encoded form.
626    ///
627    /// This implementation will error if the name ends in a dot since that
628    /// indicates an absolute name.
629    fn from_str(s: &str) -> Result<Self, Self::Err> {
630        Self::from_chars(s.chars())
631    }
632}
633
634//--- ToLabelIter and ToRelativeName
635
636impl<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
664//--- IntoIterator
665
666impl<'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
678//--- PartialEq and Eq
679
680impl<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
692//--- PartialOrd and Ord
693
694impl<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
710//--- Hash
711
712impl<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
720//--- Display and Debug
721
722impl<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
743//--- AsRef and Borrow
744
745impl<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
754/// Borrow a relative domain name.
755///
756/// Containers holding an owned `RelativeName<_>` may be queried with name
757/// over a slice. This `Borrow<_>` impl supports user code querying containers
758/// with compatible-but-different types like the following example:
759///
760/// ```
761/// use std::collections::HashMap;
762///
763/// use domain::base::RelativeName;
764///
765/// fn get_description(
766///     hash: &HashMap<RelativeName<Vec<u8>>, String>
767/// ) -> Option<&str> {
768///     let lookup_name: &RelativeName<[u8]> =
769///         RelativeName::from_slice(b"\x03ftp").unwrap();
770///     hash.get(lookup_name).map(|x| x.as_ref())
771/// }
772/// ```
773impl<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//--- Serialize and Deserialize
783
784#[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//------------ NameIter -----------------------------------------------------
906
907/// An iterator over the labels in an uncompressed name.
908#[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//============ Error Types ===================================================
952
953//------------ RelativeNameError --------------------------------------------
954
955/// An error happened while creating a domain name from octets.
956#[derive(Clone, Copy, Debug, Eq, PartialEq)]
957pub struct RelativeNameError(RelativeNameErrorEnum);
958
959#[derive(Clone, Copy, Debug, Eq, PartialEq)]
960enum RelativeNameErrorEnum {
961    /// A bad label was encountered.
962    BadLabel(LabelTypeError),
963
964    /// A compressed name was encountered.
965    CompressedName,
966
967    /// The data ended before the end of a label.
968    ShortInput,
969
970    /// The domain name was longer than 255 octets.
971    LongName,
972
973    /// The root label was encountered.
974    AbsoluteName,
975}
976
977//--- From
978
979impl 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
1003//--- Display and Error
1004
1005impl 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//------------ RelativeFromStrError ------------------------------------------
1029
1030#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1031#[non_exhaustive]
1032pub enum RelativeFromStrError {
1033    /// The name could not be parsed.
1034    FromStr(FromStrError),
1035
1036    /// The parsed name was ended in a dot.
1037    AbsoluteName,
1038}
1039
1040//--- From
1041
1042impl From<FromStrError> for RelativeFromStrError {
1043    fn from(src: FromStrError) -> Self {
1044        Self::FromStr(src)
1045    }
1046}
1047
1048//--- Display and Error
1049
1050impl 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//------------ StripSuffixError ----------------------------------------------
1065
1066/// An attempt was made to strip a suffix that wasn’t actually a suffix.
1067#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1068pub struct StripSuffixError(());
1069
1070//--- Display and Error
1071
1072impl 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//============ Testing =======================================================
1082
1083#[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        // good names
1159        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        // absolute names
1172        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        // bytes shorter than what label length says.
1182        assert_eq!(
1183            RelativeName::from_slice(b"\x03www\x07exa"),
1184            Err(RelativeNameError(RelativeNameErrorEnum::ShortInput))
1185        );
1186
1187        // label 63 long ok, 64 bad.
1188        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        // name 254 long ok, 255 bad.
1196        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        // bad label heads: compressed, other types.
1208        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        // empty name
1226        assert_eq!(RelativeName::vec_from_str("").unwrap().as_slice(), b"");
1227
1228        // relative name
1229        assert_eq!(
1230            RelativeName::vec_from_str("www.example")
1231                .unwrap()
1232                .as_slice(),
1233            b"\x03www\x07example"
1234        );
1235
1236        // absolute name
1237        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        // Check that a 254 octets long relative name converts fine.
1255        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    // chain is tested with the Chain type.
1280
1281    #[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)); // \x03
1475        assert!(!wec.is_label_start(1)); // w
1476        assert!(!wec.is_label_start(2)); // w
1477        assert!(!wec.is_label_start(3)); // w
1478        assert!(wec.is_label_start(4)); // \x07
1479        assert!(!wec.is_label_start(5)); // e
1480        assert!(!wec.is_label_start(6)); // x
1481        assert!(!wec.is_label_start(7)); // a
1482        assert!(!wec.is_label_start(8)); // m
1483        assert!(!wec.is_label_start(9)); // p
1484        assert!(!wec.is_label_start(10)); // l
1485        assert!(!wec.is_label_start(11)); // e
1486        assert!(wec.is_label_start(12)); // \x03
1487        assert!(!wec.is_label_start(13)); // c
1488        assert!(!wec.is_label_start(14)); // o
1489        assert!(!wec.is_label_start(15)); // m
1490        assert!(wec.is_label_start(16)); // empty label
1491        assert!(!wec.is_label_start(17)); //
1492    }
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    // No test for Compose since the implementation is so simple.
1666
1667    #[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        // The following is taken from section 6.1 of RFC 4034.
1716        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}