agent_first_http/shared/
time.rs1use crate::shared::error::{Error, ErrorCode};
8
9pub fn parse_duration(input: &str) -> Result<std::time::Duration, Error> {
13 if input.is_empty() {
14 return Err(Error::new(
15 ErrorCode::InvalidArgument,
16 "duration: empty input",
17 ));
18 }
19 humantime::parse_duration(input)
20 .map_err(|e| Error::new(ErrorCode::InvalidArgument, format!("duration: {e}")))
21}
22
23#[must_use]
26pub fn duration_ms(d: std::time::Duration) -> u64 {
27 u64::try_from(d.as_millis()).unwrap_or(u64::MAX)
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33 use std::time::Duration;
34
35 #[test]
36 fn parses_common_units() {
37 assert_eq!(parse_duration("30s").map(|d| d.as_secs()).ok(), Some(30));
38 assert_eq!(
39 parse_duration("250ms").map(|d| d.as_millis()).ok(),
40 Some(250)
41 );
42 assert_eq!(parse_duration("1m").map(|d| d.as_secs()).ok(), Some(60));
43 assert_eq!(
44 parse_duration("2h").map(|d| d.as_secs()).ok(),
45 Some(2 * 3600)
46 );
47 assert_eq!(
48 parse_duration("30d").map(|d| d.as_secs()).ok(),
49 Some(30 * 86400),
50 );
51 }
52
53 #[test]
54 fn empty_input_is_invalid_argument() {
55 let err = parse_duration("").err();
56 assert!(err.is_some());
57 if let Some(e) = err {
58 assert_eq!(e.error_code, ErrorCode::InvalidArgument);
59 }
60 }
61
62 #[test]
63 fn garbage_input_is_invalid_argument() {
64 let err = parse_duration("nonsense").err();
65 assert!(err.is_some());
66 if let Some(e) = err {
67 assert_eq!(e.error_code, ErrorCode::InvalidArgument);
68 }
69 }
70
71 #[test]
72 fn duration_ms_saturates() {
73 assert_eq!(duration_ms(Duration::from_millis(1234)), 1234);
74 assert_eq!(duration_ms(Duration::ZERO), 0);
75 }
76}