use crate::lib_bitfield;
use crate::result::{Error, Result};
lib_bitfield! {
pub Dsr(u16): u16 {
pub inner: 15, 0;
}
}
impl Dsr {
pub const LEN: usize = 2;
pub const DEFAULT: u16 = 0x404;
pub const fn new() -> Self {
Self(Self::DEFAULT)
}
pub const fn bytes(&self) -> [u8; Self::LEN] {
self.0.to_be_bytes()
}
pub const fn from_bits(val: u16) -> Self {
Self(val)
}
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)),
_ => Ok(Self(u16::from_be_bytes([val[0], val[1]]))),
}
}
}
impl Default for Dsr {
fn default() -> Self {
Self::new()
}
}
impl From<u16> for Dsr {
fn from(val: u16) -> Self {
Self::from_bits(val)
}
}
impl From<Dsr> for u16 {
fn from(val: Dsr) -> Self {
val.bits()
}
}
impl From<Dsr> for [u8; Dsr::LEN] {
fn from(val: Dsr) -> Self {
val.bytes()
}
}
impl TryFrom<&[u8]> for Dsr {
type Error = Error;
fn try_from(val: &[u8]) -> Result<Self> {
Self::try_from_bytes(val)
}
}
impl<const N: usize> TryFrom<&[u8; N]> for Dsr {
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 Dsr {
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() {
(1..=u16::BITS)
.map(|r| ((1u32 << r) - 1) as u16)
.for_each(|raw_dsr| {
let raw = raw_dsr.to_be_bytes();
let exp_dsr = Dsr(raw_dsr);
assert_eq!(Dsr::from_bits(raw_dsr), exp_dsr);
assert_eq!(Dsr::try_from_bytes(&raw), Ok(exp_dsr));
assert_eq!(Dsr::try_from(&raw), Ok(exp_dsr));
assert_eq!(Dsr::try_from(raw), Ok(exp_dsr));
assert_eq!(exp_dsr.bits(), raw_dsr);
assert_eq!(exp_dsr.inner(), raw_dsr);
assert_eq!(exp_dsr.bytes(), raw);
});
}
}