1use crate::client::MAX_DEVICES;
2use crate::error::Error;
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub struct Response {
6 data: [u8; MAX_DEVICES],
7 len: usize,
8}
9
10impl Default for Response {
11 fn default() -> Self {
12 Self {
13 data: [0; MAX_DEVICES],
14 len: 0,
15 }
16 }
17}
18
19impl Response {
20 #[must_use]
21 pub fn from_slice(data: &[u8]) -> Self {
22 let len = data.len().min(MAX_DEVICES);
23 let mut buf = [0u8; MAX_DEVICES];
24 buf[..len].copy_from_slice(&data[..len]);
25 Self { data: buf, len }
26 }
27
28 #[must_use]
29 pub fn data(&self) -> &[u8] {
30 &self.data[..self.len]
31 }
32
33 pub fn merge(&mut self, other: &Response) {
34 self.data[..self.len]
35 .iter_mut()
36 .zip(other.data().iter().copied())
37 .for_each(|(m, d)| {
38 if *m == 0 {
39 *m = d;
40 }
41 });
42 }
43
44 pub fn check(&self) -> Result<(), Error> {
45 match self.data().iter().enumerate().find(|&(_, &d)| d != 0) {
46 None => Ok(()),
47 Some((device, &code)) => Err(Error::DeviceError { device, code }),
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::Response;
55
56 #[test]
57 fn data_exposes_only_the_recorded_devices() {
58 assert_eq!(Response::from_slice(&[0x00, 0xAB]).data(), [0x00, 0xAB]);
59 assert!(Response::from_slice(&[]).data().is_empty());
60 }
61
62 #[test]
63 fn from_slice_clamps_to_the_device_limit() {
64 let response = Response::from_slice(&[1u8; crate::client::MAX_DEVICES + 4]);
65 assert_eq!(response.data().len(), crate::client::MAX_DEVICES);
66 }
67
68 #[test]
69 fn check_reports_the_first_nonzero_device() {
70 assert!(Response::from_slice(&[0, 0, 0]).check().is_ok());
71 let err = Response::from_slice(&[0, 0x07, 0x09]).check().unwrap_err();
72 assert!(matches!(
73 err,
74 crate::error::Error::DeviceError {
75 device: 1,
76 code: 0x07
77 }
78 ));
79 }
80}