#![feature(const_generics)]
#![feature(const_evaluatable_checked)]
#![feature(type_name_of_val)]
#![allow(incomplete_features)]
#![feature(test)]
#![cfg_attr(not(feature = "std"), no_std)]
pub unsafe trait ConstWriterAdapterCreate<'a, T: ?Sized> {
unsafe fn new<const N: usize>(buff: &'a mut T) -> Self;
}
pub trait ConstWriterAdapter {
unsafe fn write<const N: usize>(self, value: &[u8; N]) -> Self;
unsafe fn grow<const M: usize>(self) -> Self;
}
pub mod slice;
#[cfg(any(feature = "std", feature = "alloc"))]
pub mod vec;
pub struct ConstWriter<T: ConstWriterAdapter, const N: usize> {
writer_adapter: T,
}
macro_rules! implement_write {
($name:ident, $type:ty, $endian:ident) => {
pub fn $name(self, value: $type) ->ConstWriter<T, {N - core::mem::size_of::<$type>()}> {
unsafe {
ConstWriter {
writer_adapter: self.writer_adapter.write(&value.$endian()),
}
}
}
}
}
impl<T: ConstWriterAdapter, const N: usize> ConstWriter<T, {N}> {
pub fn convert<const M: usize>(self) -> ConstWriter<T, {M}> {
if M <= N { ConstWriter {
writer_adapter: self.writer_adapter,
}
} else {
unsafe {
ConstWriter { writer_adapter: self.writer_adapter.grow::<{M}>(),
}
}
}
}
}
impl<T: ConstWriterAdapter, const N: usize> ConstWriter<T, {N}> {
implement_write!(write_u8_le, u8, to_le_bytes);
implement_write!(write_u16_le, u16, to_le_bytes);
implement_write!(write_u32_le, u32, to_le_bytes);
implement_write!(write_u64_le, u64, to_le_bytes);
implement_write!(write_u128_le, u128, to_le_bytes);
implement_write!(write_i8_le, i8, to_le_bytes);
implement_write!(write_i16_le, i16, to_le_bytes);
implement_write!(write_i32_le, i32, to_le_bytes);
implement_write!(write_i64_le, i64, to_le_bytes);
implement_write!(write_i128_le, i128, to_le_bytes);
implement_write!(write_u8_be, u8, to_be_bytes);
implement_write!(write_u16_be, u16, to_be_bytes);
implement_write!(write_u32_be, u32, to_be_bytes);
implement_write!(write_u64_be, u64, to_be_bytes);
implement_write!(write_u128_be, u128, to_be_bytes);
implement_write!(write_i8_be, i8, to_be_bytes);
implement_write!(write_i16_be, i16, to_be_bytes);
implement_write!(write_i32_be, i32, to_be_bytes);
implement_write!(write_i64_be, i64, to_be_bytes);
implement_write!(write_i128_be, i128, to_be_bytes);
implement_write!(write_f32_be, f32, to_be_bytes);
implement_write!(write_f64_be, f64, to_be_bytes);
implement_write!(write_f32_le, f32, to_le_bytes);
implement_write!(write_f64_le, f64, to_le_bytes);
pub fn remaining(&self) -> usize {
N
}
}
impl<T: ConstWriterAdapter, const N: usize> ConstWriter<T, {N}> {
pub fn write_slice<const M: usize>(self, value: &[u8; M]) -> ConstWriter<T, { N-M }> {
unsafe {
ConstWriter {
writer_adapter: self.writer_adapter.write(value),
}
}
}
}
pub trait ConstWrite<'a, T: ConstWriterAdapter + ConstWriterAdapterCreate<'a, Self>> {
fn const_writer<const N: usize>(&'a mut self) -> ConstWriter<T, {N}> {
unsafe {
ConstWriter {
writer_adapter: T::new::<{ N }>(self)
}
}
}
}