use core::convert::Infallible;
use core::marker::PhantomData;
use core::ops::Index;
use core::ops::IndexMut;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use alloc_vec::*;
#[cfg(feature = "alloc")]
extern crate alloc;
#[derive(Debug)]
pub struct BufferFull;
impl core::fmt::Display for BufferFull {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("BufferFull")
}
}
pub trait Flavor {
type Output;
type PushError: core::fmt::Debug + core::fmt::Display;
type FinalizeError: core::fmt::Debug + core::fmt::Display;
#[inline]
fn try_extend(&mut self, data: &[u8]) -> Result<(), Self::PushError> {
data.iter().try_for_each(|d| self.try_push(*d))
}
fn try_push(&mut self, data: u8) -> Result<(), Self::PushError>;
fn finalize(self) -> Result<Self::Output, Self::FinalizeError>;
}
pub struct Slice<'a> {
start: *mut u8,
cursor: *mut u8,
end: *mut u8,
_pl: PhantomData<&'a [u8]>,
}
impl<'a> Slice<'a> {
pub fn new(buf: &'a mut [u8]) -> Self {
let ptr = buf.as_mut_ptr_range();
Slice {
start: ptr.start,
cursor: ptr.start,
end: ptr.end,
_pl: PhantomData,
}
}
}
impl<'a> Flavor for Slice<'a> {
type Output = &'a mut [u8];
type PushError = BufferFull;
type FinalizeError = Infallible;
#[inline(always)]
fn try_push(&mut self, b: u8) -> Result<(), BufferFull> {
if self.cursor == self.end {
Err(BufferFull)
} else {
unsafe {
self.cursor.write(b);
self.cursor = self.cursor.add(1);
}
Ok(())
}
}
#[inline(always)]
fn try_extend(&mut self, b: &[u8]) -> Result<(), BufferFull> {
let remain = (self.end as usize) - (self.cursor as usize);
let blen = b.len();
if blen > remain {
Err(BufferFull)
} else {
unsafe {
core::ptr::copy_nonoverlapping(b.as_ptr(), self.cursor, blen);
self.cursor = self.cursor.add(blen);
}
Ok(())
}
}
fn finalize(self) -> Result<Self::Output, Infallible> {
let used = (self.cursor as usize) - (self.start as usize);
let sli = unsafe { core::slice::from_raw_parts_mut(self.start, used) };
Ok(sli)
}
}
impl Index<usize> for Slice<'_> {
type Output = u8;
fn index(&self, idx: usize) -> &u8 {
let len = (self.end as usize) - (self.start as usize);
assert!(idx < len);
unsafe { &*self.start.add(idx) }
}
}
impl IndexMut<usize> for Slice<'_> {
fn index_mut(&mut self, idx: usize) -> &mut u8 {
let len = (self.end as usize) - (self.start as usize);
assert!(idx < len);
unsafe { &mut *self.start.add(idx) }
}
}
pub struct ExtendFlavor<T> {
iter: T,
}
impl<T> ExtendFlavor<T>
where
T: core::iter::Extend<u8>,
{
pub fn new(iter: T) -> Self {
Self { iter }
}
}
impl<T> Flavor for ExtendFlavor<T>
where
T: core::iter::Extend<u8>,
{
type Output = T;
type PushError = Infallible;
type FinalizeError = Infallible;
#[inline(always)]
fn try_push(&mut self, data: u8) -> Result<(), Infallible> {
self.iter.extend([data]);
Ok(())
}
#[inline(always)]
fn try_extend(&mut self, b: &[u8]) -> Result<(), Infallible> {
self.iter.extend(b.iter().copied());
Ok(())
}
fn finalize(self) -> Result<Self::Output, Infallible> {
Ok(self.iter)
}
}
#[cfg(feature = "std")]
pub mod io {
use super::Flavor;
pub struct WriteFlavor<T> {
writer: T,
}
impl<T> WriteFlavor<T>
where
T: std::io::Write,
{
pub fn new(writer: T) -> Self {
Self { writer }
}
}
impl<T> Flavor for WriteFlavor<T>
where
T: std::io::Write,
{
type Output = T;
type PushError = std::io::Error;
type FinalizeError = std::io::Error;
#[inline(always)]
fn try_push(&mut self, data: u8) -> Result<(), std::io::Error> {
self.writer.write_all(&[data])
}
#[inline(always)]
fn try_extend(&mut self, b: &[u8]) -> Result<(), std::io::Error> {
self.writer.write_all(b)
}
fn finalize(mut self) -> Result<Self::Output, std::io::Error> {
self.writer.flush()?;
Ok(self.writer)
}
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
mod alloc_vec {
extern crate alloc;
use super::Flavor;
use super::Index;
use super::IndexMut;
use alloc::vec::Vec;
use core::convert::Infallible;
#[derive(Default)]
pub struct AllocVec {
vec: Vec<u8>,
}
impl AllocVec {
pub fn new() -> Self {
Self::default()
}
}
impl Flavor for AllocVec {
type Output = Vec<u8>;
type PushError = Infallible;
type FinalizeError = Infallible;
#[inline(always)]
fn try_extend(&mut self, data: &[u8]) -> Result<(), Infallible> {
self.vec.extend_from_slice(data);
Ok(())
}
#[inline(always)]
fn try_push(&mut self, data: u8) -> Result<(), Infallible> {
self.vec.push(data);
Ok(())
}
fn finalize(self) -> Result<Self::Output, Infallible> {
Ok(self.vec)
}
}
impl Index<usize> for AllocVec {
type Output = u8;
#[inline]
fn index(&self, idx: usize) -> &u8 {
&self.vec[idx]
}
}
impl IndexMut<usize> for AllocVec {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut u8 {
&mut self.vec[idx]
}
}
}
#[derive(Default)]
pub struct Size {
size: usize,
}
impl Flavor for Size {
type Output = usize;
type PushError = Infallible;
type FinalizeError = Infallible;
#[inline(always)]
fn try_push(&mut self, _b: u8) -> Result<(), Infallible> {
self.size += 1;
Ok(())
}
#[inline(always)]
fn try_extend(&mut self, b: &[u8]) -> Result<(), Infallible> {
self.size += b.len();
Ok(())
}
fn finalize(self) -> Result<Self::Output, Infallible> {
Ok(self.size)
}
}