domain/base/name/
label.rs

1//! Domain name labels.
2//!
3//! This is a private module. Its public types are re-exported by the parent
4//! module.
5
6use super::super::wire::{FormError, ParseError};
7use super::builder::{parse_escape, LabelFromStrError};
8use core::str::FromStr;
9use core::{borrow, cmp, fmt, hash, iter, ops, slice};
10use octseq::builder::OctetsBuilder;
11
12//------------ Label ---------------------------------------------------------
13
14/// An octets slice with the content of a domain name label.
15///
16/// This is an unsized type wrapping the content of a valid label.
17///
18/// There are two types of such labels: normal labels and binary labels.
19/// Normal labels consist of up to 63 octets of data. Binary labels are a
20/// sequence of up to 256 one-bit labels. They have been invented for reverse
21/// pointer records for IPv6 but have quickly been found to be rather
22/// unwieldy and were never widely implemented. Subsequently they have been
23/// declared historic and are forbidden to be supported. So we don’t.
24///
25/// In theory there can be even more types of labels, but based on the
26/// experience with binary labels, it is very unlikely that there ever will
27/// be any.
28///
29/// Consequently, `Label` will only ever contain an octets slice of up to 63
30/// octets. It only contains the label’s content, not the length octet it is
31/// preceded by in wire format. As an unsized type, it needs to be
32/// used behind some kind of pointer, most likely a reference.
33///
34/// `Label` differs from an octets slice in how it compares: as labels are to
35/// be case-insensitive, all the comparison traits as well as `Hash` are
36/// implemented ignoring ASCII-case.
37pub struct Label([u8]);
38
39/// # Creation
40///
41impl Label {
42    /// Domain name labels have a maximum length of 63 octets.
43    pub const MAX_LEN: usize = 63;
44
45    /// Creates a label from the underlying slice without any checking.
46    ///
47    /// # Safety
48    ///
49    /// The `slice` must be at most 63 octets long.
50    pub(super) unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
51        &*(slice as *const [u8] as *const Self)
52    }
53
54    /// Creates a mutable label from the underlying slice without checking.
55    ///
56    /// # Safety
57    ///
58    /// The `slice` must be at most 63 octets long.
59    pub(super) unsafe fn from_slice_mut_unchecked(
60        slice: &mut [u8],
61    ) -> &mut Self {
62        &mut *(slice as *mut [u8] as *mut Self)
63    }
64
65    /// Returns a static reference to the root label.
66    ///
67    /// The root label is an empty label.
68    #[must_use]
69    pub fn root() -> &'static Self {
70        unsafe { Self::from_slice_unchecked(b"") }
71    }
72
73    /// Returns a static reference to the wildcard label `"*"`.
74    #[must_use]
75    pub fn wildcard() -> &'static Self {
76        unsafe { Self::from_slice_unchecked(b"*") }
77    }
78
79    /// Converts an octets slice into a label.
80    ///
81    /// This will fail if the slice is longer than 63 octets.
82    pub fn from_slice(slice: &[u8]) -> Result<&Self, LongLabelError> {
83        if slice.len() > Label::MAX_LEN {
84            Err(LongLabelError)
85        } else {
86            Ok(unsafe { Self::from_slice_unchecked(slice) })
87        }
88    }
89
90    /// Converts a mutable octets slice into a label.
91    ///
92    /// This will fail of the slice is longer than 63 octets.
93    pub fn from_slice_mut(
94        slice: &mut [u8],
95    ) -> Result<&mut Self, LongLabelError> {
96        if slice.len() > Label::MAX_LEN {
97            Err(LongLabelError)
98        } else {
99            Ok(unsafe { Self::from_slice_mut_unchecked(slice) })
100        }
101    }
102
103    /// Splits a label from the beginning of an octets slice.
104    ///
105    /// On success, the function returns a label and the remainder of
106    /// the slice.
107    pub fn split_from(
108        slice: &[u8],
109    ) -> Result<(&Self, &[u8]), SplitLabelError> {
110        let head = match slice.first() {
111            Some(ch) => *ch,
112            None => return Err(SplitLabelError::ShortInput),
113        };
114        let end = match head {
115            0..=0x3F => (head as usize) + 1,
116            0x40..=0x7F => {
117                return Err(SplitLabelError::BadType(
118                    LabelTypeError::Extended(head),
119                ))
120            }
121            0xC0..=0xFF => {
122                let res = match slice.get(1) {
123                    Some(ch) => u16::from(*ch),
124                    None => return Err(SplitLabelError::ShortInput),
125                };
126                let res = res | ((u16::from(head) & 0x3F) << 8);
127                return Err(SplitLabelError::Pointer(res));
128            }
129            _ => {
130                return Err(SplitLabelError::BadType(
131                    LabelTypeError::Undefined,
132                ))
133            }
134        };
135        if slice.len() < end {
136            return Err(SplitLabelError::ShortInput);
137        }
138        Ok((
139            unsafe { Self::from_slice_unchecked(&slice[1..end]) },
140            &slice[end..],
141        ))
142    }
143
144    /// Splits a mutable label from the beginning of an octets slice.
145    ///
146    /// On success, the function returns a label and the remainder of
147    /// the slice.
148    pub fn split_from_mut(
149        slice: &mut [u8],
150    ) -> Result<(&mut Self, &mut [u8]), SplitLabelError> {
151        let head = match slice.first_mut() {
152            Some(ch) => *ch,
153            None => return Err(SplitLabelError::ShortInput),
154        };
155        let end = match head {
156            0..=0x3F => (head as usize) + 1,
157            0x40..=0x7F => {
158                return Err(SplitLabelError::BadType(
159                    LabelTypeError::Extended(head),
160                ))
161            }
162            0xC0..=0xFF => {
163                let res = match slice.get(1) {
164                    Some(ch) => u16::from(*ch),
165                    None => return Err(SplitLabelError::ShortInput),
166                };
167                let res = res | ((u16::from(head) & 0x3F) << 8);
168                return Err(SplitLabelError::Pointer(res));
169            }
170            _ => {
171                return Err(SplitLabelError::BadType(
172                    LabelTypeError::Undefined,
173                ))
174            }
175        };
176        if slice.len() < end {
177            return Err(SplitLabelError::ShortInput);
178        }
179        let (left, right) = slice.split_at_mut(end);
180        Ok((
181            unsafe { Self::from_slice_mut_unchecked(&mut left[1..]) },
182            right,
183        ))
184    }
185
186    /// Iterator over the octets of the label.
187    pub fn iter(&self) -> iter::Copied<slice::Iter<u8>> {
188        self.as_slice().iter().copied()
189    }
190
191    /// Iterates over the labels in some part of an octets slice.
192    ///
193    /// The first label is assumed to start at index `start`.
194    ///
195    /// Stops at the root label, the first broken label, or if a compression
196    /// pointer is found that is pointing forward.
197    ///
198    /// # Panics
199    ///
200    /// Panics if `start` is beyond the end of `slice`.
201    #[must_use]
202    pub fn iter_slice(slice: &[u8], start: usize) -> SliceLabelsIter {
203        SliceLabelsIter { slice, start }
204    }
205
206    /// Returns a reference to the underlying octets slice.
207    #[must_use]
208    pub fn as_slice(&self) -> &[u8] {
209        unsafe { &*(self as *const Self as *const [u8]) }
210    }
211
212    /// Returns a mutable reference to the underlying octets slice.
213    pub fn as_slice_mut(&mut self) -> &mut [u8] {
214        unsafe { &mut *(self as *mut Label as *mut [u8]) }
215    }
216
217    /// Converts the label into the canonical form.
218    ///
219    /// This form has all octets representing ASCII letters converted to their
220    /// lower case form.
221    pub fn make_canonical(&mut self) {
222        self.0.make_ascii_lowercase()
223    }
224
225    /// Converts a sequence of labels into the canonical form.
226    ///
227    /// The function takes a mutable octets slice that contains a sequence
228    /// of labels in wire format (vulgo: a domain name) and converts each
229    /// label into its canonical form.
230    ///
231    /// # Panics
232    ///
233    /// The function panics if the slice does not contain a valid sequence
234    /// of labels.
235    pub(super) fn make_slice_canonical(mut slice: &mut [u8]) {
236        while !slice.is_empty() {
237            let (head, tail) =
238                Label::split_from_mut(slice).expect("invalid name");
239            head.make_canonical();
240            slice = tail;
241        }
242    }
243
244    /// Returns the label in canonical form.
245    ///
246    /// In this form, all ASCII letters are lowercase.
247    #[must_use]
248    pub fn to_canonical(&self) -> OwnedLabel {
249        let mut res = OwnedLabel::from_label(self);
250        res.make_canonical();
251        res
252    }
253
254    /// Returns the composed label ordering.
255    #[must_use]
256    pub fn composed_cmp(&self, other: &Self) -> cmp::Ordering {
257        match self.0.len().cmp(&other.0.len()) {
258            cmp::Ordering::Equal => {}
259            other => return other,
260        }
261        self.0.cmp(other.as_ref())
262    }
263
264    /// Returns the composed ordering with ASCII letters lowercased.
265    #[must_use]
266    pub fn lowercase_composed_cmp(&self, other: &Self) -> cmp::Ordering {
267        match self.0.len().cmp(&other.0.len()) {
268            cmp::Ordering::Equal => {}
269            other => return other,
270        }
271        self.cmp(other)
272    }
273
274    /// Appends the label to an octets builder.
275    ///
276    /// The method builds the encoded form of the label that starts with a
277    /// one octet length indicator.
278    pub fn compose<Builder: OctetsBuilder + ?Sized>(
279        &self,
280        target: &mut Builder,
281    ) -> Result<(), Builder::AppendError> {
282        target.append_slice(&[self.len() as u8])?;
283        target.append_slice(self.as_slice())
284    }
285
286    /// Appends the lowercased label to an octets builder.
287    ///
288    /// The method builds the encoded form of the label that starts with a
289    /// one octet length indicator. It also converts all ASCII letters into
290    /// their lowercase form.
291    pub fn compose_canonical<Builder: OctetsBuilder + ?Sized>(
292        &self,
293        target: &mut Builder,
294    ) -> Result<(), Builder::AppendError> {
295        target.append_slice(&[self.len() as u8])?;
296        for ch in self.into_iter() {
297            target.append_slice(&[ch.to_ascii_lowercase()])?;
298        }
299        Ok(())
300    }
301}
302
303/// # Properties
304///
305impl Label {
306    /// Returns the length of the label.
307    ///
308    /// This length is that of the label’s content only. It will _not_ contain
309    /// the initial label length octet present in the wire format.
310    #[must_use]
311    pub fn len(&self) -> usize {
312        self.as_slice().len()
313    }
314
315    /// Returns whether this is the empty label.
316    #[must_use]
317    pub fn is_empty(&self) -> bool {
318        self.as_slice().is_empty()
319    }
320
321    /// Returns whether the label is the root label.
322    #[must_use]
323    pub fn is_root(&self) -> bool {
324        self.is_empty()
325    }
326
327    /// Returns whether the label is the wildcard label.
328    #[must_use]
329    pub fn is_wildcard(&self) -> bool {
330        self.0.len() == 1 && self.0[0] == b'*'
331    }
332
333    /// Returns the length of the composed version of the label.
334    ///
335    /// This length is one more than the length of the label as their is a
336    /// leading length octet.
337    #[must_use]
338    pub fn compose_len(&self) -> u16 {
339        u16::try_from(self.len()).expect("long label") + 1
340    }
341}
342
343//--- AsRef, and AsMut
344
345impl AsRef<[u8]> for Label {
346    fn as_ref(&self) -> &[u8] {
347        self.as_slice()
348    }
349}
350
351impl AsMut<[u8]> for Label {
352    fn as_mut(&mut self) -> &mut [u8] {
353        self.as_slice_mut()
354    }
355}
356
357//--- ToOwned
358
359#[cfg(feature = "std")]
360impl std::borrow::ToOwned for Label {
361    type Owned = OwnedLabel;
362
363    fn to_owned(&self) -> Self::Owned {
364        self.into()
365    }
366}
367
368//--- PartialEq and Eq
369
370impl<T: AsRef<[u8]> + ?Sized> PartialEq<T> for Label {
371    fn eq(&self, other: &T) -> bool {
372        self.as_slice().eq_ignore_ascii_case(other.as_ref())
373    }
374}
375
376impl Eq for Label {}
377
378//--- PartialOrd and Ord
379
380impl PartialOrd for Label {
381    /// Returns an ordering between `self` and `other`.
382    ///
383    /// The canonical sort order for labels is defined in section 6.1 of
384    /// RFC 4034.
385    ///
386    /// In short, labels are ordered like octet strings except that
387    /// the case of ASCII letters is ignored.
388    ///
389    /// [RFC 4034]: https://tools.ietf.org/html/rfc4034
390    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
391        Some(self.cmp(other))
392    }
393}
394
395impl Ord for Label {
396    fn cmp(&self, other: &Self) -> cmp::Ordering {
397        self.as_slice()
398            .iter()
399            .map(u8::to_ascii_lowercase)
400            .cmp(other.as_slice().iter().map(u8::to_ascii_lowercase))
401    }
402}
403
404//--- Hash
405
406impl hash::Hash for Label {
407    fn hash<H: hash::Hasher>(&self, state: &mut H) {
408        // Include the length in the hash so we can simply hash over the
409        // labels when building a name’s hash.
410        (self.len() as u8).hash(state);
411        for c in self.iter() {
412            c.to_ascii_lowercase().hash(state)
413        }
414    }
415}
416
417//--- IntoIterator
418
419impl<'a> IntoIterator for &'a Label {
420    type Item = u8;
421    type IntoIter = iter::Copied<slice::Iter<'a, u8>>;
422
423    fn into_iter(self) -> Self::IntoIter {
424        self.iter()
425    }
426}
427
428//--- Display and Debug
429
430impl fmt::Display for Label {
431    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
432        for ch in self.iter() {
433            if ch == b' ' || ch == b'.' || ch == b'\\' {
434                write!(f, "\\{}", ch as char)?;
435            } else if !(0x20..0x7F).contains(&ch) {
436                write!(f, "\\{:03}", ch)?;
437            } else {
438                write!(f, "{}", (ch as char))?;
439            }
440        }
441        Ok(())
442    }
443}
444
445impl fmt::Debug for Label {
446    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
447        f.write_str("Label(")?;
448        fmt::Display::fmt(self, f)?;
449        f.write_str(")")
450    }
451}
452
453//------------ OwnedLabel ----------------------------------------------------
454
455/// An owned label.
456///
457/// Since labels are relatively short, this type doesn’t actually allocate any
458/// memory but is a 64 octet array.
459//
460//  This keeps the label in wire format, so the first octet is the length
461//  octet, the remainder is the content.
462#[derive(Clone, Copy)]
463pub struct OwnedLabel([u8; 64]);
464
465impl OwnedLabel {
466    /// Creates a new owned label from an existing label.
467    #[must_use]
468    pub fn from_label(label: &Label) -> Self {
469        let mut res = [0; 64];
470        res[0] = label.len() as u8;
471        res[1..=label.len()].copy_from_slice(label.as_slice());
472        OwnedLabel(res)
473    }
474
475    /// Creates a label from a sequence of chars.
476    pub fn from_chars(
477        mut chars: impl Iterator<Item = char>,
478    ) -> Result<Self, LabelFromStrError> {
479        let mut res = [0u8; 64];
480        while let Some(ch) = chars.next() {
481            if res[0] as usize >= Label::MAX_LEN {
482                return Err(LabelFromStrError::LongLabel);
483            }
484            let ch = match ch {
485                ' '..='-' | '/'..='[' | ']'..='~' => ch as u8,
486                '\\' => parse_escape(&mut chars, res[0] > 0)?,
487                _ => return Err(LabelFromStrError::IllegalCharacter(ch)),
488            };
489            res[(res[0] as usize) + 1] = ch;
490            res[0] += 1;
491        }
492        Ok(OwnedLabel(res))
493    }
494
495    /// Converts the label into the canonical form.
496    ///
497    /// This form has all octets representing ASCII letters converted to their
498    /// lower case form.
499    pub fn make_canonical(&mut self) {
500        self.0[1..].make_ascii_lowercase()
501    }
502
503    /// Returns a reference to the label.
504    #[must_use]
505    pub fn as_label(&self) -> &Label {
506        unsafe {
507            Label::from_slice_unchecked(&self.0[1..=(self.0[0] as usize)])
508        }
509    }
510
511    /// Returns a mutable reference to the label.
512    pub fn as_label_mut(&mut self) -> &mut Label {
513        let len = self.0[0] as usize;
514        unsafe { Label::from_slice_mut_unchecked(&mut self.0[1..=len]) }
515    }
516
517    /// Returns a slice that is the wire-representation of the label.
518    #[must_use]
519    pub fn as_wire_slice(&self) -> &[u8] {
520        let len = self.0[0] as usize;
521        &self.0[..=len]
522    }
523}
524
525//--- From
526
527impl<'a> From<&'a Label> for OwnedLabel {
528    fn from(label: &'a Label) -> Self {
529        Self::from_label(label)
530    }
531}
532
533//--- FromStr
534
535impl FromStr for OwnedLabel {
536    type Err = LabelFromStrError;
537
538    fn from_str(s: &str) -> Result<Self, Self::Err> {
539        Self::from_chars(s.chars())
540    }
541}
542
543//--- Deref, DerefMut, AsRef, AsMut, Borrow, and BorrowMut
544
545impl ops::Deref for OwnedLabel {
546    type Target = Label;
547
548    fn deref(&self) -> &Label {
549        self.as_label()
550    }
551}
552
553impl ops::DerefMut for OwnedLabel {
554    fn deref_mut(&mut self) -> &mut Label {
555        self.as_label_mut()
556    }
557}
558
559impl AsRef<Label> for OwnedLabel {
560    fn as_ref(&self) -> &Label {
561        self.as_label()
562    }
563}
564
565impl AsRef<[u8]> for OwnedLabel {
566    fn as_ref(&self) -> &[u8] {
567        self.as_label().as_slice()
568    }
569}
570
571impl AsMut<Label> for OwnedLabel {
572    fn as_mut(&mut self) -> &mut Label {
573        self.as_label_mut()
574    }
575}
576
577impl AsMut<[u8]> for OwnedLabel {
578    fn as_mut(&mut self) -> &mut [u8] {
579        self.as_label_mut().as_slice_mut()
580    }
581}
582
583impl borrow::Borrow<Label> for OwnedLabel {
584    fn borrow(&self) -> &Label {
585        self.as_label()
586    }
587}
588
589impl borrow::BorrowMut<Label> for OwnedLabel {
590    fn borrow_mut(&mut self) -> &mut Label {
591        self.as_label_mut()
592    }
593}
594
595//--- PartialEq and Eq
596
597impl<T: AsRef<Label>> PartialEq<T> for OwnedLabel {
598    fn eq(&self, other: &T) -> bool {
599        self.as_label().eq(other.as_ref())
600    }
601}
602
603impl Eq for OwnedLabel {}
604
605//--- PartialOrd and Ord
606
607impl<T: AsRef<Label>> PartialOrd<T> for OwnedLabel {
608    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
609        self.as_label().partial_cmp(other.as_ref())
610    }
611}
612
613impl Ord for OwnedLabel {
614    fn cmp(&self, other: &Self) -> cmp::Ordering {
615        self.as_label().cmp(other.as_ref())
616    }
617}
618
619//--- Hash
620
621impl hash::Hash for OwnedLabel {
622    fn hash<H: hash::Hasher>(&self, state: &mut H) {
623        self.as_label().hash(state)
624    }
625}
626
627//--- Display and Debug
628
629impl fmt::Display for OwnedLabel {
630    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
631        self.as_label().fmt(f)
632    }
633}
634
635impl fmt::Debug for OwnedLabel {
636    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
637        f.debug_tuple("OwnedLabel").field(&self.as_label()).finish()
638    }
639}
640
641//--- Serialize and Deserialize
642
643#[cfg(feature = "serde")]
644impl serde::Serialize for OwnedLabel {
645    fn serialize<S: serde::Serializer>(
646        &self,
647        serializer: S,
648    ) -> Result<S::Ok, S::Error> {
649        use octseq::serde::SerializeOctets;
650
651        if serializer.is_human_readable() {
652            serializer.serialize_newtype_struct(
653                "OwnedLabel",
654                &format_args!("{}", self),
655            )
656        } else {
657            serializer.serialize_newtype_struct(
658                "OwnedLabel",
659                &self.as_label().as_slice().as_serialized_octets(),
660            )
661        }
662    }
663}
664
665#[cfg(feature = "serde")]
666impl<'de> serde::Deserialize<'de> for OwnedLabel {
667    fn deserialize<D: serde::Deserializer<'de>>(
668        deserializer: D,
669    ) -> Result<Self, D::Error> {
670        use serde::de::Error;
671
672        struct InnerVisitor;
673
674        impl<'de> serde::de::Visitor<'de> for InnerVisitor {
675            type Value = OwnedLabel;
676
677            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
678                f.write_str("an domain name label")
679            }
680
681            fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
682                OwnedLabel::from_str(v).map_err(E::custom)
683            }
684
685            fn visit_borrowed_bytes<E: serde::de::Error>(
686                self,
687                value: &'de [u8],
688            ) -> Result<Self::Value, E> {
689                Label::from_slice(value)
690                    .map(OwnedLabel::from_label)
691                    .map_err(E::custom)
692            }
693        }
694
695        struct NewtypeVisitor;
696
697        impl<'de> serde::de::Visitor<'de> for NewtypeVisitor {
698            type Value = OwnedLabel;
699
700            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
701                f.write_str("an domain name label")
702            }
703
704            fn visit_newtype_struct<D: serde::Deserializer<'de>>(
705                self,
706                deserializer: D,
707            ) -> Result<Self::Value, D::Error> {
708                if deserializer.is_human_readable() {
709                    deserializer.deserialize_str(InnerVisitor)
710                } else {
711                    deserializer.deserialize_bytes(InnerVisitor)
712                }
713            }
714        }
715
716        deserializer.deserialize_newtype_struct("OwnedLabel", NewtypeVisitor)
717    }
718}
719
720//------------ SliceLabelsIter -----------------------------------------------
721
722/// An iterator over the labels in an octets slice.
723///
724/// This keeps returning [`Label`]s until it encounters the root label. If
725/// the slice ends before a root label is seen, returns the last label seen
726/// and then stops.
727///
728/// [`Label`]: struct.Label.html
729pub struct SliceLabelsIter<'a> {
730    /// The message slice to work on.
731    slice: &'a [u8],
732
733    /// The position in `slice` where the next label start.
734    ///
735    /// As a life hack, we use `usize::max_value` to fuse the iterator.
736    start: usize,
737}
738
739impl<'a> Iterator for SliceLabelsIter<'a> {
740    type Item = &'a Label;
741
742    fn next(&mut self) -> Option<Self::Item> {
743        if self.start == usize::max_value() {
744            return None;
745        }
746        loop {
747            match Label::split_from(&self.slice[self.start..]) {
748                Ok((label, _)) => {
749                    if label.is_root() {
750                        self.start = usize::max_value();
751                    } else {
752                        self.start += label.len();
753                    }
754                    return Some(label);
755                }
756                Err(SplitLabelError::Pointer(pos)) => {
757                    let pos = pos as usize;
758                    if pos > self.start {
759                        // Incidentally, this also covers the case where
760                        // pos points past the end of the message.
761                        self.start = usize::max_value();
762                        return None;
763                    }
764                    self.start = pos;
765                    continue;
766                }
767                Err(_) => {
768                    self.start = usize::max_value();
769                    return None;
770                }
771            }
772        }
773    }
774}
775
776//============ Error Types ===================================================
777
778//------------ LabelTypeError ------------------------------------------------
779
780/// A bad label type was encountered.
781#[derive(Clone, Copy, Debug, Eq, PartialEq)]
782pub enum LabelTypeError {
783    /// The label was of the undefined type `0b10`.
784    Undefined,
785
786    /// The label was of the extended label type given.
787    ///
788    /// The type value will be in the range `0x40` to `0x7F`, that is, it
789    /// includes the original label type bits `0b01`.
790    Extended(u8),
791}
792
793//--- Display and Error
794
795impl fmt::Display for LabelTypeError {
796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
797        match *self {
798            LabelTypeError::Undefined => f.write_str("undefined label type"),
799            LabelTypeError::Extended(value) => {
800                write!(f, "unknown extended label 0x{:02x}", value)
801            }
802        }
803    }
804}
805
806#[cfg(feature = "std")]
807impl std::error::Error for LabelTypeError {}
808
809//------------ LongLabelError ------------------------------------------------
810
811/// A label was longer than the allowed 63 octets.
812#[derive(Clone, Copy, Debug, Eq, PartialEq)]
813pub struct LongLabelError;
814
815//--- Display and Error
816
817impl fmt::Display for LongLabelError {
818    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
819        f.write_str("long label")
820    }
821}
822
823#[cfg(feature = "std")]
824impl std::error::Error for LongLabelError {}
825
826//------------ SplitLabelError -----------------------------------------------
827
828/// An error happened while splitting a label from an octets slice.
829#[derive(Clone, Copy, Debug, Eq, PartialEq)]
830pub enum SplitLabelError {
831    /// The label was a pointer to the given position.
832    Pointer(u16),
833
834    /// The label type was invalid.
835    BadType(LabelTypeError),
836
837    /// The octets slice was shorter than indicated by the label length.
838    ShortInput,
839}
840
841//--- From
842
843impl From<LabelTypeError> for SplitLabelError {
844    fn from(err: LabelTypeError) -> SplitLabelError {
845        SplitLabelError::BadType(err)
846    }
847}
848
849impl From<SplitLabelError> for ParseError {
850    fn from(err: SplitLabelError) -> ParseError {
851        match err {
852            SplitLabelError::Pointer(_) => {
853                ParseError::Form(FormError::new("compressed domain name"))
854            }
855            SplitLabelError::BadType(_) => {
856                ParseError::Form(FormError::new("invalid label type"))
857            }
858            SplitLabelError::ShortInput => ParseError::ShortInput,
859        }
860    }
861}
862
863//--- Display and Error
864
865impl fmt::Display for SplitLabelError {
866    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
867        match *self {
868            SplitLabelError::Pointer(_) => {
869                f.write_str("compressed domain name")
870            }
871            SplitLabelError::BadType(ltype) => ltype.fmt(f),
872            SplitLabelError::ShortInput => ParseError::ShortInput.fmt(f),
873        }
874    }
875}
876
877#[cfg(feature = "std")]
878impl std::error::Error for SplitLabelError {}
879
880//============ Testing =======================================================
881
882#[cfg(test)]
883mod test {
884    use super::*;
885
886    #[test]
887    fn from_slice() {
888        let x = [0u8; 10];
889        assert_eq!(Label::from_slice(&x[..]).unwrap().as_slice(), &x[..]);
890        let x = [0u8; 63];
891        assert_eq!(Label::from_slice(&x[..]).unwrap().as_slice(), &x[..]);
892        let x = [0u8; 64];
893        assert!(Label::from_slice(&x[..]).is_err());
894    }
895
896    #[test]
897    fn split_from() {
898        // regular label
899        assert_eq!(
900            Label::split_from(b"\x03www\x07example\x03com\0").unwrap(),
901            (
902                Label::from_slice(b"www").unwrap(),
903                &b"\x07example\x03com\0"[..]
904            )
905        );
906
907        // final regular label
908        assert_eq!(
909            Label::split_from(b"\x03www").unwrap(),
910            (Label::from_slice(b"www").unwrap(), &b""[..])
911        );
912
913        // root label
914        assert_eq!(
915            Label::split_from(b"\0some").unwrap(),
916            (Label::from_slice(b"").unwrap(), &b"some"[..])
917        );
918
919        // short slice
920        assert_eq!(
921            Label::split_from(b"\x03ww"),
922            Err(SplitLabelError::ShortInput)
923        );
924
925        // empty slice
926        assert_eq!(Label::split_from(b""), Err(SplitLabelError::ShortInput));
927
928        // compressed label
929        assert_eq!(
930            Label::split_from(b"\xc0\x05foo"),
931            Err(SplitLabelError::Pointer(5))
932        );
933
934        // undefined label type
935        assert_eq!(
936            Label::split_from(b"\xb3foo"),
937            Err(LabelTypeError::Undefined.into())
938        );
939
940        // extended label type
941        assert_eq!(
942            Label::split_from(b"\x66foo"),
943            Err(LabelTypeError::Extended(0x66).into())
944        );
945    }
946
947    #[test]
948    #[cfg(feature = "std")]
949    fn compose() {
950        use octseq::builder::infallible;
951        use std::vec::Vec;
952
953        let mut buf = Vec::new();
954        infallible(Label::root().compose(&mut buf));
955        assert_eq!(buf, &b"\0"[..]);
956
957        let mut buf = Vec::new();
958        let label = Label::from_slice(b"123").unwrap();
959        infallible(label.compose(&mut buf));
960        assert_eq!(buf, &b"\x03123"[..]);
961    }
962
963    #[test]
964    fn eq() {
965        assert_eq!(
966            Label::from_slice(b"example").unwrap(),
967            Label::from_slice(b"eXAMple").unwrap()
968        );
969        assert_ne!(
970            Label::from_slice(b"example").unwrap(),
971            Label::from_slice(b"e4ample").unwrap()
972        );
973    }
974
975    #[test]
976    fn cmp() {
977        use core::cmp::Ordering;
978
979        let labels = [
980            Label::root(),
981            Label::from_slice(b"\x01").unwrap(),
982            Label::from_slice(b"*").unwrap(),
983            Label::from_slice(b"\xc8").unwrap(),
984        ];
985        for i in 0..labels.len() {
986            for j in 0..labels.len() {
987                let ord = i.cmp(&j);
988                assert_eq!(labels[i].partial_cmp(labels[j]), Some(ord));
989                assert_eq!(labels[i].cmp(labels[j]), ord);
990            }
991        }
992
993        let l1 = Label::from_slice(b"example").unwrap();
994        let l2 = Label::from_slice(b"eXAMple").unwrap();
995        assert_eq!(l1.partial_cmp(l2), Some(Ordering::Equal));
996        assert_eq!(l1.cmp(l2), Ordering::Equal);
997    }
998
999    #[test]
1000    #[cfg(feature = "std")]
1001    fn hash() {
1002        use std::collections::hash_map::DefaultHasher;
1003        use std::hash::{Hash, Hasher};
1004
1005        let mut s1 = DefaultHasher::new();
1006        let mut s2 = DefaultHasher::new();
1007        Label::from_slice(b"example").unwrap().hash(&mut s1);
1008        Label::from_slice(b"eXAMple").unwrap().hash(&mut s2);
1009        assert_eq!(s1.finish(), s2.finish());
1010    }
1011
1012    // XXX OwnedLabel::from_str
1013
1014    #[cfg(feature = "serde")]
1015    #[test]
1016    fn owned_label_ser_de() {
1017        use serde_test::{assert_tokens, Configure, Token};
1018
1019        let label =
1020            OwnedLabel::from_label(Label::from_slice(b"fo.").unwrap());
1021        assert_tokens(
1022            &label.compact(),
1023            &[
1024                Token::NewtypeStruct { name: "OwnedLabel" },
1025                Token::BorrowedBytes(b"fo."),
1026            ],
1027        );
1028        assert_tokens(
1029            &label.readable(),
1030            &[
1031                Token::NewtypeStruct { name: "OwnedLabel" },
1032                Token::Str("fo\\."),
1033            ],
1034        );
1035    }
1036}