http_types_rs/cache/
age.rs1use crate::headers::{Header, HeaderName, HeaderValue, Headers, AGE};
2use crate::Status;
3
4use std::fmt::Debug;
5
6use std::time::Duration;
7
8#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
33pub struct Age {
34 dur: Duration,
35}
36
37impl Age {
38 pub fn new(dur: Duration) -> Self {
40 Self { dur }
41 }
42
43 pub fn from_secs(secs: u64) -> Self {
45 let dur = Duration::from_secs(secs);
46 Self { dur }
47 }
48
49 pub fn duration(&self) -> Duration {
51 self.dur
52 }
53
54 pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
56 let headers = match headers.as_ref().get(AGE) {
57 Some(headers) => headers,
58 None => return Ok(None),
59 };
60
61 let header = headers.iter().last().unwrap();
64
65 let num: u64 = header.as_str().parse::<u64>().status(400)?;
66 let dur = Duration::from_secs_f64(num as f64);
67
68 Ok(Some(Self { dur }))
69 }
70}
71
72impl Header for Age {
73 fn header_name(&self) -> HeaderName {
74 AGE
75 }
76
77 fn header_value(&self) -> HeaderValue {
78 let output = self.dur.as_secs().to_string();
79
80 unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
82 }
83}
84
85#[cfg(test)]
86mod test {
87 use super::*;
88 use crate::headers::Headers;
89
90 #[test]
91 fn smoke() -> crate::Result<()> {
92 let age = Age::new(Duration::from_secs(12));
93
94 let mut headers = Headers::new();
95 age.apply_header(&mut headers);
96
97 let age = Age::from_headers(headers)?.unwrap();
98 assert_eq!(age, Age::new(Duration::from_secs(12)));
99 Ok(())
100 }
101
102 #[test]
103 fn bad_request_on_parse_error() {
104 let mut headers = Headers::new();
105 headers.insert(AGE, "<nori ate the tag. yum.>").unwrap();
106 let err = Age::from_headers(headers).unwrap_err();
107 assert_eq!(err.status(), 400);
108 }
109}