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}