1use crate::prelude::*;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Display, Serialize, Deserialize, Deref)]
5pub struct Day(u8);
6
7impl HasSample for Day {
8 fn sample() -> Self {
9 Self(1)
10 }
11 fn sample_other() -> Self {
12 Self(15)
13 }
14}
15
16impl std::str::FromStr for Day {
17 type Err = crate::prelude::Error;
18
19 fn from_str(s: &str) -> Result<Self, Self::Err> {
30 let day = s.parse::<i32>().map_err(|_| Error::InvalidDayFromString {
31 invalid_string: s.to_string(),
32 reason: "Invalid day format".to_string(),
33 })?;
34 Self::try_from(day)
35 }
36}
37
38impl TryFrom<i32> for Day {
39 type Error = crate::prelude::Error;
40 fn try_from(day: i32) -> Result<Self> {
41 if !(1..=31).contains(&day) {
42 return Err(Error::InvalidDay {
43 day,
44 reason: "Day must be between 1 and 31".to_string(),
45 });
46 }
47 Ok(Self(day as u8))
48 }
49}
50
51impl TryFrom<u8> for Day {
52 type Error = crate::prelude::Error;
53 fn try_from(day: u8) -> Result<Self> {
54 Self::try_from(day as i32)
55 }
56}
57
58impl TryFrom<u32> for Day {
59 type Error = crate::prelude::Error;
60 fn try_from(day: u32) -> Result<Self> {
61 Self::try_from(day as i32)
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use test_log::test;
69
70 type Sut = Day;
71
72 #[test]
73 fn equality() {
74 assert_eq!(Sut::sample(), Sut::sample());
75 assert_eq!(Sut::sample_other(), Sut::sample_other());
76 }
77
78 #[test]
79 fn inequality() {
80 assert_ne!(Sut::sample(), Sut::sample_other());
81 }
82
83 #[test]
84 fn test_day_conversion() {
85 assert_eq!(Sut::try_from(1).unwrap(), Day(1));
86 assert_eq!(Sut::try_from(15).unwrap(), Day(15));
87 assert_eq!(Sut::try_from(31).unwrap(), Day(31));
88 assert!(Sut::try_from(0).is_err());
89 assert!(Sut::try_from(32).is_err());
90 }
91
92 #[test]
93 fn test_day_from_str() {
94 let day: Sut = "15".parse().unwrap();
95 assert_eq!(day, Day(15));
96 }
97
98 #[test]
99 fn test_day_from_invalid_all_reasons() {
100 let invalid_strings = [
101 "0", "32", "-1", "abc", "15.5", ];
107
108 for &s in &invalid_strings {
109 assert!(Sut::from_str(s).is_err(), "Expected error for input: {}", s);
110 }
111 }
112}