jcm/message/response/
uid_response.rs

1use std::{fmt, mem};
2
3use crate::{Error, Response, ResponseCode, Result};
4
5/// Represents the [Response] to a UID request [Message](crate::Message).
6#[repr(C)]
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct UidResponse {
9    code: ResponseCode,
10    uid: u8,
11}
12
13impl UidResponse {
14    /// Creates a new [UidResponse].
15    pub const fn new() -> Self {
16        Self {
17            code: ResponseCode::new(),
18            uid: 0,
19        }
20    }
21
22    /// Gets the [ResponseCode] for the [UidResponse].
23    pub const fn code(&self) -> ResponseCode {
24        self.code
25    }
26
27    /// Sets the [ResponseCode] for the [UidResponse].
28    pub fn set_code(&mut self, code: ResponseCode) {
29        self.code = code;
30    }
31
32    /// Builder function that sets the [ResponseCode] for the [UidResponse].
33    pub fn with_code(mut self, code: ResponseCode) -> Self {
34        self.set_code(code);
35        self
36    }
37
38    /// Gets the UID for the [UidResponse].
39    pub const fn uid(&self) -> u8 {
40        self.uid
41    }
42
43    /// Sets the UID for the [UidResponse].
44    pub fn set_uid(&mut self, uid: u8) {
45        self.uid = uid;
46    }
47
48    /// Builder function that sets the UID for the [UidResponse].
49    pub fn with_uid(mut self, uid: u8) -> Self {
50        self.set_uid(uid);
51        self
52    }
53
54    /// Gets the length of the [UidResponse].
55    pub const fn len() -> usize {
56        ResponseCode::len() + mem::size_of::<u8>()
57    }
58
59    /// Gets whether the [UidResponse] is empty.
60    pub const fn is_empty(&self) -> bool {
61        self.code.is_empty() && self.uid == 0
62    }
63
64    /// Converts a [UidResponse] into a byte buffer.
65    pub fn to_bytes(&self, buf: &mut [u8]) -> Result<()> {
66        let len = Self::len();
67        let buf_len = buf.len();
68
69        if buf_len < len {
70            Err(Error::InvalidResponseLen((buf_len, len)))
71        } else {
72            buf.iter_mut()
73                .take(len)
74                .zip([u8::from(self.code), self.uid])
75                .for_each(|(dst, src)| *dst = src);
76
77            Ok(())
78        }
79    }
80
81    /// Converts a byte buffer into a [UidResponse].
82    pub fn from_bytes(buf: &[u8]) -> Result<Self> {
83        let len = Self::len();
84        let buf_len = buf.len();
85
86        if buf_len < len {
87            Err(Error::InvalidResponseLen((buf_len, len)))
88        } else {
89            Ok(Self {
90                code: buf[0].try_into()?,
91                uid: buf[1],
92            })
93        }
94    }
95}
96
97impl Default for UidResponse {
98    fn default() -> Self {
99        Self::new()
100    }
101}
102
103impl TryFrom<&Response> for UidResponse {
104    type Error = Error;
105
106    fn try_from(val: &Response) -> Result<Self> {
107        let len = Self::len();
108        let res_len = val.len();
109
110        if res_len < len {
111            Err(Error::InvalidResponseLen((res_len, len)))
112        } else {
113            Ok(Self {
114                code: val.code,
115                uid: val.additional[0],
116            })
117        }
118    }
119}
120
121impl TryFrom<Response> for UidResponse {
122    type Error = Error;
123
124    fn try_from(val: Response) -> Result<Self> {
125        (&val).try_into()
126    }
127}
128
129impl From<UidResponse> for Response {
130    fn from(val: UidResponse) -> Self {
131        Self {
132            code: val.code,
133            additional: [val.uid].into(),
134        }
135    }
136}
137
138impl From<&UidResponse> for Response {
139    fn from(val: &UidResponse) -> Self {
140        (*val).into()
141    }
142}
143
144impl fmt::Display for UidResponse {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        write!(f, "{{")?;
147        write!(f, r#""code":{}, "#, self.code)?;
148        write!(f, r#""uid":{:#02x}"#, self.uid)?;
149        write!(f, "}}")
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use super::*;
156
157    #[test]
158    fn test_uid_response() {
159        let raw = [ResponseCode::Ack as u8, 0];
160        let exp = UidResponse::new().with_code(ResponseCode::Ack);
161        let res = Response::new()
162            .with_code(ResponseCode::Ack)
163            .with_additional(&[0]);
164        let mut out = [0u8; 2];
165
166        assert_eq!(UidResponse::from_bytes(raw.as_ref()), Ok(exp));
167        assert_eq!(UidResponse::try_from(&res), Ok(exp));
168        assert_eq!(Response::from(&exp), res);
169
170        assert!(exp.to_bytes(out.as_mut()).is_ok());
171
172        assert_eq!(out, raw);
173    }
174
175    #[test]
176    fn test_uid_response_invalid() {
177        let raw = [ResponseCode::Ack as u8, 0];
178        let exp = UidResponse::new().with_code(ResponseCode::Ack);
179        let mut out = [0u8; 2];
180
181        assert!(UidResponse::from_bytes(raw[..1].as_ref()).is_err());
182        assert!(UidResponse::from_bytes([ResponseCode::Reserved as u8, 0].as_ref()).is_err());
183        assert!(exp.to_bytes(out[..1].as_mut()).is_err());
184        assert!(exp.to_bytes(&mut []).is_err());
185        assert!(UidResponse::try_from(Response::new().with_additional(&[])).is_err());
186        assert!(UidResponse::try_from(
187            Response::new()
188                .with_code(ResponseCode::Ack)
189                .with_additional(&[])
190        )
191        .is_err());
192    }
193}