duration_human/
validation.rs

1use crate::{DurationError, DurationHuman};
2
3#[derive(Default)]
4pub struct DurationHumanValidator {
5    pub min: DurationHuman,
6    pub default: DurationHuman,
7    pub max: DurationHuman,
8}
9
10impl DurationHumanValidator {
11    /// Create a new validator, with the given minimal, default and maximal durations
12    ///
13    /// ## Panics
14    /// If any value < 1s, or if not: `minimal_nanos` <= `default_nanos` <= `maximal_nanos`
15    #[must_use]
16    pub const fn new(minimal_nanos: u64, default_nanos: u64, maximal_nanos: u64) -> Self {
17        assert!(minimal_nanos <= default_nanos && default_nanos <= maximal_nanos);
18        assert!(minimal_nanos >= DurationHuman::SEC);
19        assert!(default_nanos >= DurationHuman::SEC);
20        assert!(maximal_nanos >= DurationHuman::SEC);
21
22        Self {
23            min: DurationHuman::new(minimal_nanos),
24            default: DurationHuman::new(default_nanos),
25            max: DurationHuman::new(maximal_nanos),
26        }
27    }
28
29    const fn try_new(
30        minimal_nanos: u64,
31        default_nanos: u64,
32        maximal_nanos: u64,
33    ) -> Result<Self, DurationError> {
34        if minimal_nanos < DurationHuman::SEC {
35            Err(DurationError::DurationValidationMinMustBeMoreThanOneSecond)
36        } else if default_nanos < DurationHuman::SEC {
37            Err(DurationError::DurationValidationDefaultMustBeMoreThanOneSecond)
38        } else {
39            Ok(Self {
40                min: DurationHuman::new(minimal_nanos),
41                default: DurationHuman::new(default_nanos),
42                max: DurationHuman::new(maximal_nanos),
43            })
44        }
45    }
46
47    /// To be used as a `validate_parser` for clap
48    ///
49    /// ```compile_error
50    ///  validate_parser = {|lifetime: &str|duration_range.parse_and_validate(lifetime)}
51    /// ```
52    /// # Errors
53    ///
54    /// Will return `Err` if duration is not within the given range
55    /// permission to read it.
56    pub fn parse_and_validate(&self, duration: &str) -> Result<DurationHuman, DurationError> {
57        let duration_in_nanos = DurationHuman::try_from(duration)?;
58
59        if self.contains(&duration_in_nanos) {
60            Ok(duration_in_nanos)
61        } else {
62            Err(DurationError::DurationMustLieBetween {
63                range: self.to_string(),
64            })
65        }
66    }
67
68    #[must_use]
69    pub fn contains(&self, duration: &DurationHuman) -> bool {
70        self.min <= *duration && *duration <= self.max
71    }
72}
73
74impl From<&DurationHumanValidator> for (u64, u64, u64) {
75    fn from(duration: &DurationHumanValidator) -> Self {
76        (
77            (&duration.min).into(),
78            (&duration.default).into(),
79            (&duration.max).into(),
80        )
81    }
82}
83
84impl From<&DurationHumanValidator> for (String, String, String) {
85    fn from(duration: &DurationHumanValidator) -> Self {
86        (
87            duration.min.to_string(),
88            duration.default.to_string(),
89            duration.max.to_string(),
90        )
91    }
92}
93
94impl TryFrom<(DurationHuman, DurationHuman)> for DurationHumanValidator {
95    type Error = DurationError;
96
97    fn try_from(value: (DurationHuman, DurationHuman)) -> Result<Self, Self::Error> {
98        let (minimal, maximal) = &value;
99        if minimal > maximal {
100            Err(DurationError::DurationValidationMinMustBeLessOrEqualMax {
101                minimal: minimal.to_string(),
102                maximal: maximal.to_string(),
103            })
104        } else {
105            let (minimal_ms, maximal_ms): (u64, u64) = (minimal.into(), maximal.into());
106            Self::try_new(minimal_ms, minimal_ms, maximal_ms)
107        }
108    }
109}
110
111impl TryFrom<(DurationHuman, DurationHuman, DurationHuman)> for DurationHumanValidator {
112    type Error = DurationError;
113
114    fn try_from(value: (DurationHuman, DurationHuman, DurationHuman)) -> Result<Self, Self::Error> {
115        let (minimal, default, maximal) = &value;
116        if minimal > default || maximal < default {
117            Err(DurationError::DurationValidationMustBeOrdered {
118                minimal: minimal.to_string(),
119                default: default.to_string(),
120                maximal: maximal.to_string(),
121            })
122        } else {
123            let (minimal_ms, default_ms, maximal_ms): (u64, u64, u64) =
124                (minimal.into(), default.into(), maximal.into());
125            Self::try_new(minimal_ms, default_ms, maximal_ms)
126        }
127    }
128}
129
130impl TryFrom<(u64, u64, u64)> for DurationHumanValidator {
131    type Error = DurationError;
132
133    fn try_from(value: (u64, u64, u64)) -> Result<Self, Self::Error> {
134        let min_def_max: (DurationHuman, DurationHuman, DurationHuman) = (
135            (DurationHuman::from(value.0)),
136            (DurationHuman::from(value.1)),
137            (DurationHuman::from(value.2)),
138        );
139        Self::try_from(min_def_max)
140    }
141}
142
143impl TryFrom<(&str, &str, &str)> for DurationHumanValidator {
144    type Error = DurationError;
145
146    fn try_from(value: (&str, &str, &str)) -> Result<Self, Self::Error> {
147        let min_def_max: (DurationHuman, DurationHuman, DurationHuman) = (
148            (DurationHuman::try_from(value.0)?),
149            (DurationHuman::try_from(value.1)?),
150            (DurationHuman::try_from(value.2)?),
151        );
152
153        Self::try_from(min_def_max)
154    }
155}
156
157impl TryFrom<(u64, u64)> for DurationHumanValidator {
158    type Error = DurationError;
159
160    fn try_from(value: (u64, u64)) -> Result<Self, Self::Error> {
161        let min_max: (DurationHuman, DurationHuman) = (
162            (DurationHuman::from(value.0)),
163            (DurationHuman::from(value.1)),
164        );
165        Self::try_from(min_max)
166    }
167}
168
169impl TryFrom<(&str, &str)> for DurationHumanValidator {
170    type Error = DurationError;
171
172    fn try_from(value: (&str, &str)) -> Result<Self, Self::Error> {
173        let min_max: (DurationHuman, DurationHuman) = (
174            (DurationHuman::try_from(value.0)?),
175            (DurationHuman::try_from(value.1)?),
176        );
177
178        Self::try_from(min_max)
179    }
180}