use core::fmt;
use super::{Encodable, Encoder, ExactSizeEncoder};
#[derive(Debug, Clone)]
pub struct BytesEncoder<'sl> {
sl: Option<&'sl [u8]>,
}
impl<'sl> BytesEncoder<'sl> {
pub const fn without_length_prefix(sl: &'sl [u8]) -> Self {
Self { sl: Some(sl) }
}
}
impl Encoder for BytesEncoder<'_> {
fn current_chunk(&self) -> &[u8] {
self.sl.unwrap_or_default()
}
fn advance(&mut self) -> bool {
self.sl = None;
false
}
}
impl<'sl> ExactSizeEncoder for BytesEncoder<'sl> {
#[inline]
fn len(&self) -> usize {
self.sl.map_or(0, <[u8]>::len)
}
}
#[derive(Debug, Clone)]
pub struct ArrayEncoder<const N: usize> {
arr: Option<[u8; N]>,
}
impl<const N: usize> ArrayEncoder<N> {
pub const fn without_length_prefix(arr: [u8; N]) -> Self {
Self { arr: Some(arr) }
}
}
impl<const N: usize> Encoder for ArrayEncoder<N> {
#[inline]
fn current_chunk(&self) -> &[u8] {
self.arr.as_ref().map(|x| &x[..]).unwrap_or_default()
}
#[inline]
fn advance(&mut self) -> bool {
self.arr = None;
false
}
}
impl<const N: usize> ExactSizeEncoder for ArrayEncoder<N> {
#[inline]
fn len(&self) -> usize {
self.arr.map_or(0, |a| a.len())
}
}
#[derive(Debug, Clone)]
pub struct ArrayRefEncoder<'e, const N: usize> {
arr: Option<&'e [u8; N]>,
}
impl<'e, const N: usize> ArrayRefEncoder<'e, N> {
pub const fn without_length_prefix(arr: &'e [u8; N]) -> Self {
Self { arr: Some(arr) }
}
}
impl<const N: usize> Encoder for ArrayRefEncoder<'_, N> {
#[inline]
fn current_chunk(&self) -> &[u8] {
self.arr.map(|x| &x[..]).unwrap_or_default()
}
#[inline]
fn advance(&mut self) -> bool {
self.arr = None;
false
}
}
impl<const N: usize> ExactSizeEncoder for ArrayRefEncoder<'_, N> {
#[inline]
fn len(&self) -> usize {
self.arr.map_or(0, |a| a.len())
}
}
pub struct SliceEncoder<'e, T: Encodable> {
sl: &'e [T],
cur_enc: Option<T::Encoder<'e>>,
}
impl<'e, T: Encodable> 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: Encodable> 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: Encodable> 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: Encodable> 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) -> bool {
let Some(cur) = self.cur_enc.as_mut() else {
return false;
};
loop {
if cur.advance() {
return true;
}
self.sl = &self.sl[1..];
if let Some(x) = self.sl.first() {
*cur = x.encoder();
if !cur.current_chunk().is_empty() {
return true;
}
} else {
self.cur_enc = None; return false;
}
}
}
}
impl<'e, T> ExactSizeEncoder for SliceEncoder<'e, T>
where
T: Encodable + 'e,
T::Encoder<'e>: ExactSizeEncoder,
{
fn len(&self) -> usize {
let Some(cur_enc) = self.cur_enc.as_ref() else {
return 0;
};
let rest = self.sl.get(1..).unwrap_or_default().iter().map(|item| item.encoder().len());
cur_enc.len() + rest.sum::<usize>()
}
}
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(),)*
_ => &[],
}
}
#[inline]
fn advance(&mut self) -> bool {
match self.cur_idx {
$(
$enc_idx => {
if $enc_idx == $idx_limit - 1 {
return self.$enc_field.advance()
}
if !self.$enc_field.advance() {
self.cur_idx += 1;
}
true
}
)*
_ => false,
}
}
}
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),
}