Skip to main content

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    LabelFromStrError, LabelFromStrErrorEnum, parse_escape,
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) const unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
55        // SAFETY: Label has repr(transparent)
56        unsafe { 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        unsafe { 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 const 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                if slice.len() < 2 {
129                    return Err(SplitLabelError::ShortInput);
130                }
131                let res = slice[1] as u16;
132                let res = res | (((head as u16) & 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
145        let (left, right) = slice.split_at(end);
146        let (_, label_data) = left.split_at(1);
147        Ok((unsafe { Self::from_slice_unchecked(label_data) }, right))
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 const 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 const 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 const 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 = "alloc")]
366impl alloc::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
811impl core::error::Error for LabelTypeError {}
812
813//------------ LongLabelError ------------------------------------------------
814
815/// A label was longer than the allowed 63 octets.
816#[derive(Clone, Copy, Debug, Eq, PartialEq)]
817pub struct LongLabelError(());
818
819//--- Display and Error
820
821impl fmt::Display for LongLabelError {
822    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
823        f.write_str("long label")
824    }
825}
826
827impl core::error::Error for LongLabelError {}
828
829//------------ SplitLabelError -----------------------------------------------
830
831/// An error happened while splitting a label from an octets slice.
832#[derive(Clone, Copy, Debug, Eq, PartialEq)]
833pub enum SplitLabelError {
834    /// The label was a pointer to the given position.
835    Pointer(u16),
836
837    /// The label type was invalid.
838    BadType(LabelTypeError),
839
840    /// The octets slice was shorter than indicated by the label length.
841    ShortInput,
842}
843
844//--- From
845
846impl From<LabelTypeError> for SplitLabelError {
847    fn from(err: LabelTypeError) -> SplitLabelError {
848        SplitLabelError::BadType(err)
849    }
850}
851
852impl From<SplitLabelError> for ParseError {
853    fn from(err: SplitLabelError) -> ParseError {
854        match err {
855            SplitLabelError::Pointer(_) => {
856                ParseError::Form(FormError::new("compressed domain name"))
857            }
858            SplitLabelError::BadType(_) => {
859                ParseError::Form(FormError::new("invalid label type"))
860            }
861            SplitLabelError::ShortInput => ParseError::ShortInput,
862        }
863    }
864}
865
866//--- Display and Error
867
868impl fmt::Display for SplitLabelError {
869    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
870        match *self {
871            SplitLabelError::Pointer(_) => {
872                f.write_str("compressed domain name")
873            }
874            SplitLabelError::BadType(ltype) => ltype.fmt(f),
875            SplitLabelError::ShortInput => ParseError::ShortInput.fmt(f),
876        }
877    }
878}
879
880impl core::error::Error for SplitLabelError {}
881
882//============ Testing =======================================================
883
884#[cfg(test)]
885mod test {
886    use super::*;
887
888    #[test]
889    fn from_slice() {
890        let x = [0u8; 10];
891        assert_eq!(Label::from_slice(&x[..]).unwrap().as_slice(), &x[..]);
892        let x = [0u8; 63];
893        assert_eq!(Label::from_slice(&x[..]).unwrap().as_slice(), &x[..]);
894        let x = [0u8; 64];
895        assert!(Label::from_slice(&x[..]).is_err());
896    }
897
898    #[test]
899    fn split_from() {
900        // regular label
901        assert_eq!(
902            Label::split_from(b"\x03www\x07example\x03com\0").unwrap(),
903            (
904                Label::from_slice(b"www").unwrap(),
905                &b"\x07example\x03com\0"[..]
906            )
907        );
908
909        // final regular label
910        assert_eq!(
911            Label::split_from(b"\x03www").unwrap(),
912            (Label::from_slice(b"www").unwrap(), &b""[..])
913        );
914
915        // root label
916        assert_eq!(
917            Label::split_from(b"\0some").unwrap(),
918            (Label::from_slice(b"").unwrap(), &b"some"[..])
919        );
920
921        // short slice
922        assert_eq!(
923            Label::split_from(b"\x03ww"),
924            Err(SplitLabelError::ShortInput)
925        );
926
927        // empty slice
928        assert_eq!(Label::split_from(b""), Err(SplitLabelError::ShortInput));
929
930        // compressed label
931        assert_eq!(
932            Label::split_from(b"\xc0\x05foo"),
933            Err(SplitLabelError::Pointer(5))
934        );
935
936        // undefined label type
937        assert_eq!(
938            Label::split_from(b"\xb3foo"),
939            Err(LabelTypeError::Undefined.into())
940        );
941
942        // extended label type
943        assert_eq!(
944            Label::split_from(b"\x66foo"),
945            Err(LabelTypeError::Extended(0x66).into())
946        );
947    }
948
949    #[test]
950    #[cfg(feature = "alloc")]
951    fn compose() {
952        use alloc::vec::Vec;
953        use octseq::builder::infallible;
954
955        let mut buf = Vec::new();
956        infallible(Label::root().compose(&mut buf));
957        assert_eq!(buf, &b"\0"[..]);
958
959        let mut buf = Vec::new();
960        let label = Label::from_slice(b"123").unwrap();
961        infallible(label.compose(&mut buf));
962        assert_eq!(buf, &b"\x03123"[..]);
963    }
964
965    #[test]
966    fn eq() {
967        assert_eq!(
968            Label::from_slice(b"example").unwrap(),
969            Label::from_slice(b"eXAMple").unwrap()
970        );
971        assert_ne!(
972            Label::from_slice(b"example").unwrap(),
973            Label::from_slice(b"e4ample").unwrap()
974        );
975    }
976
977    #[test]
978    fn cmp() {
979        use core::cmp::Ordering;
980
981        let labels = [
982            Label::root(),
983            Label::from_slice(b"\x01").unwrap(),
984            Label::from_slice(b"*").unwrap(),
985            Label::from_slice(b"\xc8").unwrap(),
986        ];
987        for i in 0..labels.len() {
988            for j in 0..labels.len() {
989                let ord = i.cmp(&j);
990                assert_eq!(labels[i].partial_cmp(labels[j]), Some(ord));
991                assert_eq!(labels[i].cmp(labels[j]), ord);
992            }
993        }
994
995        let l1 = Label::from_slice(b"example").unwrap();
996        let l2 = Label::from_slice(b"eXAMple").unwrap();
997        assert_eq!(l1.partial_cmp(l2), Some(Ordering::Equal));
998        assert_eq!(l1.cmp(l2), Ordering::Equal);
999    }
1000
1001    #[test]
1002    #[cfg(feature = "std")]
1003    fn hash() {
1004        use core::hash::{Hash, Hasher};
1005        use std::collections::hash_map::DefaultHasher;
1006
1007        let mut s1 = DefaultHasher::new();
1008        let mut s2 = DefaultHasher::new();
1009        Label::from_slice(b"example").unwrap().hash(&mut s1);
1010        Label::from_slice(b"eXAMple").unwrap().hash(&mut s2);
1011        assert_eq!(s1.finish(), s2.finish());
1012    }
1013
1014    // XXX OwnedLabel::from_str
1015
1016    #[cfg(feature = "serde")]
1017    #[test]
1018    fn owned_label_ser_de() {
1019        use serde_test::{Configure, Token, assert_tokens};
1020
1021        let label =
1022            OwnedLabel::from_label(Label::from_slice(b"fo.").unwrap());
1023        assert_tokens(
1024            &label.compact(),
1025            &[
1026                Token::NewtypeStruct { name: "OwnedLabel" },
1027                Token::BorrowedBytes(b"fo."),
1028            ],
1029        );
1030        assert_tokens(
1031            &label.readable(),
1032            &[
1033                Token::NewtypeStruct { name: "OwnedLabel" },
1034                Token::Str("fo\\."),
1035            ],
1036        );
1037    }
1038
1039    #[test]
1040    fn iter_slice() {
1041        assert_eq!(None, Label::iter_slice(&[], 0).next());
1042        assert_eq!(None, Label::iter_slice(&[], 1).next());
1043
1044        // example.com.
1045        let buf = [
1046            0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f,
1047            0x6d, 0x00,
1048        ];
1049
1050        let mut it = Label::iter_slice(&buf, 0);
1051        assert_eq!(Label::from_slice(b"example").ok(), it.next());
1052        assert_eq!(Label::from_slice(b"com").ok(), it.next());
1053        assert_eq!(Some(Label::root()), it.next());
1054        assert_eq!(None, it.next());
1055
1056        let mut it = Label::iter_slice(&buf, b"example".len() + 1);
1057        assert_eq!(
1058            Label::from_slice(b"com").ok(),
1059            it.next(),
1060            "should jump to 2nd label"
1061        );
1062
1063        let mut it = Label::iter_slice(&buf, buf.len() - 1);
1064        assert_eq!(
1065            Some(Label::root()),
1066            it.next(),
1067            "should jump to last/root label"
1068        );
1069    }
1070}