use core::marker;
use core::mem::MaybeUninit;
use core::ptr;
use musli::error::Error;
use crate::error::BufferError;
use crate::writer::Writer;
pub struct FixedBytes<const N: usize, E = BufferError> {
data: [MaybeUninit<u8>; N],
init: usize,
_marker: marker::PhantomData<E>,
}
impl<const N: usize, E> FixedBytes<N, E> {
pub const fn new() -> Self {
Self {
data: unsafe { MaybeUninit::<[MaybeUninit<u8>; N]>::uninit().assume_init() },
init: 0,
_marker: marker::PhantomData,
}
}
pub const fn len(&self) -> usize {
self.init
}
pub const fn is_empty(&self) -> bool {
self.init == 0
}
pub fn clear(&mut self) {
self.init = 0;
}
pub const fn remaining(&self) -> usize {
N.saturating_sub(self.init)
}
pub fn into_bytes(self) -> Option<[u8; N]> {
if self.init == N {
unsafe { Some((&self.data as *const _ as *const [u8; N]).read()) }
} else {
None
}
}
pub fn as_slice(&self) -> &[u8] {
if self.init == 0 {
return &[];
}
unsafe { core::slice::from_raw_parts(self.data.as_ptr().cast(), self.init) }
}
pub fn as_mut_slice(&mut self) -> &[u8] {
if self.init == 0 {
return &[];
}
unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr().cast(), self.init) }
}
pub fn push(&mut self, value: u8) -> bool {
if N.saturating_sub(self.init) == 0 {
return false;
}
unsafe {
self.data
.as_mut_ptr()
.cast::<u8>()
.add(self.init)
.write(value)
}
self.init += 1;
true
}
pub fn extend_from_slice(&mut self, source: &[u8]) -> bool {
if source.len() > N.saturating_sub(self.init) {
return false;
}
unsafe {
let dst = (self.data.as_mut_ptr() as *mut u8).add(self.init);
ptr::copy_nonoverlapping(source.as_ptr(), dst, source.len());
}
self.init += source.len();
true
}
}
impl<const N: usize, E> Default for FixedBytes<N, E> {
fn default() -> Self {
Self::new()
}
}
impl<const N: usize, E> Writer for FixedBytes<N, E>
where
E: Error,
{
type Error = E;
type Mut<'this> = &'this mut Self where Self: 'this;
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
if !self.extend_from_slice(bytes) {
return Err(E::message(format_args! {
"Overflow when writing {additional} bytes at {at} with capacity {capacity}",
at = self.init,
additional = bytes.len(),
capacity = N,
}));
}
Ok(())
}
}