#![allow(unsafe_code)]
use crate::error::EncodeError;
pub trait Writer {
fn write(
&mut self,
bytes: &[u8],
) -> Result<(), EncodeError>;
#[inline(always)]
fn write_u8(
&mut self,
value: u8,
) -> Result<(), EncodeError> {
self.write(&[value])
}
}
impl<T: Writer> Writer for &mut T {
#[inline]
fn write(
&mut self,
bytes: &[u8],
) -> Result<(), EncodeError> {
(**self).write(bytes)
}
#[inline]
fn write_u8(
&mut self,
value: u8,
) -> Result<(), EncodeError> {
(**self).write_u8(value)
}
}
pub struct SliceWriter<'storage> {
slice: &'storage mut [u8],
original_length: usize,
}
impl<'storage> SliceWriter<'storage> {
pub const fn new(bytes: &'storage mut [u8]) -> Self {
let original = bytes.len();
Self {
slice: bytes,
original_length: original,
}
}
#[must_use]
pub const fn bytes_written(&self) -> usize {
self.original_length - self.slice.len()
}
}
impl Writer for SliceWriter<'_> {
#[inline(always)]
fn write(
&mut self,
bytes: &[u8],
) -> Result<(), EncodeError> {
if bytes.len() > self.slice.len() {
return crate::error::cold_encode_error_unexpected_end();
}
unsafe {
core::ptr::copy_nonoverlapping(bytes.as_ptr(), self.slice.as_mut_ptr(), bytes.len());
let ptr = self.slice.as_mut_ptr().add(bytes.len());
let len = self.slice.len() - bytes.len();
self.slice = core::slice::from_raw_parts_mut(ptr, len);
}
Ok(())
}
#[inline(always)]
fn write_u8(
&mut self,
value: u8,
) -> Result<(), EncodeError> {
if self.slice.is_empty() {
return crate::error::cold_encode_error_unexpected_end();
}
unsafe {
*self.slice.as_mut_ptr() = value;
let ptr = self.slice.as_mut_ptr().add(1);
let len = self.slice.len() - 1;
self.slice = core::slice::from_raw_parts_mut(ptr, len);
}
Ok(())
}
}
#[derive(Default)]
pub struct SizeWriter {
pub bytes_written: usize,
}
impl Writer for SizeWriter {
#[inline(always)]
fn write(
&mut self,
bytes: &[u8],
) -> Result<(), EncodeError> {
self.bytes_written += bytes.len();
Ok(())
}
#[inline(always)]
fn write_u8(
&mut self,
_: u8,
) -> Result<(), EncodeError> {
self.bytes_written += 1;
Ok(())
}
}