1use crate::error::Error;
6use std::time::Duration;
7
8pub fn parse_duration(s: &str) -> Result<Duration, Error> {
33 let s = s.trim();
34
35 if s.is_empty() {
36 return Err(Error::invalid_config(
37 "Duration cannot be empty".to_string(),
38 ));
39 }
40
41 if let Some(ms_str) = s.strip_suffix("ms") {
43 let ms: u64 = ms_str
44 .trim()
45 .parse()
46 .map_err(|_| Error::invalid_config(format!("Invalid milliseconds value: {ms_str}")))?;
47 return Ok(Duration::from_millis(ms));
48 }
49
50 if let Some(m_str) = s.strip_suffix('m') {
51 let minutes: u64 = m_str
53 .trim()
54 .parse()
55 .map_err(|_| Error::invalid_config(format!("Invalid minutes value: {m_str}")))?;
56 return Ok(Duration::from_secs(minutes * 60));
57 }
58
59 if let Some(s_str) = s.strip_suffix('s') {
60 let secs: u64 = s_str
61 .trim()
62 .parse()
63 .map_err(|_| Error::invalid_config(format!("Invalid seconds value: {s_str}")))?;
64 return Ok(Duration::from_secs(secs));
65 }
66
67 let ms: u64 = s.parse().map_err(|_| {
69 Error::invalid_config(format!(
70 "Invalid duration format: {s}. Use format like '500ms', '1s', '30s', or '1m'"
71 ))
72 })?;
73 Ok(Duration::from_millis(ms))
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_parse_duration_milliseconds() {
82 assert_eq!(parse_duration("100ms").unwrap(), Duration::from_millis(100));
83 assert_eq!(parse_duration("500ms").unwrap(), Duration::from_millis(500));
84 assert_eq!(
85 parse_duration("1000ms").unwrap(),
86 Duration::from_millis(1000)
87 );
88 }
89
90 #[test]
91 fn test_parse_duration_seconds() {
92 assert_eq!(parse_duration("1s").unwrap(), Duration::from_secs(1));
93 assert_eq!(parse_duration("30s").unwrap(), Duration::from_secs(30));
94 assert_eq!(parse_duration("120s").unwrap(), Duration::from_secs(120));
95 }
96
97 #[test]
98 fn test_parse_duration_minutes() {
99 assert_eq!(parse_duration("1m").unwrap(), Duration::from_secs(60));
100 assert_eq!(parse_duration("5m").unwrap(), Duration::from_secs(300));
101 }
102
103 #[test]
104 fn test_parse_duration_plain_number() {
105 assert_eq!(parse_duration("500").unwrap(), Duration::from_millis(500));
106 assert_eq!(parse_duration("1000").unwrap(), Duration::from_millis(1000));
107 }
108
109 #[test]
110 fn test_parse_duration_with_whitespace() {
111 assert_eq!(
112 parse_duration(" 500ms ").unwrap(),
113 Duration::from_millis(500)
114 );
115 assert_eq!(parse_duration(" 1s ").unwrap(), Duration::from_secs(1));
116 }
117
118 #[test]
119 fn test_parse_duration_empty() {
120 assert!(parse_duration("").is_err());
121 assert!(parse_duration(" ").is_err());
122 }
123
124 #[test]
125 fn test_parse_duration_invalid() {
126 assert!(parse_duration("abc").is_err());
127 assert!(parse_duration("1x").is_err());
128 assert!(parse_duration("ms").is_err());
129 assert!(parse_duration("-1s").is_err());
130 }
131}