sdmmc-core 0.5.0

SD/MMC core data structures and algorithms
Documentation
use crate::result::{Error, Result};

/// The base value for [Year].
pub const YEAR_BASE: u16 = 2000;
/// The maximum value for [Year].
pub const YEAR_MAX: u16 = 2255;

/// Represents the year field in a [ManufacturingDate](super::ManufacturingDate).
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Year(u8);

impl Year {
    /// Creates a new [Year].
    pub const fn new() -> Self {
        Self(0)
    }

    /// Gets the [Year] field adjusted to the base (2000).
    pub const fn year(&self) -> u16 {
        (self.0 as u16) + YEAR_BASE
    }

    /// Attempts to convert a [`u16`] into a [Year].
    ///
    /// **NOTE**: `val` must be in the range [YEAR_BASE]..=[YEAR_MAX].
    #[allow(clippy::manual_range_contains)]
    pub fn try_from_year(val: u16) -> Result<Self> {
        match val {
            v if v < YEAR_BASE || v > YEAR_MAX => Err(Error::InvalidVariant(val as usize)),
            _ => Ok(Self(val.saturating_sub(YEAR_BASE) as u8)),
        }
    }

    /// Gets the bit value of the [Year].
    pub const fn bits(&self) -> u8 {
        self.0
    }

    /// Converts a [`u8`] into a [Year].
    pub const fn from_bits(val: u8) -> Self {
        Self(val)
    }
}

impl Default for Year {
    fn default() -> Self {
        Self::new()
    }
}

impl From<u8> for Year {
    fn from(val: u8) -> Self {
        Self::from_bits(val)
    }
}

impl TryFrom<u16> for Year {
    type Error = Error;

    fn try_from(val: u16) -> Result<Self> {
        Self::try_from_year(val)
    }
}

impl From<Year> for u8 {
    fn from(val: Year) -> Self {
        val.bits()
    }
}

impl From<Year> for u16 {
    fn from(val: Year) -> Self {
        val.year()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid() {
        (0..=u8::MAX).for_each(|year| {
            let exp_year = Year(year);
            let adj_year = YEAR_BASE + (year as u16);

            assert_eq!(Year::from_bits(year), exp_year);
            assert_eq!(Year::try_from_year(adj_year), Ok(exp_year));

            assert_eq!(exp_year.bits(), year);
            assert_eq!(exp_year.year(), adj_year);
        });
    }

    #[test]
    fn test_invalid() {
        (0..=u16::MAX)
            .filter(|y| !(YEAR_BASE..=YEAR_MAX).contains(y))
            .for_each(|year| {
                assert_eq!(
                    Year::try_from_year(year),
                    Err(Error::InvalidVariant(year as usize))
                );
            });
    }
}