#![no_std]
#![deny(warnings)]
#![deny(missing_docs)]
mod error;
pub use error::*;
pub trait StreamingReader {
type Error;
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>;
fn share_bytes(&mut self, len: usize) -> Result<&[u8], Self::Error>;
}
#[derive(Debug)]
pub struct BufferReaderError;
pub struct BufferReader<'a> {
buffer: &'a [u8],
cursor: usize,
}
impl<'a> BufferReader<'a> {
#[inline]
pub fn new(buffer: &'a [u8]) -> BufferReader<'a> {
BufferReader { buffer, cursor: 0 }
}
#[inline]
pub fn cursor(&self) -> usize {
self.cursor
}
}
impl<'a> From<&'a [u8]> for BufferReader<'a> {
#[inline]
fn from(buffer: &'a [u8]) -> Self {
BufferReader::new(buffer)
}
}
impl<'a> StreamingReader for BufferReader<'a> {
type Error = BufferReaderError;
#[inline]
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
let len = buf.len();
let end = self.cursor + len;
if end <= self.buffer.len() {
buf.copy_from_slice(&self.buffer[self.cursor..end]);
self.cursor += len;
Ok(())
} else {
Err(BufferReaderError)
}
}
#[inline]
fn share_bytes(&mut self, len: usize) -> Result<&[u8], Self::Error> {
let end = self.cursor + len;
if end <= self.buffer.len() {
let s =
unsafe { core::slice::from_raw_parts(self.buffer.as_ptr().add(self.cursor), len) };
self.cursor += len;
Ok(s)
} else {
Err(BufferReaderError)
}
}
}
pub trait StreamingWriter {
type Error;
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Self::Error>;
fn share_bytes_mut(
&mut self,
len: usize,
) -> Result<&mut [core::mem::MaybeUninit<u8>], Self::Error>;
fn flush() -> Result<(), Self::Error>;
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct BufferWriterError;
pub struct BufferWriter<'a> {
buffer: &'a mut [u8],
cursor: usize,
}
impl<'a> BufferWriter<'a> {
#[inline]
pub fn new(buffer: &'a mut [u8]) -> BufferWriter<'a> {
BufferWriter { buffer, cursor: 0 }
}
#[inline]
pub fn cursor(&self) -> usize {
self.cursor
}
}
impl<'a> StreamingWriter for BufferWriter<'a> {
type Error = BufferWriterError;
#[inline]
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
let len = bytes.len();
let end = self.cursor + len;
if end <= self.buffer.len() {
self.buffer[self.cursor..end].copy_from_slice(bytes);
self.cursor += len;
Ok(())
} else {
Err(BufferWriterError)
}
}
#[inline]
fn share_bytes_mut(
&mut self,
len: usize,
) -> Result<&mut [core::mem::MaybeUninit<u8>], Self::Error> {
let end = self.cursor + len;
if end <= self.buffer.len() {
let s = unsafe {
&mut *(core::slice::from_raw_parts_mut(
self.buffer.as_mut_ptr().add(self.cursor),
len,
) as *mut [u8] as *mut [core::mem::MaybeUninit<u8>])
};
self.cursor += len;
Ok(s)
} else {
Err(BufferWriterError)
}
}
#[inline]
fn flush() -> Result<(), Self::Error> {
Ok(())
}
}
pub trait SerializeValue: Sized {
fn read_value<R: StreamingReader>(reader: &mut R) -> Result<Self, DecodeValueError<R::Error>>;
fn write_value<W: StreamingWriter>(val: Self, writer: &mut W) -> Result<(), W::Error>;
}
macro_rules! primitive_serialize_impl {
($ty:ty) => {
impl SerializeValue for $ty {
#[inline]
fn read_value<R: StreamingReader>(
reader: &mut R,
) -> Result<Self, DecodeValueError<R::Error>> {
let mut bytes = Self::default().to_ne_bytes();
reader.read_bytes(&mut bytes)?;
Ok(Self::from_be_bytes(bytes))
}
#[inline]
fn write_value<W: StreamingWriter>(val: Self, writer: &mut W) -> Result<(), W::Error> {
writer.write_bytes(&val.to_be_bytes())
}
}
};
}
primitive_serialize_impl!(i8);
primitive_serialize_impl!(i16);
primitive_serialize_impl!(i32);
primitive_serialize_impl!(i64);
primitive_serialize_impl!(f32);
primitive_serialize_impl!(f64);
primitive_serialize_impl!(u8);
#[inline]
pub fn write_str_value<W: StreamingWriter>(string: &str, writer: &mut W) -> Result<(), W::Error> {
writer.write_bytes(&(&(string.len() as i32 + 1)).to_be_bytes())?;
writer.write_bytes(&string.as_bytes())?;
writer.write_bytes(&[0])
}
#[inline]
pub fn read_str_value<R: StreamingReader>(
reader: &mut R,
) -> Result<&str, DecodeValueError<<R as StreamingReader>::Error>> {
let len: i32 = i32::read_value(reader)?;
if len < 0 {
return Err(DecodeValueError::InvalidValue("str length was less than 0"));
}
let len = len as usize;
let bytes = reader.share_bytes(len)?;
let s = match core::str::from_utf8(&bytes[..len - 1]) {
Ok(s) => s,
Err(_) => return Err(DecodeValueError::InvalidValue("str was not valid UTF8")),
};
Ok(s)
}
impl SerializeValue for bool {
#[inline]
fn read_value<R: StreamingReader>(
reader: &mut R,
) -> Result<Self, DecodeValueError<<R as StreamingReader>::Error>> {
let mut buffer = [0u8; 1];
reader.read_bytes(&mut buffer)?;
match buffer[0] {
0 => Ok(false),
1 => Ok(true),
_ => Err(DecodeValueError::InvalidValue("invalid bool value")),
}
}
#[inline]
fn write_value<W: StreamingWriter>(val: Self, writer: &mut W) -> Result<(), W::Error> {
SerializeValue::write_value(if val { 1i8 } else { 0i8 }, writer)
}
}