use crate::result::{Error, Result};
pub const MONTH_BASE: u8 = 1;
pub const MONTH_MAX: u8 = 12;
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Month(u8);
impl Month {
pub const fn new() -> Self {
Self(0)
}
pub const fn bits(&self) -> u8 {
self.0
}
pub const fn try_from_bits(val: u8) -> Result<Self> {
match val {
v if v < MONTH_BASE || v > MONTH_MAX => Err(Error::InvalidVariant(val as usize)),
_ => Ok(Self(val)),
}
}
}
impl Default for Month {
fn default() -> Self {
Self::new()
}
}
impl TryFrom<u8> for Month {
type Error = Error;
fn try_from(val: u8) -> Result<Self> {
Self::try_from_bits(val)
}
}
impl From<Month> for u8 {
fn from(val: Month) -> Self {
val.bits()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid() {
(MONTH_BASE..=MONTH_MAX).for_each(|month| {
let exp_month = Month(month);
assert_eq!(Month::try_from_bits(month), Ok(exp_month));
assert_eq!(exp_month.bits(), month);
});
}
#[test]
fn test_invalid() {
(0..=u8::MAX)
.filter(|y| !(MONTH_BASE..=MONTH_MAX).contains(y))
.for_each(|month| {
assert_eq!(
Month::try_from_bits(month),
Err(Error::InvalidVariant(month as usize))
);
});
}
}