rust_chain/
serializer.rs

1use core::{
2    mem::size_of,
3};
4
5use crate::{
6    string::String,
7    vec::Vec,
8    vmapi::eosio::{
9        check,
10        slice_copy,
11    },
12    varint::VarUint32,
13};
14
15///
16/// The `Packer` trait provides methods for packing and unpacking values to and from byte arrays.
17///
18/// # Examples
19///
20/// ```
21/// use crate::rust_chain::serializer::{Encoder, Decoder, Packer};
22///
23/// let mut encoder = Encoder::new(4);
24/// let value = 123u32;
25/// value.pack(&mut encoder);
26///
27/// let mut decoder = Decoder::new(&encoder.get_bytes());
28/// let mut unpacked_value = 0u32;
29/// decoder.unpack(&mut unpacked_value);
30///
31/// assert_eq!(value, unpacked_value);
32/// ```
33pub trait Packer {
34    /// Returns the size of the packed representation of this value in bytes.
35    fn size(&self) -> usize;
36
37    /// Packs this value into the given `Encoder`.
38    ///
39    /// # Arguments
40    ///
41    /// * `enc` - The encoder to pack this value into.
42    ///
43    /// # Returns
44    ///
45    /// The number of bytes written to the encoder.
46    fn pack(&self, enc: &mut Encoder) -> usize;
47
48    /// Unpacks this value from the given byte array.
49    ///
50    /// # Arguments
51    ///
52    /// * `data` - The byte array to unpack this value from.
53    ///
54    /// # Returns
55    ///
56    /// The number of bytes read from the byte array.
57    fn unpack(&mut self, data: &[u8]) -> usize;
58}
59
60/// The `Encoder` struct provides methods for packing values that implement the `Packer` trait.
61///
62/// # Examples
63///
64/// ```
65/// use rust_chain::serializer::{Encoder, Packer};
66///
67/// let mut encoder = Encoder::new(4);
68/// let value = 123u32;
69///
70/// let bytes_written = value.pack(&mut encoder);
71/// assert_eq!(bytes_written, 4);
72///
73/// let packed_bytes = encoder.get_bytes();
74/// assert_eq!(packed_bytes, [123, 0, 0, 0]);
75/// ```
76pub struct Encoder {
77    buf: Vec<u8>,
78}
79
80impl Encoder {
81    /// Constructs a new `Encoder` with the given initial capacity.
82    ///
83    /// # Arguments
84    ///
85    /// * `size` - The initial capacity of the encoder in bytes.
86    ///
87    /// # Returns
88    ///
89    /// A new `Encoder` instance with the given initial capacity.
90    pub fn new(size: usize) -> Self {
91        Self {
92            buf: Vec::with_capacity(size)
93        }
94    }
95    
96    /// Returns the packed bytes of this encoder as a byte array.
97    ///
98    /// # Returns
99    ///
100    /// A reference to the packed bytes of this encoder as a byte array.
101    pub fn get_bytes(&self) -> &[u8] {
102        &self.buf
103    }
104
105    /// Returns the number of packed bytes in this encoder.
106    ///
107    /// # Returns
108    ///
109    /// The number of packed bytes in this encoder.
110    pub fn get_size(&self) -> usize {
111        self.buf.len()
112    }
113
114    /// Allocates space in this encoder for packing a value of the given size.
115    ///
116    /// # Arguments
117    ///
118    /// * `size` - The number of bytes to allocate in this encoder.
119    ///
120    /// # Returns
121    ///
122    /// A mutable reference to the allocated
123    pub fn alloc(&mut self, size: usize) -> &mut [u8]
124    {
125        let old_size = self.buf.len();
126        self.buf.resize(old_size+size, 0u8);
127        &mut self.buf[old_size..]
128    }
129
130    /// Packs the given value using the encoder
131    ///
132    /// # Arguments
133    ///
134    /// * `value` - The value to be packed
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// use rust_chain::serializer::{Encoder, Packer};
140    ///
141    /// let data = Encoder::pack(&1234u32);
142    /// assert_eq!(data, vec![210, 4, 0, 0]);
143    /// ```
144    pub fn pack<T: Packer>(value: &T) -> Vec<u8> 
145    {
146        // Create a new Encoder with the size of the value being packed
147        let mut enc = Self::new(value.size());
148        // Pack the value using the encoder
149        value.pack(&mut enc);
150        // Return the packed data as a vector of bytes
151        enc.get_bytes().to_vec()
152    }
153
154}
155
156/// A struct for unpacking packed data
157///
158/// # Examples
159///
160/// ```
161/// use crate::rust_chain::serializer::{Decoder, Packer};
162///
163/// let data = &vec![210, 4, 0, 0];
164/// let mut decoder = Decoder::new(&data);
165/// let mut value = 0u32;
166/// decoder.unpack(&mut value);
167/// assert_eq!(value, 1234);
168/// ```
169pub struct Decoder<'a> {
170    buf: &'a [u8],
171    pos: usize
172}
173
174/// A struct for unpacking packed data
175impl<'a> Decoder<'a> {
176
177    /// Creates a new `Decoder` instance from the given byte array.
178    pub fn new(data: &'a [u8]) -> Self {
179        Self {
180            buf: data, pos: 0
181        }
182    }
183
184    /// Unpacks the given value from the decoder
185    pub fn unpack<T>(&mut self, packer: &mut T) -> usize
186    where T: Packer,
187    {
188        let size = packer.unpack(&self.buf[self.pos..]);
189        self.pos += size;
190        size
191    }
192
193    /// Returns the current position of the decoder
194    pub fn get_pos(&self) -> usize {
195        self.pos
196    }
197
198}
199
200/// A trait for packing and unpacking values
201/// 
202macro_rules! impl_packed {
203    ( $ty:ident ) => {
204        impl Packer for $ty {
205            /// Returns the size of this value in bytes.
206            fn size(&self) -> usize {
207                size_of::<$ty>()
208            }
209
210            /// Packs this value into the given encoder.
211            fn pack(&self, enc: &mut Encoder) -> usize {
212                let data = enc.alloc(size_of::<$ty>());
213                let src = self.to_le_bytes();
214                slice_copy(data, &src);
215                self.size()
216            }
217        
218            /// Unpacks this value from the given data.
219            fn unpack(&mut self, data: &[u8]) -> usize {
220                check(data.len() >= self.size(), "number: buffer overflow");
221                *self = $ty::from_le_bytes(data[..self.size()].try_into().unwrap());
222                size_of::<$ty>()
223            }
224        }
225    };
226}
227
228/// Implement`Packer` for bool type.
229impl Packer for bool {
230    fn size(&self) -> usize {
231        1usize
232    }
233
234    /// Packs this value into the given encoder.
235    fn pack(&self, enc: &mut Encoder) -> usize {
236        let data = enc.alloc(self.size());
237        if *self {
238            data[0] = 1u8;
239        } else {
240            data[0] = 0u8;
241        }
242        self.size()
243    }
244
245    /// Unpacks this value from the given data.
246    fn unpack(&mut self, data: &[u8]) -> usize {
247        check(data.len() >= self.size(), "bool::unpack: buffer overflow");
248        if data[0] == 1 {
249            *self = true;
250        } else if data[0] == 0 {
251            *self = false;
252        } else {
253            check(false, "bool::unpack: invalid raw bool value");
254        }
255        self.size()
256    }
257}
258
259/// Implement `Packer` for i8 type.
260impl Packer for i8 {
261
262    /// Returns the size of this value in bytes.
263    fn size(&self) -> usize {
264        1usize
265    }
266
267    /// Packs this value into the given encoder.
268    fn pack(&self, enc: &mut Encoder) -> usize {
269        let data = enc.alloc(self.size());
270        data[0] = *self as u8;
271        self.size()
272    }
273
274    /// Unpacks this value from the given data.
275    fn unpack(&mut self, data: &[u8]) -> usize {
276        check(data.len() >= self.size(), "i8::unpack: buffer overflow");
277        *self = data[0] as i8;
278        self.size()
279    }
280}
281
282/// Implement `Packer` for u8 type.
283impl Packer for u8 {
284
285    /// Returns the size of this value in bytes.
286    fn size(&self) -> usize {
287        1usize
288    }
289
290    /// Packs this value into the given encoder.
291    fn pack(&self, enc: &mut Encoder) -> usize {
292        let data = enc.alloc(self.size());
293        data[0] = *self;
294        self.size()
295    }
296
297    /// Unpacks this value from the given data.
298    fn unpack(&mut self, data: &[u8]) -> usize {
299        check(data.len() >= self.size(), "u8::unpack: buffer overflow");
300        *self = data[0];
301        self.size()
302    }
303}
304
305impl_packed!(i16);
306impl_packed!(u16);
307impl_packed!(i32);
308impl_packed!(u32);
309impl_packed!(i64);
310impl_packed!(u64);
311impl_packed!(i128);
312impl_packed!(u128);
313impl_packed!(f32);
314impl_packed!(f64);
315
316/// Implement `Packer` for `String` type.
317impl Packer for String {
318
319    /// Returns the size of this value in bytes.
320    fn size(&self) -> usize {
321        VarUint32::new(self.len() as u32).size() + self.len()
322    }
323
324    /// Packs this value into the given encoder.
325    fn pack(&self, enc: &mut Encoder) -> usize {
326        let pos = enc.get_size();
327
328        let raw = self.as_bytes();
329
330        let n = VarUint32::new(raw.len() as u32);
331        n.pack(enc);
332
333        let data = enc.alloc(raw.len());
334        slice_copy(data, raw);
335
336        enc.get_size() - pos
337    }
338
339    /// Unpacks this value from the given data.
340    fn unpack(&mut self, data: &[u8]) -> usize {
341        let mut length = VarUint32{n: 0};
342        let size = length.unpack(data);
343        if let Ok(s) = String::from_utf8(data[size..size+length.value() as usize].to_vec()) {
344            *self = s;
345        } else {
346            check(false, "invalid utf8 string");
347        }
348        size + length.value() as usize
349    }
350}
351
352/// Implement `Packer` for `Vec<T>` type.
353impl<T> Packer for Vec<T> where T: Packer + Default {
354    /// Returns the size of this value in bytes.
355    fn size(&self) -> usize {
356        if self.len() == 0 {
357            return 1;
358        }
359
360        let mut size: usize = 0;
361        for i in 0..self.len() {
362            size += self[i].size();
363        }
364        VarUint32::new(size as u32).size() + size
365    }
366
367    /// Packs this value into the given encoder.
368    fn pack(&self, enc: &mut Encoder) -> usize {
369        let pos = enc.get_size();
370        let len = VarUint32{n: self.len() as u32};
371        len.pack(enc);
372        for v in self {
373            v.pack(enc);
374        }
375        enc.get_size() - pos
376    }
377
378    /// Unpacks this value from the given data.
379    fn unpack(&mut self, data: &[u8]) -> usize {
380        let mut dec = Decoder::new(data);
381        let mut size = VarUint32{n: 0};
382        dec.unpack(&mut size);
383        self.reserve(size.value() as usize);
384        for _ in 0..size.value() {
385            let mut v: T = Default::default();
386            dec.unpack(&mut v);
387            self.push(v);
388        }
389        dec.get_pos()
390    }
391}
392
393/// Implement `Packer` for `Option<T>` type.
394impl<T> Packer for Option<T> where T: Packer + Default {
395
396    /// Returns the size of this value in bytes.
397    fn size(&self) -> usize {
398        match self {
399            Some(x) => 1 + x.size(),
400            None => 1,
401        }
402    }
403
404    /// Packs this value into the given encoder.
405    fn pack(&self, enc: &mut Encoder) -> usize {
406        let pos = enc.get_size();
407        match self {
408            Some(x) => {
409                1u8.pack(enc);
410                x.pack(enc);
411            }
412            None => {
413                0u8.pack(enc);
414            }
415        }
416        enc.get_size() - pos
417    }
418
419    /// Unpacks this value from the given data.
420    fn unpack(&mut self, data: &[u8]) -> usize {
421        let mut dec = Decoder::new(data);
422        let mut ty: u8 = 0;
423        let mut value: T = Default::default();
424        dec.unpack(&mut ty);
425        if ty == 0 {
426            *self = None;
427            return 1;
428        }
429
430        check(ty == 1, "bad option type!");
431
432        dec.unpack(&mut value);
433        *self = Some(value);
434        dec.get_pos()
435    }
436}