stream_httparse/header/
key.rs

1use std::cmp::Ordering;
2
3/// Allows the HeaderKey to take the form of a variety of different
4/// valid Types, mostly related to their lifetimes.
5/// This however also gives more control over how they are compared
6/// to each other, ignoring case in this case
7///
8/// ```rust
9/// use stream_httparse::header::HeaderKey;
10///
11/// assert_eq!(HeaderKey::StrRef("TeSt"), HeaderKey::StrRef("test"));
12/// ```
13#[derive(Debug, Clone)]
14pub enum HeaderKey<'a> {
15    /// Stores the Key as a refernce to a String
16    StrRef(&'a str),
17    /// Stores the Key as an owned String
18    Str(String),
19}
20
21impl<'a> From<&'a str> for HeaderKey<'a> {
22    fn from(val: &'a str) -> Self {
23        HeaderKey::StrRef(val)
24    }
25}
26impl<'a> From<String> for HeaderKey<'a> {
27    fn from(val: String) -> Self {
28        HeaderKey::Str(val)
29    }
30}
31
32impl<'a> HeaderKey<'a> {
33    /// Serializes the Key into the Buffer by appending
34    /// the Data to it
35    pub fn serialize(&self, buf: &mut Vec<u8>) {
36        match *self {
37            Self::StrRef(ref value) => {
38                buf.extend_from_slice(value.as_bytes());
39            }
40            Self::Str(ref value) => {
41                buf.extend_from_slice(value.as_bytes());
42            }
43        }
44    }
45
46    /// Clones all the needed Data in order to create a new
47    /// HeaderKey that is completly independant of the given
48    /// self reference
49    pub fn to_owned<'refed, 'owned>(&'refed self) -> HeaderKey<'owned> {
50        let value = match self {
51            Self::StrRef(tmp) => tmp.to_string(),
52            Self::Str(tmp) => tmp.to_owned(),
53        };
54
55        HeaderKey::Str(value)
56    }
57}
58
59impl AsRef<str> for HeaderKey<'_> {
60    fn as_ref(&self) -> &str {
61        match *self {
62            Self::Str(ref value) => &value,
63            Self::StrRef(ref value) => value,
64        }
65    }
66}
67
68impl PartialEq for HeaderKey<'_> {
69    fn eq(&self, other: &Self) -> bool {
70        caseless::default_caseless_match_str(self.as_ref(), other.as_ref())
71    }
72}
73
74impl Eq for HeaderKey<'_> {}
75
76impl PartialOrd for HeaderKey<'_> {
77    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
78        self.as_ref().partial_cmp(other.as_ref())
79    }
80}
81
82impl Ord for HeaderKey<'_> {
83    fn cmp(&self, other: &Self) -> Ordering {
84        self.as_ref().cmp(other.as_ref())
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn equals_ignore_case() {
94        assert_eq!(HeaderKey::StrRef("test"), HeaderKey::StrRef("test"));
95        assert_eq!(HeaderKey::StrRef("TEST"), HeaderKey::StrRef("test"));
96        assert_eq!(HeaderKey::StrRef("TeSt"), HeaderKey::StrRef("test"));
97    }
98
99    #[test]
100    fn serialize_str() {
101        let mut result: Vec<u8> = Vec::new();
102        HeaderKey::Str("test-key".to_owned()).serialize(&mut result);
103
104        assert_eq!("test-key".as_bytes(), &result);
105    }
106    #[test]
107    fn serialize_str_ref() {
108        let mut result: Vec<u8> = Vec::new();
109        HeaderKey::StrRef("test-key").serialize(&mut result);
110
111        assert_eq!("test-key".as_bytes(), &result);
112    }
113
114    #[test]
115    fn partial_ord() {
116        assert_eq!(
117            "first" < "second",
118            HeaderKey::StrRef("first") < HeaderKey::StrRef("second")
119        );
120    }
121}