use crate::lib_bitfield;
use crate::result::{Error, Result};
mod current_state;
pub use current_state::*;
lib_bitfield! {
pub CardStatus(u16): u8 {
pub crc_error: 15;
pub illegal_command: 14;
pub error: 13;
raw_current_state: 12, 9;
pub ready_for_data: 8;
pub fx_event: 6;
pub app_cmd: 5;
pub ake_seq_error: 3;
}
}
impl CardStatus {
pub const LEN: usize = 2;
pub const fn new() -> Self {
Self(0)
}
pub const fn current_state(&self) -> Result<CurrentState> {
CurrentState::from_raw(self.raw_current_state())
}
pub fn set_current_state(&mut self, val: CurrentState) {
self.set_raw_current_state(val.into_raw() as u16);
}
pub const fn try_from_bits(val: u16) -> Result<Self> {
match Self(val) {
cs if CurrentState::from_raw(cs.raw_current_state()).is_err() => {
Err(Error::invalid_field_variant(
"r6::card_status::current_state",
cs.raw_current_state() as usize,
))
}
cs => Ok(cs),
}
}
pub const fn bytes(&self) -> [u8; Self::LEN] {
self.0.to_be_bytes()
}
pub const fn try_from_bytes(val: &[u8]) -> Result<Self> {
match val.len() {
len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
_ => Self::try_from_bits(u16::from_be_bytes([val[0], val[1]])),
}
}
}
impl Default for CardStatus {
fn default() -> Self {
Self::new()
}
}
impl From<CardStatus> for u16 {
fn from(val: CardStatus) -> Self {
val.bits()
}
}
impl From<CardStatus> for [u8; CardStatus::LEN] {
fn from(val: CardStatus) -> Self {
val.bytes()
}
}
impl TryFrom<u16> for CardStatus {
type Error = Error;
fn try_from(val: u16) -> Result<Self> {
Self::try_from_bits(val)
}
}
impl TryFrom<&[u8]> for CardStatus {
type Error = Error;
fn try_from(val: &[u8]) -> Result<Self> {
Self::try_from_bytes(val)
}
}
impl<const N: usize> TryFrom<&[u8; N]> for CardStatus {
type Error = Error;
fn try_from(val: &[u8; N]) -> Result<Self> {
Self::try_from_bytes(val.as_ref())
}
}
impl<const N: usize> TryFrom<[u8; N]> for CardStatus {
type Error = Error;
fn try_from(val: [u8; N]) -> Result<Self> {
Self::try_from_bytes(val.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_field;
#[test]
fn test_fields() {
let mut cs = CardStatus::new();
test_field!(cs, ake_seq_error: 3);
test_field!(cs, app_cmd: 5);
test_field!(cs, fx_event: 6);
test_field!(cs, ready_for_data: 8);
test_field!(cs, error: 13);
test_field!(cs, illegal_command: 14);
test_field!(cs, crc_error: 15);
assert_eq!(cs.current_state(), Ok(CurrentState::new()));
let raw_cs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
raw_cs
.into_iter()
.zip([
CurrentState::Idle,
CurrentState::Ready,
CurrentState::Identification,
CurrentState::Standby,
CurrentState::Transfer,
CurrentState::Data,
CurrentState::Receive,
CurrentState::Program,
CurrentState::Disabled,
])
.for_each(|(cs_raw, cstate)| {
assert_eq!(CurrentState::from_raw(cs_raw), Ok(cstate));
cs.set_current_state(cstate);
assert_eq!(cs.current_state(), Ok(cstate));
});
(0..=0xf)
.filter_map(|r| {
if raw_cs.iter().any(|cs| cs == &r) {
None
} else {
Some(r << 1)
}
})
.for_each(|invalid_cs| {
assert_eq!(
CardStatus::try_from_bytes(&[invalid_cs, 0]),
Err(Error::invalid_field_variant(
"r6::card_status::current_state",
(invalid_cs >> 1) as usize
))
);
assert_eq!(
CardStatus::try_from_bits(u16::from_be_bytes([invalid_cs, 0])),
Err(Error::invalid_field_variant(
"r6::card_status::current_state",
(invalid_cs >> 1) as usize
))
);
});
}
}