Skip to main content

il2_utils/simple_serialization/
mod.rs

1/*
2 * BSD 3-Clause License
3 *
4 * Copyright (c) 2019-2020, InterlockLedger Network
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright notice, this
11 *   list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright notice,
14 *   this list of conditions and the following disclaimer in the documentation
15 *   and/or other materials provided with the distribution.
16 *
17 * * Neither the name of the copyright holder nor the names of its
18 *   contributors may be used to endorse or promote products derived from
19 *   this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32//=============================================================================
33//! This module implements a simple data serializer/deserialzer that can be
34//! used to read/write data serializations in memory. Most of the functions
35//! here where designed to use pre-allocated memory segments and/or vectors
36//! in place. As such, this module is not recommended for complex
37//! serializations or large values.
38//!
39//! If you want to use the operation `?` to remap the errors form this just
40//! implement the trait [`std::convert::From`] to convert [`ErrorKind`] into
41//! your own error type.
42#[cfg(test)]
43mod tests;
44
45/// Errors generated by this
46#[derive(Debug)]
47pub enum ErrorKind {
48    UnableToRead,
49    UnableToWrite,
50}
51
52pub type Result<T> = std::result::Result<T, ErrorKind>;
53
54//=============================================================================
55// SimpleDataSerializer
56//-----------------------------------------------------------------------------
57/// This trait implements a simple serializer for basic data types.
58/// It follows the format used by Java's `java.io.DataOutputStream` and write
59/// all values using the big endian format.
60///
61/// This trait also allows the definition of a custom Result type thar will
62/// allow its methods to be used with the operatior `?`.
63pub trait SimpleDataSerializer {
64    /// Writes the byte slice.
65    ///
66    /// Arguments:
67    /// - `v`: The value to write;
68    fn write(&mut self, v: &[u8]) -> Result<()>;
69
70    /// Writes an u8 value.
71    ///
72    /// Arguments:
73    /// - `v`: The value to write;
74    fn write_u8(&mut self, v: u8) -> Result<()>;
75
76    /// Writes an u16 value.
77    ///
78    /// Arguments:
79    /// - `v`: The value to write;
80    fn write_u16(&mut self, v: u16) -> Result<()> {
81        self.write(&v.to_be_bytes())
82    }
83
84    /// Writes an u32 value.
85    ///
86    /// Arguments:
87    /// - `v`: The value to write;
88    fn write_u32(&mut self, v: u32) -> Result<()> {
89        self.write(&v.to_be_bytes())
90    }
91
92    /// Writes an u64 value.
93    ///
94    /// Arguments:
95    /// - `v`: The value to write;
96    fn write_u64(&mut self, v: u64) -> Result<()> {
97        self.write(&v.to_be_bytes())
98    }
99
100    /// Writes an i8 value.
101    ///
102    /// Arguments:
103    /// - `v`: The value to write;
104    fn write_i8(&mut self, v: i8) -> Result<()> {
105        self.write_u8(v as u8)
106    }
107
108    /// Writes an i16 value.
109    ///
110    /// Arguments:
111    /// - `v`: The value to write;
112    fn write_i16(&mut self, v: i16) -> Result<()> {
113        self.write_u16(v as u16)
114    }
115
116    /// Writes an i32 value.
117    ///
118    /// Arguments:
119    /// - `v`: The value to write;
120
121    fn write_i32(&mut self, v: i32) -> Result<()> {
122        self.write_u32(v as u32)
123    }
124
125    /// Writes an i64 value.
126    ///
127    /// Arguments:
128    /// - `v`: The value to write;
129    fn write_i64(&mut self, v: i64) -> Result<()> {
130        self.write_u64(v as u64)
131    }
132
133    /// Writes a f32 value.
134    ///
135    /// Arguments:
136    /// - `v`: The value to write;
137    fn write_f32(&mut self, v: f32) -> Result<()> {
138        self.write(&v.to_be_bytes())
139    }
140
141    /// Writes a f64 value.
142    ///
143    /// Arguments:
144    /// - `v`: The value to write;
145    fn write_f64(&mut self, v: f64) -> Result<()> {
146        self.write(&v.to_be_bytes())
147    }
148
149    /// Writes a byte array. The size of the byte array is encoded
150    /// as an u16 value followed by the bytes of the array.
151    ///
152    /// Arguments:
153    /// - `v`: The value to write;
154    fn write_byte_array(&mut self, v: &[u8]) -> Result<()> {
155        self.write_u16(v.len() as u16)?;
156        self.write(v)
157    }
158}
159
160//=============================================================================
161// SimpleDataDeserializer
162//-----------------------------------------------------------------------------
163macro_rules! simpledatadeserializer_read_impl {
164    ($type: ty, $func_name:ident, $doc: expr) => {
165        #[doc = $doc]
166        fn $func_name(&mut self) -> Result<$type> {
167            const DATA_SIZE: usize = std::mem::size_of::<$type>();
168            self.read(DATA_SIZE)?;
169            let mut tmp: [u8; DATA_SIZE] = [0; DATA_SIZE];
170            tmp.copy_from_slice(self.data());
171            Ok(<$type>::from_be_bytes(tmp))
172        }
173    };
174}
175
176/// This trait implements a simple deserializer for basic data types.
177/// It follows the format used by Java's `java.io.DataOutputStream` so it
178/// reads the values using the big endian format.
179///
180/// This trait also allows the definition of a custom Result type thar will
181/// allow its methods to be used with the operatior `?`.
182pub trait SimpleDataDeserializer {
183    /// The slice with the last data read.
184    fn data(&self) -> &[u8];
185
186    /// Reads the specified umber of bytes. The data read will available
187    /// by [`Self::data()`].
188    ///
189    /// Arguments:
190    /// - `size`: Number of bytes to read;
191    fn read(&mut self, size: usize) -> Result<()>;
192
193    /// Reads an u8 value.
194    fn read_u8(&mut self) -> Result<u8> {
195        self.read(1)?;
196        Ok(self.data()[0])
197    }
198
199    /// Reads an i8 value.
200    fn read_i8(&mut self) -> Result<i8> {
201        Ok(self.read_u8()? as i8)
202    }
203
204    simpledatadeserializer_read_impl!(u16, read_u16, "Reads an u16 value.");
205    simpledatadeserializer_read_impl!(u32, read_u32, "Reads an u32 value.");
206    simpledatadeserializer_read_impl!(u64, read_u64, "Reads an u16 value.");
207    simpledatadeserializer_read_impl!(i16, read_i16, "Reads an i16 value.");
208    simpledatadeserializer_read_impl!(i32, read_i32, "Reads an i32 value.");
209    simpledatadeserializer_read_impl!(i64, read_i64, "Reads an i64 value.");
210    simpledatadeserializer_read_impl!(f32, read_f32, "Reads an f32 value.");
211    simpledatadeserializer_read_impl!(f64, read_f64, "Reads an f64 value.");
212
213    /// Writes a byte array. The size of the byte array is encoded
214    /// as an u16 value followed by the bytes of the array.
215    ///
216    /// Arguments:
217    /// - `v`: The value to write;
218    fn read_byte_array(&mut self) -> Result<()> {
219        let size = self.read_u16()? as usize;
220        self.read(size)
221    }
222}
223
224impl SimpleDataSerializer for Vec<u8> {
225    fn write(&mut self, v: &[u8]) -> Result<()> {
226        self.extend_from_slice(v);
227        Ok(())
228    }
229
230    fn write_u8(&mut self, v: u8) -> Result<()> {
231        self.push(v);
232        Ok(())
233    }
234}
235
236//=============================================================================
237// SimpleSliceSerializer
238//-----------------------------------------------------------------------------
239/// This struct implements a simple serializer that writes data into a borrowed
240/// byte slice.
241pub struct SimpleSliceSerializer<'a> {
242    slice: &'a mut [u8],
243    offset: usize,
244}
245
246impl<'a> SimpleSliceSerializer<'a> {
247    /// Creates a new instance with a given initial capacity.
248    pub fn new(slice: &'a mut [u8]) -> Self {
249        Self { slice, offset: 0 }
250    }
251
252    /// Returns the current offset.
253    pub fn offset(&self) -> usize {
254        self.offset
255    }
256
257    /// Returns the number of available bytes.
258    pub fn available(&self) -> usize {
259        self.slice.len() - self.offset
260    }
261
262    fn can_write(&self, size: usize) -> Result<()> {
263        if size <= self.available() {
264            Ok(())
265        } else {
266            Err(ErrorKind::UnableToWrite)
267        }
268    }
269}
270
271impl<'a> SimpleDataSerializer for SimpleSliceSerializer<'a> {
272    fn write(&mut self, v: &[u8]) -> Result<()> {
273        self.can_write(v.len())?;
274        self.slice[self.offset..self.offset + v.len()].copy_from_slice(v);
275        self.offset += v.len();
276        Ok(())
277    }
278
279    fn write_u8(&mut self, v: u8) -> Result<()> {
280        self.can_write(1)?;
281        self.slice[self.offset] = v;
282        self.offset += 1;
283        Ok(())
284    }
285}
286
287//=============================================================================
288// SimpleReader
289//-----------------------------------------------------------------------------
290/// This struct implements a simple data deserializer. It is the counterpart of
291/// the [`SimpleDataSerializer`] trait.
292///
293/// The template parameter E is the type used to define the type of the error
294/// that will compose the results. The actual value of E is defined by the
295/// constructor.
296pub struct SimpleSliceDeserializer<'a> {
297    data: &'a [u8],
298    offset: usize,
299    data_offset: usize,
300}
301
302impl<'a> SimpleSliceDeserializer<'a> {
303    /// Creates a new instance that reads data from the slice and returns the
304    /// specified value on error.
305    pub fn new(data: &'a [u8]) -> Self {
306        Self {
307            data,
308            offset: 0,
309            data_offset: 0,
310        }
311    }
312
313    /// Returns the current offset.
314    pub fn offset(&self) -> usize {
315        self.offset
316    }
317
318    /// Return the number of bytes availble.
319    pub fn avaliable(&self) -> usize {
320        self.data.len() - self.offset
321    }
322
323    /// Returns true if there is no more bytes to read.
324    pub fn is_empty(&self) -> bool {
325        self.avaliable() == 0
326    }
327
328    fn can_read(&self, size: usize) -> Result<()> {
329        if size <= self.avaliable() {
330            Ok(())
331        } else {
332            Err(ErrorKind::UnableToRead)
333        }
334    }
335}
336
337impl<'a> SimpleDataDeserializer for SimpleSliceDeserializer<'a> {
338    fn data(&self) -> &[u8] {
339        &self.data[self.data_offset..self.offset]
340    }
341
342    fn read(&mut self, size: usize) -> Result<()> {
343        self.can_read(size)?;
344        self.data_offset = self.offset;
345        self.offset += size;
346        Ok(())
347    }
348}