use super::ValueEncoder;
use crate::{
Codec,
CodecEncodeError,
CodecValueExt,
TranscodeError,
codec::assert_unit_bounds,
};
#[derive(Debug, Default)]
pub struct CodecValueEncoder<C> {
codec: C,
}
impl<C> CodecValueEncoder<C>
where
C: Codec,
{
#[inline]
#[must_use]
pub fn new(codec: C) -> Self {
assert_unit_bounds::<C>();
Self { codec }
}
}
impl<C> ValueEncoder<C::Value> for CodecValueEncoder<C>
where
C: Codec,
C::Unit: Default,
{
type Output = Vec<C::Unit>;
type Error = TranscodeError<CodecEncodeError<C::EncodeError>>;
fn encode(
&mut self,
input: &C::Value,
) -> Result<Self::Output, Self::Error> {
if !self.codec.can_encode_value(input) {
return Err(TranscodeError::domain(
CodecEncodeError::unencodable_value(0),
));
}
let units = C::MAX_ENCODE_RESET_UNITS
.checked_add(self.codec.encode_len(input).get())
.ok_or_else(TranscodeError::output_length_overflow)?;
let mut output = Vec::with_capacity(units);
output.resize_with(units, C::Unit::default);
let written =
self.codec.encode_value_with_reset(input, &mut output, 0)?;
output.truncate(written);
Ok(output)
}
}