use crate::lib_bitfield;
use crate::range::RangeU8;
use crate::result::Result;
use super::{ExtCsd, ExtCsdIndex};
pub type Timeout = RangeU8<1, 0x17>;
lib_bitfield! {
OperationCodesTimeout: u8,
mask: 0xff,
default: 1,
{
operation_codes_timeout: Timeout, 7, 0;
}
}
impl OperationCodesTimeout {
pub const TIMEOUT_UNIT: u32 = 100;
pub const fn timeout(&self) -> Result<u32> {
match self.operation_codes_timeout() {
Ok(t) => Ok(Self::TIMEOUT_UNIT * (1u32 << t.into_inner())),
Err(err) => Err(err),
}
}
}
impl ExtCsd {
pub const fn operation_codes_timeout(&self) -> Result<OperationCodesTimeout> {
OperationCodesTimeout::try_from_inner(
self.0[ExtCsdIndex::OperationCodesTimeout.into_inner()],
)
}
pub(crate) fn set_operation_codes_timeout(&mut self, val: OperationCodesTimeout) {
self.0[ExtCsdIndex::OperationCodesTimeout.into_inner()] = val.into_inner();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_operation_codes_timeout() {
let mut ext_csd = ExtCsd::new();
ext_csd.set_operation_codes_timeout(OperationCodesTimeout::new());
assert_eq!(
ext_csd.operation_codes_timeout(),
Ok(OperationCodesTimeout::new())
);
(0..u8::MAX).for_each(|raw_timeout| {
ext_csd.set_operation_codes_timeout(OperationCodesTimeout(raw_timeout));
match OperationCodesTimeout::try_from_inner(raw_timeout) {
Ok(timeout) => {
assert_eq!(ext_csd.operation_codes_timeout(), Ok(timeout));
assert_eq!(
timeout.timeout(),
Ok(OperationCodesTimeout::TIMEOUT_UNIT * (1u32 << raw_timeout))
);
}
Err(err) => assert_eq!(ext_csd.operation_codes_timeout(), Err(err)),
}
});
}
}