#[cfg(test)]
mod tests;
#[derive(Debug)]
pub enum ErrorKind {
UnableToRead,
UnableToWrite,
}
pub type Result<T> = std::result::Result<T, ErrorKind>;
pub trait SimpleDataSerializer {
fn write(&mut self, v: &[u8]) -> Result<()>;
fn write_u8(&mut self, v: u8) -> Result<()>;
fn write_u16(&mut self, v: u16) -> Result<()> {
self.write(&v.to_be_bytes())
}
fn write_u32(&mut self, v: u32) -> Result<()> {
self.write(&v.to_be_bytes())
}
fn write_u64(&mut self, v: u64) -> Result<()> {
self.write(&v.to_be_bytes())
}
fn write_i8(&mut self, v: i8) -> Result<()> {
self.write_u8(v as u8)
}
fn write_i16(&mut self, v: i16) -> Result<()> {
self.write_u16(v as u16)
}
fn write_i32(&mut self, v: i32) -> Result<()> {
self.write_u32(v as u32)
}
fn write_i64(&mut self, v: i64) -> Result<()> {
self.write_u64(v as u64)
}
fn write_f32(&mut self, v: f32) -> Result<()> {
self.write(&v.to_be_bytes())
}
fn write_f64(&mut self, v: f64) -> Result<()> {
self.write(&v.to_be_bytes())
}
fn write_byte_array(&mut self, v: &[u8]) -> Result<()> {
self.write_u16(v.len() as u16)?;
self.write(v)
}
}
macro_rules! simpledatadeserializer_read_impl {
($type: ty, $func_name:ident, $doc: expr) => {
#[doc = $doc]
fn $func_name(&mut self) -> Result<$type> {
const DATA_SIZE: usize = std::mem::size_of::<$type>();
self.read(DATA_SIZE)?;
let mut tmp: [u8; DATA_SIZE] = [0; DATA_SIZE];
tmp.copy_from_slice(self.data());
Ok(<$type>::from_be_bytes(tmp))
}
};
}
pub trait SimpleDataDeserializer {
fn data(&self) -> &[u8];
fn read(&mut self, size: usize) -> Result<()>;
fn read_u8(&mut self) -> Result<u8> {
self.read(1)?;
Ok(self.data()[0])
}
fn read_i8(&mut self) -> Result<i8> {
Ok(self.read_u8()? as i8)
}
simpledatadeserializer_read_impl!(u16, read_u16, "Reads an u16 value.");
simpledatadeserializer_read_impl!(u32, read_u32, "Reads an u32 value.");
simpledatadeserializer_read_impl!(u64, read_u64, "Reads an u16 value.");
simpledatadeserializer_read_impl!(i16, read_i16, "Reads an i16 value.");
simpledatadeserializer_read_impl!(i32, read_i32, "Reads an i32 value.");
simpledatadeserializer_read_impl!(i64, read_i64, "Reads an i64 value.");
simpledatadeserializer_read_impl!(f32, read_f32, "Reads an f32 value.");
simpledatadeserializer_read_impl!(f64, read_f64, "Reads an f64 value.");
fn read_byte_array(&mut self) -> Result<()> {
let size = self.read_u16()? as usize;
self.read(size)
}
}
impl SimpleDataSerializer for Vec<u8> {
fn write(&mut self, v: &[u8]) -> Result<()> {
self.extend_from_slice(v);
Ok(())
}
fn write_u8(&mut self, v: u8) -> Result<()> {
self.push(v);
Ok(())
}
}
pub struct SimpleSliceSerializer<'a> {
slice: &'a mut [u8],
offset: usize,
}
impl<'a> SimpleSliceSerializer<'a> {
pub fn new(slice: &'a mut [u8]) -> Self {
Self { slice, offset: 0 }
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn available(&self) -> usize {
self.slice.len() - self.offset
}
fn can_write(&self, size: usize) -> Result<()> {
if size <= self.available() {
Ok(())
} else {
Err(ErrorKind::UnableToWrite)
}
}
}
impl<'a> SimpleDataSerializer for SimpleSliceSerializer<'a> {
fn write(&mut self, v: &[u8]) -> Result<()> {
self.can_write(v.len())?;
self.slice[self.offset..self.offset + v.len()].copy_from_slice(v);
self.offset += v.len();
Ok(())
}
fn write_u8(&mut self, v: u8) -> Result<()> {
self.can_write(1)?;
self.slice[self.offset] = v;
self.offset += 1;
Ok(())
}
}
pub struct SimpleSliceDeserializer<'a> {
data: &'a [u8],
offset: usize,
data_offset: usize,
}
impl<'a> SimpleSliceDeserializer<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self {
data,
offset: 0,
data_offset: 0,
}
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn avaliable(&self) -> usize {
self.data.len() - self.offset
}
pub fn is_empty(&self) -> bool {
self.avaliable() == 0
}
fn can_read(&self, size: usize) -> Result<()> {
if size <= self.avaliable() {
Ok(())
} else {
Err(ErrorKind::UnableToRead)
}
}
}
impl<'a> SimpleDataDeserializer for SimpleSliceDeserializer<'a> {
fn data(&self) -> &[u8] {
&self.data[self.data_offset..self.offset]
}
fn read(&mut self, size: usize) -> Result<()> {
self.can_read(size)?;
self.data_offset = self.offset;
self.offset += size;
Ok(())
}
}