jcm/message/response/
uid_response.rs1use std::{fmt, mem};
2
3use crate::{Error, Response, ResponseCode, Result};
4
5#[repr(C)]
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct UidResponse {
9 code: ResponseCode,
10 uid: u8,
11}
12
13impl UidResponse {
14 pub const fn new() -> Self {
16 Self {
17 code: ResponseCode::new(),
18 uid: 0,
19 }
20 }
21
22 pub const fn code(&self) -> ResponseCode {
24 self.code
25 }
26
27 pub fn set_code(&mut self, code: ResponseCode) {
29 self.code = code;
30 }
31
32 pub fn with_code(mut self, code: ResponseCode) -> Self {
34 self.set_code(code);
35 self
36 }
37
38 pub const fn uid(&self) -> u8 {
40 self.uid
41 }
42
43 pub fn set_uid(&mut self, uid: u8) {
45 self.uid = uid;
46 }
47
48 pub fn with_uid(mut self, uid: u8) -> Self {
50 self.set_uid(uid);
51 self
52 }
53
54 pub const fn len() -> usize {
56 ResponseCode::len() + mem::size_of::<u8>()
57 }
58
59 pub const fn is_empty(&self) -> bool {
61 self.code.is_empty() && self.uid == 0
62 }
63
64 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 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}