use crate::lib_bitfield;
use crate::result::{Error, Result};
mod time_unit;
mod time_value;
pub use time_unit::AccessTimeUnit;
pub use time_value::AccessTimeValue;
lib_bitfield! {
TimeAsyncAccessCycles: u8,
mask: 0x7f,
default: 0x8,
{
time_value: AccessTimeValue, 6, 3;
time_unit: AccessTimeUnit, 2, 0;
}
}
impl TimeAsyncAccessCycles {
pub const UNIT_MASK: u8 = 0x7;
pub const VALUE_MASK: u8 = 0x78;
pub const VALUE_SHIFT: usize = 3;
pub const fn time_ns(&self) -> u32 {
match (self.time_value(), self.time_unit()) {
(Ok(time_value), Ok(time_unit)) => (time_value.value_int() * time_unit.ns()) / 10,
_ => 0,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
type Taac = TimeAsyncAccessCycles;
#[test]
fn test_valid() {
let taac = Taac::new();
assert_eq!(taac.time_unit(), Ok(AccessTimeUnit::new()));
assert_eq!(taac.time_value(), Ok(AccessTimeValue::new()));
(0..=u8::MAX)
.filter(|b| {
AccessTimeUnit::from_raw(b & Taac::UNIT_MASK).is_ok()
&& AccessTimeValue::from_raw((b & Taac::VALUE_MASK) >> Taac::VALUE_SHIFT)
.is_ok()
})
.for_each(|raw| {
let exp_taac = Taac::try_from_inner(raw & Taac::MASK).unwrap();
let exp_unit = AccessTimeUnit::from_raw(raw & Taac::UNIT_MASK).unwrap();
let exp_value =
AccessTimeValue::from_raw((raw & Taac::VALUE_MASK) >> Taac::VALUE_SHIFT)
.unwrap();
let exp_ns = (exp_value.value_int() * exp_unit.ns()) / 10;
assert_eq!(Taac::try_from_inner(raw), Ok(exp_taac));
assert_eq!(Taac::try_from(raw), Ok(exp_taac));
assert_eq!(exp_taac.bits(), raw & Taac::MASK);
assert_eq!(u8::from(exp_taac), raw & Taac::MASK);
assert_eq!(exp_taac.time_unit(), Ok(exp_unit));
assert_eq!(exp_taac.time_value(), Ok(exp_value));
assert_eq!(exp_taac.time_ns(), exp_ns);
});
}
#[test]
fn test_invalid() {
(0..=u8::MAX)
.filter(|b| AccessTimeUnit::from_raw(b & Taac::UNIT_MASK).is_err())
.for_each(|raw| {
assert!(Taac::try_from_inner(raw).is_err());
assert!(Taac::try_from(raw).is_err());
});
(0..=u8::MAX)
.filter(|b| {
AccessTimeUnit::from_raw(b & Taac::UNIT_MASK).is_ok()
&& AccessTimeValue::from_raw((b & Taac::VALUE_MASK) >> Taac::VALUE_SHIFT)
.is_err()
})
.for_each(|raw| {
assert!(Taac::try_from_inner(raw).is_err());
assert!(Taac::try_from(raw).is_err());
});
}
}