transip/authentication/
token_expiration.rs1use std::{fmt::Display, str::FromStr};
2
3use crate::Error;
4
5#[allow(dead_code)]
6#[derive(PartialEq, Debug, Clone)]
7pub enum TokenExpiration {
8 Seconds(u8),
9 Minutes(u8),
10 Hours(u8),
11}
12
13impl Default for TokenExpiration {
14 fn default() -> Self {
15 Self::Minutes(5)
16 }
17}
18
19fn fmt(count: &u8, unit: &'static str) -> String {
20 format!("{} {}", count, unit) + if count <= &1 { "" } else { "s" }
21}
22
23impl Display for TokenExpiration {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(
26 f,
27 "{}",
28 match self {
29 TokenExpiration::Seconds(seconds) => fmt(seconds, "second"),
30 TokenExpiration::Minutes(minutes) => fmt(minutes, "minute"),
31 TokenExpiration::Hours(hours) => fmt(hours, "hour"),
32 }
33 )
34 }
35}
36
37impl FromStr for TokenExpiration {
38 type Err = Error;
39
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 let splitted = s.split(' ').collect::<Vec<_>>();
42 if splitted.len() != 2 {
43 return Err(Error::ParseExpiration("String should contain 2 words"));
44 };
45 let first_word = splitted[0].trim().parse::<u8>()?;
46 let second_word = splitted[1].trim();
47
48 const IS_SECONDS: [&str; 2] = ["second", "seconds"];
49 if IS_SECONDS.contains(&second_word.to_lowercase().as_str()) {
50 return Ok(TokenExpiration::Seconds(first_word));
51 }
52
53 const IS_MINUTES: [&str; 2] = ["minute", "minutes"];
54 if IS_MINUTES.contains(&second_word.to_lowercase().as_str()) {
55 return Ok(TokenExpiration::Minutes(first_word));
56 }
57
58 const IS_HOURS: [&str; 2] = ["hour", "hours"];
59 if IS_HOURS.contains(&second_word.to_lowercase().as_str()) {
60 return Ok(TokenExpiration::Hours(first_word));
61 }
62
63 Err(Error::ParseExpiration("Invalid"))
64 }
65}
66
67#[cfg(test)]
68mod test {
69 use super::TokenExpiration;
70
71 #[test]
72 fn seconds_ok() {
73 let s = "5 seconds";
74 let expiration = s.parse::<TokenExpiration>().unwrap();
75 assert_eq!(expiration, TokenExpiration::Seconds(5));
76 }
77
78 #[test]
79 fn seconds_error() {
80 assert!("10 secconds".parse::<TokenExpiration>().is_err());
81 assert!("five seconds".parse::<TokenExpiration>().is_err());
82 }
83
84 #[test]
85 fn minutes_ok() {
86 assert_eq!(
87 "10 minutes".parse::<TokenExpiration>().unwrap(),
88 TokenExpiration::Minutes(10),
89 );
90 }
91
92 #[test]
93 fn minutes_err() {
94 assert!("10 minuttes".parse::<TokenExpiration>().is_err());
95 assert!("ten minutes".parse::<TokenExpiration>().is_err());
96 }
97
98 #[test]
99 fn hours_ok() {
100 assert_eq!(
101 "60 hours".parse::<TokenExpiration>().unwrap(),
102 TokenExpiration::Hours(60),
103 );
104 assert_eq!(
105 "60 HOUR".parse::<TokenExpiration>().unwrap(),
106 TokenExpiration::Hours(60),
107 );
108 }
109
110 #[test]
111 fn hours_err() {
112 assert!("10 uur".parse::<TokenExpiration>().is_err());
113 assert!("ten hours".parse::<TokenExpiration>().is_err());
114 }
115}