dns_message_parser/
label.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::{
    convert::TryFrom,
    fmt::{Display, Formatter, Result as FmtResult},
    hash::{Hash, Hasher},
    str::FromStr,
};
use thiserror::Error;

pub const LABEL_MAX_LENGTH: usize = 64;

#[derive(Debug, PartialEq, Eq, Error)]
pub enum LabelError {
    #[error("Label is too big: {LABEL_MAX_LENGTH} <= {0}")]
    Length(usize),
    #[error("Label is empty")]
    Empty,
}

#[derive(Debug, Clone, Eq)]
pub struct Label(pub(super) String);

#[inline]
fn check_label(label: &str) -> Result<(), LabelError> {
    let label_length = label.len();
    if label_length == 0 {
        Err(LabelError::Empty)
    } else if label_length < LABEL_MAX_LENGTH {
        Ok(())
    } else {
        Err(LabelError::Length(label_length))
    }
}

impl Label {
    pub fn len(&self) -> usize {
        self.0.len()
    }
}

impl TryFrom<String> for Label {
    type Error = LabelError;

    fn try_from(label: String) -> Result<Self, <Self as TryFrom<String>>::Error> {
        check_label(&label)?;
        Ok(Label(label))
    }
}

impl FromStr for Label {
    type Err = LabelError;

    fn from_str(label: &str) -> Result<Self, <Self as FromStr>::Err> {
        check_label(label)?;
        Ok(Label(label.to_owned()))
    }
}

impl Display for Label {
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
        write!(f, "{}", self.0)
    }
}

impl AsRef<str> for Label {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl PartialEq<&str> for Label {
    fn eq(&self, other: &&str) -> bool {
        self.0.to_lowercase() == other.to_lowercase()
    }
}

impl PartialEq<Label> for Label {
    fn eq(&self, other: &Label) -> bool {
        self.0.to_lowercase() == other.0.to_lowercase()
    }
}

impl Hash for Label {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.to_lowercase().hash(state);
    }
}