plabble_codec/codec/common/
slot_body.rs

1use std::collections::HashMap;
2
3use itertools::Itertools;
4
5use crate::abstractions::{Serializable, SerializationError, SerializationInfo};
6
7use super::{assert_len, dyn_int};
8
9/// A slot body is a map of slot indices to data.
10pub type SlotBody = HashMap<u16, Vec<u8>>;
11
12impl Serializable for SlotBody {
13    /// Returns the size of the serialized data in bytes.
14    fn size(&self) -> usize {
15        self.iter()
16            .map(|s| 2 + s.1.len() + dyn_int::encoded_size(s.1.len() as u128))
17            .sum::<usize>()
18    }
19
20    /// Serializes the data into a vector of bytes.
21    fn get_bytes(&self) -> Vec<u8> {
22        let mut buff = Vec::new();
23        for (idx, data) in self.iter().sorted() {
24            buff.extend_from_slice(&idx.to_be_bytes());
25            buff.append(&mut dyn_int::encode(data.len() as u128));
26            buff.extend_from_slice(data);
27        }
28        buff
29    }
30
31    /// Deserializes the data from a vector of bytes.
32    fn from_bytes(data: &[u8], _: Option<SerializationInfo>) -> Result<Self, SerializationError>
33    where
34        Self: Sized,
35    {
36        let mut slots: HashMap<u16, Vec<u8>> = HashMap::new();
37        let mut bytes_read = 0;
38        while bytes_read != data.len() {
39            assert_len(data, bytes_read + 3)?;
40            let mut idx = [0u8; 2];
41            idx.copy_from_slice(&data[bytes_read..(bytes_read + 2)]);
42            let idx = u16::from_be_bytes(idx);
43            bytes_read += 2;
44            let (data_len, read) = dyn_int::read_from_slice(&data[bytes_read..])?;
45            bytes_read += read;
46            assert_len(data, bytes_read + data_len as usize)?;
47            let data = data[bytes_read..(bytes_read + data_len as usize)].to_vec();
48            bytes_read += data_len as usize;
49            let _ = slots.insert(idx, data);
50        }
51
52        Ok(slots)
53    }
54}
55
56#[cfg(test)]
57mod test {
58    use crate::abstractions::Serializable;
59
60    use super::SlotBody;
61
62    #[test]
63    fn can_serialize_slot_body() {
64        let mut slots = SlotBody::new();
65        slots.insert(0, vec![0u8; 10]);
66        slots.insert(5, vec![1u8; 5]);
67
68        let bytes = slots.get_bytes();
69        assert_eq!(
70            vec![0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 1, 1, 1, 1, 1],
71            bytes
72        );
73    }
74
75    #[test]
76    fn can_deserialize_slot_body() {
77        let bytes = vec![0, 7, 3, 1, 2, 3, 0, 12, 5, 1, 1, 1, 1, 1];
78        let slots = SlotBody::from_bytes(&bytes, None).unwrap();
79        assert_eq!(&vec![1, 1, 1, 1, 1], slots.get(&12).unwrap());
80        assert_eq!(&vec![1, 2, 3], slots.get(&7).unwrap());
81    }
82}