use core::fmt;
use super::{
CodecTranscodeDecodeHooks,
CodecTranscodeEncodeHooks,
};
use crate::{
CapacityError,
Codec,
CodecConvertError,
CodecDecodeError,
CodecEncodeError,
TranscodeConvertEngine,
TranscodeConvertEngineError,
TranscodeConverter,
TranscodeDecodeEngineError,
TranscodeEncodeEngineError,
TranscodeError,
TranscodeProgress,
Transcoder,
};
type CodecTranscodeConvertError<D, E> =
CodecConvertError<<D as Codec>::DecodeError, <E as Codec>::EncodeError>;
type CodecTranscodeConvertEngineError<D, E> = TranscodeConvertEngineError<
TranscodeDecodeEngineError<
<D as Codec>::DecodeError,
CodecDecodeError<<D as Codec>::DecodeError>,
>,
TranscodeEncodeEngineError<
<E as Codec>::EncodeError,
CodecEncodeError<<E as Codec>::EncodeError>,
>,
>;
pub struct CodecTranscodeConverter<D, E>
where
D: Codec,
E: Codec<Value = D::Value>,
{
engine: TranscodeConvertEngine<
D,
E,
CodecTranscodeDecodeHooks,
CodecTranscodeEncodeHooks,
>,
}
impl<D, E> fmt::Debug for CodecTranscodeConverter<D, E>
where
D: Codec,
E: Codec<Value = D::Value>,
TranscodeConvertEngine<
D,
E,
CodecTranscodeDecodeHooks,
CodecTranscodeEncodeHooks,
>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CodecTranscodeConverter")
.field("engine", &self.engine)
.finish()
}
}
impl<D, E> CodecTranscodeConverter<D, E>
where
D: Codec,
E: Codec<Value = D::Value>,
{
#[inline(always)]
#[must_use]
pub fn new(decoder: D, encoder: E) -> Self {
Self {
engine: TranscodeConvertEngine::new(
decoder,
encoder,
CodecTranscodeDecodeHooks,
CodecTranscodeEncodeHooks,
),
}
}
#[must_use = "capacity planning can fail on overflow"]
#[inline(always)]
pub fn max_output_len(
&self,
input_len: usize,
) -> Result<usize, CapacityError> {
self.engine.max_output_len(input_len)
}
#[must_use = "capacity planning can fail on overflow"]
#[inline(always)]
pub fn max_finish_output_len(&self) -> Result<usize, CapacityError> {
self.engine.max_finish_output_len()
}
#[must_use = "capacity planning can fail on overflow"]
#[inline(always)]
pub fn max_reset_output_len(&self) -> Result<usize, CapacityError> {
self.engine.max_reset_output_len()
}
#[inline(always)]
pub fn reset(
&mut self,
output: &mut [E::Unit],
output_index: usize,
) -> Result<usize, TranscodeError<CodecTranscodeConvertError<D, E>>>
where
D::Value: Default,
{
self.engine.reset(output, output_index).map_err(|error| {
error.map_domain(flatten_convert_engine_error::<D, E>)
})
}
#[inline(always)]
pub fn transcode(
&mut self,
input: &[D::Unit],
input_index: usize,
output: &mut [E::Unit],
output_index: usize,
) -> Result<
TranscodeProgress,
TranscodeError<CodecTranscodeConvertError<D, E>>,
> {
self.engine
.transcode(input, input_index, output, output_index)
.map_err(|error| {
error.map_domain(flatten_convert_engine_error::<D, E>)
})
}
#[inline(always)]
pub fn finish(
&mut self,
output: &mut [E::Unit],
output_index: usize,
) -> Result<usize, TranscodeError<CodecTranscodeConvertError<D, E>>>
where
D::Value: Default,
{
self.engine.finish(output, output_index).map_err(|error| {
error.map_domain(flatten_convert_engine_error::<D, E>)
})
}
}
impl<D, E> Transcoder<D::Unit, E::Unit> for CodecTranscodeConverter<D, E>
where
D: Codec,
E: Codec<Value = D::Value>,
D::Value: Default,
{
type Error = CodecConvertError<D::DecodeError, E::EncodeError>;
#[inline(always)]
fn max_output_len(&self, input_len: usize) -> Result<usize, CapacityError> {
CodecTranscodeConverter::max_output_len(self, input_len)
}
#[inline(always)]
fn max_finish_output_len(&self) -> Result<usize, CapacityError> {
CodecTranscodeConverter::max_finish_output_len(self)
}
#[inline(always)]
fn max_reset_output_len(&self) -> Result<usize, CapacityError> {
CodecTranscodeConverter::max_reset_output_len(self)
}
#[inline(always)]
fn reset(
&mut self,
output: &mut [E::Unit],
output_index: usize,
) -> Result<usize, TranscodeError<Self::Error>> {
CodecTranscodeConverter::reset(self, output, output_index)
}
#[inline(always)]
fn transcode(
&mut self,
input: &[D::Unit],
input_index: usize,
output: &mut [E::Unit],
output_index: usize,
) -> Result<TranscodeProgress, TranscodeError<Self::Error>> {
CodecTranscodeConverter::transcode(
self,
input,
input_index,
output,
output_index,
)
}
#[inline(always)]
fn finish(
&mut self,
output: &mut [E::Unit],
output_index: usize,
) -> Result<usize, TranscodeError<Self::Error>> {
CodecTranscodeConverter::finish(self, output, output_index)
}
}
impl<D, E> TranscodeConverter<D::Unit, E::Unit>
for CodecTranscodeConverter<D, E>
where
D: Codec,
E: Codec<Value = D::Value>,
D::Value: Default,
{
}
impl<D, E> Default for CodecTranscodeConverter<D, E>
where
D: Codec,
E: Codec<Value = D::Value>,
TranscodeConvertEngine<
D,
E,
CodecTranscodeDecodeHooks,
CodecTranscodeEncodeHooks,
>: Default,
{
#[inline(always)]
fn default() -> Self {
Self {
engine: TranscodeConvertEngine::default(),
}
}
}
#[inline(always)]
fn flatten_convert_engine_error<D, E>(
error: CodecTranscodeConvertEngineError<D, E>,
) -> CodecTranscodeConvertError<D, E>
where
D: Codec,
E: Codec<Value = D::Value>,
{
match error {
TranscodeConvertEngineError::Decode(error) => match error {
TranscodeDecodeEngineError::Codec(error)
| TranscodeDecodeEngineError::Hook(error) => {
CodecConvertError::decode(error)
}
},
TranscodeConvertEngineError::Encode(error) => match error {
TranscodeEncodeEngineError::Codec(error)
| TranscodeEncodeEngineError::Hook(error) => {
CodecConvertError::encode(error)
}
},
}
}