date_validation_types/units/
validated_day.rs

1use crate::constants::{DAY_LOWER_BOUND, DAY_UPPER_BOUND};
2use derive_more::{Display, Into};
3use thiserror::Error;
4
5#[derive(Debug, Error)]
6#[error(
7    "Day {} is not between {} and {}",
8    _0,
9    DAY_LOWER_BOUND,
10    DAY_UPPER_BOUND
11)]
12pub struct InvalidDay(pub u32);
13
14#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Display, Clone, Copy, Into)]
15pub struct ValidatedDay(u32);
16
17impl ValidatedDay {
18    pub fn new(to_validated: u32) -> Result<Self, InvalidDay> {
19        to_validated.try_into()
20    }
21}
22
23impl TryFrom<u32> for ValidatedDay {
24    type Error = InvalidDay;
25    fn try_from(value: u32) -> Result<Self, Self::Error> {
26        if !(DAY_LOWER_BOUND..=DAY_UPPER_BOUND).contains(&value) {
27            Err(InvalidDay(value))
28        } else {
29            Ok(Self(value))
30        }
31    }
32}
33
34#[cfg(test)]
35mod testing {
36    use super::*;
37    use crate::units::testing_utitliy;
38
39    #[test]
40    fn should_accept_valid_days() {
41        for month_index in 1..=31 {
42            testing_utitliy::assert_accept_valid_unit::<ValidatedDay>(month_index);
43        }
44    }
45
46    #[test]
47    fn invalid_day_correct_error_msg() {
48        let invalid = ValidatedDay::new(40);
49        if let Err(error) = invalid {
50            assert_eq!("Day 40 is not between 1 and 31", error.to_string());
51        } else {
52            panic!("Should have resulted into an error for an invalid day");
53        }
54    }
55
56    #[test]
57    fn should_deny_invalid_days() {
58        testing_utitliy::assert_deny_invalid_unit::<ValidatedDay>(0);
59        testing_utitliy::assert_deny_invalid_unit::<ValidatedDay>(32);
60        testing_utitliy::assert_deny_invalid_unit::<ValidatedDay>(u32::MAX);
61        testing_utitliy::assert_deny_invalid_unit::<ValidatedDay>(u32::MAX / 2);
62    }
63}