1use std::io::{self, Read, Write};
2pub const SYNC_BYTE: u8 = 0xE0;
6
7pub const MARK_BYTE: u8 = 0xD0;
15
16#[derive(Debug, Clone)]
24pub enum Report {
25 Normal = 1,
27 IncorrectDataSize = 2,
29 InvalidData = 3,
31 Busy = 4,
33 Unknown,
35}
36
37impl From<u8> for Report {
38 fn from(value: u8) -> Self {
39 match value {
40 1 => Report::Normal,
41 2 => Report::IncorrectDataSize,
42 3 => Report::InvalidData,
43 4 => Report::Busy,
44 _ => Report::Unknown,
45 }
46 }
47}
48
49pub trait Packet: AsRef<[u8]> + AsMut<[u8]> {
51 const SIZE_INDEX: usize;
52 const DATA_BEGIN_INDEX: usize;
53 const DESTINATION_INDEX: usize;
54
55 fn len_of_packet(&self) -> usize {
56 Self::SIZE_INDEX + self.as_ref()[Self::SIZE_INDEX] as usize + 1
57 }
58
59 fn as_slice(&self) -> &[u8] {
61 &self.as_ref()[..self.len_of_packet()]
62 }
63
64 fn as_mut_slice(&mut self) -> &mut [u8] {
66 let len = self.len_of_packet();
67 &mut self.as_mut()[..len]
68 }
69
70 fn sync(&self) -> u8 {
72 self.as_ref()[0]
73 }
74
75 fn set_sync(&mut self) -> &mut Self {
76 self.as_mut()[0] = SYNC_BYTE;
77 self
78 }
79
80 fn size(&self) -> u8 {
82 self.as_ref()[Self::SIZE_INDEX]
83 }
84
85 fn set_size(&mut self, size: u8) -> &mut Self {
89 self.as_mut()[Self::SIZE_INDEX] = size;
90 self
91 }
92
93 fn dest(&self) -> u8 {
95 self.as_ref()[Self::DESTINATION_INDEX]
96 }
97
98 fn set_dest(&mut self, dest: u8) -> &mut Self {
100 self.as_mut()[Self::DESTINATION_INDEX] = dest;
101 self
102 }
103
104 fn data(&self) -> &[u8] {
106 &self.as_ref()[Self::DATA_BEGIN_INDEX..self.len_of_packet() - 1]
107 }
108
109 fn set_data(&mut self, data: &[u8]) -> &mut Self {
113 let size = data.len() + Self::DATA_BEGIN_INDEX;
114 self.as_mut()[Self::DATA_BEGIN_INDEX..size].copy_from_slice(data);
115 self.set_size((size - Self::SIZE_INDEX) as u8);
116 self
117 }
118
119 fn calculate_checksum(&mut self) -> &mut Self {
123 self.set_checksum(
124 self.as_slice()
125 .iter()
126 .skip(1)
127 .take(self.len_of_packet() - 2)
128 .fold(0, |acc: u8, &x| acc.wrapping_add(x)),
129 );
130 self
131 }
132
133 fn checksum(&self) -> u8 {
135 self.as_ref()[self.len_of_packet() - 1]
136 }
137
138 fn set_checksum(&mut self, checksum: u8) -> &mut Self {
142 let len = self.len_of_packet();
143 self.as_mut()[len - 1] = checksum;
144 self
145 }
146}
147
148pub trait ReportField: Packet {
152 const REPORT_INDEX: usize;
153
154 fn report(&self) -> Report {
156 self.as_ref()[Self::REPORT_INDEX].into()
157 }
158
159 fn report_raw(&self) -> u8 {
160 self.as_ref()[Self::REPORT_INDEX]
161 }
162
163 fn set_report(&mut self, report: impl Into<u8>) -> &mut Self {
165 self.as_mut()[Self::REPORT_INDEX] = report.into();
166 self
167 }
168}
169
170pub trait ReadByteExt: Read {
172 fn read_u8(&mut self) -> io::Result<u8> {
174 let mut buf = [0; 1];
175 self.read_exact(&mut buf)?;
176 Ok(buf[0])
177 }
178
179 fn read_u8_escaped(&mut self) -> io::Result<u8> {
181 let mut b = self.read_u8()?;
182 if b == MARK_BYTE {
183 b = self.read_u8()?.wrapping_add(1);
184 }
185 Ok(b)
186 }
187}
188
189impl<R: Read + ?Sized> ReadByteExt for R {}
190
191pub trait WriteByteExt: Write {
193 fn write_u8(&mut self, b: u8) -> io::Result<()> {
195 self.write_all(&[b])
196 }
197
198 fn write_u8_escaped(&mut self, b: u8) -> io::Result<usize> {
201 if b == SYNC_BYTE || b == MARK_BYTE {
202 self.write_all(&[MARK_BYTE, b.wrapping_sub(1)])?;
203 Ok(2)
204 } else {
205 self.write_all(&[b])?;
206 Ok(1)
207 }
208 }
209}
210
211impl<W: Write + ?Sized> WriteByteExt for W {}
212
213pub trait ReadPacket: Read {
217 fn read_packet<P: Packet>(&mut self, packet: &mut P) -> io::Result<u8> {
218 let sync = self.read_u8()?;
219
220 if sync != SYNC_BYTE {
221 return Err(io::Error::new(
222 io::ErrorKind::InvalidData,
223 format!("Expected SYNC byte (0xE0), found: {:#04x}", sync),
224 ));
225 }
226 let buf = packet.as_mut();
227 buf[0] = sync;
228
229 for b in &mut buf[1..=P::SIZE_INDEX] {
231 *b = self.read_u8_escaped()?;
232 }
233
234 let len = buf[P::SIZE_INDEX] as usize + P::SIZE_INDEX;
235
236 for b in &mut buf[P::SIZE_INDEX + 1..=len] {
237 *b = self.read_u8_escaped()?;
238 }
239
240 Ok(packet.len_of_packet() as u8)
241 }
242}
243
244impl<R: Read + ?Sized> ReadPacket for R {}
245
246pub trait WritePacket: Write {
250 fn write_packet_unchecked<P: Packet>(&mut self, packet: &P) -> io::Result<usize> {
258 if packet.len_of_packet() < P::DATA_BEGIN_INDEX + 1 {
259 return Err(io::Error::new(
260 io::ErrorKind::InvalidInput,
261 format!(
262 "The size of packet is can't be less than {}",
263 P::DATA_BEGIN_INDEX + 1
264 ),
265 ));
266 }
267 let mut bytes_written = 1;
268
269 self.write_u8(SYNC_BYTE)?;
270
271 for &b in &packet.as_slice()[1..] {
272 bytes_written += self.write_u8_escaped(b)?;
273 }
274
275 Ok(bytes_written)
276 }
277
278 fn write_packet<P: Packet>(&mut self, packet: &P) -> io::Result<usize> {
283 if packet.len_of_packet() < P::DATA_BEGIN_INDEX + 1 {
284 return Err(io::Error::new(
285 io::ErrorKind::InvalidInput,
286 format!(
287 "The size of packet is can't be less than {}",
288 P::DATA_BEGIN_INDEX + 1
289 ),
290 ));
291 }
292
293 self.write_u8(SYNC_BYTE)?;
294 let mut bytes_written: usize = 2;
295 let mut checksum: u8 = 0;
296 for &b in &packet.as_slice()[1..packet.len_of_packet() - 1] {
297 bytes_written += self.write_u8_escaped(b)?;
298 checksum = checksum.wrapping_add(b);
299 }
300
301 self.write_u8_escaped(checksum)?;
302
303 Ok(bytes_written)
304 }
305
306 #[deprecated(since = "1.1.0")]
307 fn write_packet_with_checksum<P: Packet>(&mut self, packet: &P) -> io::Result<usize> {
308 self.write_packet(packet)
309 }
310}
311
312impl<W: Write + ?Sized> WritePacket for W {}