1#![no_std]
4
5use core::cmp::Ordering;
6use core::hash::{Hash, Hasher};
7use core::ops::Deref;
8use serde::{de::Visitor, Deserialize, Serialize};
9
10#[derive(Serialize, Deserialize, Debug)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12pub struct Status<'a> {
13 #[serde(borrow)]
14 pub version: Bytes<'a>,
15 pub mtu: Option<u32>,
16 pub correlation_id: Option<u32>,
17 pub update: Option<UpdateStatus<'a>>,
18}
19
20#[derive(Serialize, Deserialize, Debug)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub struct UpdateStatus<'a> {
23 #[serde(borrow)]
24 pub version: Bytes<'a>,
25 pub offset: u32,
26}
27
28impl<'a> Status<'a> {
29 pub fn first(version: &'a [u8], mtu: Option<u32>, correlation_id: Option<u32>) -> Self {
30 Self {
31 version: Bytes::new(version),
32 mtu,
33 correlation_id,
34 update: None,
35 }
36 }
37
38 pub fn update(
39 version: &'a [u8],
40 mtu: Option<u32>,
41 offset: u32,
42 next_version: &'a [u8],
43 correlation_id: Option<u32>,
44 ) -> Self {
45 Self {
46 version: Bytes::new(version),
47 mtu,
48 correlation_id,
49 update: Some(UpdateStatus {
50 offset,
51 version: Bytes::new(next_version),
52 }),
53 }
54 }
55}
56#[derive(Serialize, Deserialize, Debug)]
57#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58pub enum Command<'a> {
59 Wait {
60 correlation_id: Option<u32>,
61 poll: Option<u32>,
62 },
63 Sync {
64 #[serde(borrow)]
65 version: Bytes<'a>,
66 correlation_id: Option<u32>,
67 poll: Option<u32>,
68 },
69 Write {
70 #[serde(borrow)]
71 version: Bytes<'a>,
72 correlation_id: Option<u32>,
73 offset: u32,
74 #[serde(borrow)]
75 data: Bytes<'a>,
76 },
77 Swap {
78 #[serde(borrow)]
79 version: Bytes<'a>,
80 correlation_id: Option<u32>,
81 #[serde(borrow)]
82 checksum: Bytes<'a>,
83 },
84}
85
86impl<'a> Command<'a> {
87 pub fn new_wait(poll: Option<u32>, correlation_id: Option<u32>) -> Self {
88 Self::Wait {
89 correlation_id,
90 poll,
91 }
92 }
93
94 pub fn new_sync(version: &'a [u8], poll: Option<u32>, correlation_id: Option<u32>) -> Self {
95 Self::Sync {
96 version: Bytes::new(version),
97 correlation_id,
98 poll,
99 }
100 }
101
102 pub fn new_swap(version: &'a [u8], checksum: &'a [u8], correlation_id: Option<u32>) -> Self {
103 Self::Swap {
104 version: Bytes::new(version),
105 correlation_id,
106 checksum: Bytes::new(checksum),
107 }
108 }
109
110 pub fn new_write(
111 version: &'a [u8],
112 offset: u32,
113 data: &'a [u8],
114 correlation_id: Option<u32>,
115 ) -> Self {
116 Self::Write {
117 version: Bytes::new(version),
118 correlation_id,
119 offset,
120 data: Bytes::new(data),
121 }
122 }
123}
124
125#[derive(Debug)]
126#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127pub struct Bytes<'a> {
128 data: &'a [u8],
129}
130
131impl<'a> Bytes<'a> {
132 pub fn new(data: &'a [u8]) -> Self {
133 Self { data }
134 }
135}
136
137impl<'a> Serialize for Bytes<'a> {
138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: serde::Serializer,
141 {
142 serializer.serialize_bytes(self.data)
143 }
144}
145
146impl<'a, 'de: 'a> Deserialize<'de> for Bytes<'a> {
147 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
148 where
149 D: serde::Deserializer<'de>,
150 {
151 deserializer.deserialize_bytes(BytesVisitor)
152 }
153}
154
155impl<'a> AsRef<[u8]> for Bytes<'a> {
156 fn as_ref(&self) -> &[u8] {
157 &self.data
158 }
159}
160
161impl<'a> Deref for Bytes<'a> {
162 type Target = [u8];
163
164 fn deref(&self) -> &Self::Target {
165 &self.data
166 }
167}
168
169impl<'a> Default for Bytes<'a> {
170 fn default() -> Self {
171 Bytes::new(&[])
172 }
173}
174
175impl<'a, Rhs> PartialEq<Rhs> for Bytes<'a>
176where
177 Rhs: ?Sized + AsRef<[u8]>,
178{
179 fn eq(&self, other: &Rhs) -> bool {
180 self.as_ref().eq(other.as_ref())
181 }
182}
183
184impl<'a, Rhs> PartialOrd<Rhs> for Bytes<'a>
185where
186 Rhs: ?Sized + AsRef<[u8]>,
187{
188 fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
189 self.as_ref().partial_cmp(other.as_ref())
190 }
191}
192
193impl<'a> Hash for Bytes<'a> {
194 fn hash<H: Hasher>(&self, state: &mut H) {
195 self.data.hash(state);
196 }
197}
198
199struct BytesVisitor;
200
201impl<'de> Visitor<'de> for BytesVisitor {
202 type Value = Bytes<'de>;
203
204 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
205 formatter.write_str("a byte slice")
206 }
207
208 fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
209 where
210 E: serde::de::Error,
211 {
212 Ok(Bytes::new(v))
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 extern crate std;
219 use super::*;
220 use std::println;
221 use std::vec::Vec;
222
223 #[test]
224 fn deserialize_ref() {
225 let s = Command::new_write(b"1234", 0, &[1, 2, 3, 4], None);
226 let out = serde_cbor::to_vec(&s).unwrap();
227
228 let s: Command = serde_cbor::from_slice(&out).unwrap();
229 println!("Out: {:?}", s);
230 }
231
232 #[test]
233 fn serialized_status_size() {
234 let version = &[1];
236 let mtu = Some(4);
237 let cid = None;
238 let offset = 0;
239 let next_version = &[2];
240
241 let s = Status::first(version, mtu, cid);
242 let first = encode(&s);
243
244 let s = Status::update(version, mtu, offset, next_version, cid);
245 let update = encode(&s);
246 println!(
247 "Serialized size:\n FIRST:\t{}\nUPDATE:\t{}",
248 first.len(),
249 update.len(),
250 );
251 }
252
253 #[test]
254 fn serialized_command_size() {
255 let version = &[1];
257 let payload = &[1, 2, 3, 4];
258 let checksum = &[1, 2, 3, 4];
259
260 let s = Command::new_write(version, 0, payload, None);
261 let write = encode(&s);
262
263 let s = Command::new_wait(Some(1), None);
264 let wait = encode(&s);
265
266 let s = Command::new_sync(version, Some(1), None);
267 let sync = encode(&s);
268
269 let s = Command::new_swap(version, checksum, None);
270 let swap = encode(&s);
271 println!(
272 "Serialized size:\n WRITE:\t{}\nWAIT:\t{}\nSYNC:\t{}\nSWAP:\t{}",
273 write.len(),
274 wait.len(),
275 sync.len(),
276 swap.len()
277 );
278 }
279
280 fn encode<T>(value: &T) -> Vec<u8>
281 where
282 T: serde::Serialize,
283 {
284 serde_cbor::ser::to_vec_packed(value).unwrap()
285 }
286}