use {
crate::writer::Writer,
core::{mem::MaybeUninit, slice},
};
pub unsafe trait Encode {
fn size(&self) -> Size;
unsafe fn encode_unchecked(&self, w: &mut Writer);
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Size(pub usize);
impl Size {
#[inline]
pub fn expand(self, Self(more): Self) -> Self {
Self(usize::checked_add(self.0, more).expect("size cannot overflow"))
}
}
unsafe impl<E> Encode for &E
where
E: Encode + ?Sized,
{
#[inline]
fn size(&self) -> Size {
(**self).size()
}
#[inline]
unsafe fn encode_unchecked(&self, w: &mut Writer) {
unsafe { (**self).encode_unchecked(w) }
}
}
unsafe impl Encode for () {
#[inline]
fn size(&self) -> Size {
Size(0)
}
#[inline]
unsafe fn encode_unchecked(&self, _: &mut Writer) {}
}
unsafe impl Encode for [u8] {
#[inline]
fn size(&self) -> Size {
Size(self.len())
}
#[inline]
unsafe fn encode_unchecked(&self, w: &mut Writer) {
unsafe { w.write_slice(self) }
}
}
unsafe impl<const N: usize> Encode for [u8; N] {
#[inline]
fn size(&self) -> Size {
self[..].size()
}
#[inline]
unsafe fn encode_unchecked(&self, w: &mut Writer) {
unsafe { self[..].encode_unchecked(w) }
}
}
unsafe impl Encode for u8 {
#[inline]
fn size(&self) -> Size {
Size(size_of::<Self>())
}
#[inline]
unsafe fn encode_unchecked(&self, w: &mut Writer) {
unsafe { w.write_byte(*self) }
}
}
struct Then<A, B>(A, B);
unsafe impl<A, B> Encode for Then<A, B>
where
A: Encode,
B: Encode,
{
#[inline]
fn size(&self) -> Size {
let Self(a, b) = self;
a.size().expand(b.size())
}
#[inline]
unsafe fn encode_unchecked(&self, w: &mut Writer) {
let Self(a, b) = self;
unsafe { a.encode_unchecked(w) }
unsafe { b.encode_unchecked(w) }
}
}
pub trait EncodeExt: Encode + Sized {
#[inline]
fn then<E>(self, e: E) -> impl Encode
where
E: Encode,
{
Then(self, e)
}
#[inline]
fn u8(self, u: u8) -> impl Encode {
Then(self, u)
}
#[inline]
fn u16(self, u: u16) -> impl Encode {
Then(self, u16::to_be_bytes(u))
}
#[inline]
fn u32(self, u: u32) -> impl Encode {
Then(self, u32::to_be_bytes(u))
}
#[inline]
fn u64(self, u: u64) -> impl Encode {
Then(self, u64::to_be_bytes(u))
}
#[inline]
fn u128(self, u: u128) -> impl Encode {
Then(self, u128::to_be_bytes(u))
}
#[inline]
fn usize(self, u: usize) -> impl Encode {
Then(self, usize::to_be_bytes(u))
}
#[inline]
fn encode<B>(self, buf: &mut B) -> Result<&mut [u8], usize>
where
B: Buffer + ?Sized,
{
let buf = buf.buffer();
let Size(size) = self.size();
if size == buf.len() {
let mut w = Writer::new(buf);
debug_assert_eq!(
w.remaining(),
size,
"the buffer must not be filled at the beginning",
);
unsafe { self.encode_unchecked(&mut w) }
debug_assert_eq!(
w.remaining(),
0,
"afterward the buffer must be completely filled",
);
let init = unsafe { w.init() };
Ok(init)
} else {
Err(size)
}
}
}
impl<E> EncodeExt for E where E: Encode {}
pub trait LittleEndianEncodeExt: Encode + Sized {
#[inline]
fn u16_le(self, u: u16) -> impl Encode {
Then(self, u16::to_le_bytes(u))
}
#[inline]
fn u32_le(self, u: u32) -> impl Encode {
Then(self, u32::to_le_bytes(u))
}
#[inline]
fn u64_le(self, u: u64) -> impl Encode {
Then(self, u64::to_le_bytes(u))
}
#[inline]
fn u128_le(self, u: u128) -> impl Encode {
Then(self, u128::to_le_bytes(u))
}
#[inline]
fn usize_le(self, u: usize) -> impl Encode {
Then(self, usize::to_le_bytes(u))
}
}
impl<E> LittleEndianEncodeExt for E where E: Encode {}
pub trait Buffer {
fn buffer(&mut self) -> &mut [MaybeUninit<u8>];
}
impl Buffer for [MaybeUninit<u8>] {
#[inline]
fn buffer(&mut self) -> &mut [MaybeUninit<u8>] {
self
}
}
impl<const N: usize> Buffer for [MaybeUninit<u8>; N] {
#[inline]
fn buffer(&mut self) -> &mut [MaybeUninit<u8>] {
self
}
}
impl Buffer for [u8] {
#[inline]
fn buffer(&mut self) -> &mut [MaybeUninit<u8>] {
fn slice_mut_as_init(s: &mut [u8]) -> &mut [MaybeUninit<u8>] {
unsafe { slice::from_raw_parts_mut(s.as_mut_ptr().cast(), s.len()) }
}
slice_mut_as_init(self)
}
}
impl<const N: usize> Buffer for [u8; N] {
#[inline]
fn buffer(&mut self) -> &mut [MaybeUninit<u8>] {
self[..].buffer()
}
}