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