use std::collections::HashMap;
use itertools::Itertools;
use crate::abstractions::{Serializable, SerializationError, SerializationInfo};
use super::{assert_len, dyn_int};
pub type SlotBody = HashMap<u16, Vec<u8>>;
impl Serializable for SlotBody {
fn size(&self) -> usize {
self.iter()
.map(|s| 2 + s.1.len() + dyn_int::encoded_size(s.1.len() as u128))
.sum::<usize>()
}
fn get_bytes(&self) -> Vec<u8> {
let mut buff = Vec::new();
for (idx, data) in self.iter().sorted() {
buff.extend_from_slice(&idx.to_be_bytes());
buff.append(&mut dyn_int::encode(data.len() as u128));
buff.extend_from_slice(data);
}
buff
}
fn from_bytes(data: &[u8], _: Option<SerializationInfo>) -> Result<Self, SerializationError>
where
Self: Sized,
{
let mut slots: HashMap<u16, Vec<u8>> = HashMap::new();
let mut bytes_read = 0;
while bytes_read != data.len() {
assert_len(data, bytes_read + 3)?;
let mut idx = [0u8; 2];
idx.copy_from_slice(&data[bytes_read..(bytes_read + 2)]);
let idx = u16::from_be_bytes(idx);
bytes_read += 2;
let (data_len, read) = dyn_int::read_from_slice(&data[bytes_read..])?;
bytes_read += read;
assert_len(data, bytes_read + data_len as usize)?;
let data = data[bytes_read..(bytes_read + data_len as usize)].to_vec();
bytes_read += data_len as usize;
let _ = slots.insert(idx, data);
}
Ok(slots)
}
}
#[cfg(test)]
mod test {
use crate::abstractions::Serializable;
use super::SlotBody;
#[test]
fn can_serialize_slot_body() {
let mut slots = SlotBody::new();
slots.insert(0, vec![0u8; 10]);
slots.insert(5, vec![1u8; 5]);
let bytes = slots.get_bytes();
assert_eq!(
vec![0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 1, 1, 1, 1, 1],
bytes
);
}
#[test]
fn can_deserialize_slot_body() {
let bytes = vec![0, 7, 3, 1, 2, 3, 0, 12, 5, 1, 1, 1, 1, 1];
let slots = SlotBody::from_bytes(&bytes, None).unwrap();
assert_eq!(&vec![1, 1, 1, 1, 1], slots.get(&12).unwrap());
assert_eq!(&vec![1, 2, 3], slots.get(&7).unwrap());
}
}