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