laser_wire/filter/
headers.rs1use super::eval::{HeaderNeed, HeaderRef, HeaderValueRef};
2use crate::headers::CONTENT_TYPE;
3
4pub fn decode(mut bytes: &[u8]) -> Option<Vec<HeaderRef<'_>>> {
9 let mut headers: Vec<HeaderRef<'_>> = Vec::new();
10 while !bytes.is_empty() {
11 let (key_kind, key) = field(&mut bytes)?;
12 let (value_kind, value) = field(&mut bytes)?;
13 if key_kind != 2 {
14 continue;
15 }
16 let key = std::str::from_utf8(key).ok()?;
17 let value = scalar(value_kind, value)?;
18 headers.push(HeaderRef { key, value });
19 }
20 Some(headers)
21}
22
23pub enum DecodedHeaders<'a> {
27 Empty,
28 ContentType(Option<HeaderRef<'a>>),
29 All(Vec<HeaderRef<'a>>),
30}
31
32impl<'a> std::ops::Deref for DecodedHeaders<'a> {
33 type Target = [HeaderRef<'a>];
34 fn deref(&self) -> &Self::Target {
35 match self {
36 Self::Empty => &[],
37 Self::ContentType(header) => header.as_slice(),
38 Self::All(headers) => headers,
39 }
40 }
41}
42
43pub fn decode_for(need: HeaderNeed, bytes: &[u8]) -> Option<DecodedHeaders<'_>> {
44 match need {
45 HeaderNeed::None => Some(DecodedHeaders::Empty),
46 HeaderNeed::ContentType => content_type_one(bytes).map(DecodedHeaders::ContentType),
47 HeaderNeed::All => decode(bytes).map(DecodedHeaders::All),
48 }
49}
50
51pub fn content_type(bytes: &[u8]) -> Option<Vec<HeaderRef<'static>>> {
55 content_type_one(bytes).map(|header| header.into_iter().collect())
56}
57
58fn content_type_one(mut bytes: &[u8]) -> Option<Option<HeaderRef<'static>>> {
59 let mut found = None;
60 while !bytes.is_empty() {
61 let (key_kind, key) = field(&mut bytes)?;
62 let (value_kind, value) = field(&mut bytes)?;
63 if key_kind == 2 && key == CONTENT_TYPE.as_bytes() {
64 found = match scalar(value_kind, value)? {
66 HeaderValueRef::Uint(code) => Some(HeaderValueRef::Uint(code)),
67 HeaderValueRef::Int(code) => Some(HeaderValueRef::Int(code)),
68 _ => None,
69 }
70 .map(|value| HeaderRef {
71 key: CONTENT_TYPE,
72 value,
73 });
74 }
75 }
76 Some(found)
77}
78
79fn field<'a>(bytes: &mut &'a [u8]) -> Option<(u8, &'a [u8])> {
80 let kind = *bytes.first()?;
81 let length = u32::from_le_bytes(bytes.get(1..5)?.try_into().ok()?) as usize;
82 if kind == 0 || !(1..=255).contains(&length) {
83 return None;
84 }
85 let value = bytes.get(5..5 + length)?;
86 *bytes = &bytes[5 + length..];
87 Some((kind, value))
88}
89
90fn scalar(kind: u8, value: &[u8]) -> Option<HeaderValueRef<'_>> {
91 Some(match kind {
92 2 => HeaderValueRef::String(std::str::from_utf8(value).ok()?),
93 3 => match value {
94 [0] => HeaderValueRef::Bool(false),
95 [1] => HeaderValueRef::Bool(true),
96 _ => return None,
97 },
98 4 => HeaderValueRef::Int(i64::from(i8::from_le_bytes(value.try_into().ok()?))),
99 5 => HeaderValueRef::Int(i64::from(i16::from_le_bytes(value.try_into().ok()?))),
100 6 => HeaderValueRef::Int(i64::from(i32::from_le_bytes(value.try_into().ok()?))),
101 7 => HeaderValueRef::Int(i64::from_le_bytes(value.try_into().ok()?)),
102 8 | 13 if value.len() != 16 => return None,
104 9 => HeaderValueRef::Uint(u64::from(u8::from_le_bytes(value.try_into().ok()?))),
105 10 => HeaderValueRef::Uint(u64::from(u16::from_le_bytes(value.try_into().ok()?))),
106 11 => HeaderValueRef::Uint(u64::from(u32::from_le_bytes(value.try_into().ok()?))),
107 12 => HeaderValueRef::Uint(u64::from_le_bytes(value.try_into().ok()?)),
108 14 => HeaderValueRef::Float(f64::from(f32::from_le_bytes(value.try_into().ok()?))),
109 15 => HeaderValueRef::Float(f64::from_le_bytes(value.try_into().ok()?)),
110 _ => HeaderValueRef::Raw(value),
111 })
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 fn entry(key: &str, kind: u8, value: &[u8]) -> Vec<u8> {
119 let mut bytes = vec![2];
120 bytes.extend_from_slice(&(key.len() as u32).to_le_bytes());
121 bytes.extend_from_slice(key.as_bytes());
122 bytes.push(kind);
123 bytes.extend_from_slice(&(value.len() as u32).to_le_bytes());
124 bytes.extend_from_slice(value);
125 bytes
126 }
127
128 #[test]
129 fn given_unknown_and_known_headers_when_decoded_then_should_preserve_both() {
130 let mut bytes = entry("future", 99, b"opaque");
131 bytes.extend(entry("priority", 9, &[2]));
132 let headers = decode(&bytes).expect("valid headers");
133 assert_eq!(headers[0].value, HeaderValueRef::Raw(b"opaque"));
134 assert_eq!(headers[1].value, HeaderValueRef::Uint(2));
135 }
136
137 #[test]
138 fn given_many_headers_when_only_the_content_type_is_read_then_should_decode_just_that_one() {
139 let mut bytes = entry("frostline.unit", 2, b"reefer");
140 bytes.extend(entry("agdx.ct", 9, &[1]));
141 bytes.extend(entry("agdx.ct", 9, &[3]));
142 bytes.extend(entry("odd", 3, &[2]));
143 let headers = content_type(&bytes).expect("the structure parses");
144 assert_eq!(headers.len(), 1);
145 assert_eq!(
146 (headers[0].key, headers[0].value),
147 ("agdx.ct", HeaderValueRef::Uint(3))
148 );
149 assert!(
150 content_type(&entry("frostline.unit", 2, b"reefer"))
151 .expect("parses")
152 .is_empty()
153 );
154 let mut truncated = entry("agdx.ct", 9, &[1]);
155 truncated.truncate(truncated.len() - 1);
156 assert!(content_type(&truncated).is_none());
157 assert!(content_type(&entry("agdx.ct", 9, &[1, 2])).is_none());
158 }
159
160 #[test]
161 fn given_malformed_known_headers_when_decoded_then_should_fault_the_whole_block() {
162 for (kind, value) in [
163 (11, vec![1]),
164 (3, vec![2]),
165 (8, vec![0; 15]),
166 (2, vec![255]),
167 ] {
168 let mut bytes = entry("priority", 9, &[2]);
169 bytes.extend(entry("broken", kind, &value));
170 assert!(decode(&bytes).is_none());
171 }
172 }
173}