1pub trait FromHeaderValue<'de>: Sized {
12 fn parse_header_value(slice: &'de str) -> Option<Self>;
23}
24
25fn trim(string: &str) -> &str {
26 string.trim_matches(' ').trim_end_matches(' ')
27}
28
29impl<'de> FromHeaderValue<'de> for bool {
30 fn parse_header_value(slice: &'de str) -> Option<Self> {
31 match trim(slice) {
32 "true" => Some(true),
33 "false" => Some(false),
34 _ => None,
35 }
36 }
37}
38
39impl<'de> FromHeaderValue<'de> for u8 {
40 fn parse_header_value(slice: &'de str) -> Option<Self> {
41 trim(slice).parse().ok()
42 }
43}
44
45impl<'de> FromHeaderValue<'de> for u16 {
46 fn parse_header_value(slice: &'de str) -> Option<Self> {
47 trim(slice).parse().ok()
48 }
49}
50
51impl<'de> FromHeaderValue<'de> for u32 {
52 fn parse_header_value(slice: &'de str) -> Option<Self> {
53 trim(slice).parse().ok()
54 }
55}
56
57impl<'de> FromHeaderValue<'de> for u64 {
58 fn parse_header_value(slice: &'de str) -> Option<Self> {
59 trim(slice).parse().ok()
60 }
61}
62
63impl<'de> FromHeaderValue<'de> for u128 {
64 fn parse_header_value(slice: &'de str) -> Option<Self> {
65 trim(slice).parse().ok()
66 }
67}
68
69impl<'de> FromHeaderValue<'de> for usize {
70 fn parse_header_value(slice: &'de str) -> Option<Self> {
71 trim(slice).parse().ok()
72 }
73}
74
75impl<'de> FromHeaderValue<'de> for i8 {
76 fn parse_header_value(slice: &'de str) -> Option<Self> {
77 trim(slice).parse().ok()
78 }
79}
80
81impl<'de> FromHeaderValue<'de> for i16 {
82 fn parse_header_value(slice: &'de str) -> Option<Self> {
83 trim(slice).parse().ok()
84 }
85}
86
87impl<'de> FromHeaderValue<'de> for i32 {
88 fn parse_header_value(slice: &'de str) -> Option<Self> {
89 trim(slice).parse().ok()
90 }
91}
92
93impl<'de> FromHeaderValue<'de> for i64 {
94 fn parse_header_value(slice: &'de str) -> Option<Self> {
95 trim(slice).parse().ok()
96 }
97}
98
99impl<'de> FromHeaderValue<'de> for i128 {
100 fn parse_header_value(slice: &'de str) -> Option<Self> {
101 trim(slice).parse().ok()
102 }
103}
104
105impl<'de> FromHeaderValue<'de> for isize {
106 fn parse_header_value(slice: &'de str) -> Option<Self> {
107 trim(slice).parse().ok()
108 }
109}
110
111impl<'de> FromHeaderValue<'de> for f32 {
112 fn parse_header_value(slice: &'de str) -> Option<Self> {
113 trim(slice).parse().ok()
114 }
115}
116
117impl<'de> FromHeaderValue<'de> for f64 {
118 fn parse_header_value(slice: &'de str) -> Option<Self> {
119 trim(slice).parse().ok()
120 }
121}
122
123impl<'de> FromHeaderValue<'de> for &'de [u8] {
124 fn parse_header_value(slice: &'de str) -> Option<Self> {
125 Some(slice.as_bytes())
126 }
127}
128
129impl<'de> FromHeaderValue<'de> for &'de str {
130 fn parse_header_value(slice: &'de str) -> Option<Self> {
131 Some(trim(slice))
132 }
133}
134
135impl<'de> FromHeaderValue<'de> for String {
136 fn parse_header_value(slice: &'de str) -> Option<Self> {
137 Some(trim(slice).to_owned())
138 }
139}
140
141impl<'de, T: FromHeaderValue<'de>> FromHeaderValue<'de> for Vec<T> {
142 fn parse_header_value(slice: &'de str) -> Option<Self> {
143 let mut values = vec![];
144 for value in slice.split(',') {
145 let parsed = T::parse_header_value(value)?;
146 values.push(parsed);
147 }
148 Some(values)
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155 use rstest::rstest;
156 use std::usize;
157
158 #[rstest]
159 #[case("true", Some(true))]
160 #[case("false", Some(false))]
161 #[case("falsey", None)]
162 fn bool_test(#[case] input: &str, #[case] expected: Option<bool>) {
163 assert_eq!(expected, bool::parse_header_value(input));
164 }
165
166 #[rstest]
167 #[case("42", Some(42))]
168 #[case("255", Some(255))]
169 #[case("-1", None)]
170 #[case("256", None)]
171 fn u8_test(#[case] input: &str, #[case] expected: Option<u8>) {
172 assert_eq!(expected, u8::parse_header_value(input));
173 }
174
175 #[rstest]
176 #[case("42", Some(42))]
177 #[case("-1", None)]
178 fn u16_test(#[case] input: &str, #[case] expected: Option<u16>) {
179 assert_eq!(expected, u16::parse_header_value(input));
180 }
181
182 #[rstest]
183 #[case("42", Some(42))]
184 #[case("-1", None)]
185 fn u32_test(#[case] input: &str, #[case] expected: Option<u32>) {
186 assert_eq!(expected, u32::parse_header_value(input));
187 }
188
189 #[rstest]
190 #[case("42", Some(42))]
191 #[case("-1", None)]
192 fn u64_test(#[case] input: &str, #[case] expected: Option<u64>) {
193 assert_eq!(expected, u64::parse_header_value(input));
194 }
195
196 #[rstest]
197 #[case("42", Some(42))]
198 #[case("-1", None)]
199 fn u128_test(#[case] input: &str, #[case] expected: Option<u128>) {
200 assert_eq!(expected, u128::parse_header_value(input));
201 }
202
203 #[rstest]
204 #[case("42", Some(42))]
205 #[case("-1", None)]
206 fn usize_test(#[case] input: &str, #[case] expected: Option<usize>) {
207 assert_eq!(expected, usize::parse_header_value(input));
208 }
209
210 #[rstest]
211 #[case("42", Some(42))]
212 #[case("-42", Some(-42))]
213 #[case("idk", None)]
214 fn i8_test(#[case] input: &str, #[case] expected: Option<i8>) {
215 assert_eq!(expected, i8::parse_header_value(input));
216 }
217
218 #[rstest]
219 #[case("42", Some(42))]
220 #[case("-42", Some(-42))]
221 #[case("idk", None)]
222 fn i16_test(#[case] input: &str, #[case] expected: Option<i16>) {
223 assert_eq!(expected, i16::parse_header_value(input));
224 }
225
226 #[rstest]
227 #[case("42", Some(42))]
228 #[case("-42", Some(-42))]
229 #[case("idk", None)]
230 fn i32_test(#[case] input: &str, #[case] expected: Option<i32>) {
231 assert_eq!(expected, i32::parse_header_value(input));
232 }
233
234 #[rstest]
235 #[case("42", Some(42))]
236 #[case("-42", Some(-42))]
237 #[case("idk", None)]
238 fn i64_test(#[case] input: &str, #[case] expected: Option<i64>) {
239 assert_eq!(expected, i64::parse_header_value(input));
240 }
241
242 #[rstest]
243 #[case("42", Some(42))]
244 #[case("-42", Some(-42))]
245 #[case("idk", None)]
246 fn i128_test(#[case] input: &str, #[case] expected: Option<i128>) {
247 assert_eq!(expected, i128::parse_header_value(input));
248 }
249
250 #[rstest]
251 #[case("42", Some(42))]
252 #[case("-42", Some(-42))]
253 #[case("idk", None)]
254 fn isize_test(#[case] input: &str, #[case] expected: Option<isize>) {
255 assert_eq!(expected, isize::parse_header_value(input));
256 }
257
258 #[rstest]
259 #[case("42.7", Some(42.7))]
260 #[case("-42.7", Some(-42.7))]
261 #[case("idk", None)]
262 fn f32_test(#[case] input: &str, #[case] expected: Option<f32>) {
263 assert_eq!(expected, f32::parse_header_value(input));
264 }
265
266 #[rstest]
267 #[case("5.6789", Some(5.6789f64))]
268 #[case("-5.6789", Some(-5.6789f64))]
269 #[case("idk", None)]
270 fn f64_test(#[case] input: &str, #[case] expected: Option<f64>) {
271 assert_eq!(expected, f64::parse_header_value(input));
272 }
273
274 #[rstest]
275 #[case("hello", Some(b"hello".as_slice()))]
276 #[case(" hello ", Some(b" hello ".as_slice()))]
277 fn bytes_test(#[case] input: &str, #[case] expected: Option<&[u8]>) {
278 assert_eq!(expected, <&[u8]>::parse_header_value(input));
279 }
280
281 #[rstest]
282 #[case("hello", Some("hello"))]
283 #[case(" hello ", Some("hello"))]
284 fn str_test(#[case] input: &str, #[case] expected: Option<&str>) {
285 assert_eq!(expected, <&str>::parse_header_value(input));
286 }
287
288 #[rstest]
289 #[case("hello", Some("hello".to_owned()))]
290 #[case(" hello ", Some("hello".to_owned()))]
291 fn string_test(#[case] input: &str, #[case] expected: Option<String>) {
292 assert_eq!(expected, String::parse_header_value(input));
293 }
294
295 #[rstest]
296 #[case("1", Some(vec![1]))]
297 #[case("1, 2", Some(vec![1, 2]))]
298 #[case("1, 2, 3", Some(vec![1, 2, 3]))]
299 #[case("idk", None)]
300 fn vec_test(#[case] input: &str, #[case] expected: Option<Vec<u8>>) {
301 assert_eq!(expected, Vec::<_>::parse_header_value(input));
302 }
303}