use crate::response::sd::r7::VoltageAccepted;
use crate::response::spi::r1::R1;
use crate::result::{Error, Result};
use crate::{lib_bitfield, response};
lib_bitfield! {
pub R7(MSB0 [u8; 5]): u8 {
raw_r1: 39, 32;
pub command_version: 31, 28;
raw_voltage_accepted: 11, 8;
pub echo_check: 7, 0;
}
}
response! {
R7 {
response_mode: Spi,
}
}
impl R7 {
pub const LEN: usize = 5;
pub const DEFAULT: [u8; Self::LEN] = [0, 0, 0, 0x1, 0];
pub const fn new() -> Self {
Self(Self::DEFAULT)
}
pub const fn r1(&self) -> Result<R1> {
R1::try_from_bits(self.raw_r1())
}
pub fn set_r1(&mut self, r1: R1) {
self.set_raw_r1(r1.bits());
}
pub const fn voltage_accepted(&self) -> Result<VoltageAccepted> {
VoltageAccepted::from_raw(self.raw_voltage_accepted())
}
pub fn set_voltage_accepted(&mut self, voltage_accepted: VoltageAccepted) {
self.set_raw_voltage_accepted(voltage_accepted.into_raw());
}
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)),
_ => match R7([val[0], val[1], val[2], val[3], val[4]]) {
r7 if r7.r1().is_err() => {
Err(Error::invalid_field_variant("r7::r1", r7.raw_r1() as usize))
}
r7 if r7.voltage_accepted().is_err() => Err(Error::invalid_field_variant(
"r7::voltage_accepted",
r7.raw_voltage_accepted() as usize,
)),
r7 => Ok(r7),
},
}
}
}
impl Default for R7 {
fn default() -> Self {
Self::new()
}
}
impl TryFrom<&[u8]> for R7 {
type Error = Error;
fn try_from(val: &[u8]) -> Result<Self> {
Self::try_from_bytes(val)
}
}
impl<const N: usize> TryFrom<[u8; N]> for R7 {
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 R7 {
type Error = Error;
fn try_from(val: &[u8; N]) -> Result<Self> {
Self::try_from_bytes(val.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fields() {
let mut r7 = R7::new();
assert_eq!(r7.r1(), Ok(R1::new()));
assert_eq!(r7.command_version(), 0);
assert_eq!(r7.voltage_accepted(), Ok(VoltageAccepted::new()));
assert_eq!(r7.echo_check(), 0);
(0..=u8::MAX)
.zip(0..=u8::MAX)
.map(|(r1, cmd)| (r1, cmd & 0xf))
.zip(0..=u8::MAX)
.map(|(s, va)| (s, va & 0xf))
.zip(0..=u8::MAX)
.for_each(|(((r1, cmd), va), echo)| {
let raw = [r1, cmd << 4, 0, va, echo];
match (R1::try_from_bits(r1), VoltageAccepted::from_raw(va)) {
(Ok(r1), Ok(va)) => {
r7 = R7(raw);
assert_eq!(R7::try_from_bytes(raw.as_ref()), Ok(r7));
assert_eq!(R7::try_from(raw), Ok(r7));
assert_eq!(r7.r1(), Ok(r1));
assert_eq!(r7.command_version(), cmd);
assert_eq!(r7.voltage_accepted(), Ok(va));
assert_eq!(r7.echo_check(), echo);
r7.set_r1(R1::new());
assert_eq!(r7.r1(), Ok(R1::new()));
r7.set_r1(r1);
assert_eq!(r7.r1(), Ok(r1));
r7.set_command_version(0);
assert_eq!(r7.command_version(), 0);
r7.set_command_version(cmd);
assert_eq!(r7.command_version(), cmd);
r7.set_echo_check(0);
assert_eq!(r7.echo_check(), 0);
r7.set_echo_check(echo);
assert_eq!(r7.echo_check(), echo);
r7.set_voltage_accepted(VoltageAccepted::new());
assert_eq!(r7.voltage_accepted(), Ok(VoltageAccepted::new()));
r7.set_voltage_accepted(va);
assert_eq!(r7.voltage_accepted(), Ok(va));
}
(Err(_), _) => {
assert_eq!(
R7::try_from_bytes(raw.as_ref()),
Err(Error::invalid_field_variant("r7::r1", r1 as usize))
);
assert_eq!(
R7::try_from(raw),
Err(Error::invalid_field_variant("r7::r1", r1 as usize))
);
}
(_, Err(_)) => {
assert_eq!(
R7::try_from_bytes(raw.as_ref()),
Err(Error::invalid_field_variant(
"r7::voltage_accepted",
va as usize
))
);
assert_eq!(
R7::try_from(raw),
Err(Error::invalid_field_variant(
"r7::voltage_accepted",
va as usize
))
);
}
}
});
}
}