#[cfg(feature = "alloc")]
use core::convert::Infallible;
use core::fmt;
use core::marker;
use core::mem::take;
use musli::Context;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use musli::context::Buffer;
pub const MAX_FIXED_BYTES_LEN: usize = 128;
#[derive(Debug)]
pub struct SliceOverflow {
n: usize,
capacity: usize,
}
impl fmt::Display for SliceOverflow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let SliceOverflow { n, capacity } = self;
write!(
f,
"Tried to write {n} bytes to slice, with a remaining capacity of {capacity}"
)
}
}
pub trait Writer {
type Error;
type Mut<'this>: Writer<Error = Self::Error>
where
Self: 'this;
fn borrow_mut(&mut self) -> Self::Mut<'_>;
fn write_buffer<C, B>(&mut self, cx: &mut C, buffer: B) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
B: Buffer;
fn write_bytes<C>(&mut self, cx: &mut C, bytes: &[u8]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>;
#[inline]
fn write_byte<C>(&mut self, cx: &mut C, b: u8) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
self.write_bytes(cx, &[b])
}
#[inline]
fn write_array<C, const N: usize>(&mut self, cx: &mut C, array: [u8; N]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
self.write_bytes(cx, &array)
}
}
impl<W> Writer for &mut W
where
W: ?Sized + Writer,
{
type Error = W::Error;
type Mut<'this> = &'this mut W where Self: 'this;
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn write_buffer<C, B>(&mut self, cx: &mut C, buffer: B) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
B: Buffer,
{
(*self).write_buffer(cx, buffer)
}
#[inline]
fn write_bytes<C>(&mut self, cx: &mut C, bytes: &[u8]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
(*self).write_bytes(cx, bytes)
}
#[inline]
fn write_byte<C>(&mut self, cx: &mut C, b: u8) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
(*self).write_byte(cx, b)
}
#[inline]
fn write_array<C, const N: usize>(&mut self, cx: &mut C, array: [u8; N]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
(*self).write_array(cx, array)
}
}
#[cfg(feature = "alloc")]
impl Writer for Vec<u8> {
type Error = Infallible;
type Mut<'this> = &'this mut Self where Self: 'this;
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn write_buffer<C, B>(&mut self, cx: &mut C, buffer: B) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
B: Buffer,
{
self.write_bytes(cx, unsafe { buffer.as_slice() })
}
#[inline]
fn write_bytes<C>(&mut self, cx: &mut C, bytes: &[u8]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
self.extend_from_slice(bytes);
cx.advance(bytes.len());
Ok(())
}
#[inline]
fn write_byte<C>(&mut self, cx: &mut C, b: u8) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
self.push(b);
cx.advance(1);
Ok(())
}
#[inline]
fn write_array<C, const N: usize>(&mut self, cx: &mut C, array: [u8; N]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
self.extend_from_slice(&array[..]);
cx.advance(N);
Ok(())
}
}
impl Writer for &mut [u8] {
type Error = SliceOverflow;
type Mut<'this> = &'this mut Self where Self: 'this;
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn write_buffer<C, B>(&mut self, cx: &mut C, buffer: B) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
B: Buffer,
{
self.write_bytes(cx, unsafe { buffer.as_slice() })
}
#[inline]
fn write_bytes<C>(&mut self, cx: &mut C, bytes: &[u8]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
if self.len() < bytes.len() {
return Err(cx.report(SliceOverflow {
n: bytes.len(),
capacity: self.len(),
}));
}
let next = take(self);
let (this, next) = next.split_at_mut(bytes.len());
this.copy_from_slice(bytes);
*self = next;
Ok(())
}
#[inline]
fn write_byte<C>(&mut self, cx: &mut C, b: u8) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
if self.is_empty() {
return Err(cx.message(format_args!(
"Buffer overflow, remaining is {} while tried to write 1",
self.len()
)));
}
self[0] = b;
*self = &mut take(self)[1..];
Ok(())
}
#[inline]
fn write_array<C, const N: usize>(&mut self, cx: &mut C, array: [u8; N]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
if self.len() < N {
return Err(cx.message(format_args!(
"Buffer overflow, remaining is {} while tried to write {}",
self.len(),
N
)));
}
let next = take(self);
let (this, next) = next.split_at_mut(N);
this.copy_from_slice(&array[..]);
*self = next;
Ok(())
}
}
pub struct BufferWriter<T, E> {
buffer: T,
_marker: marker::PhantomData<E>,
}
impl<T, E> BufferWriter<T, E> {
pub fn new(buffer: T) -> Self {
Self {
buffer,
_marker: marker::PhantomData,
}
}
pub fn into_inner(self) -> T {
self.buffer
}
}
impl<T, E> Writer for BufferWriter<T, E>
where
T: Buffer,
{
type Error = E;
type Mut<'this> = &'this mut Self
where
Self: 'this;
#[inline(always)]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline(always)]
fn write_buffer<C, B>(&mut self, cx: &mut C, buffer: B) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
B: Buffer,
{
if !self.buffer.copy_back(buffer) {
return Err(cx.message("Buffer overflow"));
}
Ok(())
}
#[inline(always)]
fn write_bytes<C>(&mut self, cx: &mut C, bytes: &[u8]) -> Result<(), C::Error>
where
C: Context<Input = Self::Error>,
{
if !self.buffer.write(bytes) {
return Err(cx.message("Buffer overflow"));
}
Ok(())
}
}