domain_core/bits/name/
relative.rs

1/// Uncompressed, relative domain names.
2///
3/// This is a private module. Its public types are re-exported by the parent.
4
5use std::{cmp, fmt, hash, ops};
6use bytes::{BufMut, Bytes};
7use ::bits::compose::Compose;
8use super::builder::DnameBuilder;
9use super::chain::{Chain, LongChainError};
10use super::dname::Dname;
11use super::label::{Label, LabelTypeError, SplitLabelError};
12use super::traits::{ToLabelIter, ToRelativeDname};
13
14
15//------------ RelativeDname -------------------------------------------------
16
17/// An uncompressed, relative domain name.
18///
19/// A relative domain name is one that doesn’t end with the root label. As the
20/// name suggests, it is relative to some other domain name. This type wraps
21/// a [`Bytes`] value containing such a relative name similarly to the way
22/// [`Dname`] wraps an absolute one. In fact, it behaves very similarly to
23/// [`Dname`] taking into account differences when slicing and dicing names.
24///
25/// `RelativeDname` guarantees that the name is at most 254 bytes long. As the
26/// length limit for a domain name is actually 255 bytes, this means that you
27/// can always safely turn a `RelativeDname` into a `Dname` by adding the root
28/// label (which is exactly one byte long).
29///
30/// [`Bytes`]: ../../../bytes/struct.Bytes.html
31/// [`Dname`]: struct.Dname.html
32#[derive(Clone)]
33pub struct RelativeDname {
34    bytes: Bytes,
35}
36
37/// # Creation and Conversion
38///
39impl RelativeDname {
40    /// Creates a relative domain name from a bytes value without checking.
41    ///
42    /// Since the content of the bytes value can be anything, really, this is
43    /// an unsafe function.
44    pub(super) unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self {
45        RelativeDname { bytes }
46    }
47
48    /// Creates an empty relative domain name.
49    ///
50    /// Determining what this could possibly be useful for is left as an
51    /// excercise to the reader.
52    pub fn empty() -> Self {
53        unsafe {
54            RelativeDname::from_bytes_unchecked(Bytes::from_static(b""))
55        }
56    }
57
58    /// Creates a relative domain name representing the wildcard label.
59    ///
60    /// The wildcard label is intended to match any label. There are special
61    /// rules for names with wildcard labels. Note that the comparison traits
62    /// implemented for domain names do *not* consider wildcards and treat
63    /// them as regular labels.
64    pub fn wildcard() -> Self {
65        unsafe {
66            RelativeDname::from_bytes_unchecked(Bytes::from_static(b"\x01*"))
67        }
68    }
69
70    /// Creates a relative domain name from a bytes value.
71    ///
72    /// This checks that `bytes` contains a properly encoded relative domain
73    /// name and fails if it doesn’t.
74    pub fn from_bytes(bytes: Bytes) -> Result<Self, RelativeDnameError> {
75        if bytes.len() > 254 {
76            return Err(RelativeDnameError::LongName)
77        }
78        {
79            let mut tmp = bytes.as_ref();
80            while !tmp.is_empty() {
81                let (label, tail) = Label::split_from(tmp)?;
82                if label.is_root() {
83                    return Err(RelativeDnameError::AbsoluteName);
84                }
85                tmp = tail;
86            }
87        }
88        Ok(unsafe { RelativeDname::from_bytes_unchecked(bytes) })
89    }
90
91    /// Creates a relative domain name from a byte slice.
92    ///
93    /// The function will create a new bytes value from the slice’s content.
94    /// If the slice does not contain a correctly encoded, relative domain
95    /// name, the function will fail.
96    pub fn from_slice(slice: &[u8]) -> Result<Self, RelativeDnameError> {
97        Self::from_bytes(slice.into())
98    }
99
100    /// Returns a reference to the underlying bytes value.
101    pub fn as_bytes(&self) -> &Bytes {
102        &self.bytes
103    }
104
105    /// Returns a reference to the underlying byte slice.
106    pub fn as_slice(&self) -> &[u8] {
107        self.bytes.as_ref()
108    }
109
110    /// Converts the name into the underlying bytes value.
111    pub fn into_bytes(self) -> Bytes {
112        self.bytes
113    }
114
115    /// Converts the name into a domain name builder for appending data.
116    ///
117    /// If the underlying bytes value can be converted into a [`BytesMut`][]
118    /// (via its [`try_mut`] method), the builder will use that directly.
119    /// Otherwise, it will create an all new [`BytesMut`] from the name’s
120    /// content.
121    ///
122    /// [`BytesMut`]: ../../../bytes/struct.BytesMut.html
123    /// [`try_mut`]: ../../../bytes/struct.BytesMut.html#method.try_mut
124    pub fn into_builder(self) -> DnameBuilder {
125        let bytes = match self.bytes.try_mut() {
126            Ok(bytes) => bytes,
127            Err(bytes) => bytes.as_ref().into()
128        };
129        unsafe { DnameBuilder::from_bytes(bytes) }
130    }
131
132    /// Converts the name into an absolute name by appending the root label.
133    ///
134    /// This manipulates the name itself and thus may have to copy it. If
135    /// you just need an absolute name, you can perhaps use [`chain_root`]
136    /// instead.
137    ///
138    /// [`chain_root`]: #method.chain_root
139    pub fn into_absolute(self) -> Dname {
140        self.into_builder().into_dname().unwrap()
141    }
142
143    /// Creates a domain name by concatenating `self` with `other`.
144    ///
145    /// Depending on whether `other` is an absolute or relative domain name,
146    /// the resulting name will behave like an absolute or relative name.
147    /// 
148    /// The method will fail if the combined length of the two names is
149    /// greater than the size limit of 255. Note that in this case you will
150    /// loose both `self` and `other`, so it might be worthwhile to check
151    /// first.
152    pub fn chain<N: Compose>(self, other: N)
153                                -> Result<Chain<Self, N>, LongChainError> {
154        Chain::new(self, other)
155    }
156
157    /// Creates an absolute name by chaining the root label to it.
158    pub fn chain_root(self) -> Chain<Self, Dname> {
159        self.chain(Dname::root()).unwrap()
160    }
161}
162
163/// # Working with Labels
164///
165impl RelativeDname {
166    /// Returns an iterator over the labels of the domain name.
167    pub fn iter(&self) -> DnameIter {
168        DnameIter::new(self.bytes.as_ref())
169    }
170
171    /// Returns the number of labels in the name.
172    pub fn label_count(&self) -> usize {
173        self.iter().count()
174    }
175
176    /// Returns a reference to the first label if the name isn’t empty.
177    pub fn first(&self) -> Option<&Label> {
178        self.iter().next()
179    }
180
181    /// Returns a reference to the last label if the name isn’t empty.
182    pub fn last(&self) -> Option<&Label> {
183        self.iter().next_back()
184    }
185
186    /// Returns the number of dots in the string representation of the name.
187    ///
188    /// Specifically, returns a value equal to the number of labels minus one,
189    /// except for an empty name where it returns a zero, also.
190    pub fn ndots(&self) -> usize {
191        if self.is_empty() { 0 }
192        else {
193            self.label_count() - 1
194        }
195    }
196
197    /// Determines whether `base` is a prefix of `self`.
198    pub fn starts_with<'a, N: ToLabelIter<'a>>(&'a self, base: &'a N) -> bool {
199        <Self as ToLabelIter>::starts_with(self, base)
200    }
201
202    /// Determines whether `base` is a suffix of `self`.
203    pub fn ends_with<'a, N: ToLabelIter<'a>>(&'a self, base: &'a N) -> bool {
204        <Self as ToLabelIter>::ends_with(self, base)
205    }
206
207    /// Returns whether an index points to the first byte of a label.
208    pub fn is_label_start(&self, mut index: usize) -> bool {
209        if index == 0 {
210            return true
211        }
212        let mut tmp = self.as_slice();
213        while !tmp.is_empty() {
214            let (label, tail) = Label::split_from(tmp).unwrap();
215            let len = label.len() + 1;
216            if index < len {
217                return false
218            }
219            else if index == len {
220                return true
221            }
222            index -= len;
223            tmp = tail;
224        }
225        false
226    }
227
228    /// Like `is_label_start` but panics if it isn’t.
229    fn check_index(&self, index: usize) {
230        if !self.is_label_start(index) {
231            panic!("index not at start of a label");
232        }
233    }
234
235    /// Returns a part of the name indicated by start and end positions.
236    ///
237    /// The returned name will start at position `begin` and end right before
238    /// position `end`. Both positions need to be the beginning of a label.
239    ///
240    /// # Panics
241    ///
242    /// The method panics if either position is not the beginning of a label
243    /// or is out of bounds.
244    pub fn slice(&self, begin: usize, end: usize) -> Self {
245        self.check_index(begin);
246        self.check_index(end);
247        unsafe { Self::from_bytes_unchecked(self.bytes.slice(begin, end)) }
248    }
249
250    /// Returns the part of the name starting at the given position.
251    ///
252    /// # Panics
253    ///
254    /// The method panics if the position is not the beginning of a label
255    /// or is beyond the end of the name.
256    pub fn slice_from(&self, begin: usize) -> Self {
257        self.check_index(begin);
258        unsafe { Self::from_bytes_unchecked(self.bytes.slice_from(begin)) }
259    }
260
261    /// Returns the part of the name ending before the given position.
262    ///
263    /// # Panics
264    ///
265    /// The method panics if the position is not the beginning of a label
266    /// or is beyond the end of the name.
267    pub fn slice_to(&self, end: usize) -> Self {
268        self.check_index(end);
269        unsafe { Self::from_bytes_unchecked(self.bytes.slice_to(end)) }
270    }
271
272    /// Splits the name into two at the given position.
273    ///
274    /// Afterwards, `self` will contain the name ending before the position
275    /// while the name starting at the position will be returned.
276    ///
277    /// # Panics
278    ///
279    /// The method panics if the position is not the beginning of a label
280    /// or is beyond the end of the name.
281    pub fn split_off(&mut self, mid: usize) -> Self {
282        self.check_index(mid);
283        unsafe { Self::from_bytes_unchecked(self.bytes.split_off(mid)) }
284    }
285
286    /// Splits the name into two at the given position.
287    ///
288    /// Afterwards, `self` will contain the name starting at the position
289    /// while the name ending right before it will be returned. 
290    ///
291    /// # Panics
292    ///
293    /// The method panics if the position is not the beginning of a label
294    /// or is beyond the end of the name.
295    pub fn split_to(&mut self, mid: usize) -> Self {
296        self.check_index(mid);
297        unsafe { Self::from_bytes_unchecked(self.bytes.split_to(mid)) }
298    }
299
300    /// Truncates the name to the given length.
301    ///
302    /// # Panics
303    ///
304    /// The method panics if the position is not the beginning of a label
305    /// or is beyond the end of the name.
306    pub fn truncate(&mut self, len: usize) {
307        self.check_index(len);
308        self.bytes.truncate(len);
309    }
310
311    /// Splits off the first label.
312    ///
313    /// If there is at least one label in the name, returns the first label
314    /// as a relative domain name with exactly one label and makes `self`
315    /// contain the domain name starting after that first label. If the name
316    /// is empty, returns `None`.
317    pub fn split_first(&mut self) -> Option<Self> {
318        if self.is_empty() {
319            return None
320        }
321        let first_end = match self.iter().next() {
322            Some(label) => label.len() + 1,
323            None => return None
324        };
325        Some(unsafe {
326            Self::from_bytes_unchecked(self.bytes.split_to(first_end))
327        })
328    }
329
330    /// Reduces the name to its parent.
331    ///
332    /// Returns whether that actually happened, since if the name is already
333    /// empty it can’t.
334    pub fn parent(&mut self) -> bool {
335        self.split_first().is_some()
336    }
337
338    /// Strips the suffix `base` from the domain name.
339    ///
340    /// This will fail if `base` isn’t actually a suffix, i.e., if
341    /// [`ends_with`] doesn’t return `true`.
342    ///
343    /// [`ends_with`]: #method.ends_with
344    pub fn strip_suffix<N: ToRelativeDname>(&mut self, base: &N)
345                                            -> Result<(), StripSuffixError> {
346        if self.ends_with(base) {
347            let idx = self.bytes.len() - base.compose_len();
348            self.bytes.split_off(idx);
349            Ok(())
350        }
351        else {
352            Err(StripSuffixError)
353        }
354    }
355}
356
357
358//--- Compose
359
360impl Compose for RelativeDname {
361    fn compose_len(&self) -> usize {
362        self.bytes.len()
363    }
364
365    fn compose<B: BufMut>(&self, buf: &mut B) {
366        buf.put_slice(self.as_ref())
367    }
368}
369
370
371//--- ToLabelIter and ToRelativeDname
372
373impl<'a> ToLabelIter<'a> for RelativeDname {
374    type LabelIter = DnameIter<'a>;
375
376    fn iter_labels(&'a self) -> Self::LabelIter {
377        self.iter()
378    }
379}
380
381impl ToRelativeDname for RelativeDname {
382    fn to_name(&self) -> RelativeDname {
383        self.clone()
384    }
385    
386    fn as_flat_slice(&self) -> Option<&[u8]> {
387        Some(self.as_slice())
388    }
389}
390
391
392//--- Deref and AsRef
393
394impl ops::Deref for RelativeDname {
395    type Target = Bytes;
396
397    fn deref(&self) -> &Bytes {
398        self.as_ref()
399    }
400}
401
402impl AsRef<Bytes> for RelativeDname {
403    fn as_ref(&self) -> &Bytes {
404        &self.bytes
405    }
406}
407
408impl AsRef<[u8]> for RelativeDname {
409    fn as_ref(&self) -> &[u8] {
410        self.bytes.as_ref()
411    }
412}
413
414
415//--- IntoIterator
416
417impl<'a> IntoIterator for &'a RelativeDname {
418    type Item = &'a Label;
419    type IntoIter = DnameIter<'a>;
420
421    fn into_iter(self) -> Self::IntoIter {
422        self.iter()
423    }
424}
425
426
427//--- PartialEq and Eq
428
429impl<N: ToRelativeDname> PartialEq<N> for RelativeDname {
430    fn eq(&self, other: &N) -> bool {
431        self.name_eq(other)
432    }
433}
434
435impl Eq for RelativeDname { }
436
437
438//--- PartialOrd and Ord
439
440impl PartialOrd for RelativeDname {
441    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
442        Some(self.name_cmp(other))
443    }
444}
445
446impl Ord for RelativeDname {
447    fn cmp(&self, other: &Self) -> cmp::Ordering {
448        self.name_cmp(other)
449    }
450}
451
452
453//--- Hash
454
455impl hash::Hash for RelativeDname {
456    fn hash<H: hash::Hasher>(&self, state: &mut H) {
457        for item in self.iter() {
458            item.hash(state)
459        }
460    }
461}
462
463
464//--- Display and Debug
465
466impl fmt::Display for RelativeDname {
467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
468        let mut iter = self.iter();
469        match iter.next() {
470            Some(label) => label.fmt(f)?,
471            None => return Ok(())
472        }
473        for label in iter {
474            f.write_str(".")?;
475            label.fmt(f)?;
476        }
477        Ok(())
478    }
479}
480
481impl fmt::Debug for RelativeDname {
482    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483        write!(f, "RelativeDname({})", self)
484    }
485}
486
487
488//------------ DnameIter -----------------------------------------------------
489
490/// An iterator over the labels in an uncompressed name.
491#[derive(Clone, Debug)]
492pub struct DnameIter<'a> {
493    slice: &'a [u8],
494}
495
496impl<'a> DnameIter<'a> {
497    pub(super) fn new(slice: &'a [u8]) -> Self {
498        DnameIter { slice }
499    }
500}
501
502impl<'a> Iterator for DnameIter<'a> {
503    type Item = &'a Label;
504
505    fn next(&mut self) -> Option<Self::Item> {
506        let (label, tail) = match Label::split_from(self.slice) {
507            Ok(res) => res,
508            Err(_) => return None,
509        };
510        self.slice = tail;
511        Some(label)
512    }
513}
514
515impl<'a> DoubleEndedIterator for DnameIter<'a> {
516    fn next_back(&mut self) -> Option<Self::Item> {
517        if self.slice.is_empty() {
518            return None
519        }
520        let mut tmp = self.slice;
521        loop {
522            let (label, tail) = Label::split_from(tmp).unwrap();
523            if tail.is_empty() {
524                let end = self.slice.len() - (label.len() + 1);
525                self.slice = &self.slice[..end];
526                return Some(label)
527            }
528            else {
529                tmp = tail
530            }
531        }
532    }
533}
534
535
536//------------ RelativeDnameError --------------------------------------------
537
538/// An error happened while creating a domain name from octets.
539#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
540pub enum RelativeDnameError {
541    /// A bad label was encountered.
542    #[fail(display="{}", _0)]
543    BadLabel(LabelTypeError),
544
545    /// A compressed name was encountered.
546    #[fail(display="compressed domain name")]
547    CompressedName,
548
549    /// The data ended before the end of a label.
550    #[fail(display="unexpected end of input")]
551    ShortData,
552
553    /// The domain name was longer than 255 octets.
554    #[fail(display="long domain name")]
555    LongName,
556
557    /// The root label was encountered.
558    #[fail(display="absolute domain name")]
559    AbsoluteName,
560}
561
562impl From<LabelTypeError> for RelativeDnameError {
563    fn from(err: LabelTypeError) -> Self {
564        RelativeDnameError::BadLabel(err)
565    }
566}
567
568impl From<SplitLabelError> for RelativeDnameError {
569    fn from(err: SplitLabelError) -> Self {
570        match err {
571            SplitLabelError::Pointer(_) => RelativeDnameError::CompressedName,
572            SplitLabelError::BadType(t) => RelativeDnameError::BadLabel(t),
573            SplitLabelError::ShortBuf => RelativeDnameError::ShortData,
574        }
575    }
576}
577
578
579//------------ StripSuffixError ----------------------------------------------
580
581/// An attempt was made to strip a suffix that wasn’t actually a suffix.
582#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
583#[fail(display="suffix not found")]
584pub struct StripSuffixError;
585
586
587//============ Testing =======================================================
588
589#[cfg(test)]
590mod test {
591    use super::*;
592    use ::bits::parse::ShortBuf;
593
594    macro_rules! assert_panic {
595        ( $cond:expr ) => {
596            {
597                let result = ::std::panic::catch_unwind(|| $cond);
598                assert!(result.is_err());
599            }
600        }
601    }
602
603    #[test]
604    fn empty() {
605        assert_eq!(RelativeDname::empty().as_slice(), b"");
606    }
607
608    #[test]
609    fn wildcard() {
610        assert_eq!(RelativeDname::wildcard().as_slice(), b"\x01*");
611    }
612
613    #[test]
614    fn from_slice() {
615        // good names
616        assert_eq!(RelativeDname::from_slice(b"").unwrap().as_slice(), b"");
617        assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap().as_slice(),
618                   b"\x03www");
619        assert_eq!(RelativeDname::from_slice(b"\x03www\x07example")
620                                 .unwrap().as_slice(),
621                   b"\x03www\x07example");
622
623        // absolute names
624        assert_eq!(RelativeDname::from_slice(b"\x03www\x07example\x03com\0"),
625                   Err(RelativeDnameError::AbsoluteName));
626        assert_eq!(RelativeDname::from_slice(b"\0"),
627                   Err(RelativeDnameError::AbsoluteName));
628
629        // bytes shorter than what label length says.
630        assert_eq!(Dname::from_slice(b"\x03www\x07exa"),
631                   Err(ShortBuf.into()));
632
633        // label 63 long ok, 64 bad.
634        let mut slice = [0u8; 64];
635        slice[0] = 63;
636        assert!(RelativeDname::from_slice(&slice[..]).is_ok());
637        let mut slice = [0u8; 65];
638        slice[0] = 64;
639        assert!(RelativeDname::from_slice(&slice[..]).is_err());
640
641        // name 254 long ok, 255 bad.
642        let mut buf = Vec::new();
643        for _ in 0..25 {
644            buf.extend_from_slice(b"\x09123456789");
645        }
646        assert_eq!(buf.len(), 250);
647        let mut tmp = buf.clone();
648        tmp.extend_from_slice(b"\x03123");
649        assert_eq!(RelativeDname::from_slice(&tmp).map(|_| ()), Ok(()));
650        buf.extend_from_slice(b"\x041234");
651        assert!(RelativeDname::from_slice(&buf).is_err());
652        
653        // bad label heads: compressed, other types.
654        assert_eq!(RelativeDname::from_slice(b"\xa2asdasds"),
655                   Err(LabelTypeError::Undefined.into()));
656        assert_eq!(RelativeDname::from_slice(b"\x62asdasds"),
657                   Err(LabelTypeError::Extended(0x62).into()));
658        assert_eq!(RelativeDname::from_slice(b"\xccasdasds"),
659                   Err(RelativeDnameError::CompressedName.into()));
660    }
661
662    #[test]
663    fn into_absolute() {
664        assert_eq!(RelativeDname::from_slice(b"\x03www\x07example\x03com")
665                                 .unwrap().into_absolute().as_slice(),
666                   b"\x03www\x07example\x03com\0");
667    }
668
669    // chain is tested with the Chain type.
670
671    #[test]
672    fn chain_root() {
673        assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
674                   RelativeDname::from_slice(b"\x03www\x07example\x03com")
675                                 .unwrap().chain_root());
676    }
677
678    #[test]
679    fn iter() {
680        use ::bits::name::dname::test::cmp_iter;
681
682        cmp_iter(RelativeDname::empty().iter(), &[]);
683        cmp_iter(RelativeDname::wildcard().iter(), &[b"*"]);
684        cmp_iter(RelativeDname::from_slice(b"\x03www\x07example\x03com")
685                               .unwrap().iter(),
686                 &[b"www", b"example", b"com"]);
687    }
688
689    #[test]
690    fn iter_back() {
691        use ::bits::name::dname::test::cmp_iter_back;
692
693        cmp_iter_back(RelativeDname::empty().iter(), &[]);
694        cmp_iter_back(RelativeDname::wildcard().iter(), &[b"*"]);
695        cmp_iter_back(RelativeDname::from_slice(b"\x03www\x07example\x03com")
696                                    .unwrap().iter(),
697                      &[b"com", b"example", b"www"]);
698    }
699
700    #[test]
701    fn label_count() {
702        assert_eq!(RelativeDname::empty().label_count(), 0);
703        assert_eq!(RelativeDname::wildcard().label_count(), 1);
704        assert_eq!(RelativeDname::from_slice(b"\x03www\x07example\x03com")
705                                 .unwrap().label_count(),
706                   3);
707    }
708
709    #[test]
710    fn first() {
711        assert_eq!(RelativeDname::empty().first(), None);
712        assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap()
713                                 .first().unwrap().as_slice(),
714                   b"www");
715        assert_eq!(RelativeDname::from_slice(b"\x03www\x07example").unwrap()
716                                 .first().unwrap().as_slice(),
717                   b"www");
718    }
719
720    #[test]
721    fn last() {
722        assert_eq!(RelativeDname::empty().last(), None);
723        assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap()
724                                 .last().unwrap().as_slice(),
725                   b"www");
726        assert_eq!(RelativeDname::from_slice(b"\x03www\x07example").unwrap()
727                                 .last().unwrap().as_slice(),
728                   b"example");
729    }
730
731    #[test]
732    fn ndots() {
733        assert_eq!(RelativeDname::empty().ndots(), 0);
734        assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap().ndots(),
735                   0);
736        assert_eq!(RelativeDname::from_slice(b"\x03www\x07example").unwrap()
737                                 .ndots(),
738                   1);
739    }
740
741    #[test]
742    fn starts_with() {
743        let matrix = [
744            ( RelativeDname::empty(),
745              [ true, false, false, false, false, false ]),
746            ( RelativeDname::from_slice(b"\x03www").unwrap(),
747              [ true, true, false, false, false, false ]),
748            ( RelativeDname::from_slice(b"\x03www\x07example").unwrap(),
749              [ true, true, true, false, false, false ]),
750            ( RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
751              [ true, true, true, true, false, false ]),
752            ( RelativeDname::from_slice(b"\x07example\x03com").unwrap(),
753              [ true, false, false, false, true, false ]),
754            ( RelativeDname::from_slice(b"\x03com").unwrap(),
755              [ true, false, false, false, false, true ])
756        ];
757        for i in 0..6 {
758            for j in 0..6 {
759                assert_eq!(matrix[i].0.starts_with(&matrix[j].0),
760                           matrix[i].1[j],
761                           "i={}, j={}", i, j)
762            }
763        }
764    }
765
766    #[test]
767    fn ends_with() {
768        let matrix = [
769            ( RelativeDname::empty(),
770              [ true, false, false, false, false, false ]),
771            ( RelativeDname::from_slice(b"\x03www").unwrap(),
772              [ true, true, false, false, false, false ]),
773            ( RelativeDname::from_slice(b"\x03www\x07example").unwrap(),
774              [ true, false, true, false, false, false ]),
775            ( RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
776              [ true, false, false, true, true, true]),
777            ( RelativeDname::from_slice(b"\x07example\x03com").unwrap(),
778              [ true, false, false, false, true, true]),
779            ( RelativeDname::from_slice(b"\x03com").unwrap(),
780              [ true, false, false, false, false, true ]),
781        ];
782        for i in 0..matrix.len() {
783            for j in 0..matrix.len() {
784                assert_eq!(matrix[i].0.ends_with(&matrix[j].0),
785                           matrix[i].1[j],
786                           "i={}, j={}", i, j)
787            }
788        }
789    }
790
791    #[test]
792    fn is_label_start() {
793        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
794                                .unwrap();
795
796        assert!( wec.is_label_start(0)); // \x03
797        assert!(!wec.is_label_start(1)); // w
798        assert!(!wec.is_label_start(2)); // w
799        assert!(!wec.is_label_start(3)); // w
800        assert!( wec.is_label_start(4)); // \x07
801        assert!(!wec.is_label_start(5)); // e
802        assert!(!wec.is_label_start(6)); // x
803        assert!(!wec.is_label_start(7)); // a
804        assert!(!wec.is_label_start(8)); // m
805        assert!(!wec.is_label_start(9)); // p
806        assert!(!wec.is_label_start(10)); // l
807        assert!(!wec.is_label_start(11)); // e
808        assert!( wec.is_label_start(12)); // \x03
809        assert!(!wec.is_label_start(13)); // c
810        assert!(!wec.is_label_start(14)); // o
811        assert!(!wec.is_label_start(15)); // m
812        assert!( wec.is_label_start(16)); // empty label
813        assert!(!wec.is_label_start(17)); // 
814    }
815
816    #[test]
817    fn slice() {
818        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
819                                .unwrap();
820        assert_eq!(wec.slice(0, 4).as_slice(), b"\x03www");
821        assert_eq!(wec.slice(0, 12).as_slice(), b"\x03www\x07example");
822        assert_eq!(wec.slice(4, 12).as_slice(), b"\x07example");
823        assert_eq!(wec.slice(4, 16).as_slice(), b"\x07example\x03com");
824
825        assert_panic!(wec.slice(0,3));
826        assert_panic!(wec.slice(1,4));
827        assert_panic!(wec.slice(0,11));
828        assert_panic!(wec.slice(1,12));
829        assert_panic!(wec.slice(0,17));
830        assert_panic!(wec.slice(4,17));
831        assert_panic!(wec.slice(0,18));
832    }
833
834    #[test]
835    fn slice_from() {
836        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
837                                .unwrap();
838
839        assert_eq!(wec.slice_from(0).as_slice(),
840                   b"\x03www\x07example\x03com");
841        assert_eq!(wec.slice_from(4).as_slice(), b"\x07example\x03com");
842        assert_eq!(wec.slice_from(12).as_slice(), b"\x03com");
843        assert_eq!(wec.slice_from(16).as_slice(), b"");
844
845        assert_panic!(wec.slice_from(17));
846        assert_panic!(wec.slice_from(18));
847    }
848
849    #[test]
850    fn slice_to() {
851        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
852                                .unwrap();
853
854        assert_eq!(wec.slice_to(0).as_slice(), b"");
855        assert_eq!(wec.slice_to(4).as_slice(), b"\x03www");
856        assert_eq!(wec.slice_to(12).as_slice(), b"\x03www\x07example");
857        assert_eq!(wec.slice_to(16).as_slice(), b"\x03www\x07example\x03com");
858
859        assert_panic!(wec.slice_to(17));
860        assert_panic!(wec.slice_to(18));
861    }
862
863    #[test]
864    fn split_off() {
865        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
866                                .unwrap();
867
868        let mut tmp = wec.clone();
869        assert_eq!(tmp.split_off(0).as_slice(), b"\x03www\x07example\x03com");
870        assert_eq!(tmp.as_slice(), b"");
871
872        let mut tmp = wec.clone();
873        assert_eq!(tmp.split_off(4).as_slice(), b"\x07example\x03com");
874        assert_eq!(tmp.as_slice(), b"\x03www");
875
876        let mut tmp = wec.clone();
877        assert_eq!(tmp.split_off(12).as_slice(), b"\x03com");
878        assert_eq!(tmp.as_slice(), b"\x03www\x07example");
879
880        let mut tmp = wec.clone();
881        assert_eq!(tmp.split_off(16).as_slice(), b"");
882        assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
883
884        assert_panic!(wec.clone().split_off(1));
885        assert_panic!(wec.clone().split_off(14));
886        assert_panic!(wec.clone().split_off(17));
887        assert_panic!(wec.clone().split_off(18));
888    }
889
890    #[test]
891    fn split_to() {
892        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
893                                .unwrap();
894
895        let mut tmp = wec.clone();
896        assert_eq!(tmp.split_to(0).as_slice(), b"");
897        assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
898
899        let mut tmp = wec.clone();
900        assert_eq!(tmp.split_to(4).as_slice(), b"\x03www");
901        assert_eq!(tmp.as_slice(), b"\x07example\x03com");
902
903        let mut tmp = wec.clone();
904        assert_eq!(tmp.split_to(12).as_slice(), b"\x03www\x07example");
905        assert_eq!(tmp.as_slice(), b"\x03com");
906
907        let mut tmp = wec.clone();
908        assert_eq!(tmp.split_to(16).as_slice(), b"\x03www\x07example\x03com");
909        assert_eq!(tmp.as_slice(), b"");
910
911        assert_panic!(wec.clone().split_to(1));
912        assert_panic!(wec.clone().split_to(14));
913        assert_panic!(wec.clone().split_to(17));
914        assert_panic!(wec.clone().split_to(18));
915    }
916
917    #[test]
918    fn truncate() {
919        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
920                                .unwrap();
921
922        let mut tmp = wec.clone();
923        tmp.truncate(0);
924        assert_eq!(tmp.as_slice(), b"");
925
926        let mut tmp = wec.clone();
927        tmp.truncate(4);
928        assert_eq!(tmp.as_slice(), b"\x03www");
929
930        let mut tmp = wec.clone();
931        tmp.truncate(12);
932        assert_eq!(tmp.as_slice(), b"\x03www\x07example");
933
934        let mut tmp = wec.clone();
935        tmp.truncate(16);
936        assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
937        
938        assert_panic!(wec.clone().truncate(1));
939        assert_panic!(wec.clone().truncate(14));
940        assert_panic!(wec.clone().truncate(17));
941        assert_panic!(wec.clone().truncate(18));
942    }
943
944    #[test]
945    fn split_first() {
946        let mut wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
947                                    .unwrap();
948
949        assert_eq!(wec.split_first().unwrap().as_slice(), b"\x03www");
950        assert_eq!(wec.as_slice(), b"\x07example\x03com");
951        assert_eq!(wec.split_first().unwrap().as_slice(), b"\x07example");
952        assert_eq!(wec.as_slice(), b"\x03com");
953        assert_eq!(wec.split_first().unwrap().as_slice(), b"\x03com");
954        assert_eq!(wec.as_slice(), b"");
955        assert!(wec.split_first().is_none());
956        assert_eq!(wec.as_slice(), b"");
957        assert!(wec.split_first().is_none());
958        assert_eq!(wec.as_slice(), b"");
959    }
960
961    #[test]
962    fn parent() {
963        let mut wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
964                                    .unwrap();
965
966        assert!(wec.parent());
967        assert_eq!(wec.as_slice(), b"\x07example\x03com");
968        assert!(wec.parent());
969        assert_eq!(wec.as_slice(), b"\x03com");
970        assert!(wec.parent());
971        assert_eq!(wec.as_slice(), b"");
972        assert!(!wec.parent());
973        assert_eq!(wec.as_slice(), b"");
974        assert!(!wec.parent());
975        assert_eq!(wec.as_slice(), b"");
976    }
977
978    #[test]
979    fn strip_suffix() {
980        let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
981                                .unwrap();
982        let ec = RelativeDname::from_slice(b"\x07example\x03com").unwrap();
983        let c = RelativeDname::from_slice(b"\x03com").unwrap();
984        let wen = RelativeDname::from_slice(b"\x03www\x07example\x03net")
985                                .unwrap();
986        let en = RelativeDname::from_slice(b"\x07example\x03net").unwrap();
987        let n = RelativeDname::from_slice(b"\x03net").unwrap();
988
989        let mut tmp = wec.clone();
990        assert_eq!(tmp.strip_suffix(&wec), Ok(()));
991        assert_eq!(tmp.as_slice(), b"");
992
993        let mut tmp = wec.clone();
994        assert_eq!(tmp.strip_suffix(&ec), Ok(()));
995        assert_eq!(tmp.as_slice(), b"\x03www");
996
997        let mut tmp = wec.clone();
998        assert_eq!(tmp.strip_suffix(&c), Ok(()));
999        assert_eq!(tmp.as_slice(), b"\x03www\x07example");
1000
1001        let mut tmp = wec.clone();
1002        assert_eq!(tmp.strip_suffix(&RelativeDname::empty()), Ok(()));
1003        assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
1004
1005        assert_eq!(wec.clone().strip_suffix(&wen), Err(StripSuffixError));
1006        assert_eq!(wec.clone().strip_suffix(&en), Err(StripSuffixError));
1007        assert_eq!(wec.clone().strip_suffix(&n), Err(StripSuffixError));
1008    }
1009
1010    // No test for Compose since the implementation is so simple.
1011
1012    #[test]
1013    fn eq() {
1014        assert_eq!(
1015            RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1016            RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap()
1017        );
1018        assert_eq!(
1019            RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1020            RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap()
1021        );
1022        assert_eq!(
1023            RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1024            RelativeDname::from_slice(b"\x03www").unwrap()
1025                .chain(RelativeDname::from_slice(b"\x07example\x03com")
1026                                     .unwrap())
1027                .unwrap()
1028        );
1029        assert_eq!(
1030            RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1031            RelativeDname::from_slice(b"\x03wWw").unwrap()
1032                .chain(RelativeDname::from_slice(b"\x07eXAMple\x03coM")
1033                                     .unwrap())
1034                .unwrap()
1035        );
1036
1037        assert_ne!(
1038            RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1039            RelativeDname::from_slice(b"\x03ww4\x07example\x03com").unwrap()
1040        );
1041        assert_ne!(
1042            RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1043            RelativeDname::from_slice(b"\x03www").unwrap()
1044                .chain(RelativeDname::from_slice(b"\x073xample\x03com")
1045                                     .unwrap())
1046                .unwrap()
1047        );
1048    }
1049
1050    #[test]
1051    fn cmp() {
1052        use std::cmp::Ordering;
1053
1054        // The following is taken from section 6.1 of RFC 4034.
1055        let names = [
1056            RelativeDname::from_slice(b"\x07example").unwrap(),
1057            RelativeDname::from_slice(b"\x01a\x07example").unwrap(),
1058            RelativeDname::from_slice(b"\x08yljkjljk\x01a\x07example").unwrap(),
1059            RelativeDname::from_slice(b"\x01Z\x01a\x07example").unwrap(),
1060            RelativeDname::from_slice(b"\x04zABC\x01a\x07example").unwrap(),
1061            RelativeDname::from_slice(b"\x01z\x07example").unwrap(),
1062            RelativeDname::from_slice(b"\x01\x01\x01z\x07example").unwrap(),
1063            RelativeDname::from_slice(b"\x01*\x01z\x07example").unwrap(),
1064            RelativeDname::from_slice(b"\x01\xc8\x01z\x07example").unwrap(),
1065        ];
1066        for i in 0..names.len() {
1067            for j in 0..names.len() {
1068                let ord = if i < j { Ordering::Less }
1069                          else if i == j { Ordering::Equal }
1070                          else { Ordering::Greater };
1071                assert_eq!(names[i].partial_cmp(&names[j]), Some(ord));
1072                assert_eq!(names[i].cmp(&names[j]), ord);
1073            }
1074        }
1075
1076        let n1 = RelativeDname::from_slice(b"\x03www\x07example\x03com")
1077                               .unwrap();
1078        let n2 = RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com")
1079                                .unwrap();
1080        assert_eq!(n1.partial_cmp(&n2), Some(Ordering::Equal));
1081        assert_eq!(n1.cmp(&n2), Ordering::Equal);
1082    }
1083
1084    #[test]
1085    fn hash() {
1086        use std::collections::hash_map::DefaultHasher;
1087        use std::hash::{Hash, Hasher};
1088
1089        let mut s1 = DefaultHasher::new();
1090        let mut s2 = DefaultHasher::new();
1091        RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap()
1092                       .hash(&mut s1);
1093        RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap()
1094                       .hash(&mut s2);
1095        assert_eq!(s1.finish(), s2.finish());
1096    }
1097
1098    // Display and Debug skipped for now.
1099}
1100