use core::num::NonZeroUsize;
use super::super::engine::TranscodeEncodeHooks;
use super::super::{
encode_context::EncodeContext,
encode_plan::EncodePlan,
};
use crate::{
Codec,
CodecEncodeError,
};
#[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>;
type PlanAction = ();
#[inline(always)]
fn prepare_encode(
&mut self,
codec: &mut C,
input_value: &C::Value,
input_index: usize,
) -> Result<EncodePlan<Self::PlanAction>, Self::Error> {
if !codec.can_encode_value(input_value) {
return Err(CodecEncodeError::unencodable_value(input_index));
}
Ok(EncodePlan::new(codec.encode_len(input_value).get(), ()))
}
#[inline(always)]
unsafe fn write_encode(
&mut self,
codec: &mut C,
context: EncodeContext<'_, C::Value, C::Unit>,
_plan: EncodePlan<Self::PlanAction>,
) -> Result<usize, Self::Error> {
unsafe {
codec.encode(
context.input_value,
context.output,
context.output_index,
)
}
.map(NonZeroUsize::get)
.map_err(|error| CodecEncodeError::encode(error, context.input_index))
}
#[inline(always)]
fn map_encode_reset_error(
&mut self,
_codec: &mut C,
error: C::EncodeError,
) -> Self::Error {
CodecEncodeError::encode(error, 0)
}
}