domain/base/name/
parsed.rs

1//! Parsed domain names.
2//!
3//! This is a private module. Its public types are re-exported by the parent
4//! module.
5
6use super::super::cmp::CanonicalOrd;
7use super::super::wire::{FormError, ParseError};
8use super::absolute::Name;
9use super::label::{Label, LabelTypeError};
10use super::relative::RelativeName;
11use super::traits::{FlattenInto, ToLabelIter, ToName};
12use core::{cmp, fmt, hash};
13use octseq::builder::{
14    BuilderAppendError, EmptyBuilder, FreezeBuilder, FromBuilder,
15    OctetsBuilder,
16};
17use octseq::octets::Octets;
18use octseq::parse::Parser;
19
20//------------ ParsedName ----------------------------------------------------
21
22/// A domain name parsed from a DNS message.
23///
24/// In an attempt to keep messages small, DNS uses a procedure called ‘name
25/// compression.’ It tries to minimize the space used for repeatedly
26/// appearing domain names by simply refering to the first occurence of the
27/// name. This works not only for complete names but also for suffixes. In
28/// this case, the first unique labels of the name are included and then a
29/// pointer is included for the remainder of the name.
30///
31/// A consequence of this is that when parsing a domain name, its labels can
32/// be scattered all over the message and we would need to allocate some
33/// space to re-assemble the original name. However, in many cases we don’t
34/// need the complete name. Many operations can be performed by just
35/// iterating over the labels which we can do in place.
36///
37/// [`ParsedName`] deals with such names. It takes a copy of a [`Parser`]
38/// representing a reference to the underlying DNS message and, if nedded,
39/// traverses over the name starting at the current position of the parser.
40/// When being created, the type quickly walks over the name to check that it
41/// is, indeed, a valid name. While this does take a bit of time, it spares
42/// you having to deal with possible parse errors later on.
43///
44/// [`ParsedName`] implementes the [`ToName`] trait, so you can use it
45/// everywhere where a generic absolute domain name is accepted. In
46/// particular, you can compare it to other names or chain it to the end of a
47/// relative name. If necessary, [`ToName::to_name`] can be used to produce
48/// a flat, self-contained [`Name`].
49#[derive(Clone, Copy)]
50pub struct ParsedName<Octs> {
51    /// The octets the name is embedded in.
52    ///
53    /// This needs to be the full message as compression pointers in the name
54    /// are indexes into this sequence.
55    octets: Octs,
56
57    /// The start position of the name within `octets`.
58    pos: usize,
59
60    /// The length of the uncompressed name in octets.
61    ///
62    /// We need this for implementing [`ToLabelIter`].
63    name_len: u16,
64
65    /// Whether the name is compressed.
66    ///
67    /// This allows various neat optimizations for the case where it isn’t.
68    compressed: bool,
69}
70
71impl<Octs> ParsedName<Octs> {
72    /// Returns whether the name is compressed.
73    pub fn is_compressed(&self) -> bool {
74        self.compressed
75    }
76
77    /// Returns whether the name is the root label only.
78    pub fn is_root(&self) -> bool {
79        self.name_len == 1
80    }
81
82    /// Returns a correctly positioned parser.
83    fn parser(&self) -> Parser<Octs>
84    where
85        Octs: AsRef<[u8]>,
86    {
87        let mut res = Parser::from_ref(&self.octets);
88        res.advance(self.pos).expect("illegal pos in ParsedName");
89        res
90    }
91
92    /// Returns an equivalent name for a reference to the contained octets.
93    pub fn ref_octets(&self) -> ParsedName<&Octs> {
94        ParsedName {
95            octets: &self.octets,
96            pos: self.pos,
97            name_len: self.name_len,
98            compressed: self.compressed,
99        }
100    }
101}
102
103impl<'a, Octs: Octets + ?Sized> ParsedName<&'a Octs> {
104    #[must_use]
105    pub fn deref_octets(&self) -> ParsedName<Octs::Range<'a>> {
106        ParsedName {
107            octets: self.octets.range(..),
108            pos: self.pos,
109            name_len: self.name_len,
110            compressed: self.compressed,
111        }
112    }
113}
114
115/// # Working with Labels
116///
117impl<Octs: AsRef<[u8]>> ParsedName<Octs> {
118    /// Returns an iterator over the labels of the name.
119    pub fn iter(&self) -> ParsedNameIter {
120        ParsedNameIter::new(self.octets.as_ref(), self.pos, self.name_len)
121    }
122
123    /// Returns an iterator over the suffixes of the name.
124    ///
125    /// The returned iterator starts with the full name and then for each
126    /// additional step returns a name with the left-most label stripped off
127    /// until it reaches the root label.
128    pub fn iter_suffixes(&self) -> ParsedSuffixIter<Octs> {
129        ParsedSuffixIter::new(self)
130    }
131
132    /// Returns the number of labels in the domain name.
133    pub fn label_count(&self) -> usize {
134        self.iter().count()
135    }
136
137    /// Returns a reference to the first label.
138    pub fn first(&self) -> &Label {
139        self.iter().next().unwrap()
140    }
141
142    /// Returns a reference to the last label.
143    ///
144    /// Because the last label in an absolute name is always the root label,
145    /// this method can return a static reference. It is also a wee bit silly,
146    /// but here for completeness.
147    pub fn last(&self) -> &'static Label {
148        Label::root()
149    }
150
151    /// Determines whether `base` is a prefix of `self`.
152    pub fn starts_with<N: ToLabelIter>(&self, base: &N) -> bool {
153        <Self as ToLabelIter>::starts_with(self, base)
154    }
155
156    /// Determines whether `base` is a suffix of `self`.
157    pub fn ends_with<N: ToLabelIter>(&self, base: &N) -> bool {
158        <Self as ToLabelIter>::ends_with(self, base)
159    }
160
161    /// Splits off the first label.
162    ///
163    /// If this name is longer than just the root label, returns the first
164    /// label as a relative name and removes it from the name itself. If the
165    /// name is only the root label, returns `None` and does nothing.
166    pub fn split_first(&mut self) -> Option<RelativeName<Octs::Range<'_>>>
167    where
168        Octs: Octets,
169    {
170        if self.name_len == 1 {
171            return None;
172        }
173        let mut name_len = self.name_len;
174        let range = {
175            let mut parser = self.parser();
176            let len = loop {
177                match LabelType::peek(&parser).unwrap() {
178                    LabelType::Normal(0) => {
179                        unreachable!()
180                    }
181                    LabelType::Normal(label_len) => break label_len + 1,
182                    LabelType::Compressed(pos) => {
183                        parser.seek(pos).unwrap();
184                    }
185                }
186            };
187            name_len -= len;
188            parser.pos()..parser.pos() + usize::from(len)
189        };
190        self.pos = range.end;
191        self.name_len = name_len;
192        Some(unsafe {
193            RelativeName::from_octets_unchecked(self.octets.range(range))
194        })
195    }
196
197    /// Reduces the name to the parent of the current name.
198    ///
199    /// If the name consists of the root label only, returns `false` and does
200    /// nothing. Otherwise, drops the first label and returns `true`.
201    pub fn parent(&mut self) -> bool {
202        if self.name_len == 1 {
203            return false;
204        }
205        let (pos, len) = {
206            let mut parser = self.parser();
207            let len = loop {
208                match LabelType::peek(&parser).unwrap() {
209                    LabelType::Normal(0) => {
210                        unreachable!()
211                    }
212                    LabelType::Normal(label_len) => break label_len + 1,
213                    LabelType::Compressed(pos) => {
214                        parser.seek(pos).unwrap();
215                    }
216                }
217            };
218            (parser.pos() + usize::from(len), len)
219        };
220        self.name_len -= len;
221        self.pos = pos;
222        true
223    }
224}
225
226impl<Octs> ParsedName<Octs> {
227    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
228        parser: &mut Parser<'a, Src>,
229    ) -> Result<Self, ParseError> {
230        ParsedName::parse_ref(parser).map(|res| res.deref_octets())
231    }
232}
233
234impl<'a, Octs: AsRef<[u8]> + ?Sized> ParsedName<&'a Octs> {
235    pub fn parse_ref(
236        parser: &mut Parser<'a, Octs>,
237    ) -> Result<Self, ParseError> {
238        let mut name_len = 0;
239        let mut pos = parser.pos();
240
241        // Phase One: No compression pointers have been found yet.
242        //
243        // Parse labels. If we encounter the root label, return an
244        // uncompressed name. Otherwise continue to phase two.
245        let mut ptr = loop {
246            match LabelType::parse(parser)? {
247                LabelType::Normal(0) => {
248                    // Root label.
249                    name_len += 1;
250                    return Ok(ParsedName {
251                        octets: parser.octets_ref(),
252                        pos,
253                        name_len,
254                        compressed: false,
255                    });
256                }
257                LabelType::Normal(label_len) => {
258                    parser.advance(usize::from(label_len))?;
259                    name_len += label_len + 1;
260                    if name_len >= 255 {
261                        return Err(ParsedDnameError::LongName.into());
262                    }
263                }
264                LabelType::Compressed(ptr) => {
265                    break ptr;
266                }
267            }
268        };
269
270        // Phase Two: Compression has occured.
271        //
272        // Now we need to add up label lengths until we encounter the root
273        // label or the name becomes too long.
274        //
275        // We are going to work on a temporary parser so we can jump around.
276        // The actual parser has already reached the end of the name, so we
277        // can just shadow it. (Because parsers are copy, dereferencing them
278        // clones them.)
279        let mut parser = *parser;
280        let mut compressed = true;
281        loop {
282            // Check that the compression pointer points backwards. Because
283            // it is 16 bit long and the current position is behind the label
284            // header, it needs to less than the current position minus 2 --
285            // less so can’t point to itself.
286            if ptr >= parser.pos() - 2 {
287                return Err(ParsedDnameError::ExcessiveCompression.into());
288            }
289
290            // If this is the first label, the returned name may as well start
291            // here.
292            if name_len == 0 {
293                pos = ptr;
294                compressed = false;
295            }
296
297            // Reposition and read next label.
298            parser.seek(ptr)?;
299
300            loop {
301                match LabelType::parse(&mut parser)? {
302                    LabelType::Normal(0) => {
303                        // Root label.
304                        name_len += 1;
305                        return Ok(ParsedName {
306                            octets: parser.octets_ref(),
307                            pos,
308                            name_len,
309                            compressed,
310                        });
311                    }
312                    LabelType::Normal(label_len) => {
313                        parser.advance(usize::from(label_len))?;
314                        name_len += label_len + 1;
315                        if name_len >= 255 {
316                            return Err(ParsedDnameError::LongName.into());
317                        }
318                    }
319                    LabelType::Compressed(new_ptr) => {
320                        ptr = new_ptr;
321                        compressed = true;
322                        break;
323                    }
324                }
325            }
326        }
327    }
328}
329
330impl ParsedName<()> {
331    /// Skip over a domain name.
332    ///
333    /// This will only check the uncompressed part of the name. If the name
334    /// is compressed but the compression pointer is invalid or the name
335    /// pointed to is invalid or too long, the function will still succeed.
336    ///
337    /// If you need to check that the name you are skipping over is valid, you
338    /// will have to use `parse` and drop the result.
339    pub fn skip<Src: AsRef<[u8]> + ?Sized>(
340        parser: &mut Parser<Src>,
341    ) -> Result<(), ParseError> {
342        let mut len = 0;
343        loop {
344            match LabelType::parse(parser) {
345                Ok(LabelType::Normal(0)) => {
346                    len += 1;
347                    if len > 255 {
348                        return Err(ParsedDnameError::LongName.into());
349                    }
350                    return Ok(());
351                }
352                Ok(LabelType::Normal(label_len)) => {
353                    parser.advance(label_len.into())?;
354                    len += label_len + 1;
355                    if len > 255 {
356                        return Err(ParsedDnameError::LongName.into());
357                    }
358                }
359                Ok(LabelType::Compressed(_)) => return Ok(()),
360                Err(err) => return Err(err),
361            }
362        }
363    }
364}
365
366//--- From
367
368impl<Octs: AsRef<[u8]>> From<Name<Octs>> for ParsedName<Octs> {
369    fn from(name: Name<Octs>) -> ParsedName<Octs> {
370        let name_len = name.compose_len();
371        ParsedName {
372            octets: name.into_octets(),
373            pos: 0,
374            name_len,
375            compressed: false,
376        }
377    }
378}
379
380//--- FlattenInto
381
382impl<Octs, Target> FlattenInto<Name<Target>> for ParsedName<Octs>
383where
384    Octs: Octets,
385    Target: FromBuilder,
386    <Target as FromBuilder>::Builder: EmptyBuilder,
387{
388    type AppendError = BuilderAppendError<Target>;
389
390    fn try_flatten_into(self) -> Result<Name<Target>, Self::AppendError> {
391        let mut builder =
392            Target::Builder::with_capacity(self.compose_len().into());
393        if let Some(slice) = self.as_flat_slice() {
394            builder.append_slice(slice)?;
395        } else {
396            self.iter_labels()
397                .try_for_each(|label| label.compose(&mut builder))?;
398        }
399        Ok(unsafe { Name::from_octets_unchecked(builder.freeze()) })
400    }
401}
402
403//--- PartialEq and Eq
404
405impl<Octs, N> PartialEq<N> for ParsedName<Octs>
406where
407    Octs: AsRef<[u8]>,
408    N: ToName + ?Sized,
409{
410    fn eq(&self, other: &N) -> bool {
411        self.name_eq(other)
412    }
413}
414
415impl<Octs: AsRef<[u8]>> Eq for ParsedName<Octs> {}
416
417//--- PartialOrd, Ord, and CanonicalOrd
418
419impl<Octs, N> PartialOrd<N> for ParsedName<Octs>
420where
421    Octs: AsRef<[u8]>,
422    N: ToName + ?Sized,
423{
424    fn partial_cmp(&self, other: &N) -> Option<cmp::Ordering> {
425        Some(self.name_cmp(other))
426    }
427}
428
429impl<Octs: AsRef<[u8]>> Ord for ParsedName<Octs> {
430    fn cmp(&self, other: &Self) -> cmp::Ordering {
431        self.name_cmp(other)
432    }
433}
434
435impl<Octs, N> CanonicalOrd<N> for ParsedName<Octs>
436where
437    Octs: AsRef<[u8]>,
438    N: ToName + ?Sized,
439{
440    fn canonical_cmp(&self, other: &N) -> cmp::Ordering {
441        self.name_cmp(other)
442    }
443}
444
445//--- Hash
446
447impl<Octs: AsRef<[u8]>> hash::Hash for ParsedName<Octs> {
448    fn hash<H: hash::Hasher>(&self, state: &mut H) {
449        for item in self.iter() {
450            item.hash(state)
451        }
452    }
453}
454
455//--- ToLabelIter and ToName
456
457impl<Octs: AsRef<[u8]>> ToLabelIter for ParsedName<Octs> {
458    type LabelIter<'s>
459        = ParsedNameIter<'s>
460    where
461        Octs: 's;
462
463    fn iter_labels(&self) -> Self::LabelIter<'_> {
464        self.iter()
465    }
466
467    fn compose_len(&self) -> u16 {
468        self.name_len
469    }
470}
471
472impl<Octs: AsRef<[u8]>> ToName for ParsedName<Octs> {
473    fn as_flat_slice(&self) -> Option<&[u8]> {
474        if self.compressed {
475            None
476        } else {
477            Some(
478                &self.octets.as_ref()
479                    [self.pos..self.pos + usize::from(self.name_len)],
480            )
481        }
482    }
483}
484
485//--- IntoIterator
486
487impl<'a, Octs> IntoIterator for &'a ParsedName<Octs>
488where
489    Octs: AsRef<[u8]>,
490{
491    type Item = &'a Label;
492    type IntoIter = ParsedNameIter<'a>;
493
494    fn into_iter(self) -> Self::IntoIter {
495        self.iter()
496    }
497}
498
499//--- Display and Debug
500
501impl<Octs: AsRef<[u8]>> fmt::Display for ParsedName<Octs> {
502    /// Formats the domain name.
503    ///
504    /// This will produce the domain name in common display format without
505    /// the trailing dot.
506    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
507        let mut iter = self.iter();
508        write!(f, "{}", iter.next().unwrap())?;
509        for label in iter {
510            if !label.is_root() {
511                write!(f, ".{}", label)?
512            }
513        }
514        Ok(())
515    }
516}
517
518impl<Octs: AsRef<[u8]>> fmt::Debug for ParsedName<Octs> {
519    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
520        write!(f, "ParsedName({}.)", self)
521    }
522}
523
524//--- Serialize
525
526#[cfg(feature = "serde")]
527impl<Octs: AsRef<[u8]>> serde::Serialize for ParsedName<Octs> {
528    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
529    where
530        S: serde::Serializer,
531    {
532        serializer.collect_str(self)
533    }
534}
535
536//------------ ParsedNameIter -----------------------------------------------
537
538/// An iterator over the labels in a parsed domain name.
539#[derive(Clone)]
540pub struct ParsedNameIter<'a> {
541    slice: &'a [u8],
542    pos: usize,
543    len: u16,
544}
545
546impl<'a> ParsedNameIter<'a> {
547    /// Creates a new iterator from the parser and the name length.
548    ///
549    /// The parser must be positioned at the beginning of the name.
550    pub(crate) fn new(slice: &'a [u8], pos: usize, len: u16) -> Self {
551        ParsedNameIter { slice, pos, len }
552    }
553
554    /// Returns the next label.
555    ///
556    /// This just assumes that there is a label at the current beginning
557    /// of the parser. This may lead to funny results if there isn’t,
558    /// including panics if the label head is illegal or points beyond the
559    /// end of the message.
560    fn get_label(&mut self) -> &'a Label {
561        let end = loop {
562            let ltype = self.slice[self.pos];
563            self.pos += 1;
564            match ltype {
565                0..=0x3F => break self.pos + (ltype as usize),
566                0xC0..=0xFF => {
567                    self.pos = (self.slice[self.pos] as usize)
568                        | (((ltype as usize) & 0x3F) << 8);
569                }
570                _ => panic!("bad label"),
571            }
572        };
573        let res = unsafe {
574            Label::from_slice_unchecked(&self.slice[self.pos..end])
575        };
576        self.pos = end;
577        self.len -= res.compose_len();
578        res
579    }
580}
581
582impl<'a> Iterator for ParsedNameIter<'a> {
583    type Item = &'a Label;
584
585    fn next(&mut self) -> Option<&'a Label> {
586        if self.len == 0 {
587            return None;
588        }
589        Some(self.get_label())
590    }
591}
592
593impl<'a> DoubleEndedIterator for ParsedNameIter<'a> {
594    fn next_back(&mut self) -> Option<&'a Label> {
595        if self.len == 0 {
596            return None;
597        }
598        let mut tmp = self.clone();
599        let label = loop {
600            let label = tmp.get_label();
601            if tmp.len == 0 {
602                break label;
603            }
604        };
605        self.len -= label.compose_len();
606        Some(label)
607    }
608}
609
610//------------ ParsedSuffixIter ----------------------------------------------
611
612/// An iterator over ever shorter suffixes of a parsed domain name.
613#[derive(Clone)]
614pub struct ParsedSuffixIter<'a, Octs: ?Sized> {
615    name: Option<ParsedName<&'a Octs>>,
616}
617
618impl<'a, Octs> ParsedSuffixIter<'a, Octs> {
619    /// Creates a new iterator cloning `name`.
620    fn new(name: &'a ParsedName<Octs>) -> Self {
621        ParsedSuffixIter {
622            name: Some(name.ref_octets()),
623        }
624    }
625}
626
627impl<'a, Octs: Octets + ?Sized> Iterator for ParsedSuffixIter<'a, Octs> {
628    type Item = ParsedName<Octs::Range<'a>>;
629
630    fn next(&mut self) -> Option<Self::Item> {
631        let name = match self.name {
632            Some(ref mut name) => name,
633            None => return None,
634        };
635        let res = name.deref_octets();
636        if !name.parent() {
637            self.name = None
638        }
639        Some(res)
640    }
641}
642
643//------------ LabelType -----------------------------------------------------
644
645/// The type of a label.
646#[derive(Clone, Copy, Debug, Eq, PartialEq)]
647enum LabelType {
648    /// A normal label with its size in octets.
649    Normal(u16),
650
651    /// A compressed label with the position of where to continue.
652    Compressed(usize),
653}
654
655impl LabelType {
656    /// Attempts to take a label type from the beginning of `parser`.
657    pub fn parse<Octs: AsRef<[u8]> + ?Sized>(
658        parser: &mut Parser<Octs>,
659    ) -> Result<Self, ParseError> {
660        let ltype = parser.parse_u8()?;
661        match ltype {
662            0..=0x3F => Ok(LabelType::Normal(ltype.into())),
663            0xC0..=0xFF => {
664                let res = usize::from(parser.parse_u8()?);
665                let res = res | ((usize::from(ltype) & 0x3F) << 8);
666                Ok(LabelType::Compressed(res))
667            }
668            _ => Err(ParseError::Form(FormError::new("invalid label type"))),
669        }
670    }
671
672    /// Returns the label type at the beginning of `parser` without advancing.
673    pub fn peek<Ref: AsRef<[u8]> + ?Sized>(
674        parser: &Parser<Ref>,
675    ) -> Result<Self, ParseError> {
676        let ltype = parser.peek(1)?[0];
677        match ltype {
678            0..=0x3F => Ok(LabelType::Normal(ltype.into())),
679            0xC0..=0xFF => {
680                let res = usize::from(parser.peek(2)?[1]);
681                let res = res | ((usize::from(ltype) & 0x3F) << 8);
682                Ok(LabelType::Compressed(res))
683            }
684            _ => Err(ParseError::Form(FormError::new("invalid label type"))),
685        }
686    }
687}
688
689//------------ ParsedDnameError ----------------------------------------------
690
691/// Parsing a domain name failed.
692///
693/// This type isn’t used as a public error type but is only converted into
694/// [`FormError`]s etc. Thus it doesn’t need to be public.
695#[derive(Clone, Copy, Debug, Eq, PartialEq)]
696enum ParsedDnameError {
697    /// A bad label was encountered.
698    BadLabel(LabelTypeError),
699
700    /// The name is longer than the 255 octets allowed.
701    LongName,
702
703    /// Too many compression pointers.
704    ExcessiveCompression,
705}
706
707impl fmt::Display for ParsedDnameError {
708    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
709        FormError::from(*self).fmt(f)
710    }
711}
712
713#[cfg(feature = "std")]
714impl std::error::Error for ParsedDnameError {}
715
716impl From<LabelTypeError> for ParsedDnameError {
717    fn from(err: LabelTypeError) -> Self {
718        ParsedDnameError::BadLabel(err)
719    }
720}
721
722impl From<ParsedDnameError> for FormError {
723    fn from(err: ParsedDnameError) -> FormError {
724        match err {
725            ParsedDnameError::BadLabel(_) => {
726                FormError::new("invalid label type")
727            }
728            ParsedDnameError::LongName => FormError::new("long domain name"),
729            ParsedDnameError::ExcessiveCompression => {
730                FormError::new("too many compression pointers")
731            }
732        }
733    }
734}
735
736impl From<ParsedDnameError> for ParseError {
737    fn from(err: ParsedDnameError) -> ParseError {
738        ParseError::Form(err.into())
739    }
740}
741
742//============ Testing =======================================================
743
744#[cfg(test)]
745mod test {
746    use super::*;
747
748    macro_rules! name {
749        (root) => {
750            name!(b"123\0", 3, 1, false)
751        };
752        (flat) => {
753            name!(b"\x03www\x07example\x03com\0\xc0\0", 0, 17, false)
754        };
755        (copy) => {
756            name!(b"\x03www\x07example\x03com\0\xc0\0", 17, 17, false)
757        };
758        (once) => {
759            name!(b"\x03com\0\x03www\x07example\xC0\0", 5, 17, true)
760        };
761        (twice) => {
762            name!(b"\x03com\0\x07example\xc0\0\x03www\xc0\x05", 15, 17, true)
763        };
764
765        ($bytes:expr, $start:expr, $len:expr, $compressed:expr) => {{
766            let mut parser = Parser::from_ref($bytes.as_ref());
767            parser.advance($start).unwrap();
768            ParsedName {
769                octets: $bytes.as_ref(),
770                pos: $start,
771                name_len: $len,
772                compressed: $compressed,
773            }
774        }};
775    }
776
777    static WECR: &[u8] = b"\x03www\x07example\x03com\0";
778
779    #[test]
780    fn len() {
781        assert_eq!(name!(root).compose_len(), 1);
782        assert_eq!(name!(flat).compose_len(), 17);
783        assert_eq!(name!(once).compose_len(), 17);
784        assert_eq!(name!(twice).compose_len(), 17);
785    }
786
787    #[test]
788    fn is_compressed() {
789        assert!(!name!(root).is_compressed());
790        assert!(!name!(flat).is_compressed());
791        assert!(name!(once).is_compressed());
792        assert!(name!(twice).is_compressed());
793    }
794
795    #[test]
796    fn is_root() {
797        assert!(name!(root).is_root());
798        assert!(!name!(flat).is_root());
799        assert!(!name!(once).is_root());
800        assert!(!name!(twice).is_root());
801    }
802
803    #[test]
804    fn iter() {
805        use crate::base::name::absolute::test::cmp_iter;
806
807        let labels: &[&[u8]] = &[b"www", b"example", b"com", b""];
808        cmp_iter(name!(root).iter(), &[b""]);
809        cmp_iter(name!(flat).iter(), labels);
810        cmp_iter(name!(once).iter(), labels);
811        cmp_iter(name!(twice).iter(), labels);
812    }
813
814    #[test]
815    fn iter_back() {
816        use crate::base::name::absolute::test::cmp_iter_back;
817
818        let labels: &[&[u8]] = &[b"", b"com", b"example", b"www"];
819        cmp_iter_back(name!(root).iter(), &[b""]);
820        cmp_iter_back(name!(flat).iter(), labels);
821        cmp_iter_back(name!(once).iter(), labels);
822        cmp_iter_back(name!(twice).iter(), labels);
823    }
824
825    fn cmp_iter_suffixes<'a, I>(iter: I, labels: &[&[u8]])
826    where
827        I: Iterator<Item = ParsedName<&'a [u8]>>,
828    {
829        for (name, labels) in iter.zip(labels) {
830            let mut iter = name.iter();
831            let labels = Name::from_slice(labels).unwrap();
832            let mut labels_iter = labels.iter();
833            loop {
834                match (iter.next(), labels_iter.next()) {
835                    (Some(left), Some(right)) => assert_eq!(left, right),
836                    (None, None) => break,
837                    (_, None) => panic!("extra items in iterator"),
838                    (None, _) => panic!("missing items in iterator"),
839                }
840            }
841        }
842    }
843
844    #[test]
845    fn iter_suffixes() {
846        let suffixes: &[&[u8]] = &[
847            b"\x03www\x07example\x03com\0",
848            b"\x07example\x03com\0",
849            b"\x03com\0",
850            b"\0",
851        ];
852        cmp_iter_suffixes(name!(root).iter_suffixes(), &[b"\0"]);
853        cmp_iter_suffixes(name!(flat).iter_suffixes(), suffixes);
854        cmp_iter_suffixes(name!(once).iter_suffixes(), suffixes);
855        cmp_iter_suffixes(name!(twice).iter_suffixes(), suffixes);
856    }
857
858    #[test]
859    fn label_count() {
860        assert_eq!(name!(root).label_count(), 1);
861        assert_eq!(name!(flat).label_count(), 4);
862        assert_eq!(name!(once).label_count(), 4);
863        assert_eq!(name!(twice).label_count(), 4);
864    }
865
866    #[test]
867    fn first() {
868        assert_eq!(name!(root).first().as_slice(), b"");
869        assert_eq!(name!(flat).first().as_slice(), b"www");
870        assert_eq!(name!(once).first().as_slice(), b"www");
871        assert_eq!(name!(twice).first().as_slice(), b"www");
872    }
873
874    #[test]
875    fn starts_with() {
876        let root = name!(root);
877        let flat_wec = name!(flat);
878        let once_wec = name!(once);
879        let twice_wec = name!(twice);
880
881        let test = Name::root_ref();
882        assert!(root.starts_with(&test));
883        assert!(!flat_wec.starts_with(&test));
884        assert!(!once_wec.starts_with(&test));
885        assert!(!twice_wec.starts_with(&test));
886
887        let test = RelativeName::empty_ref();
888        assert!(root.starts_with(&test));
889        assert!(flat_wec.starts_with(&test));
890        assert!(once_wec.starts_with(&test));
891        assert!(twice_wec.starts_with(&test));
892
893        let test = RelativeName::from_slice(b"\x03www").unwrap();
894        assert!(!root.starts_with(&test));
895        assert!(flat_wec.starts_with(&test));
896        assert!(once_wec.starts_with(&test));
897        assert!(twice_wec.starts_with(&test));
898
899        let test = RelativeName::from_slice(b"\x03www\x07example").unwrap();
900        assert!(!root.starts_with(&test));
901        assert!(flat_wec.starts_with(&test));
902        assert!(once_wec.starts_with(&test));
903        assert!(twice_wec.starts_with(&test));
904
905        let test =
906            RelativeName::from_slice(b"\x03www\x07example\x03com").unwrap();
907        assert!(!root.starts_with(&test));
908        assert!(flat_wec.starts_with(&test));
909        assert!(once_wec.starts_with(&test));
910        assert!(twice_wec.starts_with(&test));
911
912        let test = Name::from_slice(b"\x03www\x07example\x03com\0").unwrap();
913        assert!(!root.starts_with(&test));
914        assert!(flat_wec.starts_with(&test));
915        assert!(once_wec.starts_with(&test));
916        assert!(twice_wec.starts_with(&test));
917
918        let test = RelativeName::from_slice(b"\x07example\x03com").unwrap();
919        assert!(!root.starts_with(&test));
920        assert!(!flat_wec.starts_with(&test));
921        assert!(!once_wec.starts_with(&test));
922        assert!(!twice_wec.starts_with(&test));
923
924        let test = RelativeName::from_octets(b"\x03www".as_ref())
925            .unwrap()
926            .chain(
927                RelativeName::from_octets(b"\x07example".as_ref()).unwrap(),
928            )
929            .unwrap();
930        assert!(!root.starts_with(&test));
931        assert!(flat_wec.starts_with(&test));
932        assert!(once_wec.starts_with(&test));
933        assert!(twice_wec.starts_with(&test));
934
935        let test = test
936            .chain(RelativeName::from_octets(b"\x03com".as_ref()).unwrap())
937            .unwrap();
938        assert!(!root.starts_with(&test));
939        assert!(flat_wec.starts_with(&test));
940        assert!(once_wec.starts_with(&test));
941        assert!(twice_wec.starts_with(&test));
942    }
943
944    #[test]
945    fn ends_with() {
946        let root = name!(root);
947        let flat_wec = name!(flat);
948        let once_wec = name!(once);
949        let twice_wec = name!(twice);
950        let wecr = Name::from_octets(b"\x03www\x07example\x03com\0".as_ref())
951            .unwrap();
952
953        for name in wecr.iter_suffixes() {
954            if name.is_root() {
955                assert!(root.ends_with(&name))
956            } else {
957                assert!(!root.ends_with(&name))
958            }
959            assert!(flat_wec.ends_with(&name));
960            assert!(once_wec.ends_with(&name));
961            assert!(twice_wec.ends_with(&name));
962        }
963    }
964
965    #[test]
966    #[cfg(feature = "std")]
967    fn split_first() {
968        fn split_first_wec(mut name: ParsedName<&[u8]>) {
969            assert_eq!(
970                name.to_vec().as_slice(),
971                b"\x03www\x07example\x03com\0"
972            );
973            assert_eq!(
974                name.split_first().unwrap().as_slice(),
975                b"\x03www".as_ref()
976            );
977            assert_eq!(name.to_vec().as_slice(), b"\x07example\x03com\0");
978            assert_eq!(
979                name.split_first().unwrap().as_slice(),
980                b"\x07example".as_ref()
981            );
982            assert_eq!(name.to_vec().as_slice(), b"\x03com\0");
983            assert_eq!(
984                name.split_first().unwrap().as_slice(),
985                b"\x03com".as_ref()
986            );
987            assert_eq!(name.to_vec().as_slice(), b"\0");
988            assert_eq!(name.split_first(), None);
989            assert_eq!(name.split_first(), None);
990        }
991
992        split_first_wec(name!(flat));
993        split_first_wec(name!(once));
994        split_first_wec(name!(twice));
995    }
996
997    #[test]
998    #[cfg(feature = "std")]
999    fn parent() {
1000        fn parent_wec(mut name: ParsedName<&[u8]>) {
1001            assert_eq!(
1002                name.to_vec().as_slice(),
1003                b"\x03www\x07example\x03com\0"
1004            );
1005            assert!(name.parent());
1006            assert_eq!(name.to_vec().as_slice(), b"\x07example\x03com\0");
1007            assert!(name.parent());
1008            assert_eq!(name.to_vec().as_slice(), b"\x03com\0");
1009            assert!(name.parent());
1010            assert_eq!(name.to_vec().as_slice(), b"\0");
1011            assert!(!name.parent());
1012            assert!(!name.parent());
1013        }
1014
1015        parent_wec(name!(flat));
1016        parent_wec(name!(once));
1017        parent_wec(name!(twice));
1018    }
1019
1020    #[test]
1021    #[cfg(feature = "std")]
1022    fn parse_and_skip() {
1023        use std::vec::Vec;
1024
1025        fn name_eq(parsed: ParsedName<&[u8]>, name: ParsedName<&[u8]>) {
1026            assert_eq!(parsed.octets, name.octets);
1027            assert_eq!(parsed.pos, name.pos);
1028            assert_eq!(parsed.name_len, name.name_len);
1029            assert_eq!(parsed.compressed, name.compressed);
1030        }
1031
1032        fn parse(
1033            mut parser: Parser<&[u8]>,
1034            equals: ParsedName<&[u8]>,
1035            compose_len: usize,
1036        ) {
1037            let end = parser.pos() + compose_len;
1038            name_eq(ParsedName::parse(&mut parser).unwrap(), equals);
1039            assert_eq!(parser.pos(), end);
1040        }
1041
1042        fn skip(name: ParsedName<&[u8]>, len: usize) {
1043            let mut parser = name.parser();
1044            let pos = parser.pos();
1045            assert_eq!(ParsedName::skip(&mut parser), Ok(()));
1046            assert_eq!(parser.pos(), pos + len);
1047        }
1048
1049        fn p(slice: &[u8], pos: usize) -> Parser<[u8]> {
1050            let mut res = Parser::from_ref(slice);
1051            res.advance(pos).unwrap();
1052            res
1053        }
1054
1055        // Correctly formatted names.
1056        parse(name!(root).parser(), name!(root), 1);
1057        parse(name!(flat).parser(), name!(flat), 17);
1058        parse(name!(copy).parser(), name!(flat), 2);
1059        parse(name!(once).parser(), name!(once), 14);
1060        parse(name!(twice).parser(), name!(twice), 6);
1061        skip(name!(root), 1);
1062        skip(name!(flat), 17);
1063        skip(name!(copy), 2);
1064        skip(name!(once), 14);
1065        skip(name!(twice), 6);
1066
1067        // Short buffer in the middle of a label.
1068        let mut parser = p(b"\x03www\x07exam", 0);
1069        assert_eq!(
1070            ParsedName::parse(&mut parser.clone()),
1071            Err(ParseError::ShortInput)
1072        );
1073        assert_eq!(
1074            ParsedName::skip(&mut parser),
1075            Err(ParseError::ShortInput)
1076        );
1077
1078        // Short buffer at end of label.
1079        let mut parser = p(b"\x03www\x07example", 0);
1080        assert_eq!(
1081            ParsedName::parse(&mut parser.clone()),
1082            Err(ParseError::ShortInput)
1083        );
1084        assert_eq!(
1085            ParsedName::skip(&mut parser),
1086            Err(ParseError::ShortInput)
1087        );
1088
1089        // Compression pointer beyond the end of buffer.
1090        let mut parser = p(b"\x03www\xc0\xee12", 0);
1091        assert!(ParsedName::parse(&mut parser.clone()).is_err());
1092        assert_eq!(ParsedName::skip(&mut parser), Ok(()));
1093        assert_eq!(parser.remaining(), 2);
1094
1095        // Compression pointer to itself
1096        assert!(ParsedName::parse(&mut p(b"\x03www\xc0\x0412", 4)).is_err());
1097
1098        // Compression pointer forward
1099        assert!(ParsedName::parse(&mut p(b"\x03www\xc0\x0612", 4)).is_err());
1100
1101        // Bad label header.
1102        let mut parser = p(b"\x03www\x07example\xbffoo", 0);
1103        assert!(ParsedName::parse(&mut parser.clone()).is_err());
1104        assert!(ParsedName::skip(&mut parser).is_err());
1105
1106        // Long name: 255 bytes is fine.
1107        let mut buf = Vec::from(&b"\x03123\0"[..]);
1108        for _ in 0..25 {
1109            buf.extend_from_slice(b"\x09123456789");
1110        }
1111        buf.extend_from_slice(b"\xc0\x0012");
1112        let mut parser = Parser::from_ref(buf.as_slice());
1113        parser.advance(5).unwrap();
1114        let name = ParsedName::parse(&mut parser.clone()).unwrap();
1115        assert_eq!(name.compose_len(), 255);
1116        assert_eq!(ParsedName::skip(&mut parser), Ok(()));
1117        assert_eq!(parser.remaining(), 2);
1118
1119        // Long name: 256 bytes are bad.
1120        let mut buf = Vec::from(&b"\x041234\x00"[..]);
1121        for _ in 0..25 {
1122            buf.extend_from_slice(b"\x09123456789");
1123        }
1124        buf.extend_from_slice(b"\xc0\x0012");
1125        let mut parser = Parser::from_ref(buf.as_slice());
1126        parser.advance(6).unwrap();
1127        assert!(ParsedName::parse(&mut parser.clone()).is_err());
1128        assert_eq!(ParsedName::skip(&mut parser), Ok(()));
1129        assert_eq!(parser.remaining(), 2);
1130
1131        // Long name through recursion
1132        let mut parser = p(b"\x03www\xc0\x0012", 0);
1133        assert!(ParsedName::parse(&mut parser.clone()).is_err());
1134        assert_eq!(ParsedName::skip(&mut parser), Ok(()));
1135        assert_eq!(parser.remaining(), 2);
1136
1137        // Single-step infinite recursion
1138        let mut parser = p(b"\xc0\x0012", 0);
1139        assert!(ParsedName::parse(&mut parser.clone()).is_err());
1140        assert_eq!(ParsedName::skip(&mut parser), Ok(()));
1141        assert_eq!(parser.remaining(), 2);
1142
1143        // Two-step infinite recursion
1144        let mut parser = p(b"\xc0\x02\xc0\x0012", 2);
1145        assert!(ParsedName::parse(&mut parser.clone()).is_err());
1146        assert_eq!(ParsedName::skip(&mut parser), Ok(()));
1147        assert_eq!(parser.remaining(), 2);
1148    }
1149
1150    #[test]
1151    #[cfg(feature = "std")]
1152    fn compose() {
1153        use octseq::builder::infallible;
1154        use std::vec::Vec;
1155
1156        fn step(name: ParsedName<&[u8]>, result: &[u8]) {
1157            let mut buf = Vec::new();
1158            infallible(name.compose(&mut buf));
1159            assert_eq!(buf.as_slice(), result);
1160        }
1161
1162        step(name!(root), b"\x00");
1163        step(name!(flat), WECR);
1164        step(name!(once), WECR);
1165        step(name!(twice), WECR);
1166    }
1167
1168    // XXX TODO compose_canonical
1169
1170    #[test]
1171    fn as_flat_slice() {
1172        assert_eq!(name!(root).as_flat_slice(), Some(b"\x00".as_ref()));
1173        assert_eq!(name!(flat).as_flat_slice(), Some(WECR));
1174        assert_eq!(name!(once).as_flat_slice(), None);
1175        assert_eq!(name!(twice).as_flat_slice(), None);
1176    }
1177
1178    #[test]
1179    fn eq() {
1180        fn step<N: ToName + fmt::Debug>(name: N) {
1181            assert_eq!(name!(flat), &name);
1182            assert_eq!(name!(once), &name);
1183            assert_eq!(name!(twice), &name);
1184        }
1185
1186        fn ne_step<N: ToName + fmt::Debug>(name: N) {
1187            assert_ne!(name!(flat), &name);
1188            assert_ne!(name!(once), &name);
1189            assert_ne!(name!(twice), &name);
1190        }
1191
1192        step(name!(flat));
1193        step(name!(once));
1194        step(name!(twice));
1195
1196        step(Name::from_slice(b"\x03www\x07example\x03com\x00").unwrap());
1197        step(Name::from_slice(b"\x03wWw\x07EXAMPLE\x03com\x00").unwrap());
1198        step(
1199            RelativeName::from_octets(b"\x03www\x07example\x03com")
1200                .unwrap()
1201                .chain_root(),
1202        );
1203        step(
1204            RelativeName::from_octets(b"\x03www\x07example")
1205                .unwrap()
1206                .chain(Name::from_octets(b"\x03com\x00").unwrap())
1207                .unwrap(),
1208        );
1209
1210        ne_step(Name::from_slice(b"\x03ww4\x07EXAMPLE\x03com\x00").unwrap());
1211    }
1212
1213    // XXX TODO Test for cmp and hash.
1214}