use crate::lib_bitfield;
use crate::result::{Error, Result};
mod io_current_state;
pub use io_current_state::*;
lib_bitfield! {
pub Flags(u8): u8 {
pub crc_error: 7;
pub illegal_command: 6;
raw_io_current_state: 5, 4;
pub error: 3;
pub function_number: 1;
pub out_of_range: 0;
}
}
impl Flags {
pub const fn new() -> Self {
Self(0)
}
pub const fn io_current_state(&self) -> Result<IoCurrentState> {
IoCurrentState::from_raw(self.raw_io_current_state())
}
pub fn set_io_current_state(&mut self, val: IoCurrentState) {
self.set_raw_io_current_state(val.into_raw())
}
pub const fn try_from_bits(val: u8) -> Result<Self> {
let flags = Self(val);
match flags.io_current_state() {
Ok(_) => Ok(flags),
Err(_) => Err(Error::invalid_field_variant(
"r5::flags::io_current_state",
flags.raw_io_current_state() as usize,
)),
}
}
}
impl Default for Flags {
fn default() -> Self {
Self::new()
}
}
impl From<Flags> for u8 {
fn from(val: Flags) -> Self {
val.bits()
}
}
impl TryFrom<u8> for Flags {
type Error = Error;
fn try_from(val: u8) -> Result<Self> {
Self::try_from_bits(val)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid() {
let mut flags = Flags::new();
test_field!(flags, out_of_range: 0);
test_field!(flags, function_number: 1);
test_field!(flags, error: 3);
test_field!(flags, illegal_command: 6);
test_field!(flags, crc_error: 7);
[
IoCurrentState::Disabled,
IoCurrentState::Command,
IoCurrentState::Transfer,
]
.into_iter()
.for_each(|io_cs| {
let raw_io_cs = io_cs.into_raw();
let mut exp_flags = Flags(raw_io_cs << 4);
assert_eq!(Flags::try_from_bits(raw_io_cs << 4), Ok(exp_flags));
assert_eq!(exp_flags.io_current_state(), Ok(io_cs));
exp_flags.set_io_current_state(IoCurrentState::new());
assert_eq!(exp_flags.io_current_state(), Ok(IoCurrentState::new()));
});
}
#[test]
fn test_invalid() {
let raw_io_cs = [
IoCurrentState::Disabled,
IoCurrentState::Command,
IoCurrentState::Transfer,
]
.map(|r| r.into_raw());
(0..=u8::MAX)
.filter(|b| !raw_io_cs.iter().any(|&c| ((b >> 4) & 0x3) == c))
.for_each(|invalid_bits| {
let invalid_io_cs = (invalid_bits >> 4) & 0x3;
assert_eq!(
Flags::try_from_bits(invalid_bits),
Err(Error::invalid_field_variant(
"r5::flags::io_current_state",
invalid_io_cs as usize
)),
);
});
}
}