tanzim_validate/
duration.rs1use crate::error::{Error, ErrorKind};
2use crate::{Meta, Validator};
3use tanzim_value::{Value, ValueType};
4
5#[derive(Debug, Clone, Default)]
8pub struct Duration {
9 meta: Meta,
10 millis: bool,
11}
12
13impl Duration {
14 pub fn with_meta(mut self, meta: Meta) -> Self {
16 self.meta = meta;
17 self
18 }
19
20 pub fn new() -> Self {
21 Self::default()
22 }
23
24 pub fn millis(mut self) -> Self {
26 self.millis = true;
27 self
28 }
29}
30
31crate::impl_meta_methods!(Duration);
32
33impl Validator for Duration {
34 fn meta(&self) -> &Meta {
35 &self.meta
36 }
37
38 fn meta_mut(&mut self) -> &mut Meta {
39 &mut self.meta
40 }
41
42 fn check(&self, value: &mut Value) -> Result<(), Error> {
43 let text = match value {
44 Value::String(text) => text,
45 other => {
46 return Err(Error::new(ErrorKind::Type {
47 expected: ValueType::String,
48 found: other.type_name(),
49 }));
50 }
51 };
52
53 let parsed = match humantime::parse_duration(text) {
54 Ok(parsed) => parsed,
55 Err(_) => {
56 return Err(Error::new(ErrorKind::Format {
57 expected: "duration",
58 }));
59 }
60 };
61
62 let amount = if self.millis {
63 parsed.as_millis()
64 } else {
65 parsed.as_secs() as u128
66 };
67 let coerced = match isize::try_from(amount) {
68 Ok(coerced) => coerced,
69 Err(_) => {
70 return Err(Error::new(ErrorKind::NotConvertible {
71 target: ValueType::Int,
72 found: ValueType::String,
73 }));
74 }
75 };
76
77 *value = Value::Int(coerced);
78 Ok(())
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn coerces_to_seconds() {
88 let mut value = Value::String("1h30m".into());
89 Duration::new().validate(&mut value).unwrap();
90 assert_eq!(value, Value::Int(5400));
91 }
92
93 #[test]
94 fn coerces_to_millis() {
95 let mut value = Value::String("250ms".into());
96 Duration::new().millis().validate(&mut value).unwrap();
97 assert_eq!(value, Value::Int(250));
98 }
99
100 #[test]
101 fn rejects_garbage() {
102 let mut value = Value::String("soon".into());
103 assert!(Duration::new().validate(&mut value).is_err());
104 }
105}