hyper_old_types/header/
raw.rs

1use std::borrow::Cow;
2use std::fmt;
3use bytes::Bytes;
4
5/// A raw header value.
6#[derive(Clone, Debug)]
7pub struct Raw(Lines);
8
9impl Raw {
10    /// Returns the amount of lines.
11    #[inline]
12    pub fn len(&self) -> usize {
13        match self.0 {
14            Lines::Empty => 0,
15            Lines::One(..) => 1,
16            Lines::Many(ref lines) => lines.len()
17        }
18    }
19
20    /// Returns the line if there is only 1.
21    #[inline]
22    pub fn one(&self) -> Option<&[u8]> {
23        match self.0 {
24            Lines::One(ref line) => Some(line.as_ref()),
25            Lines::Many(ref lines) if lines.len() == 1 => Some(lines[0].as_ref()),
26            _ => None
27        }
28    }
29
30    /// Iterate the lines of raw bytes.
31    #[inline]
32    pub fn iter(&self) -> RawLines {
33        RawLines {
34            inner: &self.0,
35            pos: 0,
36        }
37    }
38
39    /// Append a line to this `Raw` header value.
40    pub fn push<V: Into<Raw>>(&mut self, val: V) {
41        let raw = val.into();
42        match raw.0 {
43            Lines::Empty => (),
44            Lines::One(one) => self.push_line(one),
45            Lines::Many(lines) => {
46                for line in lines {
47                    self.push_line(line);
48                }
49            }
50        }
51    }
52
53    fn push_line(&mut self, line: Bytes) {
54        let lines = ::std::mem::replace(&mut self.0, Lines::Empty);
55        match lines {
56            Lines::Empty => {
57                self.0 = Lines::One(line);
58            }
59            Lines::One(one) => {
60                self.0 = Lines::Many(vec![one, line]);
61            }
62            Lines::Many(mut lines) => {
63                lines.push(line);
64                self.0 = Lines::Many(lines);
65            }
66        }
67    }
68}
69
70#[derive(Clone)]
71enum Lines {
72    Empty,
73    One(Bytes),
74    Many(Vec<Bytes>),
75}
76
77fn eq_many<A: AsRef<[u8]>, B: AsRef<[u8]>>(a: &[A], b: &[B]) -> bool {
78    if a.len() != b.len() {
79        false
80    } else {
81        for (a, b) in a.iter().zip(b.iter()) {
82            if a.as_ref() != b.as_ref() {
83                return false
84            }
85        }
86        true
87    }
88}
89
90fn eq<B: AsRef<[u8]>>(raw: &Raw, b: &[B]) -> bool {
91    match raw.0 {
92        Lines::Empty => b.is_empty(),
93        Lines::One(ref line) => eq_many(&[line], b),
94        Lines::Many(ref lines) => eq_many(lines, b)
95    }
96}
97
98impl PartialEq for Raw {
99    fn eq(&self, other: &Raw) -> bool {
100        match other.0 {
101            Lines::Empty => eq(self, &[] as &[Bytes]),
102            Lines::One(ref line) => eq(self, &[line]),
103            Lines::Many(ref lines) => eq(self, lines),
104        }
105    }
106}
107
108impl Eq for Raw {}
109
110impl PartialEq<[Vec<u8>]> for Raw {
111    fn eq(&self, bytes: &[Vec<u8>]) -> bool {
112        eq(self, bytes)
113    }
114}
115
116impl<'a> PartialEq<[&'a [u8]]> for Raw {
117    fn eq(&self, bytes: &[&[u8]]) -> bool {
118        eq(self, bytes)
119    }
120}
121
122impl PartialEq<[String]> for Raw {
123    fn eq(&self, bytes: &[String]) -> bool {
124        eq(self, bytes)
125    }
126}
127
128impl<'a> PartialEq<[&'a str]> for Raw {
129    fn eq(&self, bytes: &[&'a str]) -> bool {
130        eq(self, bytes)
131    }
132}
133
134impl PartialEq<[u8]> for Raw {
135    fn eq(&self, bytes: &[u8]) -> bool {
136        match self.0 {
137            Lines::Empty => bytes.is_empty(),
138            Lines::One(ref line) => line.as_ref() == bytes,
139            Lines::Many(..) => false
140        }
141    }
142}
143
144impl PartialEq<str> for Raw {
145    fn eq(&self, s: &str) -> bool {
146        self == s.as_bytes()
147    }
148}
149
150impl From<Vec<Vec<u8>>> for Raw {
151    #[inline]
152    fn from(val: Vec<Vec<u8>>) -> Raw {
153        Raw(Lines::Many(
154            val.into_iter()
155                .map(|vec| maybe_literal(vec.into()))
156                .collect()
157        ))
158    }
159}
160
161impl From<String> for Raw {
162    #[inline]
163    fn from(val: String) -> Raw {
164        Raw::from(val.into_bytes())
165    }
166}
167
168impl From<Vec<u8>> for Raw {
169    #[inline]
170    fn from(val: Vec<u8>) -> Raw {
171        Raw(Lines::One(maybe_literal(val.into())))
172    }
173}
174
175impl<'a> From<&'a str> for Raw {
176    fn from(val: &'a str) -> Raw {
177        Raw::from(val.as_bytes())
178    }
179}
180
181impl<'a> From<&'a [u8]> for Raw {
182    fn from(val: &'a [u8]) -> Raw {
183        Raw(Lines::One(maybe_literal(val.into())))
184    }
185}
186
187impl From<Bytes> for Raw {
188    #[inline]
189    fn from(val: Bytes) -> Raw {
190        Raw(Lines::One(val))
191    }
192}
193
194pub fn parsed(val: Bytes) -> Raw {
195    Raw(Lines::One(From::from(val)))
196}
197
198pub fn push(raw: &mut Raw, val: Bytes) {
199    raw.push_line(val);
200}
201
202pub fn new() -> Raw {
203    Raw(Lines::Empty)
204}
205
206impl fmt::Debug for Lines {
207    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208        match *self {
209            Lines::Empty => f.pad("[]"),
210            Lines::One(ref line) => fmt::Debug::fmt(&[line], f),
211            Lines::Many(ref lines) => fmt::Debug::fmt(lines, f)
212        }
213    }
214}
215
216impl ::std::ops::Index<usize> for Raw {
217    type Output = [u8];
218
219    fn index(&self, idx: usize) -> &[u8] {
220        match self.0 {
221            Lines::Empty => panic!("index of out of bounds: {}", idx),
222            Lines::One(ref line) => if idx == 0 {
223                line.as_ref()
224            } else {
225                panic!("index out of bounds: {}", idx)
226            },
227            Lines::Many(ref lines) => lines[idx].as_ref()
228        }
229    }
230}
231
232macro_rules! literals {
233    ($($len:expr => $($value:expr),+;)+) => (
234        fn maybe_literal(s: Cow<[u8]>) -> Bytes {
235            match s.len() {
236                $($len => {
237                    $(
238                    if s.as_ref() == $value {
239                        return Bytes::from_static($value);
240                    }
241                    )+
242                })+
243
244                _ => ()
245            }
246
247            Bytes::from(s.into_owned())
248        }
249
250        #[test]
251        fn test_literal_lens() {
252            $(
253            $({
254                let s = $value;
255                assert!(s.len() == $len, "{:?} has len of {}, listed as {}", s, s.len(), $len);
256            })+
257            )+
258        }
259    );
260}
261
262literals! {
263    1  => b"*", b"0";
264    3  => b"*/*";
265    4  => b"gzip";
266    5  => b"close";
267    7  => b"chunked";
268    10 => b"keep-alive";
269}
270
271impl<'a> IntoIterator for &'a Raw {
272    type IntoIter = RawLines<'a>;
273    type Item = &'a [u8];
274
275    fn into_iter(self) -> RawLines<'a> {
276        self.iter()
277    }
278}
279
280pub struct RawLines<'a> {
281    inner: &'a Lines,
282    pos: usize,
283}
284
285impl<'a> fmt::Debug for RawLines<'a> {
286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287        f.debug_tuple("RawLines")
288            .field(&self.inner)
289            .finish()
290    }
291}
292
293impl<'a> Iterator for RawLines<'a> {
294    type Item = &'a [u8];
295
296    #[inline]
297    fn next(&mut self) -> Option<&'a [u8]> {
298        let current_pos = self.pos;
299        self.pos += 1;
300        match *self.inner {
301            Lines::Empty => None,
302            Lines::One(ref line) => {
303                if current_pos == 0 {
304                    Some(line.as_ref())
305                } else {
306                    None
307                }
308            }
309            Lines::Many(ref lines) => lines.get(current_pos).map(|l| l.as_ref()),
310        }
311    }
312}