sdmmc_core/command/class/class8/cmd56/
arg.rs

1use crate::lib_bitfield;
2use crate::result::{Error, Result};
3
4mod rw;
5
6pub use rw::*;
7
8lib_bitfield! {
9    /// Argumentument for CMD56.
10    pub Argument(u32): u16 {
11        raw_rw: 0;
12    }
13}
14
15impl Argument {
16    /// Represents the byte length of the [Argument].
17    pub const LEN: usize = 4;
18    /// Represents the raw default value of the [Argument].
19    pub const DEFAULT: u32 = 0;
20
21    /// Creates a new [Argument].
22    pub const fn new() -> Self {
23        Self(Self::DEFAULT)
24    }
25
26    /// Gets the `rd/wr` field for the [Argument].
27    pub const fn rw(&self) -> ReadWrite {
28        ReadWrite::from_bool(self.raw_rw())
29    }
30
31    /// Sets the `rd/wr` field for the [Argument].
32    pub fn set_rw(&mut self, val: ReadWrite) {
33        self.set_raw_rw(val.into_bool())
34    }
35
36    /// Converts a [`u32`] into an [Argument].
37    pub const fn from_bits(val: u32) -> Self {
38        Self(val)
39    }
40
41    /// Attempts to convert a [`u32`] into an [Argument].
42    pub const fn try_from_bits(val: u32) -> Result<Self> {
43        Ok(Self(val))
44    }
45
46    /// Converts the [Argument] into a byte array.
47    pub const fn bytes(&self) -> [u8; Self::LEN] {
48        self.0.to_be_bytes()
49    }
50
51    /// Attempts to convert a byte slice into an [Argument].
52    pub const fn try_from_bytes(val: &[u8]) -> Result<Self> {
53        match val.len() {
54            len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
55            _ => Self::try_from_bits(u32::from_be_bytes([val[0], val[1], val[2], val[3]])),
56        }
57    }
58}
59
60impl Default for Argument {
61    fn default() -> Self {
62        Self::new()
63    }
64}
65
66impl From<u32> for Argument {
67    fn from(val: u32) -> Self {
68        Self::from_bits(val)
69    }
70}
71
72impl From<Argument> for u32 {
73    fn from(val: Argument) -> Self {
74        val.bits()
75    }
76}
77
78impl From<Argument> for [u8; Argument::LEN] {
79    fn from(val: Argument) -> Self {
80        val.bytes()
81    }
82}
83
84impl TryFrom<&[u8]> for Argument {
85    type Error = Error;
86
87    fn try_from(val: &[u8]) -> Result<Self> {
88        Self::try_from_bytes(val)
89    }
90}
91
92impl<const N: usize> TryFrom<&[u8; N]> for Argument {
93    type Error = Error;
94
95    fn try_from(val: &[u8; N]) -> Result<Self> {
96        Self::try_from_bytes(val.as_ref())
97    }
98}
99
100impl<const N: usize> TryFrom<[u8; N]> for Argument {
101    type Error = Error;
102
103    fn try_from(val: [u8; N]) -> Result<Self> {
104        Self::try_from_bytes(val.as_ref())
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn test_fields() {
114        let new_rw = ReadWrite::new();
115
116        (1..=u32::BITS)
117            .map(|r| ((1u64 << r) - 1) as u32)
118            .for_each(|raw| {
119                let exp_rw = ReadWrite::from_bool((raw & 0x1) != 0);
120                let raw_bytes = raw.to_be_bytes();
121
122                let mut exp_arg = Argument(raw);
123
124                assert_eq!(Argument::try_from_bits(raw), Ok(exp_arg));
125                assert_eq!(Argument::from_bits(raw), exp_arg);
126                assert_eq!(Argument::from(raw), exp_arg);
127
128                assert_eq!(Argument::try_from_bytes(&raw_bytes), Ok(exp_arg));
129                assert_eq!(Argument::try_from(raw_bytes), Ok(exp_arg));
130                assert_eq!(Argument::try_from(&raw_bytes), Ok(exp_arg));
131
132                assert_eq!(exp_arg.bytes(), raw_bytes);
133                assert_eq!(<[u8; Argument::LEN]>::from(exp_arg), raw_bytes);
134
135                assert_eq!(exp_arg.rw(), exp_rw);
136
137                exp_arg.set_rw(new_rw);
138                assert_eq!(exp_arg.rw(), new_rw);
139
140                exp_arg.set_rw(exp_rw);
141                assert_eq!(exp_arg.rw(), exp_rw);
142            });
143    }
144}