domain_core/bits/name/
dname.rs

1/// Uncompressed, absolute domain names.
2///
3/// This is a private module. Its public types are re-exported by the parent.
4
5use std::{cmp, fmt, hash, ops, str};
6use bytes::{BufMut, Bytes};
7use ::bits::compose::{Compose, Compress, Compressor};
8use ::bits::parse::{Parse, ParseAll, Parser, ShortBuf};
9use ::master::scan::{CharSource, Scan, Scanner, ScanError, SyntaxError};
10use super::label::{Label, LabelTypeError, SplitLabelError};
11use super::relative::{RelativeDname, DnameIter};
12use super::traits::{ToLabelIter, ToDname};
13use super::uncertain::{UncertainDname, FromStrError};
14
15
16//------------ Dname ---------------------------------------------------------
17
18/// An uncompressed, absolute domain name.
19///
20/// The type wraps a [`Bytes`] value and guarantees that it always contains
21/// a correctly encoded, absolute domain name. It derefs to [`Bytes`] and
22/// therefore to `[u8]` allowing you direct access to the underlying byte
23/// slice. It does overide all applicable methods providing access to parts
24/// of the byte slice, though, returning either `Dname` or [`RelativeDname`]s
25/// instead.
26///
27/// You can construct a domain name from a string via the `FromStr` trait or
28/// manually via a [`DnameBuilder`]. In addition, you can also parse it from
29/// a message. This will, however, require the name to be uncompressed.
30///
31/// [`Bytes`]: ../../../bytes/struct.Bytes.html
32/// [`DnameBuilder`]: struct.DnameBuilder.html
33/// [`RelativeDname`]: struct.RelativeDname.html
34#[derive(Clone)]
35pub struct Dname {
36    bytes: Bytes
37}
38
39/// # Creation and Conversion
40///
41impl Dname {
42    /// Creates a domain name from the underlying bytes without any check.
43    ///
44    /// Since this will allow to actually construct an incorrectly encoded
45    /// domain name value, the function is unsafe.
46    pub(super) unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self {
47        Dname { bytes }
48    }
49
50    /// Creates a domain name representing the root.
51    ///
52    /// The resulting domain name will consist of the root label only.
53    pub fn root() -> Self {
54        unsafe { Self::from_bytes_unchecked(Bytes::from_static(b"\0")) }
55    }
56
57    /// Creates a domain name from a bytes value.
58    ///
59    /// This will only succeed if `bytes` contains a properly encoded
60    /// absolute domain name. Because the function checks, this will take
61    /// a wee bit of time.
62    pub fn from_bytes(bytes: Bytes) -> Result<Self, DnameBytesError> {
63        if bytes.len() > 255 {
64            return Err(DnameError::LongName.into());
65        }
66        {
67            let mut tmp = bytes.as_ref();
68            loop {
69                let (label, tail) = Label::split_from(tmp)?;
70                if label.is_root() {
71                    if tail.is_empty() {
72                        break;
73                    }
74                    else {
75                        return Err(DnameBytesError::TrailingData)
76                    }
77                }
78                if tail.is_empty() {
79                    return Err(DnameBytesError::RelativeName)
80                }
81                tmp = tail;
82            }
83        }
84        Ok(unsafe { Dname::from_bytes_unchecked(bytes) })
85    }
86
87    /// Creates a domain name from a byte slice.
88    ///
89    /// The function will create a new bytes value from the slice’s content.
90    /// If the slice does not contain a correctly encoded, absolute domain
91    /// name, the function will fail.
92    pub fn from_slice(s: &[u8]) -> Result<Self, DnameBytesError> {
93        Self::from_bytes(s.into())
94    }
95
96    /// Creates a domain name from a sequence of characters.
97    ///
98    /// The sequence must result in a domain name in master format
99    /// representation. That is, its labels should be separated by dots.
100    /// Actual dots, white space and backslashes should be escaped by a
101    /// preceeding backslash, and any byte value that is not a printable
102    /// ASCII character should be encoded by a backslash followed by its
103    /// three digit decimal value.
104    ///
105    /// The name will always be an absolute name. If the last character in the
106    /// sequence is not a dot, the function will quietly add a root label,
107    /// anyway. In most cases, this is likely what you want. If it isn’t,
108    /// though, use [`UncertainDname`] instead to be able to check.
109    ///
110    /// [`UncertainDname`]: enum.UncertainDname.html
111    pub fn from_chars<C>(chars: C) -> Result<Self, FromStrError>
112                      where C: IntoIterator<Item=char> {
113        UncertainDname::from_chars(chars).map(|res| res.into_absolute())
114    }
115
116    /// Returns a reference to the underlying bytes value.
117    pub fn as_bytes(&self) -> &Bytes {
118        &self.bytes
119    }
120
121    /// Returns a reference to the underlying byte slice.
122    pub fn as_slice(&self) -> &[u8] {
123        self.bytes.as_ref()
124    }
125
126    /// Converts the domain name into its underlying bytes value.
127    pub fn into_bytes(self) -> Bytes {
128        self.bytes
129    }
130 
131    /// Converts the name into a relative name by dropping the root label.
132    pub fn into_relative(mut self) -> RelativeDname {
133        let len = self.bytes.len() - 1;
134        self.bytes.truncate(len);
135        unsafe { RelativeDname::from_bytes_unchecked(self.bytes) }
136    }
137}
138
139/// # Properties
140///
141/// More of the usual methods on byte sequences, such as
142/// [`len`](#method.len), are available via
143/// [deref to `Bytes`](#deref-methods).
144impl Dname {
145    /// Returns whether the name is the root label only.
146    pub fn is_root(&self) -> bool {
147        self.len() == 1
148    }
149}
150
151
152/// # Working with Labels
153///
154impl Dname {
155    /// Returns an iterator over the labels of the domain name.
156    pub fn iter(&self) -> DnameIter {
157        DnameIter::new(self.bytes.as_ref())
158    }
159
160    /// Returns an iterator over the suffixes of the name.
161    ///
162    /// The returned iterator starts with the full name and then for each
163    /// additional step returns a name with the left-most label stripped off
164    /// until it reaches the root label.
165    pub fn iter_suffixes(&self) -> SuffixIter {
166        SuffixIter::new(self)
167    }
168
169    /// Returns the number of labels in the domain name.
170    pub fn label_count(&self) -> usize {
171        self.iter().count()
172    }
173
174    /// Returns a reference to the first label.
175    pub fn first(&self) -> &Label {
176        self.iter().next().unwrap()
177    }
178
179    /// Returns a reference to the last label.
180    ///
181    /// Because the last label in an absolute name is always the root label,
182    /// this method can return a static reference. It is also a wee bit silly,
183    /// but here for completeness.
184    pub fn last(&self) -> &'static Label {
185        Label::root()
186    }
187
188    /// Determines whether `base` is a prefix of `self`.
189    pub fn starts_with<'a, N: ToLabelIter<'a>>(&'a self, base: &'a N) -> bool {
190        <Self as ToLabelIter>::starts_with(self, base)
191    }
192
193    /// Determines whether `base` is a suffix of `self`.
194    pub fn ends_with<'a, N: ToLabelIter<'a>>(&'a self, base: &'a N) -> bool {
195        <Self as ToLabelIter>::ends_with(self, base)
196    }
197
198    /// Returns whether an index points to the first byte of a non-root label.
199    pub fn is_label_start(&self, mut index: usize) -> bool {
200        if index == 0 {
201            return true
202        }
203        let mut tmp = self.as_slice();
204        while !tmp.is_empty() {
205            let (label, tail) = Label::split_from(tmp).unwrap();
206            let len = label.len() + 1;
207            if index < len || len == 1 { // length 1: root label.
208                return false
209            }
210            else if index == len {
211                return true
212            }
213            index -= len;
214            tmp = tail;
215        }
216        false
217    }
218
219    /// Like `is_label_start` but panics if it isn’t.
220    fn check_index(&self, index: usize) {
221        if !self.is_label_start(index) {
222            panic!("index not at start of a label");
223        }
224    }
225
226    /// Returns the part of the name indicated by start and end positions.
227    ///
228    /// The returned name will start at position `begin` and end right before
229    /// position `end`. Both positions must point to the begining of a label.
230    ///
231    /// # Panics
232    ///
233    /// The method panics if either position is not the start of a label or
234    /// is out of bounds.
235    ///
236    /// Because the returned domain name is relative, the method will also
237    /// panic if the end is equal to the length of the name. If you
238    /// want to slice the entire end of the name including the final root
239    /// label, you can use [`slice_from()`] instead.
240    ///
241    /// [`slice_from()`]: #method.slice_from
242    pub fn slice(&self, begin: usize, end: usize) -> RelativeDname {
243        self.check_index(begin);
244        self.check_index(end);
245        unsafe {
246            RelativeDname::from_bytes_unchecked(self.bytes.slice(begin, end))
247        }
248    }
249
250    /// Returns the part of the name starting at the given position.
251    ///
252    /// # Panics
253    ///
254    /// The method panics if `begin` isn’t the index of the beginning of a
255    /// label or is out of bounds.
256    pub fn slice_from(&self, begin: usize) -> Self {
257        self.check_index(begin);
258        unsafe {
259            Self::from_bytes_unchecked(self.bytes.slice_from(begin))
260        }
261    }
262
263    /// Returns the part of the name ending at the given position.
264    ///
265    /// # Panics
266    ///
267    /// The method panics if `end` is not the beginning of a label or is out
268    /// of bounds. Because the returned domain name is relative, the method
269    /// will also panic if the end is equal to the length of the name.
270    pub fn slice_to(&self, end: usize) -> RelativeDname {
271        self.check_index(end);
272        unsafe {
273            RelativeDname::from_bytes_unchecked(self.bytes.slice_to(end))
274        }
275    }
276
277    /// Splits the name into two at the given position.
278    ///
279    /// Unlike the version on [`Bytes`], the method consumes `self` since the
280    /// left side needs to be converted into a [`RelativeDname`].
281    /// Consequently, it returns a pair of the left and right parts.
282    ///
283    /// # Panics
284    ///
285    /// The method will panic if `mid` is not the index of the beginning of
286    /// a label or if it is out of bounds.
287    ///
288    /// [`Bytes`]: ../../../bytes/struct.Bytes.html#method.split_off
289    /// [`RelativeDname`]: struct.RelativeDname.html
290    pub fn split_off(mut self, mid: usize) -> (RelativeDname, Dname) {
291        let left = self.split_to(mid);
292        (left, self)
293    }
294
295    /// Splits the name into two at the given position.
296    ///
297    /// Afterwards, `self` will contain the name starting at the position
298    /// while the name ending right before it will be returned.
299    ///
300    /// # Panics
301    ///
302    /// The method will panic if `mid` is not the start of a new label or is
303    /// out of bounds.
304    pub fn split_to(&mut self, mid: usize) -> RelativeDname {
305        self.check_index(mid);
306        unsafe {
307            RelativeDname::from_bytes_unchecked(self.bytes.split_to(mid))
308        }
309    }
310
311    /// Truncates the name before `len`.
312    ///
313    /// Because truncating converts the name into a relative name, the method
314    /// consumes self.
315    ///
316    /// # Panics
317    ///
318    /// The method will panic if `len` is not the index of a new label or if
319    /// it is out of bounds.
320    pub fn truncate(mut self, len: usize) -> RelativeDname {
321        self.check_index(len);
322        self.bytes.truncate(len);
323        unsafe { RelativeDname::from_bytes_unchecked(self.bytes) }
324    }
325
326    /// Splits off the first label.
327    ///
328    /// If this name is longer than just the root label, returns the first
329    /// label as a relative name and removes it from the name itself. If the
330    /// name is only the root label, returns `None` and does nothing.
331    pub fn split_first(&mut self) -> Option<RelativeDname> {
332        if self.len() == 1 {
333            return None
334        }
335        let end = self.iter().next().unwrap().len() + 1;
336        Some(unsafe {
337            RelativeDname::from_bytes_unchecked(self.bytes.split_to(end))
338        })
339    }
340
341    /// Reduces the name to the parent of the current name.
342    ///
343    /// If the name consists of the root label only, returns `false` and does
344    /// nothing. Otherwise, drops the first label and returns `true`.
345    pub fn parent(&mut self) -> bool {
346        self.split_first().is_some()
347    }
348
349    /// Strips the suffix `base` from the domain name.
350    ///
351    /// If `base` is indeed a suffix, returns a relative domain name with the
352    /// remainder of the name. Otherwise, returns an error with an unmodified
353    /// `self`.
354    pub fn strip_suffix<N: ToDname>(self, base: &N)
355                                    -> Result<RelativeDname, Dname> {
356        if self.ends_with(base) {
357            let len = self.compose_len() - base.compose_len();
358            Ok(self.truncate(len))
359        }
360        else {
361            Err(self)
362        }
363    }
364}
365
366
367//--- Parse, ParseAll, and Compose
368
369impl Parse for Dname {
370    type Err = DnameParseError;
371
372    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
373        let len = name_len(parser)?;
374        Ok(unsafe {
375            Self::from_bytes_unchecked(parser.parse_bytes(len).unwrap())
376        })
377    }
378
379    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
380        let len = name_len(parser)?;
381        parser.advance(len)?;
382        Ok(())
383    }
384}
385
386fn name_len(parser: &mut Parser) -> Result<usize, DnameParseError> {
387    let len = {
388        let mut tmp = parser.peek_all();
389        loop {
390            if tmp.is_empty() {
391                return Err(ShortBuf.into())
392            }
393            let (label, tail) = Label::split_from(tmp)?;
394            tmp = tail;
395            if label.is_root() {
396                break;
397            }
398        }
399        parser.remaining() - tmp.len()
400    };
401    if len > 255 {
402        Err(DnameError::LongName.into())
403    }
404    else {
405        Ok(len)
406    }
407}
408
409impl ParseAll for Dname {
410    type Err = DnameBytesError;
411
412    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
413        Self::from_bytes(parser.parse_bytes(len)?)
414    }
415}
416
417
418impl Compose for Dname {
419    fn compose_len(&self) -> usize {
420        self.bytes.len()
421    }
422
423    fn compose<B: BufMut>(&self, buf: &mut B) {
424        buf.put_slice(self.as_ref())
425    }
426}
427
428impl Compress for Dname {
429    fn compress(&self, compressor: &mut Compressor) -> Result<(), ShortBuf> {
430        compressor.compress_name(self)
431    }
432}
433
434
435//--- FromStr
436
437impl str::FromStr for Dname {
438    type Err = FromStrError;
439
440    /// Parses a string into an absolute domain name.
441    ///
442    /// The implementation assumes that the string refers to an absolute name
443    /// whether it ends in a dot or not. If you need to be able to distinguish
444    /// between those two cases, you can use [`UncertainDname`] instead.
445    ///
446    /// [`UncertainDname`]: struct.UncertainDname.html
447    fn from_str(s: &str) -> Result<Self, Self::Err> {
448        UncertainDname::from_str(s).map(|res| res.into_absolute())
449    }
450}
451
452
453//--- ToLabelIter and ToDname
454
455impl<'a> ToLabelIter<'a> for Dname {
456    type LabelIter = DnameIter<'a>;
457
458    fn iter_labels(&'a self) -> Self::LabelIter {
459        self.iter()
460    }
461}
462
463impl ToDname for Dname {
464    fn to_name(&self) -> Dname {
465        self.clone()
466    }
467
468    fn as_flat_slice(&self) -> Option<&[u8]> {
469        Some(self.as_slice())
470    }
471}
472
473
474//--- Deref and AsRef
475
476impl ops::Deref for Dname {
477    type Target = Bytes;
478
479    fn deref(&self) -> &Bytes {
480        self.as_ref()
481    }
482}
483
484impl AsRef<Bytes> for Dname {
485    fn as_ref(&self) -> &Bytes {
486        &self.bytes
487    }
488}
489
490impl AsRef<[u8]> for Dname {
491    fn as_ref(&self) -> &[u8] {
492        self.bytes.as_ref()
493    }
494}
495
496
497//--- IntoIterator
498
499impl<'a> IntoIterator for &'a Dname {
500    type Item = &'a Label;
501    type IntoIter = DnameIter<'a>;
502
503    fn into_iter(self) -> Self::IntoIter {
504        self.iter()
505    }
506}
507
508
509//--- PartialEq and Eq
510
511impl<N: ToDname> PartialEq<N> for Dname {
512    fn eq(&self, other: &N) -> bool {
513        self.name_eq(other)
514    }
515}
516
517impl Eq for Dname { }
518
519
520//--- PartialOrd and Ord
521
522impl<N: ToDname> PartialOrd<N> for Dname {
523    /// Returns the ordering between `self` and `other`.
524    ///
525    /// Domain name order is determined according to the ‘canonical DNS
526    /// name order’ as defined in [section 6.1 of RFC 4034][RFC4034-6.1].
527    ///
528    /// [RFC4034-6.1]: https://tools.ietf.org/html/rfc4034#section-6.1
529    fn partial_cmp(&self, other: &N) -> Option<cmp::Ordering> {
530        Some(self.name_cmp(other))
531    }
532}
533
534impl Ord for Dname {
535    /// Returns the ordering between `self` and `other`.
536    ///
537    /// Domain name order is determined according to the ‘canonical DNS
538    /// name order’ as defined in [section 6.1 of RFC 4034][RFC4034-6.1].
539    ///
540    /// [RFC4034-6.1]: https://tools.ietf.org/html/rfc4034#section-6.1
541    fn cmp(&self, other: &Self) -> cmp::Ordering {
542        self.name_cmp(other)
543    }
544}
545
546
547//--- Hash
548
549impl hash::Hash for Dname {
550    fn hash<H: hash::Hasher>(&self, state: &mut H) {
551        for item in self.iter() {
552            item.hash(state)
553        }
554    }
555}
556
557
558//--- Scan and Display
559
560impl Scan for Dname {
561    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
562                           -> Result<Self, ScanError> {
563        let pos = scanner.pos();
564        let name = match UncertainDname::scan(scanner)? {
565            UncertainDname::Relative(name) => name,
566            UncertainDname::Absolute(name) => return Ok(name)
567        };
568        let origin = match *scanner.origin() {
569            Some(ref origin) => origin,
570            None => return Err((SyntaxError::NoOrigin, pos).into())
571        };
572        name.into_builder().append_origin(origin)
573                           .map_err(|err| (SyntaxError::from(err), pos).into())
574    }
575}
576
577impl fmt::Display for Dname {
578    /// Formats the domain name.
579    ///
580    /// This will produce the domain name in ‘common display format’ without
581    /// the trailing dot.
582    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
583        let mut iter = self.iter();
584        write!(f, "{}", iter.next().unwrap())?;
585        for label in iter {
586            if !label.is_root() {
587                write!(f, ".{}", label)?
588            }
589        }
590        Ok(())
591    }
592}
593
594
595//--- Debug
596
597impl fmt::Debug for Dname {
598    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
599        write!(f, "Dname({}.)", self)
600    }
601}
602
603
604//------------ SuffixIter ----------------------------------------------------
605
606/// An iterator over ever shorter suffixes of a domain name.
607#[derive(Clone, Debug)]
608pub struct SuffixIter {
609    name: Option<Dname>,
610}
611
612impl SuffixIter {
613    /// Creates a new iterator cloning `name`.
614    fn new(name: &Dname) -> Self {
615        SuffixIter {
616            name: Some(name.clone())
617        }
618    }
619}
620
621impl Iterator for SuffixIter {
622    type Item = Dname;
623
624    fn next(&mut self) -> Option<Self::Item> {
625        let (res, ok) = match self.name {
626            Some(ref mut name) => (name.clone(), name.parent()),
627            None => return None
628        };
629        if !ok {
630            self.name = None
631        }
632        Some(res)
633    }
634}
635
636
637//------------ DnameError ----------------------------------------------------
638
639/// A domain name wasn’t encoded correctly.
640#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
641pub enum DnameError {
642    #[fail(display="{}", _0)]
643    BadLabel(LabelTypeError),
644
645    #[fail(display="compressed domain name")]
646    CompressedName,
647
648    #[fail(display="long domain name")]
649    LongName,
650}
651
652impl From<LabelTypeError> for DnameError {
653    fn from(err: LabelTypeError) -> DnameError {
654        DnameError::BadLabel(err)
655    }
656}
657
658
659//------------ DnameParseError -----------------------------------------------
660
661/// An error happened while parsing a domain name.
662#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
663pub enum DnameParseError {
664    #[fail(display="{}", _0)]
665    BadName(DnameError),
666
667    #[fail(display="unexpected end of buffer")]
668    ShortBuf,
669}
670
671impl<T: Into<DnameError>> From<T> for DnameParseError {
672    fn from(err: T) -> DnameParseError {
673        DnameParseError::BadName(err.into())
674    }
675}
676
677impl From<SplitLabelError> for DnameParseError {
678    fn from(err: SplitLabelError) -> DnameParseError {
679        match err {
680            SplitLabelError::Pointer(_)
681                => DnameParseError::BadName(DnameError::CompressedName),
682            SplitLabelError::BadType(t)
683                => DnameParseError::BadName(DnameError::BadLabel(t)),
684            SplitLabelError::ShortBuf => DnameParseError::ShortBuf,
685        }
686    }
687}
688
689impl From<ShortBuf> for DnameParseError {
690    fn from(_: ShortBuf) -> DnameParseError {
691        DnameParseError::ShortBuf
692    }
693}
694
695
696//------------ DnameBytesError -----------------------------------------------
697
698/// An error happened while converting a bytes value into a domain name.
699#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
700pub enum DnameBytesError {
701    #[fail(display="{}", _0)]
702    ParseError(DnameParseError),
703
704    #[fail(display="relative name")]
705    RelativeName,
706
707    #[fail(display="trailing data")]
708    TrailingData,
709}
710
711impl<T: Into<DnameParseError>> From<T> for DnameBytesError {
712    fn from(err: T) -> DnameBytesError {
713        DnameBytesError::ParseError(err.into())
714    }
715}
716
717
718//============ Testing =======================================================
719//
720// Some of the helper functions herein are resused by the tests of other
721// sub-modules of ::bits::name. Hence the `pub(crate)` designation.
722
723#[cfg(test)]
724pub(crate) mod test {
725    use std::cmp::Ordering;
726    use super::*;
727
728    macro_rules! assert_panic {
729        ( $cond:expr ) => {
730            {
731                let result = ::std::panic::catch_unwind(|| $cond);
732                assert!(result.is_err());
733            }
734        }
735    }
736
737    #[test]
738    fn root() {
739        assert_eq!(Dname::root().as_slice(), b"\0");
740    }
741
742    #[test]
743    fn from_slice() {
744        // a simple good name
745        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0")
746                         .unwrap().as_slice(),
747                   b"\x03www\x07example\x03com\0");
748        
749        // relative name
750        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com"),
751                   Err(DnameBytesError::RelativeName));
752
753        // bytes shorter than what label length says.
754        assert_eq!(Dname::from_slice(b"\x03www\x07exa"),
755                   Err(ShortBuf.into()));
756
757        // label 63 long ok, 64 bad.
758        let mut slice = [0u8; 65];
759        slice[0] = 63;
760        assert!(Dname::from_slice(&slice[..]).is_ok());
761        let mut slice = [0u8; 66];
762        slice[0] = 64;
763        assert!(Dname::from_slice(&slice[..]).is_err());
764
765        // name 255 long ok, 256 bad.
766        let mut buf = Vec::new();
767        for _ in 0..25 {
768            buf.extend_from_slice(b"\x09123456789");
769        }
770        assert_eq!(buf.len(), 250);
771        let mut tmp = buf.clone();
772        tmp.extend_from_slice(b"\x03123\0");
773        assert_eq!(Dname::from_slice(&tmp).map(|_| ()), Ok(()));
774        buf.extend_from_slice(b"\x041234\0");
775        assert!(Dname::from_slice(&buf).is_err());
776
777        // trailing data
778        assert!(Dname::from_slice(b"\x03com\0\x03www\0").is_err());
779
780        // bad label heads: compressed, other types.
781        assert_eq!(Dname::from_slice(b"\xa2asdasds"),
782                   Err(LabelTypeError::Undefined.into()));
783        assert_eq!(Dname::from_slice(b"\x62asdasds"),
784                   Err(LabelTypeError::Extended(0x62).into()));
785        assert_eq!(Dname::from_slice(b"\xccasdasds"),
786                   Err(DnameError::CompressedName.into()));
787
788        // empty input
789        assert_eq!(Dname::from_slice(b""), Err(ShortBuf.into()));
790    }
791
792    // No test for `Dname::from_chars` necessary since it only defers to
793    // `UncertainDname`.
794    //
795    // No tests for the simple conversion methods because, well, simple.
796
797    #[test]
798    fn into_relative() {
799        assert_eq!(Dname::from_slice(b"\x03www\0").unwrap()
800                         .into_relative().as_slice(),
801                   b"\x03www");
802    }
803
804    #[test]
805    fn is_root() {
806        assert_eq!(Dname::from_slice(b"\0").unwrap().is_root(), true);
807        assert_eq!(Dname::from_slice(b"\x03www\0").unwrap().is_root(), false);
808        assert_eq!(Dname::root().is_root(), true);
809    }
810
811    pub fn cmp_iter<I>(mut iter: I, labels: &[&[u8]])
812    where
813        I: Iterator,
814        I::Item: AsRef<[u8]>
815    {
816        let mut labels = labels.iter();
817        loop {
818            match (iter.next(), labels.next()) {
819                (Some(left), Some(right)) => assert_eq!(left.as_ref(), *right),
820                (None, None) => break,
821                (_, None) => panic!("extra items in iterator"),
822                (None, _) => panic!("missing items in iterator"),
823            }
824        }
825    }
826
827    #[test]
828    fn iter() {
829        cmp_iter(Dname::root().iter(), &[b""]);
830        cmp_iter(Dname::from_slice(b"\x03www\x07example\x03com\0")
831                       .unwrap().iter(),
832                 &[b"www", b"example", b"com", b""]);
833    }
834
835    pub fn cmp_iter_back<I>(mut iter: I, labels: &[&[u8]])
836    where
837        I: DoubleEndedIterator,
838        I::Item: AsRef<[u8]>
839    {
840        let mut labels = labels.iter();
841        loop {
842            match (iter.next_back(), labels.next()) {
843                (Some(left), Some(right)) => assert_eq!(left.as_ref(), *right),
844                (None, None) => break,
845                (_, None) => panic!("extra items in iterator"),
846                (None, _) => panic!("missing items in iterator"),
847            }
848        }
849    }
850
851    #[test]
852    fn iter_back() {
853        cmp_iter_back(Dname::root().iter(), &[b""]);
854        cmp_iter_back(Dname::from_slice(b"\x03www\x07example\x03com\0")
855                            .unwrap().iter(),
856                      &[b"", b"com", b"example", b"www"]);
857    }
858
859    #[test]
860    fn iter_suffixes() {
861        cmp_iter(Dname::root().iter_suffixes(), &[b"\0"]);
862        cmp_iter(Dname::from_slice(b"\x03www\x07example\x03com\0")
863                       .unwrap().iter_suffixes(),
864                 &[b"\x03www\x07example\x03com\0", b"\x07example\x03com\0",
865                   b"\x03com\0", b"\0"]);
866    }
867
868    #[test]
869    fn label_count() {
870        assert_eq!(Dname::root().label_count(), 1);
871        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap()
872                         .label_count(),
873                   4);
874    }
875
876    #[test]
877    fn first() {
878        assert_eq!(Dname::root().first().as_slice(), b"");
879        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap()
880                         .first().as_slice(),
881                   b"www");
882    }
883
884    // No test for `last` because it is so trivial.
885
886    #[test]
887    fn last() {
888        assert_eq!(Dname::root().last().as_slice(), b"");
889        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap()
890                         .last().as_slice(),
891                   b"");
892    }
893
894    #[test]
895    fn starts_with() {
896        let root = Dname::root();
897        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
898
899        assert!(root.starts_with(&root));
900        assert!(wecr.starts_with(&wecr));
901        
902        assert!( root.starts_with(&RelativeDname::empty()));
903        assert!( wecr.starts_with(&RelativeDname::empty()));
904        
905        let test = RelativeDname::from_slice(b"\x03www").unwrap();
906        assert!(!root.starts_with(&test));
907        assert!( wecr.starts_with(&test));
908        
909        let test = RelativeDname::from_slice(b"\x03www\x07example").unwrap();
910        assert!(!root.starts_with(&test));
911        assert!( wecr.starts_with(&test));
912
913        let test = RelativeDname::from_slice(b"\x03www\x07example\x03com")
914                                 .unwrap();
915        assert!(!root.starts_with(&test));
916        assert!( wecr.starts_with(&test));
917
918        let test = RelativeDname::from_slice(b"\x07example\x03com").unwrap();
919        assert!(!root.starts_with(&test));
920        assert!(!wecr.starts_with(&test));
921
922        let test = RelativeDname::from_slice(b"\x03www").unwrap()
923                    .chain(RelativeDname::from_slice(b"\x07example").unwrap())
924                    .unwrap();
925        assert!(!root.starts_with(&test));
926        assert!( wecr.starts_with(&test));
927
928        let test = test.chain(RelativeDname::from_slice(b"\x03com")
929                                            .unwrap())
930                       .unwrap();
931        assert!(!root.starts_with(&test));
932        assert!( wecr.starts_with(&test));
933    }
934
935    #[test]
936    fn ends_with() {
937        let root = Dname::root();
938        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
939
940        for name in wecr.iter_suffixes() {
941            if name.is_root() {
942                assert!(root.ends_with(&name));
943            }
944            else {
945                assert!(!root.ends_with(&name));
946            }
947            assert!(wecr.ends_with(&name));
948        }
949    }
950
951    #[test]
952    fn is_label_start() {
953        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
954
955        assert!( wecr.is_label_start(0)); // \x03
956        assert!(!wecr.is_label_start(1)); // w
957        assert!(!wecr.is_label_start(2)); // w
958        assert!(!wecr.is_label_start(3)); // w
959        assert!( wecr.is_label_start(4)); // \x07
960        assert!(!wecr.is_label_start(5)); // e
961        assert!(!wecr.is_label_start(6)); // x
962        assert!(!wecr.is_label_start(7)); // a
963        assert!(!wecr.is_label_start(8)); // m
964        assert!(!wecr.is_label_start(9)); // p
965        assert!(!wecr.is_label_start(10)); // l
966        assert!(!wecr.is_label_start(11)); // e
967        assert!( wecr.is_label_start(12)); // \x03
968        assert!(!wecr.is_label_start(13)); // c
969        assert!(!wecr.is_label_start(14)); // o
970        assert!(!wecr.is_label_start(15)); // m
971        assert!( wecr.is_label_start(16)); // \0
972        assert!(!wecr.is_label_start(17)); //
973        assert!(!wecr.is_label_start(18)); //
974    }
975
976    #[test]
977    fn slice() {
978        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
979
980        assert_eq!(wecr.slice(0, 4).as_slice(), b"\x03www");
981        assert_eq!(wecr.slice(0, 12).as_slice(), b"\x03www\x07example");
982        assert_eq!(wecr.slice(4, 12).as_slice(), b"\x07example");
983        assert_eq!(wecr.slice(4, 16).as_slice(), b"\x07example\x03com");
984
985        assert_panic!(wecr.slice(0,3));
986        assert_panic!(wecr.slice(1,4));
987        assert_panic!(wecr.slice(0,11));
988        assert_panic!(wecr.slice(1,12));
989        assert_panic!(wecr.slice(0,17));
990        assert_panic!(wecr.slice(4,17));
991        assert_panic!(wecr.slice(0,18));
992    }
993
994    #[test]
995    fn slice_from() {
996        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
997
998        assert_eq!(wecr.slice_from(0).as_slice(),
999                   b"\x03www\x07example\x03com\0");
1000        assert_eq!(wecr.slice_from(4).as_slice(), b"\x07example\x03com\0");
1001        assert_eq!(wecr.slice_from(12).as_slice(), b"\x03com\0");
1002        assert_eq!(wecr.slice_from(16).as_slice(), b"\0");
1003
1004        assert_panic!(wecr.slice_from(17));
1005        assert_panic!(wecr.slice_from(18));
1006    }
1007
1008    #[test]
1009    fn slice_to() {
1010        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
1011
1012        assert_eq!(wecr.slice_to(0).as_slice(), b"");
1013        assert_eq!(wecr.slice_to(4).as_slice(), b"\x03www");
1014        assert_eq!(wecr.slice_to(12).as_slice(), b"\x03www\x07example");
1015        assert_eq!(wecr.slice_to(16).as_slice(), b"\x03www\x07example\x03com");
1016
1017        assert_panic!(wecr.slice_to(17));
1018        assert_panic!(wecr.slice_to(18));
1019    }
1020
1021    #[test]
1022    fn split_off() {
1023        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
1024
1025        let (left, right) = wecr.clone().split_off(0);
1026        assert_eq!(left.as_slice(), b"");
1027        assert_eq!(right.as_slice(), b"\x03www\x07example\x03com\0");
1028
1029        let (left, right) = wecr.clone().split_off(4);
1030        assert_eq!(left.as_slice(), b"\x03www");
1031        assert_eq!(right.as_slice(), b"\x07example\x03com\0");
1032
1033        let (left, right) = wecr.clone().split_off(12);
1034        assert_eq!(left.as_slice(), b"\x03www\x07example");
1035        assert_eq!(right.as_slice(), b"\x03com\0");
1036
1037        let (left, right) = wecr.clone().split_off(16);
1038        assert_eq!(left.as_slice(), b"\x03www\x07example\x03com");
1039        assert_eq!(right.as_slice(), b"\0");
1040
1041        assert_panic!(wecr.clone().split_off(1));
1042        assert_panic!(wecr.clone().split_off(14));
1043        assert_panic!(wecr.clone().split_off(17));
1044        assert_panic!(wecr.clone().split_off(18));
1045    }
1046
1047    #[test]
1048    fn split_to() {
1049        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
1050
1051        let mut tmp = wecr.clone();
1052        assert_eq!(tmp.split_to(0).as_slice(), b"");
1053        assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com\0");
1054
1055        let mut tmp = wecr.clone();
1056        assert_eq!(tmp.split_to(4).as_slice(), b"\x03www");
1057        assert_eq!(tmp.as_slice(), b"\x07example\x03com\0");
1058
1059        let mut tmp = wecr.clone();
1060        assert_eq!(tmp.split_to(12).as_slice(), b"\x03www\x07example");
1061        assert_eq!(tmp.as_slice(), b"\x03com\0");
1062
1063        let mut tmp = wecr.clone();
1064        assert_eq!(tmp.split_to(16).as_slice(), b"\x03www\x07example\x03com");
1065        assert_eq!(tmp.as_slice(), b"\0");
1066
1067        assert_panic!(wecr.clone().split_to(1));
1068        assert_panic!(wecr.clone().split_to(14));
1069        assert_panic!(wecr.clone().split_to(17));
1070        assert_panic!(wecr.clone().split_to(18));
1071    }
1072
1073    #[test]
1074    fn truncate() {
1075        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
1076
1077        assert_eq!(wecr.clone().truncate(0).as_slice(),
1078                   b"");
1079        assert_eq!(wecr.clone().truncate(4).as_slice(),
1080                   b"\x03www");
1081        assert_eq!(wecr.clone().truncate(12).as_slice(),
1082                   b"\x03www\x07example");
1083        assert_eq!(wecr.clone().truncate(16).as_slice(),
1084                   b"\x03www\x07example\x03com");
1085        
1086        assert_panic!(wecr.clone().truncate(1));
1087        assert_panic!(wecr.clone().truncate(14));
1088        assert_panic!(wecr.clone().truncate(17));
1089        assert_panic!(wecr.clone().truncate(18));
1090    }
1091
1092    #[test]
1093    fn split_first() {
1094        let mut wecr = Dname::from_slice(b"\x03www\x07example\x03com\0")
1095                             .unwrap();
1096
1097        assert_eq!(wecr.split_first().unwrap().as_slice(), b"\x03www");
1098        assert_eq!(wecr.as_slice(), b"\x07example\x03com\0");
1099        assert_eq!(wecr.split_first().unwrap().as_slice(), b"\x07example");
1100        assert_eq!(wecr.as_slice(), b"\x03com\0");
1101        assert_eq!(wecr.split_first().unwrap().as_slice(), b"\x03com");
1102        assert_eq!(wecr.as_slice(), b"\0");
1103        assert!(wecr.split_first().is_none());
1104        assert_eq!(wecr.as_slice(), b"\0");
1105        assert!(wecr.split_first().is_none());
1106        assert_eq!(wecr.as_slice(), b"\0");
1107    }
1108
1109    #[test]
1110    fn parent() {
1111        let mut wecr = Dname::from_slice(b"\x03www\x07example\x03com\0")
1112                             .unwrap();
1113
1114        assert!(wecr.parent());
1115        assert_eq!(wecr.as_slice(), b"\x07example\x03com\0");
1116        assert!(wecr.parent());
1117        assert_eq!(wecr.as_slice(), b"\x03com\0");
1118        assert!(wecr.parent());
1119        assert_eq!(wecr.as_slice(), b"\0");
1120        assert!(!wecr.parent());
1121        assert_eq!(wecr.as_slice(), b"\0");
1122        assert!(!wecr.parent());
1123        assert_eq!(wecr.as_slice(), b"\0");
1124    }
1125
1126    #[test]
1127    fn strip_suffix() {
1128        let wecr = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
1129        let ecr = Dname::from_slice(b"\x07example\x03com\0").unwrap();
1130        let cr = Dname::from_slice(b"\x03com\0").unwrap();
1131        let wenr = Dname::from_slice(b"\x03www\x07example\x03net\0").unwrap();
1132        let enr = Dname::from_slice(b"\x07example\x03net\0").unwrap();
1133        let nr = Dname::from_slice(b"\x03net\0").unwrap();
1134
1135        assert_eq!(wecr.clone().strip_suffix(&wecr).unwrap().as_slice(),
1136                   b"");
1137        assert_eq!(wecr.clone().strip_suffix(&ecr).unwrap().as_slice(),
1138                   b"\x03www");
1139        assert_eq!(wecr.clone().strip_suffix(&cr).unwrap().as_slice(),
1140                   b"\x03www\x07example");
1141        assert_eq!(wecr.clone().strip_suffix(&Dname::root())
1142                               .unwrap().as_slice(),
1143                   b"\x03www\x07example\x03com");
1144
1145        assert_eq!(wecr.clone().strip_suffix(&wenr).unwrap_err().as_slice(),
1146                   b"\x03www\x07example\x03com\0");
1147        assert_eq!(wecr.clone().strip_suffix(&enr).unwrap_err().as_slice(),
1148                   b"\x03www\x07example\x03com\0");
1149        assert_eq!(wecr.clone().strip_suffix(&nr).unwrap_err().as_slice(),
1150                   b"\x03www\x07example\x03com\0");
1151    }
1152
1153    #[test]
1154    fn parse() {
1155        // Parse a correctly formatted name.
1156        let mut p = Parser::from_static(b"\x03www\x07example\x03com\0af");
1157        assert_eq!(Dname::parse(&mut p).unwrap().as_slice(),
1158                  b"\x03www\x07example\x03com\0");
1159        assert_eq!(p.peek_all(), b"af");
1160
1161        // Short buffer in middle of label.
1162        let mut p = Parser::from_static(b"\x03www\x07exam");
1163        assert_eq!(Dname::parse(&mut p), Err(ShortBuf.into()));
1164
1165        // Short buffer at end of label.
1166        let mut p = Parser::from_static(b"\x03www\x07example");
1167        assert_eq!(Dname::parse(&mut p), Err(ShortBuf.into()));
1168
1169        // Compressed name.
1170        let mut p = Parser::from_static(b"\x03com\x03www\x07example\xc0\0");
1171        p.advance(4).unwrap();
1172        assert_eq!(Dname::parse(&mut p),
1173                   Err(DnameError::CompressedName.into()));
1174
1175        // Bad label header.
1176        let mut p = Parser::from_static(b"\x03www\x07example\xbffoo");
1177        assert_eq!(Dname::parse(&mut p),
1178                   Err(LabelTypeError::Undefined.into()));
1179
1180        // Long name: 255 bytes is fine.
1181        let mut buf = Vec::new();
1182        for _ in 0..50 {
1183            buf.extend_from_slice(b"\x041234");
1184        }
1185        buf.extend_from_slice(b"\x03123\0");
1186        assert_eq!(buf.len(), 255);
1187        let mut p = Parser::from_bytes(buf.into());
1188        assert!(Dname::parse(&mut p).is_ok());
1189        assert_eq!(p.peek_all(), b"");
1190
1191        // Long name: 256 bytes are bad.
1192        let mut buf = Vec::new();
1193        for _ in 0..51 {
1194            buf.extend_from_slice(b"\x041234");
1195        }
1196        buf.extend_from_slice(b"\0");
1197        assert_eq!(buf.len(), 256);
1198        let mut p = Parser::from_bytes(buf.into());
1199        assert_eq!(Dname::parse(&mut p),
1200                   Err(DnameError::LongName.into()));
1201    }
1202
1203    #[test]
1204    fn parse_all() {
1205        // The current implementation defers to `Dname::from_bytes`. As there
1206        // are test cases for the error cases with that function, all we need
1207        // to do is make sure it defers correctly.
1208
1209        let mut p = Parser::from_static(b"\x03www\x07example\x03com\0af");
1210        assert_eq!(Dname::parse_all(&mut p, 17).unwrap().as_slice(),
1211                  b"\x03www\x07example\x03com\0");
1212        assert_eq!(p.peek_all(), b"af");
1213        
1214        let mut p = Parser::from_static(b"\0af");
1215        assert_eq!(Dname::parse_all(&mut p, 1).unwrap().as_slice(), b"\0");
1216        assert_eq!(p.peek_all(), b"af");
1217    }
1218
1219    // I don’t think we need tests for `Compose` and `Compress`. The
1220    // former only copies the underlying bytes, the latter simply
1221    // defers to `Compressor::compress_name` which is tested separately.
1222
1223    #[test]
1224    fn from_str() {
1225        // Another simple test. `UncertainDname` does all the heavy lifting,
1226        // so we don’t need to test all the escape sequence shenanigans here.
1227        // Just check that we’ll always get a name, final dot or not, unless
1228        // the string is empty.
1229        use std::str::FromStr;
1230
1231        assert_eq!(Dname::from_str("www.example.com").unwrap().as_slice(),
1232                   b"\x03www\x07example\x03com\0");
1233        assert_eq!(Dname::from_str("www.example.com.").unwrap().as_slice(),
1234                   b"\x03www\x07example\x03com\0");
1235    }
1236
1237    #[test]
1238    fn eq() {
1239        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
1240                   Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap());
1241        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
1242                   Dname::from_slice(b"\x03wWw\x07eXAMple\x03Com\0").unwrap());
1243        assert_eq!(
1244            Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
1245            RelativeDname::from_slice(b"\x03www").unwrap()
1246                .chain(RelativeDname::from_slice(b"\x07example\x03com")
1247                                     .unwrap())
1248                    .unwrap()
1249                .chain(Dname::root()).unwrap()
1250        );
1251        assert_eq!(
1252            Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
1253            RelativeDname::from_slice(b"\x03wWw").unwrap()
1254                .chain(RelativeDname::from_slice(b"\x07eXAMple\x03coM")
1255                                     .unwrap())
1256                    .unwrap()
1257                .chain(Dname::root()).unwrap()
1258        );
1259
1260        assert_ne!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
1261                   Dname::from_slice(b"\x03ww4\x07example\x03com\0").unwrap());
1262        assert_ne!(
1263            Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
1264            RelativeDname::from_slice(b"\x03www").unwrap()
1265                .chain(RelativeDname::from_slice(b"\x073xample\x03com")
1266                                     .unwrap())
1267                    .unwrap()
1268                .chain(Dname::root()).unwrap()
1269        );
1270    }
1271
1272    #[test]
1273    fn cmp() {
1274        // The following is taken from section 6.1 of RFC 4034.
1275        let names = [
1276            Dname::from_slice(b"\x07example\0").unwrap(),
1277            Dname::from_slice(b"\x01a\x07example\0").unwrap(),
1278            Dname::from_slice(b"\x08yljkjljk\x01a\x07example\0").unwrap(),
1279            Dname::from_slice(b"\x01Z\x01a\x07example\0").unwrap(),
1280            Dname::from_slice(b"\x04zABC\x01a\x07example\0").unwrap(),
1281            Dname::from_slice(b"\x01z\x07example\0").unwrap(),
1282            Dname::from_slice(b"\x01\x01\x01z\x07example\0").unwrap(),
1283            Dname::from_slice(b"\x01*\x01z\x07example\0").unwrap(),
1284            Dname::from_slice(b"\x01\xc8\x01z\x07example\0").unwrap(),
1285        ];
1286        for i in 0..names.len() {
1287            for j in 0..names.len() {
1288                let ord = if i < j { Ordering::Less }
1289                          else if i == j { Ordering::Equal }
1290                          else { Ordering::Greater };
1291                assert_eq!(names[i].partial_cmp(&names[j]), Some(ord));
1292                assert_eq!(names[i].cmp(&names[j]), ord);
1293            }
1294        }
1295
1296        let n1 = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
1297        let n2 = Dname::from_slice(b"\x03wWw\x07eXAMple\x03Com\0").unwrap();
1298        assert_eq!(n1.partial_cmp(&n2), Some(Ordering::Equal));
1299        assert_eq!(n1.cmp(&n2), Ordering::Equal);
1300    }
1301
1302    #[test]
1303    fn hash() {
1304        use std::collections::hash_map::DefaultHasher;
1305        use std::hash::{Hash, Hasher};
1306
1307        let mut s1 = DefaultHasher::new();
1308        let mut s2 = DefaultHasher::new();
1309        Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap()
1310              .hash(&mut s1);
1311        Dname::from_slice(b"\x03wWw\x07eXAMple\x03Com\0").unwrap()
1312              .hash(&mut s2);
1313        assert_eq!(s1.finish(), s2.finish());
1314    }
1315
1316    // Scan and Display skipped for now.
1317}
1318