hvcg_student_openapi_application/
header.rs

1use chrono::{DateTime, Utc};
2use hyper::header::HeaderValue;
3use std::convert::TryFrom;
4use std::fmt;
5use std::ops::Deref;
6
7/// A struct to allow homogeneous conversion into a HeaderValue. We can't
8/// implement the From/Into trait on HeaderValue because we don't own
9/// either of the types.
10#[derive(Debug, Clone)]
11pub(crate) struct IntoHeaderValue<T>(pub T);
12
13// Generic implementations
14
15impl<T> Deref for IntoHeaderValue<T> {
16    type Target = T;
17
18    fn deref(&self) -> &T {
19        &self.0
20    }
21}
22
23// Derive for each TryFrom<T> in hyper::header::HeaderValue
24
25macro_rules! ihv_generate {
26    ($t:ident) => {
27        impl TryFrom<HeaderValue> for IntoHeaderValue<$t> {
28            type Error = String;
29
30            fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
31                match hdr_value.to_str() {
32                    Ok(hdr_value) => match hdr_value.parse::<$t>() {
33                        Ok(hdr_value) => Ok(IntoHeaderValue(hdr_value)),
34                        Err(e) => Err(format!("Unable to parse {} as a string: {}",
35                            stringify!($t), e)),
36                    },
37                    Err(e) => Err(format!("Unable to parse header {:?} as a string - {}",
38                        hdr_value, e)),
39                }
40            }
41        }
42
43        impl TryFrom<IntoHeaderValue<$t>> for HeaderValue {
44            type Error = String;
45
46            fn try_from(hdr_value: IntoHeaderValue<$t>) -> Result<Self, Self::Error> {
47                Ok(hdr_value.0.into())
48            }
49        }
50    };
51}
52
53ihv_generate!(u64);
54ihv_generate!(i64);
55ihv_generate!(i16);
56ihv_generate!(u16);
57ihv_generate!(u32);
58ihv_generate!(usize);
59ihv_generate!(isize);
60ihv_generate!(i32);
61
62// Custom derivations
63
64// Vec<String>
65
66impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
67    type Error = String;
68
69    fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
70        match hdr_value.to_str() {
71            Ok(hdr_value) => Ok(IntoHeaderValue(
72                hdr_value
73                .split(',')
74                .filter_map(|x| match x.trim() {
75                    "" => None,
76                    y => Some(y.to_string()),
77                })
78                .collect())),
79            Err(e) => Err(format!("Unable to parse header: {:?} as a string - {}",
80                hdr_value, e)),
81        }
82    }
83}
84
85impl TryFrom<IntoHeaderValue<Vec<String>>> for HeaderValue {
86    type Error = String;
87
88    fn try_from(hdr_value: IntoHeaderValue<Vec<String>>) -> Result<Self, Self::Error> {
89       match HeaderValue::from_str(&hdr_value.0.join(", ")) {
90           Ok(hdr_value) => Ok(hdr_value),
91           Err(e) => Err(format!("Unable to convert {:?} into a header - {}",
92               hdr_value, e))
93       }
94    }
95}
96
97// String
98
99impl TryFrom<HeaderValue> for IntoHeaderValue<String> {
100    type Error = String;
101
102    fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
103        match hdr_value.to_str() {
104            Ok(hdr_value) => Ok(IntoHeaderValue(hdr_value.to_string())),
105            Err(e) => Err(format!("Unable to convert header {:?} to {}",
106                hdr_value, e)),
107        }
108    }
109}
110
111impl TryFrom<IntoHeaderValue<String>> for HeaderValue {
112    type Error = String;
113
114    fn try_from(hdr_value: IntoHeaderValue<String>) -> Result<Self, Self::Error> {
115        match HeaderValue::from_str(&hdr_value.0) {
116            Ok(hdr_value) => Ok(hdr_value),
117            Err(e) => Err(format!("Unable to convert {:?} from a header {}",
118                hdr_value, e))
119        }
120    }
121}
122
123// bool
124impl TryFrom<HeaderValue> for IntoHeaderValue<bool> {
125    type Error = String;
126
127    fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
128        match hdr_value.to_str() {
129            Ok(hdr_value) => match hdr_value.parse() {
130                Ok(hdr_value) => Ok(IntoHeaderValue(hdr_value)),
131                Err(e) => Err(format!("Unable to parse bool from {} - {}",
132                    hdr_value, e)),
133            },
134            Err(e) => Err(format!("Unable to convert {:?} from a header {}",
135                hdr_value, e)),
136        }
137    }
138}
139
140impl TryFrom<IntoHeaderValue<bool>> for HeaderValue {
141    type Error = String;
142
143    fn try_from(hdr_value: IntoHeaderValue<bool>) -> Result<Self, Self::Error> {
144        match HeaderValue::from_str(&hdr_value.0.to_string()) {
145            Ok(hdr_value) => Ok(hdr_value),
146            Err(e) => Err(format!("Unable to convert: {:?} into a header: {}",
147                hdr_value, e))
148        }
149    }
150}
151
152// DateTime
153
154impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
155    type Error = String;
156
157    fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
158        match hdr_value.to_str() {
159            Ok(hdr_value) => match DateTime::parse_from_rfc3339(hdr_value) {
160                Ok(date) => Ok(IntoHeaderValue(date.with_timezone(&Utc))),
161                Err(e) => Err(format!("Unable to parse: {} as date - {}",
162                    hdr_value, e)),
163            },
164            Err(e) => Err(format!("Unable to convert header {:?} to string {}",
165                    hdr_value, e)),
166        }
167    }
168}
169
170impl TryFrom<IntoHeaderValue<DateTime<Utc>>> for HeaderValue {
171    type Error = String;
172
173    fn try_from(hdr_value: IntoHeaderValue<DateTime<Utc>>) -> Result<Self, Self::Error> {
174        match HeaderValue::from_str(hdr_value.0.to_rfc3339().as_str()) {
175            Ok(hdr_value) => Ok(hdr_value),
176            Err(e) => Err(format!("Unable to convert {:?} to a header: {}",
177                hdr_value, e)),
178        }
179    }
180}