wasefire_protocol_usb/
common.rs1use alloc::vec::Vec;
32
33use wasefire_logger as log;
34
35pub const PACKET_NO_REQUEST: [u8; 64] = [0; 64];
36
37#[derive(Debug, Copy, Clone, PartialEq, Eq)]
38pub struct Packet<'a> {
39 pub order: Order,
40 pub content: &'a [u8],
41}
42
43impl<'a> Packet<'a> {
44 pub fn decode(bytes: &'a [u8; 64]) -> Option<Self> {
45 let header = bytes[0];
46 ensure(header & 0x3e == 0)?;
47 let first = header & 0x80 != 0;
48 let last = header & 0x40 != 0;
49 let order = Order::new(first, last)?;
50 let mut content = &bytes[1 ..];
51 if header & 0x01 != 0 {
52 let length = bytes[63] as usize;
53 ensure((0 ..= 62).contains(&length))?;
54 ensure_zero(&content[length .. 62])?;
55 content = &content[.. length];
56 };
57 Some(Packet { order, content })
58 }
59
60 #[allow(clippy::identity_op)]
61 pub fn encode(self, bytes: &mut [u8; 64]) {
62 let Packet { order, content } = self;
63 let has_footer = content.len() != 63;
64 bytes[0] = 0;
65 bytes[0] |= 0x80 * matches!(order, Order::First) as u8;
66 bytes[0] |= 0x40 * matches!(order, Order::Last) as u8;
67 bytes[0] |= 0x01 * has_footer as u8;
68 bytes[1 ..][.. content.len()].copy_from_slice(content);
69 if has_footer {
70 bytes[1 + content.len() ..].fill(0);
71 bytes[63] = content.len() as u8;
72 }
73 }
74}
75
76#[derive(Debug, Copy, Clone, PartialEq, Eq)]
77pub enum Order {
78 First,
79 Middle,
80 Last,
81}
82
83impl Order {
84 fn new(first: bool, last: bool) -> Option<Self> {
85 Some(match (first, last) {
86 (true, true) => return None,
87 (true, false) => Order::First,
88 (false, true) => Order::Last,
89 (false, false) => Order::Middle,
90 })
91 }
92}
93
94#[derive(Default)]
95pub struct Encoder<'a> {
96 message: &'a [u8],
97 count: usize, }
99
100impl<'a> Encoder<'a> {
101 pub fn new(message: &'a [u8]) -> Self {
102 Encoder { message, count: 0 }
103 }
104}
105
106impl Iterator for Encoder<'_> {
107 type Item = [u8; 64];
108
109 fn next(&mut self) -> Option<[u8; 64]> {
110 let total = core::cmp::max(2, self.message.len().div_ceil(63));
111 ensure(self.count < total)?;
112 let first = self.count == 0;
113 let start = core::cmp::min(self.message.len(), 63 * self.count);
114 let length = core::cmp::min(63, self.message.len().saturating_sub(63 * self.count));
115 let content = &self.message[start ..][.. length];
116 self.count += 1;
117 let last = self.count == total;
118 let order = Order::new(first, last).unwrap();
119 let mut packet = [0; 64];
120 Packet { order, content }.encode(&mut packet);
121 Some(packet)
122 }
123}
124
125#[derive(Default)]
126pub struct Decoder {
127 message: Option<Vec<u8>>,
129}
130
131impl Decoder {
132 pub fn push(mut self, packet: &[u8; 64]) -> Option<Result<Vec<u8>, Decoder>> {
133 let Packet { order, content } = Packet::decode(packet)?;
134 if order == Order::First {
135 if self.message.is_some() {
136 log::warn!("Discarding previous message on repeated first packet.");
137 }
138 self.message = Some(content.to_vec());
139 return Some(Err(self));
140 }
141 let message = match &mut self.message {
142 Some(x) => x,
143 None => {
144 log::debug!("Discarding until first packet.");
145 return Some(Err(self));
146 }
147 };
148 message.extend_from_slice(content);
149 if order == Order::Last {
150 return Some(Ok(core::mem::take(message)));
151 }
152 Some(Err(self))
153 }
154}
155
156fn ensure_zero(xs: &[u8]) -> Option<()> {
157 xs.iter().all(|&x| x == 0).then_some(())
158}
159
160fn ensure(cond: bool) -> Option<()> {
161 cond.then_some(())
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn message_at_least_two_packets() {
170 assert_eq!(Encoder::new(&[]).count(), 2);
171 assert_eq!(Encoder::new(&[0]).count(), 2);
172 assert_eq!(Encoder::new(&[0; 126]).count(), 2);
173 assert_eq!(Encoder::new(&[0; 127]).count(), 3);
174 }
175
176 #[test]
177 fn message_round_trip() {
178 let max_len = 3 * 63;
179 let pattern: Vec<u8> = (1 ..= max_len as u8).collect();
180 for len in 0 ..= max_len {
181 let expected = &pattern[.. len];
182 let mut decoder = Decoder::default();
183 let mut packets = Encoder::new(expected);
184 let result = loop {
185 let packet = packets.next().unwrap();
186 match decoder.push(&packet).unwrap() {
187 Ok(x) => break x,
188 Err(x) => decoder = x,
189 }
190 };
191 assert_eq!(packets.next(), None);
192 assert_eq!(result, expected);
193 }
194 }
195}