1use crate::{
2 abstractions::{
3 Serializable,
4 SerializationError::{self, InvalidFormat, MissingInfo},
5 SerializationInfo, KEY_SIZE, TYPE_APPEND, TYPE_CONNECT, TYPE_CREATE, TYPE_PUT,
6 TYPE_REQUEST, TYPE_SUBSCRIBE, TYPE_UNSUBSCRIBE, TYPE_WIPE,
7 },
8 codec::{
9 common::{assert_len, dyn_int, SlotBody, SlotRange},
10 ptp_packet::PtpBody,
11 },
12};
13
14#[derive(Debug)]
27pub enum RequestBody {
28 CONNECT {
29 protocol_version: u8,
30 pub_key: [u8; KEY_SIZE],
31 },
32 CREATE(SlotRange),
33 PUT {
34 slots: SlotBody,
35 },
36 APPEND {
37 items: Vec<Vec<u8>>,
38 },
39 WIPE(SlotRange),
40 REQUEST(SlotRange),
41 SUBSCRIBE(SlotRange),
42 UNSUBSCRIBE,
43}
44
45impl PtpBody for RequestBody {
46 fn packet_type(&self) -> u8 {
47 match self {
48 RequestBody::CONNECT { .. } => TYPE_CONNECT,
49 RequestBody::CREATE(_) => TYPE_CREATE,
50 RequestBody::PUT { .. } => TYPE_PUT,
51 RequestBody::APPEND { .. } => TYPE_APPEND,
52 RequestBody::WIPE(_) => TYPE_WIPE,
53 RequestBody::REQUEST(_) => TYPE_REQUEST,
54 RequestBody::SUBSCRIBE(_) => TYPE_SUBSCRIBE,
55 RequestBody::UNSUBSCRIBE => TYPE_UNSUBSCRIBE,
56 }
57 }
58}
59
60impl Serializable for RequestBody {
61 fn size(&self) -> usize {
62 match self {
63 RequestBody::CONNECT { .. } => 1 + KEY_SIZE,
64 RequestBody::PUT { slots } => slots.size(),
65 RequestBody::APPEND { items } => items
66 .iter()
67 .map(|s| s.len() + dyn_int::encoded_size(s.len() as u128))
68 .sum::<usize>(),
69 RequestBody::CREATE(sr)
70 | RequestBody::WIPE(sr)
71 | RequestBody::REQUEST(sr)
72 | RequestBody::SUBSCRIBE(sr) => sr.size(),
73 RequestBody::UNSUBSCRIBE => 0,
74 }
75 }
76
77 fn get_bytes(&self) -> Vec<u8> {
78 let mut buff = Vec::new();
79 match self {
80 RequestBody::CONNECT {
81 protocol_version,
82 pub_key,
83 } => {
84 buff.push(*protocol_version);
85 buff.extend_from_slice(pub_key);
86 }
87 RequestBody::PUT { slots } => {
88 buff = slots.get_bytes();
89 }
90 RequestBody::APPEND { items } => {
91 for data in items.iter() {
92 buff.append(&mut dyn_int::encode(data.len() as u128));
93 buff.extend_from_slice(data)
94 }
95 }
96 RequestBody::CREATE(sr)
97 | RequestBody::WIPE(sr)
98 | RequestBody::REQUEST(sr)
99 | RequestBody::SUBSCRIBE(sr) => {
100 buff = sr.get_bytes(); }
102 _ => (),
103 };
104
105 buff
106 }
107
108 fn from_bytes(data: &[u8], info: Option<SerializationInfo>) -> Result<Self, SerializationError>
109 where
110 Self: Sized,
111 {
112 if let Some(SerializationInfo::PacketType(packet_type)) = info {
113 match packet_type {
114 TYPE_CONNECT => {
115 assert_len(data, 1 + KEY_SIZE)?;
116 let protocol_version = data[0];
117 let pub_key: [u8; KEY_SIZE] = data[1..]
118 .try_into()
119 .expect("Failed to copy pub_key from slice");
120 Ok(RequestBody::CONNECT {
121 protocol_version,
122 pub_key,
123 })
124 }
125 TYPE_CREATE => Ok(RequestBody::CREATE(SlotRange::from_bytes(data, None)?)),
126 TYPE_PUT => Ok(RequestBody::PUT {
127 slots: SlotBody::from_bytes(data, None)?,
128 }),
129 TYPE_APPEND => {
130 let mut items = Vec::new();
131 let mut bytes_read = 0;
132 while bytes_read != data.len() {
133 assert_len(data, bytes_read + 1)?;
134 let (data_len, read) = dyn_int::read_from_slice(&data[bytes_read..])?;
135 bytes_read += read;
136 assert_len(data, bytes_read + data_len as usize)?;
137 let data = data[bytes_read..(bytes_read + data_len as usize)].to_vec();
138 bytes_read += data_len as usize;
139 items.push(data);
140 }
141 Ok(RequestBody::APPEND { items })
142 }
143 TYPE_WIPE => Ok(RequestBody::WIPE(SlotRange::from_bytes(data, None)?)),
144 TYPE_REQUEST => Ok(RequestBody::REQUEST(SlotRange::from_bytes(data, None)?)),
145 TYPE_SUBSCRIBE => Ok(RequestBody::SUBSCRIBE(SlotRange::from_bytes(data, None)?)),
146 TYPE_UNSUBSCRIBE => Ok(RequestBody::UNSUBSCRIBE),
147 _ => Err(InvalidFormat(format!(
148 "Packet type {} is not supported",
149 packet_type
150 ))),
151 }
152 } else {
153 Err(MissingInfo(String::from(
154 "Missing info paramter of PacketType",
155 )))
156 }
157 }
158}
159
160#[cfg(test)]
161mod parse_test {
162 use std::vec;
163
164 use super::*;
165 use crate::abstractions::{Serializable, SerializationError::InvalidFormat};
166
167 #[test]
172 fn can_parse_connect_req() {
173 let data = &[
174 0x77u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
175 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
176 ];
177 let connect = RequestBody::from_bytes(data, Some(SerializationInfo::PacketType(0)));
178
179 match connect {
180 Ok(RequestBody::CONNECT {
181 protocol_version,
182 pub_key,
183 }) => {
184 assert_eq!(0x77, protocol_version);
185 assert_eq!(&data[1..33], pub_key);
186 assert_eq!(data.len(), connect.unwrap().size());
187 }
188 Err(e) => panic!("Error: {:?}", e),
189 _ => panic!("Not a connect"),
190 }
191 }
192
193 #[test]
194 fn can_parse_put_req() {
195 let data = &[
196 0, 5u8, 0xA, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 2u8, 0x5, 1, 2, 3, 4, 5,
197 ];
198 let put = RequestBody::from_bytes(data, Some(SerializationInfo::PacketType(2))).unwrap();
199 assert_eq!(21, put.size());
200 if let RequestBody::PUT { slots } = put {
201 assert_eq!(2, slots.len());
202 assert!(slots.keys().any(|x| *x == 5));
203 assert!(slots.keys().any(|x| *x == 2));
204 assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], slots[&5]);
205 assert_eq!(vec![1, 2, 3, 4, 5], slots[&2]);
206 } else {
207 panic!("Not a put request");
208 }
209 }
210
211 #[test]
212 fn can_parse_append_req() {
213 let data = &[10u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5u8, 1, 2, 3, 4, 5];
214 let append = RequestBody::from_bytes(data, Some(SerializationInfo::PacketType(3))).unwrap();
215 assert_eq!(17, append.size());
216 if let RequestBody::APPEND { items } = append {
217 assert_eq!(2, items.len());
218 assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], items[0]);
219 assert_eq!(vec![1, 2, 3, 4, 5], items[1]);
220 } else {
221 panic!("Not an append request");
222 }
223 }
224
225 #[test]
226 fn can_parse_slot_range_0_slots_req() {
227 let data: &[u8] = &[];
228 if let RequestBody::REQUEST(sr) =
229 RequestBody::from_bytes(data, Some(SerializationInfo::PacketType(5))).unwrap()
230 {
231 assert_eq!(None, sr.from);
232 assert_eq!(None, sr.to);
233 } else {
234 panic!("Not a request");
235 }
236 }
237
238 #[test]
239 fn can_parse_slot_range_1_slot_req() {
240 let data: &[u8] = &[0, 15];
241 if let RequestBody::WIPE(sr) =
242 RequestBody::from_bytes(data, Some(SerializationInfo::PacketType(4))).unwrap()
243 {
244 assert_eq!(Some(15), sr.from);
245 assert_eq!(None, sr.to);
246 } else {
247 panic!("Not a wipe request");
248 }
249 }
250
251 #[test]
252 fn can_parse_slot_range_2_slots_req() {
253 let data: &[u8] = &[0, 15, 255, 255];
254 let body = RequestBody::from_bytes(data, Some(SerializationInfo::PacketType(6))).unwrap();
255 assert_eq!(4, body.size());
256 if let RequestBody::SUBSCRIBE(sr) = body {
257 assert_eq!(Some(15), sr.from);
258 assert_eq!(Some(u16::MAX), sr.to);
259 } else {
260 panic!("Not a subscribe request");
261 }
262 }
263
264 #[test]
265 fn cant_parse_unknown_packet_type() {
266 let data = &[0u8, 0];
267 let packet_type = 8;
268 let error = RequestBody::from_bytes(data, Some(SerializationInfo::PacketType(packet_type)))
269 .unwrap_err();
270 assert_eq!(
271 InvalidFormat(String::from("Packet type 8 is not supported")),
272 error
273 );
274 }
275}
276
277#[cfg(test)]
278mod serialize_test {
279 use std::collections::HashMap;
280
281 use crate::abstractions::Serializable;
282
283 use super::*;
284 #[test]
289 fn can_serialize_connect_req() {
290 let connect = RequestBody::CONNECT {
291 protocol_version: 5,
292 pub_key: [
293 1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
294 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
295 ],
296 };
297 let expected = vec![
298 5, 1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
299 24, 25, 26, 27, 28, 29, 30, 31, 32,
300 ];
301 let serialized = connect.get_bytes();
302 assert_eq!(expected, serialized);
303 }
304
305 #[test]
306 fn can_serialize_put_req() {
307 let mut slots = HashMap::new();
308 slots.insert(25, vec![1, 2, 3, 4, 5]);
309 slots.insert(6, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
310 let put = RequestBody::PUT { slots }.get_bytes();
311 assert_eq!(
312 put,
313 vec![0, 6, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 25, 5, 1, 2, 3, 4, 5],
314 );
315 }
316
317 #[test]
318 fn can_serialize_create_req() {
319 let create = RequestBody::CREATE(SlotRange {
320 from: Some(5),
321 to: None,
322 })
323 .get_bytes();
324 assert_eq!(vec![0, 5], create);
325 }
326
327 #[test]
328 fn can_serialize_create_req_2() {
329 let create = RequestBody::CREATE(SlotRange {
330 from: Some(5),
331 to: Some(u16::MAX - 256),
332 })
333 .get_bytes();
334 assert_eq!(vec![0, 5, 254, 255], create);
335 }
336
337 #[test]
338 fn can_serialize_append_req() {
339 let items = vec![vec![1, 2, 3, 4, 5], vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]];
340 let append = RequestBody::APPEND { items }.get_bytes();
341 assert_eq!(
342 vec![5, 1, 2, 3, 4, 5, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
343 append
344 );
345 }
346}