use core::num::NonZeroUsize;
use super::super::encode_context::EncodeContext;
use super::super::engine::TranscodeEncodeHooks;
use crate::{
Codec,
CodecEncodeError,
EncodeOutcome,
};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub(in crate::transcode) struct CodecTranscodeEncodeHooks;
impl<C> TranscodeEncodeHooks<C> for CodecTranscodeEncodeHooks
where
C: Codec,
{
type Error = CodecEncodeError<C::EncodeError>;
#[inline(always)]
fn encode_value(
&mut self,
codec: &mut C,
context: EncodeContext<'_, C::Value, C::Unit>,
) -> Result<EncodeOutcome, Self::Error> {
if !codec.can_encode_value(context.input_value()) {
return Err(CodecEncodeError::unencodable_value(
context.input_index(),
));
}
let required = if C::MIN_UNITS_PER_VALUE == C::MAX_UNITS_PER_VALUE {
C::MAX_UNITS_PER_VALUE
} else {
codec.encode_len(context.input_value())
};
if context.available_output() < required.get() {
return Ok(EncodeOutcome::need_output(required));
}
let (value, input_index, output, output_index) = context.into_parts();
unsafe { codec.encode(value, output, output_index) }
.map(NonZeroUsize::get)
.map(EncodeOutcome::consumed)
.map_err(|error| CodecEncodeError::encode(error, input_index))
}
}