use crate::register::Ocr;
use crate::response::{End, Start};
use crate::result::{Error, Result};
use crate::{lib_bitfield, response};
lib_bitfield! {
pub R3(MSB0 [u8; 6]): u32 {
raw_start: 47, 40;
raw_ocr: 39, 8;
raw_end: 7, 0;
}
}
response! {
R3 {
response_mode: Sd,
}
}
impl R3 {
pub const LEN: usize = 6;
pub const DEFAULT: [u8; Self::LEN] = [0x3f, 0, 0, 0, 0, 0xff];
pub const fn new() -> Self {
Self(Self::DEFAULT)
}
pub const fn start(&self) -> Result<Start> {
Start::try_from_bits(self.raw_start() as u8)
}
pub const fn ocr(&self) -> Ocr {
Ocr::from_bits(self.raw_ocr())
}
pub fn set_ocr(&mut self, val: Ocr) {
self.set_raw_ocr(val.bits());
}
pub const fn end(&self) -> Result<End> {
End::try_from_bits(self.raw_end() as u8)
}
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)),
_ => {
let r3 = Self([val[0], val[1], val[2], val[3], val[4], val[5]]);
let exp_start = Start::from_bits(0x3f);
let exp_end = End::from_bits(0xff);
match (r3.start(), r3.end()) {
(Ok(exp_start), Ok(exp_end)) => Ok(r3),
(_, Ok(exp_end)) => Err(Error::invalid_field_variant(
"r3::start",
r3.raw_start() as usize,
)),
(_, _) => Err(Error::invalid_field_variant(
"r3::end",
r3.raw_end() as usize,
)),
}
}
}
}
}
impl Default for R3 {
fn default() -> Self {
Self::new()
}
}
impl TryFrom<&[u8]> for R3 {
type Error = Error;
fn try_from(val: &[u8]) -> Result<Self> {
Self::try_from_bytes(val)
}
}
impl<const N: usize> TryFrom<&[u8; N]> for R3 {
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 R3 {
type Error = Error;
fn try_from(val: [u8; N]) -> Result<Self> {
Self::try_from_bytes(val.as_ref())
}
}
impl From<R3> for [u8; R3::LEN] {
fn from(val: R3) -> Self {
val.bytes()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid() {
let exp_start = Start::from_bits(0x3f);
let exp_end = End::from_bits(0xff);
(1..=u32::BITS)
.map(|r| ((1u64 << r) - 1) as u32)
.for_each(|raw_ocr| {
let ocr = Ocr::from_bits(raw_ocr);
let [ocr0, ocr1, ocr2, ocr3] = ocr.bytes();
let raw = [0x3f, ocr0, ocr1, ocr2, ocr3, 0xff];
let mut exp_r3 = R3::new();
exp_r3.set_ocr(ocr);
assert_eq!(R3::try_from_bytes(raw.as_ref()), Ok(exp_r3));
assert_eq!(exp_r3.start(), Ok(exp_start));
assert_eq!(exp_r3.ocr(), ocr);
assert_eq!(exp_r3.end(), Ok(exp_end));
exp_r3.set_ocr(Ocr::new());
assert_eq!(exp_r3.ocr(), Ocr::new());
exp_r3.set_ocr(ocr);
assert_eq!(exp_r3.ocr(), ocr);
});
}
}