use crate::prelude::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Display, Serialize, Deserialize, Deref)]
pub struct Day(u8);
impl HasSample for Day {
fn sample() -> Self {
Self(1)
}
fn sample_other() -> Self {
Self(15)
}
}
impl std::str::FromStr for Day {
type Err = crate::prelude::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let day = s.parse::<i32>().map_err(|_| Error::InvalidDayFromString {
invalid_string: s.to_string(),
reason: "Invalid day format".to_string(),
})?;
Self::try_from(day)
}
}
impl TryFrom<i32> for Day {
type Error = crate::prelude::Error;
fn try_from(day: i32) -> Result<Self> {
if !(1..=31).contains(&day) {
return Err(Error::InvalidDay {
day,
reason: "Day must be between 1 and 31".to_string(),
});
}
Ok(Self(day as u8))
}
}
impl TryFrom<u8> for Day {
type Error = crate::prelude::Error;
fn try_from(day: u8) -> Result<Self> {
Self::try_from(day as i32)
}
}
impl TryFrom<u32> for Day {
type Error = crate::prelude::Error;
fn try_from(day: u32) -> Result<Self> {
Self::try_from(day as i32)
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_log::test;
type Sut = Day;
#[test]
fn equality() {
assert_eq!(Sut::sample(), Sut::sample());
assert_eq!(Sut::sample_other(), Sut::sample_other());
}
#[test]
fn inequality() {
assert_ne!(Sut::sample(), Sut::sample_other());
}
#[test]
fn test_day_conversion() {
assert_eq!(Sut::try_from(1).unwrap(), Day(1));
assert_eq!(Sut::try_from(15).unwrap(), Day(15));
assert_eq!(Sut::try_from(31).unwrap(), Day(31));
assert!(Sut::try_from(0).is_err());
assert!(Sut::try_from(32).is_err());
}
#[test]
fn test_day_from_str() {
let day: Sut = "15".parse().unwrap();
assert_eq!(day, Day(15));
}
#[test]
fn test_day_from_invalid_all_reasons() {
let invalid_strings = [
"0", "32", "-1", "abc", "15.5", ];
for &s in &invalid_strings {
assert!(Sut::from_str(s).is_err(), "Expected error for input: {}", s);
}
}
}