inth_oauth2_async/token/
expiring.rs1use serde_json::Value;
2use std::time::{Duration, SystemTime};
3
4use crate::client::response::{FromResponse, ParseError};
5use crate::token::Lifetime;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9pub struct Expiring {
10 expires: SystemTime,
11}
12
13impl Expiring {
14 pub fn expires(&self) -> SystemTime { self.expires }
16}
17
18impl Lifetime for Expiring {
19 fn expired(&self) -> bool { self.expires < SystemTime::now() }
20}
21
22impl FromResponse for Expiring {
23 fn from_response(json: &Value) -> Result<Self, ParseError> {
24 let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
25
26 if obj.contains_key("refresh_token") {
27 return Err(ParseError::UnexpectedField("refresh_token"));
28 }
29
30 let expires_in = obj.get("expires_in")
31 .and_then(Value::as_i64)
32 .ok_or(ParseError::ExpectedFieldType("expires_in", "i64"))?;
33
34 Ok(Expiring {
35 expires: SystemTime::now() + Duration::from_secs(expires_in.try_into().unwrap_or(0)),
36 })
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn from_response() {
46 let json = r#"{"expires_in":3600}"#.parse().unwrap();
47 let expiring = Expiring::from_response(&json).unwrap();
48 assert!(expiring.expires > SystemTime::now());
49 assert!(expiring.expires <= SystemTime::now() + Duration::from_secs(3600));
50 }
51}