use core::fmt;
use super::{Encode, Encoder, EncoderStatus, ExactSizeEncoder};
#[derive(Debug, Clone)]
pub struct BytesEncoder<'sl> {
sl: &'sl [u8],
}
impl<'sl> BytesEncoder<'sl> {
pub const fn without_length_prefix(sl: &'sl [u8]) -> Self { Self { sl } }
}
impl Encoder for BytesEncoder<'_> {
fn current_chunk(&self) -> &[u8] { self.sl }
fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
}
impl<'sl> ExactSizeEncoder for BytesEncoder<'sl> {
#[inline]
fn len(&self) -> usize { self.sl.len() }
}
#[derive(Debug, Clone)]
pub struct ArrayEncoder<const N: usize> {
arr: [u8; N],
}
impl<const N: usize> ArrayEncoder<N> {
pub const fn without_length_prefix(arr: [u8; N]) -> Self { Self { arr } }
}
impl<const N: usize> Encoder for ArrayEncoder<N> {
#[inline]
fn current_chunk(&self) -> &[u8] { &self.arr }
#[inline]
fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
}
impl<const N: usize> ExactSizeEncoder for ArrayEncoder<N> {
#[inline]
fn len(&self) -> usize { self.arr.len() }
}
#[derive(Debug, Clone)]
pub struct ArrayRefEncoder<'e, const N: usize> {
arr: &'e [u8; N],
}
impl<'e, const N: usize> ArrayRefEncoder<'e, N> {
pub const fn without_length_prefix(arr: &'e [u8; N]) -> Self { Self { arr } }
}
impl<const N: usize> Encoder for ArrayRefEncoder<'_, N> {
#[inline]
fn current_chunk(&self) -> &[u8] { self.arr }
#[inline]
fn advance(&mut self) -> EncoderStatus { EncoderStatus::Finished }
}
impl<const N: usize> ExactSizeEncoder for ArrayRefEncoder<'_, N> {
#[inline]
fn len(&self) -> usize { self.arr.len() }
}
pub struct SliceEncoder<'e, T: Encode> {
sl: &'e [T],
cur_enc: Option<T::Encoder<'e>>,
}
impl<'e, T: Encode> SliceEncoder<'e, T> {
pub fn without_length_prefix(sl: &'e [T]) -> Self {
Self { sl, cur_enc: sl.first().map(|x| T::encoder(x)) }
}
}
impl<'e, T: Encode> fmt::Debug for SliceEncoder<'e, T>
where
T::Encoder<'e>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SliceEncoder")
.field("sl", &self.sl.len())
.field("cur_enc", &self.cur_enc)
.finish()
}
}
impl<'e, T: Encode> Clone for SliceEncoder<'e, T>
where
T::Encoder<'e>: Clone,
{
fn clone(&self) -> Self { Self { sl: self.sl, cur_enc: self.cur_enc.clone() } }
}
impl<T: Encode> Encoder for SliceEncoder<'_, T> {
fn current_chunk(&self) -> &[u8] {
self.cur_enc.as_ref().map(T::Encoder::current_chunk).unwrap_or_default()
}
fn advance(&mut self) -> EncoderStatus {
let Some(cur) = self.cur_enc.as_mut() else {
return EncoderStatus::Finished;
};
loop {
if cur.advance().has_more() {
return EncoderStatus::HasMore;
}
self.sl = &self.sl[1..];
if let Some(x) = self.sl.first() {
*cur = x.encoder();
if !cur.current_chunk().is_empty() {
return EncoderStatus::HasMore;
}
} else {
self.cur_enc = None; return EncoderStatus::Finished;
}
}
}
}
macro_rules! define_encoder_n {
(
$(#[$attr:meta])*
$name:ident, $idx_limit:literal;
$(($enc_idx:literal, $enc_ty:ident, $enc_field:ident),)*
) => {
$(#[$attr])*
#[derive(Debug, Clone)]
pub struct $name<$($enc_ty,)*> {
cur_idx: usize,
$($enc_field: $enc_ty,)*
}
impl<$($enc_ty,)*> $name<$($enc_ty,)*> {
pub const fn new($($enc_field: $enc_ty,)*) -> Self {
Self { cur_idx: 0, $($enc_field,)* }
}
}
impl<$($enc_ty: Encoder,)*> Encoder for $name<$($enc_ty,)*> {
#[inline]
fn current_chunk(&self) -> &[u8] {
match self.cur_idx {
$($enc_idx => self.$enc_field.current_chunk(),)*
_ => unreachable!("index never reaches this value"),
}
}
#[inline]
fn advance(&mut self) -> EncoderStatus {
match self.cur_idx {
$(
$enc_idx => {
if $enc_idx == $idx_limit - 1 {
return self.$enc_field.advance()
}
if self.$enc_field.advance().has_finished() {
self.cur_idx += 1;
}
EncoderStatus::HasMore
}
)*
_ => EncoderStatus::Finished,
}
}
}
impl<$($enc_ty,)*> ExactSizeEncoder for $name<$($enc_ty,)*>
where
$($enc_ty: Encoder + ExactSizeEncoder,)*
{
#[inline]
fn len(&self) -> usize {
0 $(+ self.$enc_field.len())*
}
}
};
}
define_encoder_n! {
Encoder2, 2;
(0, A, enc_1), (1, B, enc_2),
}
define_encoder_n! {
Encoder3, 3;
(0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
}
define_encoder_n! {
Encoder4, 4;
(0, A, enc_1), (1, B, enc_2),
(2, C, enc_3), (3, D, enc_4),
}
define_encoder_n! {
Encoder6, 6;
(0, A, enc_1), (1, B, enc_2), (2, C, enc_3),
(3, D, enc_4), (4, E, enc_5), (5, F, enc_6),
}