use core::convert::TryInto as _;
use crate::error::{ParseError, SerializationError};
pub struct Serializer<'a> {
buffer: &'a mut [u8],
bytes_written: usize,
}
impl<'a> Serializer<'a> {
pub fn new(buffer: &'a mut [u8]) -> Self {
buffer.into()
}
pub fn push_slice(&mut self, data: &[u8]) -> Result<(), SerializationError> {
let n = data.len();
if self.bytes_written + n <= self.buffer.len() {
self.buffer[self.bytes_written..self.bytes_written + n].copy_from_slice(data);
self.bytes_written += n;
Ok(())
} else {
Err(SerializationError::BufferTooSmall)
}
}
pub fn bytes_written(&self) -> usize {
self.bytes_written
}
}
impl<'a> From<&'a mut [u8]> for Serializer<'a> {
fn from(buffer: &'a mut [u8]) -> Self {
Self {
buffer,
bytes_written: 0,
}
}
}
pub struct Parser<'a> {
data: &'a [u8],
offset: usize,
}
impl<'a> Parser<'a> {
pub fn new(data: &'a [u8]) -> Self {
data.into()
}
pub fn take(&mut self) -> Result<u8, ParseError> {
if self.data.len() > self.offset {
let data = self.data[self.offset];
self.offset += 1;
Ok(data)
} else {
Err(ParseError::NotEnoughData)
}
}
pub fn take_array_ref<const N: usize>(&mut self) -> Result<&'a [u8; N], ParseError> {
if self.data.len() >= self.offset + N {
let data = self.data[self.offset..self.offset + N]
.try_into()
.map_err(|_| ParseError::NotEnoughData)?;
self.offset += N;
Ok(data)
} else {
Err(ParseError::NotEnoughData)
}
}
pub fn take_array<const N: usize>(&mut self) -> Result<[u8; N], ParseError> {
self.take_array_ref().map(|data| *data)
}
pub fn take_into<const N: usize, R: From<&'a [u8; N]>>(&mut self) -> Result<R, ParseError> {
self.take_array_ref().map(From::from)
}
pub fn into_rest(self) -> &'a [u8] {
&self.data[self.offset..]
}
}
impl<'a> From<&'a [u8]> for Parser<'a> {
fn from(data: &'a [u8]) -> Self {
Self { data, offset: 0 }
}
}