sdmmc-core 0.5.0

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

/// Represents a ranged index value with a min-max bound.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RangedIndex<const MIN: usize, const MAX: usize>(usize);

impl<const MIN: usize, const MAX: usize> RangedIndex<MIN, MAX> {
    /// Creates a new [RangedIndex].
    pub const fn new() -> Self {
        Self(MIN)
    }

    /// Gets the minimum range index.
    pub const fn min() -> usize {
        MIN
    }

    /// Gets the maximum range index.
    pub const fn max() -> usize {
        MAX
    }

    /// Attempts to convert a raw index value into a [RangedIndex].
    pub const fn try_from_inner(val: usize) -> Result<Self> {
        if val >= MIN && val <= MAX {
            Ok(Self(val))
        } else {
            Err(Error::invalid_field_value("index", val, MIN, MAX))
        }
    }

    /// Converts a raw index value into a [RangedIndex] with no bounds check.
    ///
    /// # Panics
    ///
    /// Panics if the provided index is out-of-bounds.
    ///
    /// Caller must ensure that the index is in the valid range.
    pub const fn try_from_unchecked(val: usize) -> Self {
        match Self::try_from_inner(val) {
            Ok(i) => i,
            Err(_) => panic!("ranged index out-of-bounds"),
        }
    }

    /// Converts a [RangedIndex] into a raw index value.
    pub const fn into_inner(self) -> usize {
        self.0
    }
}

impl<const MIN: usize, const MAX: usize> Default for RangedIndex<MIN, MAX> {
    fn default() -> Self {
        Self::new()
    }
}

impl<const MIN: usize, const MAX: usize> TryFrom<usize> for RangedIndex<MIN, MAX> {
    type Error = Error;

    fn try_from(val: usize) -> Result<Self> {
        Self::try_from_inner(val)
    }
}

impl<const MIN: usize, const MAX: usize> From<RangedIndex<MIN, MAX>> for usize {
    fn from(val: RangedIndex<MIN, MAX>) -> Self {
        val.into_inner()
    }
}

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

    #[test]
    fn test_ranged_index() {
        const MIN: usize = 1;
        const MAX: usize = 256;

        type TestIndex = RangedIndex<MIN, MAX>;

        assert_eq!(TestIndex::new().into_inner(), MIN);
        assert_eq!(TestIndex::default().into_inner(), MIN);

        (MIN..=MAX).for_each(|index| {
            let exp_index = TestIndex::try_from(index).unwrap();

            assert_eq!(TestIndex::try_from_inner(index), Ok(exp_index));
            assert_eq!(TestIndex::try_from(index), Ok(exp_index));

            assert_eq!(exp_index.into_inner(), index);
            assert_eq!(usize::from(exp_index), index);
        });
    }
}