use super::ValueDecoder;
use crate::{
Codec,
CodecDecodeError,
codec::assert_unit_bounds,
};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct CodecValueDecoder<C> {
codec: C,
}
impl<C> CodecValueDecoder<C> {
#[must_use]
#[inline(always)]
pub const fn new(codec: C) -> Self {
Self { codec }
}
}
impl<C> ValueDecoder<[C::Unit]> for CodecValueDecoder<C>
where
C: Codec,
{
type Output = C::Value;
type Error = CodecDecodeError<C::DecodeError>;
fn decode(&self, input: &[C::Unit]) -> Result<Self::Output, Self::Error> {
assert_unit_bounds::<C>(&self.codec);
let min_units = self.codec.min_units_per_value().get();
if input.len() < min_units {
return Err(CodecDecodeError::incomplete(0, min_units, input.len()));
}
let (value, consumed) =
unsafe { self.codec.decode_unchecked(input, 0) }.map_err(|error| CodecDecodeError::decode(error, 0))?;
let consumed = consumed.get();
assert!(
consumed <= input.len(),
"Codec::decode_unchecked consumed beyond available input",
);
let remaining = input.len() - consumed;
if remaining == 0 {
Ok(value)
} else {
Err(CodecDecodeError::trailing_input(consumed, remaining))
}
}
}