Line data Source code
1 : //! Utilities for binary serialization/deserialization.
2 : //!
3 : //! The [`BeSer`] trait allows us to define data structures
4 : //! that can match data structures that are sent over the wire
5 : //! in big-endian form with no packing.
6 : //!
7 : //! The [`LeSer`] trait does the same thing, in little-endian form.
8 : //!
9 : //! Note: you will get a compile error if you try to `use` both traits
10 : //! in the same module or scope. This is intended to be a safety
11 : //! mechanism: mixing big-endian and little-endian encoding in the same file
12 : //! is error-prone.
13 :
14 : #![warn(missing_docs)]
15 :
16 : use std::io::{self, Read, Write};
17 :
18 : use bincode::Options;
19 : use serde::Serialize;
20 : use serde::de::DeserializeOwned;
21 : use thiserror::Error;
22 :
23 : /// An error that occurred during a deserialize operation
24 : ///
25 : /// This could happen because the input data was too short,
26 : /// or because an invalid value was encountered.
27 : #[derive(Debug, Error)]
28 : pub enum DeserializeError {
29 : /// The deserializer isn't able to deserialize the supplied data.
30 : #[error("deserialize error")]
31 : BadInput,
32 : /// While deserializing from a `Read` source, an `io::Error` occurred.
33 : #[error("deserialize error: {0}")]
34 : Io(io::Error),
35 : }
36 :
37 : impl From<bincode::Error> for DeserializeError {
38 2 : fn from(e: bincode::Error) -> Self {
39 2 : match *e {
40 2 : bincode::ErrorKind::Io(io_err) => DeserializeError::Io(io_err),
41 0 : _ => DeserializeError::BadInput,
42 : }
43 2 : }
44 : }
45 :
46 : /// An error that occurred during a serialize operation
47 : ///
48 : /// This probably means our [`Write`] failed, e.g. we tried
49 : /// to write beyond the end of a buffer.
50 : #[derive(Debug, Error)]
51 : pub enum SerializeError {
52 : /// The serializer isn't able to serialize the supplied data.
53 : #[error("serialize error")]
54 : BadInput,
55 : /// While serializing into a `Write` sink, an `io::Error` occurred.
56 : #[error("serialize error: {0}")]
57 : Io(io::Error),
58 : }
59 :
60 : impl From<bincode::Error> for SerializeError {
61 0 : fn from(e: bincode::Error) -> Self {
62 0 : match *e {
63 0 : bincode::ErrorKind::Io(io_err) => SerializeError::Io(io_err),
64 0 : _ => SerializeError::BadInput,
65 : }
66 0 : }
67 : }
68 :
69 : /// A shortcut that configures big-endian binary serialization
70 : ///
71 : /// Properties:
72 : /// - Big endian
73 : /// - Fixed integer encoding (i.e. 1u32 is 00000001 not 01)
74 : ///
75 : /// Does not allow trailing bytes in deserialization. If this is desired, you
76 : /// may set [`Options::allow_trailing_bytes`] to explicitly accommodate this.
77 29224783 : pub fn be_coder() -> impl Options {
78 29224783 : bincode::DefaultOptions::new()
79 29224783 : .with_big_endian()
80 29224783 : .with_fixint_encoding()
81 29224783 : }
82 :
83 : /// A shortcut that configures little-ending binary serialization
84 : ///
85 : /// Properties:
86 : /// - Little endian
87 : /// - Fixed integer encoding (i.e. 1u32 is 00000001 not 01)
88 : ///
89 : /// Does not allow trailing bytes in deserialization. If this is desired, you
90 : /// may set [`Options::allow_trailing_bytes`] to explicitly accommodate this.
91 671525 : pub fn le_coder() -> impl Options {
92 671525 : bincode::DefaultOptions::new()
93 671525 : .with_little_endian()
94 671525 : .with_fixint_encoding()
95 671525 : }
96 :
97 : /// Binary serialize/deserialize helper functions (Big Endian)
98 : ///
99 : pub trait BeSer {
100 : /// Serialize into a byte slice
101 0 : fn ser_into_slice(&self, mut b: &mut [u8]) -> Result<(), SerializeError>
102 0 : where
103 0 : Self: Serialize,
104 0 : {
105 0 : // &mut [u8] implements Write, but `ser_into` needs a mutable
106 0 : // reference to that. So we need the slightly awkward "mutable
107 0 : // reference to a mutable reference.
108 0 : self.ser_into(&mut b)
109 0 : }
110 :
111 : /// Serialize into a borrowed writer
112 : ///
113 : /// This is useful for most `Write` types except `&mut [u8]`, which
114 : /// can more easily use [`ser_into_slice`](Self::ser_into_slice).
115 10185274 : fn ser_into<W: Write>(&self, w: &mut W) -> Result<(), SerializeError>
116 10185274 : where
117 10185274 : Self: Serialize,
118 10185274 : {
119 10185274 : be_coder().serialize_into(w, &self).map_err(|e| e.into())
120 10185274 : }
121 :
122 : /// Serialize into a new heap-allocated buffer
123 4175006 : fn ser(&self) -> Result<Vec<u8>, SerializeError>
124 4175006 : where
125 4175006 : Self: Serialize,
126 4175006 : {
127 4175006 : be_coder().serialize(&self).map_err(|e| e.into())
128 4175006 : }
129 :
130 : /// Deserialize from the full contents of a byte slice
131 : ///
132 : /// See also: [`BeSer::des_prefix`]
133 5509216 : fn des(buf: &[u8]) -> Result<Self, DeserializeError>
134 5509216 : where
135 5509216 : Self: DeserializeOwned,
136 5509216 : {
137 5509216 : be_coder()
138 5509216 : .deserialize(buf)
139 5509216 : .or(Err(DeserializeError::BadInput))
140 5509216 : }
141 :
142 : /// Deserialize from a prefix of the byte slice
143 : ///
144 : /// Uses as much of the byte slice as is necessary to deserialize the
145 : /// type, but does not guarantee that the entire slice is used.
146 : ///
147 : /// See also: [`BeSer::des`]
148 2465 : fn des_prefix(buf: &[u8]) -> Result<Self, DeserializeError>
149 2465 : where
150 2465 : Self: DeserializeOwned,
151 2465 : {
152 2465 : be_coder()
153 2465 : .allow_trailing_bytes()
154 2465 : .deserialize(buf)
155 2465 : .or(Err(DeserializeError::BadInput))
156 2465 : }
157 :
158 : /// Deserialize from a reader
159 2 : fn des_from<R: Read>(r: &mut R) -> Result<Self, DeserializeError>
160 2 : where
161 2 : Self: DeserializeOwned,
162 2 : {
163 2 : be_coder().deserialize_from(r).map_err(|e| e.into())
164 2 : }
165 :
166 : /// Compute the serialized size of a data structure
167 : ///
168 : /// Note: it may be faster to serialize to a buffer and then measure the
169 : /// buffer length, than to call `serialized_size` and then `ser_into`.
170 9352820 : fn serialized_size(&self) -> Result<u64, SerializeError>
171 9352820 : where
172 9352820 : Self: Serialize,
173 9352820 : {
174 9352820 : be_coder().serialized_size(self).map_err(|e| e.into())
175 9352820 : }
176 : }
177 :
178 : /// Binary serialize/deserialize helper functions (Little Endian)
179 : ///
180 : pub trait LeSer {
181 : /// Serialize into a byte slice
182 0 : fn ser_into_slice(&self, mut b: &mut [u8]) -> Result<(), SerializeError>
183 0 : where
184 0 : Self: Serialize,
185 0 : {
186 0 : // &mut [u8] implements Write, but `ser_into` needs a mutable
187 0 : // reference to that. So we need the slightly awkward "mutable
188 0 : // reference to a mutable reference.
189 0 : self.ser_into(&mut b)
190 0 : }
191 :
192 : /// Serialize into a borrowed writer
193 : ///
194 : /// This is useful for most `Write` types except `&mut [u8]`, which
195 : /// can more easily use [`ser_into_slice`](Self::ser_into_slice).
196 24 : fn ser_into<W: Write>(&self, w: &mut W) -> Result<(), SerializeError>
197 24 : where
198 24 : Self: Serialize,
199 24 : {
200 24 : le_coder().serialize_into(w, &self).map_err(|e| e.into())
201 24 : }
202 :
203 : /// Serialize into a new heap-allocated buffer
204 37877 : fn ser(&self) -> Result<Vec<u8>, SerializeError>
205 37877 : where
206 37877 : Self: Serialize,
207 37877 : {
208 37877 : le_coder().serialize(&self).map_err(|e| e.into())
209 37877 : }
210 :
211 : /// Deserialize from the full contents of a byte slice
212 : ///
213 : /// See also: [`LeSer::des_prefix`]
214 317547 : fn des(buf: &[u8]) -> Result<Self, DeserializeError>
215 317547 : where
216 317547 : Self: DeserializeOwned,
217 317547 : {
218 317547 : le_coder()
219 317547 : .deserialize(buf)
220 317547 : .or(Err(DeserializeError::BadInput))
221 317547 : }
222 :
223 : /// Deserialize from a prefix of the byte slice
224 : ///
225 : /// Uses as much of the byte slice as is necessary to deserialize the
226 : /// type, but does not guarantee that the entire slice is used.
227 : ///
228 : /// See also: [`LeSer::des`]
229 9 : fn des_prefix(buf: &[u8]) -> Result<Self, DeserializeError>
230 9 : where
231 9 : Self: DeserializeOwned,
232 9 : {
233 9 : le_coder()
234 9 : .allow_trailing_bytes()
235 9 : .deserialize(buf)
236 9 : .or(Err(DeserializeError::BadInput))
237 9 : }
238 :
239 : /// Deserialize from a reader
240 316065 : fn des_from<R: Read>(r: &mut R) -> Result<Self, DeserializeError>
241 316065 : where
242 316065 : Self: DeserializeOwned,
243 316065 : {
244 316065 : le_coder().deserialize_from(r).map_err(|e| e.into())
245 316065 : }
246 :
247 : /// Compute the serialized size of a data structure
248 : ///
249 : /// Note: it may be faster to serialize to a buffer and then measure the
250 : /// buffer length, than to call `serialized_size` and then `ser_into`.
251 3 : fn serialized_size(&self) -> Result<u64, SerializeError>
252 3 : where
253 3 : Self: Serialize,
254 3 : {
255 3 : le_coder().serialized_size(self).map_err(|e| e.into())
256 3 : }
257 : }
258 :
259 : // Because usage of `BeSer` or `LeSer` can be done with *either* a Serialize or
260 : // DeserializeOwned implementation, the blanket implementation has to be for every type.
261 : impl<T> BeSer for T {}
262 : impl<T> LeSer for T {}
263 :
264 : #[cfg(test)]
265 : mod tests {
266 : use std::io::Cursor;
267 :
268 : use serde::{Deserialize, Serialize};
269 :
270 : use super::DeserializeError;
271 :
272 2 : #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
273 : pub struct ShortStruct {
274 : a: u8,
275 : b: u32,
276 : }
277 :
278 : const SHORT1: ShortStruct = ShortStruct { a: 7, b: 65536 };
279 : const SHORT1_ENC_BE: &[u8] = &[7, 0, 1, 0, 0];
280 : const SHORT1_ENC_BE_TRAILING: &[u8] = &[7, 0, 1, 0, 0, 255, 255, 255];
281 : const SHORT1_ENC_LE: &[u8] = &[7, 0, 0, 1, 0];
282 : const SHORT1_ENC_LE_TRAILING: &[u8] = &[7, 0, 0, 1, 0, 255, 255, 255];
283 :
284 : const SHORT2: ShortStruct = ShortStruct {
285 : a: 8,
286 : b: 0x07030000,
287 : };
288 : const SHORT2_ENC_BE: &[u8] = &[8, 7, 3, 0, 0];
289 : const SHORT2_ENC_BE_TRAILING: &[u8] = &[8, 7, 3, 0, 0, 0xff, 0xff, 0xff];
290 : const SHORT2_ENC_LE: &[u8] = &[8, 0, 0, 3, 7];
291 : const SHORT2_ENC_LE_TRAILING: &[u8] = &[8, 0, 0, 3, 7, 0xff, 0xff, 0xff];
292 :
293 0 : #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
294 : struct NewTypeStruct(u32);
295 : const NT1: NewTypeStruct = NewTypeStruct(414243);
296 : const NT1_INNER: u32 = 414243;
297 :
298 0 : #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
299 : pub struct LongMsg {
300 : pub tag: u8,
301 : pub blockpos: u32,
302 : pub last_flush_position: u64,
303 : pub apply: u64,
304 : pub timestamp: i64,
305 : pub reply_requested: u8,
306 : }
307 :
308 : const LONG1: LongMsg = LongMsg {
309 : tag: 42,
310 : blockpos: 0x1000_2000,
311 : last_flush_position: 0x1234_2345_3456_4567,
312 : apply: 0x9876_5432_10FE_DCBA,
313 : timestamp: 0x7788_99AA_BBCC_DDFF,
314 : reply_requested: 1,
315 : };
316 :
317 : #[test]
318 1 : fn be_short() {
319 : use super::BeSer;
320 :
321 1 : assert_eq!(SHORT1.serialized_size().unwrap(), 5);
322 :
323 1 : let encoded = SHORT1.ser().unwrap();
324 1 : assert_eq!(encoded, SHORT1_ENC_BE);
325 :
326 1 : let decoded = ShortStruct::des(SHORT2_ENC_BE).unwrap();
327 1 : assert_eq!(decoded, SHORT2);
328 :
329 : // with trailing data
330 1 : let decoded = ShortStruct::des_prefix(SHORT2_ENC_BE_TRAILING).unwrap();
331 1 : assert_eq!(decoded, SHORT2);
332 1 : let err = ShortStruct::des(SHORT2_ENC_BE_TRAILING).unwrap_err();
333 1 : assert!(matches!(err, DeserializeError::BadInput));
334 :
335 : // serialize into a `Write` sink.
336 1 : let mut buf = Cursor::new(vec![0xFF; 8]);
337 1 : SHORT1.ser_into(&mut buf).unwrap();
338 1 : assert_eq!(buf.into_inner(), SHORT1_ENC_BE_TRAILING);
339 :
340 : // deserialize from a `Write` sink.
341 1 : let mut buf = Cursor::new(SHORT2_ENC_BE);
342 1 : let decoded = ShortStruct::des_from(&mut buf).unwrap();
343 1 : assert_eq!(decoded, SHORT2);
344 :
345 : // deserialize from a `Write` sink that terminates early.
346 1 : let mut buf = Cursor::new([0u8; 4]);
347 1 : let err = ShortStruct::des_from(&mut buf).unwrap_err();
348 1 : assert!(matches!(err, DeserializeError::Io(_)));
349 1 : }
350 :
351 : #[test]
352 1 : fn le_short() {
353 : use super::LeSer;
354 :
355 1 : assert_eq!(SHORT1.serialized_size().unwrap(), 5);
356 :
357 1 : let encoded = SHORT1.ser().unwrap();
358 1 : assert_eq!(encoded, SHORT1_ENC_LE);
359 :
360 1 : let decoded = ShortStruct::des(SHORT2_ENC_LE).unwrap();
361 1 : assert_eq!(decoded, SHORT2);
362 :
363 : // with trailing data
364 1 : let decoded = ShortStruct::des_prefix(SHORT2_ENC_LE_TRAILING).unwrap();
365 1 : assert_eq!(decoded, SHORT2);
366 1 : let err = ShortStruct::des(SHORT2_ENC_LE_TRAILING).unwrap_err();
367 1 : assert!(matches!(err, DeserializeError::BadInput));
368 :
369 : // serialize into a `Write` sink.
370 1 : let mut buf = Cursor::new(vec![0xFF; 8]);
371 1 : SHORT1.ser_into(&mut buf).unwrap();
372 1 : assert_eq!(buf.into_inner(), SHORT1_ENC_LE_TRAILING);
373 :
374 : // deserialize from a `Write` sink.
375 1 : let mut buf = Cursor::new(SHORT2_ENC_LE);
376 1 : let decoded = ShortStruct::des_from(&mut buf).unwrap();
377 1 : assert_eq!(decoded, SHORT2);
378 :
379 : // deserialize from a `Write` sink that terminates early.
380 1 : let mut buf = Cursor::new([0u8; 4]);
381 1 : let err = ShortStruct::des_from(&mut buf).unwrap_err();
382 1 : assert!(matches!(err, DeserializeError::Io(_)));
383 1 : }
384 :
385 : #[test]
386 1 : fn be_long() {
387 : use super::BeSer;
388 :
389 1 : assert_eq!(LONG1.serialized_size().unwrap(), 30);
390 :
391 1 : let msg = LONG1;
392 1 :
393 1 : let encoded = msg.ser().unwrap();
394 1 : let expected = hex_literal::hex!(
395 1 : "2A 1000 2000 1234 2345 3456 4567 9876 5432 10FE DCBA 7788 99AA BBCC DDFF 01"
396 1 : );
397 1 : assert_eq!(encoded, expected);
398 :
399 1 : let msg2 = LongMsg::des(&encoded).unwrap();
400 1 : assert_eq!(msg, msg2);
401 1 : }
402 :
403 : #[test]
404 1 : fn le_long() {
405 : use super::LeSer;
406 :
407 1 : assert_eq!(LONG1.serialized_size().unwrap(), 30);
408 :
409 1 : let msg = LONG1;
410 1 :
411 1 : let encoded = msg.ser().unwrap();
412 1 : let expected = hex_literal::hex!(
413 1 : "2A 0020 0010 6745 5634 4523 3412 BADC FE10 3254 7698 FFDD CCBB AA99 8877 01"
414 1 : );
415 1 : assert_eq!(encoded, expected);
416 :
417 1 : let msg2 = LongMsg::des(&encoded).unwrap();
418 1 : assert_eq!(msg, msg2);
419 1 : }
420 :
421 : #[test]
422 : /// Ensure that newtype wrappers around u32 don't change the serialization format
423 1 : fn be_nt() {
424 : use super::BeSer;
425 :
426 1 : assert_eq!(NT1.serialized_size().unwrap(), 4);
427 :
428 1 : let msg = NT1;
429 1 :
430 1 : let encoded = msg.ser().unwrap();
431 1 : let expected = hex_literal::hex!("0006 5223");
432 1 : assert_eq!(encoded, expected);
433 :
434 1 : assert_eq!(encoded, NT1_INNER.ser().unwrap());
435 :
436 1 : let msg2 = NewTypeStruct::des(&encoded).unwrap();
437 1 : assert_eq!(msg, msg2);
438 1 : }
439 :
440 : #[test]
441 : /// Ensure that newtype wrappers around u32 don't change the serialization format
442 1 : fn le_nt() {
443 : use super::LeSer;
444 :
445 1 : assert_eq!(NT1.serialized_size().unwrap(), 4);
446 :
447 1 : let msg = NT1;
448 1 :
449 1 : let encoded = msg.ser().unwrap();
450 1 : let expected = hex_literal::hex!("2352 0600");
451 1 : assert_eq!(encoded, expected);
452 :
453 1 : assert_eq!(encoded, NT1_INNER.ser().unwrap());
454 :
455 1 : let msg2 = NewTypeStruct::des(&encoded).unwrap();
456 1 : assert_eq!(msg, msg2);
457 1 : }
458 : }
|