use core::fmt;
use super::ValueDecoder;
use crate::{
Codec,
CodecDecodeError,
CodecValueExt,
TranscodeError,
codec::assert_unit_bounds,
};
pub struct CodecValueDecoder<C>
where
C: Codec,
{
codec: C,
flush_scratch: Vec<C::Value>,
}
impl<C> fmt::Debug for CodecValueDecoder<C>
where
C: Codec + fmt::Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("CodecValueDecoder")
.field("codec", &self.codec)
.field("flush_scratch_len", &self.flush_scratch.len())
.field("flush_scratch_capacity", &self.flush_scratch.capacity())
.finish()
}
}
impl<C> Default for CodecValueDecoder<C>
where
C: Codec + Default,
{
#[inline(always)]
fn default() -> Self {
Self::new(C::default())
}
}
impl<C> CodecValueDecoder<C>
where
C: Codec,
{
#[inline]
#[must_use]
pub fn new(codec: C) -> Self {
assert_unit_bounds::<C>();
Self {
codec,
flush_scratch: Vec::new(),
}
}
}
impl<C> ValueDecoder<[C::Unit]> for CodecValueDecoder<C>
where
C: Codec,
C::Value: Default,
{
type Output = C::Value;
type Error = TranscodeError<CodecDecodeError<C::DecodeError>>;
fn decode(
&mut self,
input: &[C::Unit],
) -> Result<Self::Output, Self::Error> {
let flush_cap = C::MAX_DECODE_FLUSH_VALUES;
let (value, _) = if flush_cap == 0 {
self.codec
.decode_exact_value_with_flush(input, &mut [], 0)?
} else {
if self.flush_scratch.len() < flush_cap {
self.flush_scratch.resize_with(flush_cap, C::Value::default);
}
self.codec.decode_exact_value_with_flush(
input,
&mut self.flush_scratch,
0,
)?
};
Ok(value)
}
}