Expand encoder API

This commit is contained in:
Michael Pfaff 2022-11-07 10:11:27 -05:00
parent 301f3c8945
commit da343e43f3
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
1 changed files with 95 additions and 6 deletions

View File

@ -370,9 +370,15 @@ macro_rules! common_impl {
}};
}
macro_rules! define_encode_str {
($name:ident$(<$N:ident>)?($in:ty) $(where $( $where:tt )+)?) => {
fn $name$(<const $N: usize>)?(src: $in) -> String $( where $( $where )+ )?;
macro_rules! define_encode {
($name:ident$(<$N:ident>)?($in:ty) {
str => $str:ident,
write => $write:ident
$(,)?
} $(where $( $where:tt )+)?) => {
fn $str$(<const $N: usize>)?(src: $in) -> String $( where $( $where )+ )?;
fn $write$(<const $N: usize>)?(w: impl std::fmt::Write, src: $in) -> std::fmt::Result $( where $( $where )+ )?;
};
}
@ -386,6 +392,42 @@ macro_rules! impl_encode_str {
};
}
macro_rules! impl_encode_write {
($name:ident$(<$N:ident>)?($in:ty) => $impl:ident (|$bytes:ident| $into_slice:expr) $(where $( $where:tt )+)?) => {
#[inline]
fn $name$(<const $N: usize>)?(mut w: impl std::fmt::Write, src: $in) -> std::fmt::Result $( where $( $where )+ )? {
let $bytes = Self::$impl(src);
let s = unsafe { std::str::from_utf8_unchecked($into_slice) };
w.write_str(s)
}
};
}
pub struct DisplaySized<'a, E: Encode + ?Sized, const N: usize>(&'a [u8; N], std::marker::PhantomData<E>);
pub struct DisplaySizedHeap<'a, E: Encode + ?Sized, const N: usize>(&'a [u8; N], std::marker::PhantomData<E>);
pub struct DisplaySlice<'a, E: Encode + ?Sized>(&'a [u8], std::marker::PhantomData<E>);
impl<'a, E: Encode, const N: usize> std::fmt::Display for DisplaySized<'a, E, N> where [u8; N * 2]: {
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
E::write_sized(f, self.0)
}
}
impl<'a, E: Encode, const N: usize> std::fmt::Display for DisplaySizedHeap<'a, E, N> where [u8; N * 2]: {
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
E::write_sized_heap(f, self.0)
}
}
impl<'a, E: Encode> std::fmt::Display for DisplaySlice<'a, E> {
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
E::write_slice(f, self.0)
}
}
pub trait Encode {
/// Encodes the sized input on the stack.
fn enc_sized<const N: usize>(src: &[u8; N]) -> [u8; N * 2]
@ -400,9 +442,31 @@ pub trait Encode {
/// Encodes the unsized input on the heap.
fn enc_slice(src: &[u8]) -> Box<[u8]>;
define_encode_str!(enc_str_sized<N>(&[u8; N]) where [u8; N * 2]:);
define_encode_str!(enc_str_sized_heap<N>(&[u8; N]) where [u8; N * 2]:);
define_encode_str!(enc_str_slice(&[u8]));
define_encode!(enc_sized<N>(&[u8; N]) {
str => enc_str_sized,
write => write_sized,
} where [u8; N * 2]:);
define_encode!(enc_sized_heap<N>(&[u8; N]) {
str => enc_str_sized_heap,
write => write_sized_heap,
} where [u8; N * 2]:);
define_encode!(enc_slice(&[u8]) {
str => enc_str_slice,
write => write_slice,
});
/// Returns an `impl Display` of the sized input on the stack.
fn display_sized<const N: usize>(src: &[u8; N]) -> DisplaySized<'_, Self, N>
where
[u8; N * 2]:;
/// Returns an `impl Display` of the sized input on the heap.
fn display_sized_heap<const N: usize>(src: &[u8; N]) -> DisplaySizedHeap<'_, Self, N>
where
[u8; N * 2]:;
/// Returns an `impl Display` of the unsized input on the heap.
fn display_slice(src: &[u8]) -> DisplaySlice<'_, Self>;
}
pub struct Encoder<const UPPER: bool = false>;
@ -448,6 +512,31 @@ impl<const UPPER: bool> Encode for Encoder<UPPER> {
Vec::from_raw_parts(Box::into_raw(bytes) as *mut u8, N * 2, N * 2)
}) where [u8; N * 2]:);
impl_encode_str!(enc_str_slice(&[u8]) => enc_slice (|bytes| Vec::from(bytes)));
impl_encode_write!(write_sized<N>(&[u8; N]) => enc_sized (|bytes| &bytes) where [u8; N * 2]:);
impl_encode_write!(write_sized_heap<N>(&[u8; N]) => enc_sized_heap (|bytes| bytes.as_ref()) where [u8; N * 2]:);
impl_encode_write!(write_slice(&[u8]) => enc_slice (|bytes| bytes.as_ref()));
#[inline(always)]
fn display_sized<const N: usize>(src: &[u8; N]) -> DisplaySized<'_, Self, N>
where
[u8; N * 2]:,
{
DisplaySized(src, std::marker::PhantomData)
}
#[inline(always)]
fn display_sized_heap<const N: usize>(src: &[u8; N]) -> DisplaySizedHeap<'_, Self, N>
where
[u8; N * 2]:,
{
DisplaySizedHeap(src, std::marker::PhantomData)
}
#[inline(always)]
fn display_slice(src: &[u8]) -> DisplaySlice<'_, Self> {
DisplaySlice(src, std::marker::PhantomData)
}
}
impl<const UPPER: bool> Encoder<UPPER> {