Skip to main content

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) const 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 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    /// Returns an empty relative name atop a unsized slice.
161    #[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    /// Checks whether an octet slice contains a correctly encoded name.
172    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    /// Creates an empty relative name atop a slice reference.
208    #[must_use]
209    pub fn empty_ref() -> Self {
210        Self::empty()
211    }
212
213    /// Creates a wildcard relative name atop a slice reference.
214    #[must_use]
215    pub fn wildcard_ref() -> Self {
216        Self::wildcard()
217    }
218}
219
220#[cfg(feature = "std")]
221impl RelativeName<Vec<u8>> {
222    /// Creates an empty relative name atop a `Vec<u8>`.
223    #[must_use]
224    pub fn empty_vec() -> Self {
225        Self::empty()
226    }
227
228    /// Creates a wildcard relative name atop a `Vec<u8>`.
229    #[must_use]
230    pub fn wildcard_vec() -> Self {
231        Self::wildcard()
232    }
233
234    /// Parses a string into a relative name atop a `Vec<u8>`.
235    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    /// Creates an empty relative name atop a bytes value.
243    pub fn empty_bytes() -> Self {
244        Self::empty()
245    }
246
247    /// Creates a wildcard relative name atop a bytes value.
248    pub fn wildcard_bytes() -> Self {
249        Self::wildcard()
250    }
251
252    /// Parses a string into a relative name atop a `Bytes`.
253    pub fn bytes_from_str(s: &str) -> Result<Self, RelativeFromStrError> {
254        FromStr::from_str(s)
255    }
256}
257
258/// # Conversions
259///
260impl<Octs: ?Sized> RelativeName<Octs> {
261    /// Returns a reference to the underlying octets.
262    pub fn as_octets(&self) -> &Octs {
263        &self.0
264    }
265
266    /// Converts the name into the underlying octets.
267    pub fn into_octets(self) -> Octs
268    where
269        Octs: Sized,
270    {
271        self.0
272    }
273
274    /// Returns a domain name using a reference to the octets.
275    pub fn for_ref(&self) -> RelativeName<&Octs> {
276        unsafe { RelativeName::from_octets_unchecked(&self.0) }
277    }
278
279    /// Returns a reference to an octets slice with the content of the name.
280    pub fn as_slice(&self) -> &[u8]
281    where
282        Octs: AsRef<[u8]>,
283    {
284        self.0.as_ref()
285    }
286
287    /// Returns a domain name for the octets slice of the content.
288    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    /// Converts the name into its canonical form.
296    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    /// Converts the name into a domain name builder for appending data.
306    ///
307    /// This method is only available for octets sequences that have an
308    /// associated octets builder such as `Vec<u8>` or `Bytes`.
309    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    /// Converts the name into an absolute name by appending the root label.
317    ///
318    /// This manipulates the name itself and thus is only available for
319    /// octets sequences that can be converted into an octets builder and back
320    /// such as `Vec<u8>`.
321    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    /// Chains another name to the end of this name.
331    ///
332    /// Depending on whether `other` is an absolute or relative domain name,
333    /// the resulting name will behave like an absolute or relative name.
334    ///
335    /// The method will fail if the combined length of the two names is
336    /// greater than the size limit of 255. Note that in this case you will
337    /// loose both `self` and `other`, so it might be worthwhile to check
338    /// first.
339    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    /// Creates an absolute name by chaining the root label to it.
350    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
358/// # Properties
359///
360impl<Octs: AsRef<[u8]> + ?Sized> RelativeName<Octs> {
361    /// Returns the length of the name.
362    pub fn len(&self) -> usize {
363        self.0.as_ref().len()
364    }
365
366    /// Returns whether the name is empty.
367    pub fn is_empty(&self) -> bool {
368        self.0.as_ref().is_empty()
369    }
370}
371
372/// # Working with Labels
373///
374impl<Octs: AsRef<[u8]> + ?Sized> RelativeName<Octs> {
375    /// Returns an iterator over the labels of the domain name.
376    pub fn iter(&self) -> NameIter<'_> {
377        NameIter::new(self.0.as_ref())
378    }
379
380    /// Returns the number of labels in the name.
381    pub fn label_count(&self) -> usize {
382        self.iter().count()
383    }
384
385    /// Returns a reference to the first label if the name isn’t empty.
386    pub fn first(&self) -> Option<&Label> {
387        self.iter().next()
388    }
389
390    /// Returns a reference to the last label if the name isn’t empty.
391    pub fn last(&self) -> Option<&Label> {
392        self.iter().next_back()
393    }
394
395    /// Returns the number of dots in the string representation of the name.
396    ///
397    /// Specifically, returns a value equal to the number of labels minus one,
398    /// except for an empty name where it returns a zero, also.
399    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    /// Determines whether `base` is a prefix of `self`.
408    pub fn starts_with<N: ToLabelIter>(&self, base: &N) -> bool {
409        <Self as ToLabelIter>::starts_with(self, base)
410    }
411
412    /// Determines whether `base` is a suffix of `self`.
413    pub fn ends_with<N: ToLabelIter>(&self, base: &N) -> bool {
414        <Self as ToLabelIter>::ends_with(self, base)
415    }
416
417    /// Returns whether an index points to the first octet of a label.
418    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    /// Like `is_label_start` but panics if it isn’t.
438    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    /// Returns a part of the name indicated by start and end positions.
461    ///
462    /// The returned name will start at position `begin` and end right before
463    /// position `end`. Both positions are given as indexes into the
464    /// underlying octets sequence and must point to the begining of a label.
465    ///
466    /// The method returns a reference to an unsized relative domain name and
467    /// is thus best suited for temporary referencing. If you want to keep the
468    /// part of the name around, [`range`] is likely a better choice.
469    ///
470    /// # Panics
471    ///
472    /// The method panics if either position is not the beginning of a label
473    /// or is out of bounds.
474    ///
475    /// [`range`]: RelativeName::range
476    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    /// Returns a part of the name indicated by start and end positions.
487    ///
488    /// The returned name will start at position `begin` and end right before
489    /// position `end`. Both positions are given as indexes into the
490    /// underlying octets sequence and must point to the begining of a label.
491    ///
492    /// # Panics
493    ///
494    /// The method panics if either position is not the beginning of a label
495    /// or is out of bounds.
496    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    /// Splits the name into two at the given position.
510    ///
511    /// Returns a pair of the left and right part of the split name.
512    ///
513    /// # Panics
514    ///
515    /// The method panics if the position is not the beginning of a label
516    /// or is beyond the end of the name.
517    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    /// Truncates the name to the given length.
534    ///
535    /// # Panics
536    ///
537    /// The method panics if the position is not the beginning of a label
538    /// or is beyond the end of the name.
539    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    /// Splits off the first label.
548    ///
549    /// If there is at least one label in the name, returns the first label
550    /// as a relative domain name with exactly one label and makes `self`
551    /// contain the domain name starting after that first label. If the name
552    /// is empty, returns `None`.
553    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    /// Returns the parent name.
567    ///
568    /// Returns `None` if the name was empty.
569    pub fn parent(&self) -> Option<RelativeName<Octs::Range<'_>>>
570    where
571        Octs: Octets,
572    {
573        self.split_first().map(|(_, parent)| parent)
574    }
575
576    /// Strips the suffix `base` from the domain name.
577    ///
578    /// This will fail if `base` isn’t actually a suffix, i.e., if
579    /// [`ends_with`] doesn’t return `true`.
580    ///
581    /// [`ends_with`]: RelativeName::ends_with
582    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
599//--- AsRef
600
601impl<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
613//--- OctetsFrom
614
615impl<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
629//--- FromStr
630
631impl<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    /// Parses a string into an absolute domain name.
642    ///
643    /// The name needs to be formatted in representation format, i.e., as a
644    /// sequence of labels separated by dots. If Internationalized Domain
645    /// Name (IDN) labels are to be used, these need to be given in punycode
646    /// encoded form.
647    ///
648    /// This implementation will error if the name ends in a dot since that
649    /// indicates an absolute name.
650    fn from_str(s: &str) -> Result<Self, Self::Err> {
651        Self::from_chars(s.chars())
652    }
653}
654
655//--- ToLabelIter and ToRelativeName
656
657impl<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
685//--- IntoIterator
686
687impl<'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
699//--- PartialEq and Eq
700
701impl<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
713//--- PartialOrd and Ord
714
715impl<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
731//--- Hash
732
733impl<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
741//--- Display and Debug
742
743impl<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
764//--- AsRef and Borrow
765
766impl<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
775/// Borrow a relative domain name.
776///
777/// Containers holding an owned `RelativeName<_>` may be queried with name
778/// over a slice. This `Borrow<_>` impl supports user code querying containers
779/// with compatible-but-different types like the following example:
780///
781/// ```
782/// use std::collections::HashMap;
783///
784/// use domain::base::RelativeName;
785///
786/// fn get_description(
787///     hash: &HashMap<RelativeName<Vec<u8>>, String>
788/// ) -> Option<&str> {
789///     let lookup_name: &RelativeName<[u8]> =
790///         RelativeName::from_slice(b"\x03ftp").unwrap();
791///     hash.get(lookup_name).map(|x| x.as_ref())
792/// }
793/// ```
794impl<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//--- Serialize and Deserialize
804
805#[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//------------ NameIter -----------------------------------------------------
927
928/// An iterator over the labels in an uncompressed name.
929#[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//============ Error Types ===================================================
973
974//------------ RelativeNameError --------------------------------------------
975
976/// An error happened while creating a domain name from octets.
977#[derive(Clone, Copy, Debug, Eq, PartialEq)]
978pub struct RelativeNameError(RelativeNameErrorEnum);
979
980#[derive(Clone, Copy, Debug, Eq, PartialEq)]
981enum RelativeNameErrorEnum {
982    /// A bad label was encountered.
983    BadLabel(LabelTypeError),
984
985    /// A compressed name was encountered.
986    CompressedName,
987
988    /// The data ended before the end of a label.
989    ShortInput,
990
991    /// The domain name was longer than 255 octets.
992    LongName,
993
994    /// The root label was encountered.
995    AbsoluteName,
996}
997
998//--- From
999
1000impl 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
1024//--- Display and Error
1025
1026impl 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//------------ RelativeFromStrError ------------------------------------------
1049
1050#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1051#[non_exhaustive]
1052pub enum RelativeFromStrError {
1053    /// The name could not be parsed.
1054    FromStr(FromStrError),
1055
1056    /// The parsed name was ended in a dot.
1057    AbsoluteName,
1058}
1059
1060//--- From
1061
1062impl From<FromStrError> for RelativeFromStrError {
1063    fn from(src: FromStrError) -> Self {
1064        Self::FromStr(src)
1065    }
1066}
1067
1068//--- Display and Error
1069
1070impl 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//------------ StripSuffixError ----------------------------------------------
1084
1085/// An attempt was made to strip a suffix that wasn’t actually a suffix.
1086#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1087pub struct StripSuffixError(());
1088
1089//--- Display and Error
1090
1091impl 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//============ Testing =======================================================
1100
1101#[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        // good names
1177        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        // absolute names
1190        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        // bytes shorter than what label length says.
1200        assert_eq!(
1201            RelativeName::from_slice(b"\x03www\x07exa"),
1202            Err(RelativeNameError(RelativeNameErrorEnum::ShortInput))
1203        );
1204
1205        // label 63 long ok, 64 bad.
1206        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        // name 254 long ok, 255 bad.
1214        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        // bad label heads: compressed, other types.
1226        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        // empty name
1244        assert_eq!(RelativeName::vec_from_str("").unwrap().as_slice(), b"");
1245
1246        // relative name
1247        assert_eq!(
1248            RelativeName::vec_from_str("www.example")
1249                .unwrap()
1250                .as_slice(),
1251            b"\x03www\x07example"
1252        );
1253
1254        // absolute name
1255        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        // Check that a 254 octets long relative name converts fine.
1273        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    // chain is tested with the Chain type.
1298
1299    #[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)); // \x03
1493        assert!(!wec.is_label_start(1)); // w
1494        assert!(!wec.is_label_start(2)); // w
1495        assert!(!wec.is_label_start(3)); // w
1496        assert!(wec.is_label_start(4)); // \x07
1497        assert!(!wec.is_label_start(5)); // e
1498        assert!(!wec.is_label_start(6)); // x
1499        assert!(!wec.is_label_start(7)); // a
1500        assert!(!wec.is_label_start(8)); // m
1501        assert!(!wec.is_label_start(9)); // p
1502        assert!(!wec.is_label_start(10)); // l
1503        assert!(!wec.is_label_start(11)); // e
1504        assert!(wec.is_label_start(12)); // \x03
1505        assert!(!wec.is_label_start(13)); // c
1506        assert!(!wec.is_label_start(14)); // o
1507        assert!(!wec.is_label_start(15)); // m
1508        assert!(wec.is_label_start(16)); // empty label
1509        assert!(!wec.is_label_start(17)); //
1510    }
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    // No test for Compose since the implementation is so simple.
1684
1685    #[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        // The following is taken from section 6.1 of RFC 4034.
1734        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}