Skip to main content

TranscodeConvertEngine

Struct TranscodeConvertEngine 

Source
pub struct TranscodeConvertEngine<D, E, DH, EH>
where D: Codec, E: Codec<Value = D::Value>, DH: TranscodeDecodeHooks<D>, EH: TranscodeEncodeHooks<E>,
{ /* private fields */ }
Expand description

Reusable buffered conversion engine for codec-backed converters.

The engine owns reusable buffered decode and encode engines. It keeps common converter control flow private: index validation, pending-value retention, finish draining, decode-error policy dispatch, encode attempts, output-capacity checks, and crate::TranscodeStatus reporting.

Use this type to build a streaming converter over two one-value Codec implementations that share the same logical value type. Each hot-path step decodes one source unit sequence into a value, then immediately tries to encode that value into the target output buffer. If the target buffer lacks capacity, the decoded value is retained in an internal pending slot and must be drained before more source input is consumed, preserving output order across buffer turns.

TranscodeConvertEngine is intentionally batch-oriented. Its public Self::transcode method drives a source/output buffer loop and reuses the same unchecked codec and hook primitives as crate::engine::TranscodeDecodeEngine and crate::engine::TranscodeEncodeEngine. It does not call one-value public transcoders in the hot path.

For strict codec-backed conversion with default decode and encode policies, use crate::CodecTranscodeConverter. Use TranscodeConvertEngine directly when either side needs custom malformed-input repair, encode planning, skipped values, or finish-time output.

The engine follows the same lifecycle as crate::Transcoder: reset → transcode* → finish → reset. Call Self::reset before starting a new logical stream and Self::finish after EOF once any incomplete source tail has been handled.

§Example

use core::{
    convert::Infallible,
    num::NonZeroUsize,
};
use qubit_codec::{
    Codec,
    TranscodeDecodeErrorOf,
    TranscodeEncodeErrorOf,
    DecodeFailure,
    TranscodeStatus,
};
use qubit_codec::engine::{
    DecodeContext,
    EncodeContext,
    EncodeUnencodableAction,
    TranscodeConvertEngine,
    TranscodeDecodeHooks,
    TranscodeEncodeHooks,
};

#[derive(Clone, Copy)]
struct SourceCodec;

#[derive(Clone, Copy)]
struct TargetCodec;

impl Codec for SourceCodec {
    type Value = u8;
    type Unit = u8;
    type DecodeError = Infallible;
    type EncodeError = Infallible;

    const MIN_UNITS_PER_VALUE: usize = 1;
    const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
    const MAX_DECODE_UNITS_PER_VALUE: usize = 1;

    unsafe fn decode(
        &mut self,
        input: &[u8],
        index: usize,
    ) -> Result<(u8, NonZeroUsize), DecodeFailure<Self::DecodeError>> {
        Ok((input[index].wrapping_add(1), NonZeroUsize::MIN))
    }

    unsafe fn encode(
        &mut self,
        value: &u8,
        output: &mut [u8],
        index: usize,
    ) -> Result<usize, Self::EncodeError> {
        output[index] = *value;
        Ok(1)
    }
}

impl Codec for TargetCodec {
    type Value = u8;
    type Unit = u8;
    type DecodeError = Infallible;
    type EncodeError = Infallible;

    const MIN_UNITS_PER_VALUE: usize = 1;
    const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
    const MAX_DECODE_UNITS_PER_VALUE: usize = 1;

    unsafe fn decode(
        &mut self,
        input: &[u8],
        index: usize,
    ) -> Result<(u8, NonZeroUsize), DecodeFailure<Self::DecodeError>> {
        Ok((input[index], NonZeroUsize::MIN))
    }

    unsafe fn encode(
        &mut self,
        value: &u8,
        output: &mut [u8],
        index: usize,
    ) -> Result<usize, Self::EncodeError> {
        output[index] = *value;
        Ok(1)
    }
}

struct StrictDecodeHooks;

impl TranscodeDecodeHooks<SourceCodec> for StrictDecodeHooks {
    fn handle_invalid_decode(
        &mut self,
        _codec: &mut SourceCodec,
        error: &Infallible,
        _consumed: Option<NonZeroUsize>,
        _context: DecodeContext,
    ) -> Result<qubit_codec::engine::DecodeInvalidAction<u8>, TranscodeDecodeErrorOf<SourceCodec>> {
        match *error {}
    }
}

struct StrictEncodeHooks;

impl TranscodeEncodeHooks<TargetCodec> for StrictEncodeHooks {
    fn handle_unencodable_encode(
        &mut self,
        _codec: &mut TargetCodec,
        _context: &EncodeContext<'_, u8>,
    ) -> Result<EncodeUnencodableAction<u8>, TranscodeEncodeErrorOf<TargetCodec>> {
        unreachable!("TargetCodec accepts every u8")
    }
}

let mut engine = TranscodeConvertEngine::new(
    SourceCodec,
    TargetCodec,
    StrictDecodeHooks,
    StrictEncodeHooks,
);
let input = [1_u8, 2, 3];
let mut output = [0_u8; 2];
let mut reset_output = [];
engine.reset(&mut reset_output, 0)?;

let progress = engine.transcode(&input, 0, &mut output, 0)?;
match progress.status() {
    TranscodeStatus::NeedOutput { .. } => {
        assert_eq!(2, progress.written());
        assert_eq!([2, 3], output);
        // Drain `output[..progress.written()]`, then resume at
        // `progress.read()` with fresh output capacity.
    }
    TranscodeStatus::Complete => unreachable!("output is intentionally short"),
    TranscodeStatus::NeedInput { .. } => unreachable!("input is complete"),
}

§Type Parameters

  • D: Source-side decoder codec.
  • E: Target-side encoder codec.
  • DH: Source-side decode hooks.
  • EH: Target-side encode hooks.

Implementations§

Source§

impl<D, E, DH, EH> TranscodeConvertEngine<D, E, DH, EH>
where D: Codec, E: Codec<Value = D::Value>, DH: TranscodeDecodeHooks<D>, EH: TranscodeEncodeHooks<E>,

Source

pub fn new(decoder: D, encoder: E, decode_hooks: DH, encode_hooks: EH) -> Self

Creates a buffered converter engine.

The caller supplies decode hooks and encode hooks directly.

§Parameters
  • decoder: Low-level codec used for source decoding.
  • encoder: Low-level codec used for target encoding.
  • decode_hooks: Decode-side policy hooks.
  • encode_hooks: Encode-side policy hooks.
§Returns

Returns a buffered converter engine.

§Compile-Time Checks

Fails to compile when either codec declares a zero decode unit bound or when Codec::MIN_UNITS_PER_VALUE exceeds Codec::MAX_DECODE_UNITS_PER_VALUE.

Source

pub fn source_codec(&self) -> &D

Returns the source-side codec.

§Returns

Returns a shared reference to the decoder codec owned by this engine.

Source

pub fn source_codec_mut(&mut self) -> &mut D

Returns the source-side codec mutably.

§Returns

Returns a mutable reference to the decoder codec owned by this engine.

Source

pub fn target_codec(&self) -> &E

Returns the target-side codec.

§Returns

Returns a shared reference to the encoder codec owned by this engine.

Source

pub fn target_codec_mut(&mut self) -> &mut E

Returns the target-side codec mutably.

§Returns

Returns a mutable reference to the encoder codec owned by this engine.

Source

pub const fn decode_hooks(&self) -> &DH

Returns the decode hooks used by this engine.

§Returns

Returns a shared reference to the decode hooks owned by this engine.

Source

pub fn decode_hooks_mut(&mut self) -> &mut DH

Returns the decode hooks mutably.

Mutating the returned hooks does not reset the converter or clear a pending value. The replacement hooks must continue to satisfy their global output-capacity contract for every reachable converter state.

§Returns

Returns a mutable reference to the decode hooks owned by this engine.

Source

pub const fn encode_hooks(&self) -> &EH

Returns the encode hooks used by this engine.

§Returns

Returns a shared reference to the encode hooks owned by this engine.

Source

pub fn encode_hooks_mut(&mut self) -> &mut EH

Returns the encode hooks mutably.

Mutating the returned hooks does not reset the converter or clear a pending value. The replacement hooks must continue to satisfy their global output-capacity contract for every reachable converter state.

§Returns

Returns a mutable reference to the encode hooks owned by this engine.

Source

pub fn into_parts(self) -> (D, E, DH, EH)

Consumes the engine and returns its codecs and hooks.

Any pending value and lifecycle state owned by the converter are discarded. Callers should use this only when no further conversion state needs to be preserved.

§Returns

Returns the source codec, target codec, decode hooks, and encode hooks.

Source

pub fn max_transcode_output_len( &self, input_len: usize, ) -> Result<usize, CapacityError>

Returns an upper bound for target units produced from input_len units.

The bound sums three parts: one possible retained pending value, the maximum decoded values from the source side, and the maximum target units for those values on the encode side. It covers only the streaming convert phase and remains valid even when no value is currently pending. Downstream converters must use this engine-level API for capacity planning instead of recomputing the bound from the source or target Codec constants.

§Parameters
  • input_len: Number of source units the caller plans to convert.
§Returns

Returns a conservative upper bound, or a capacity error on arithmetic overflow.

Source

pub fn max_reset_output_len(&self) -> Result<usize, CapacityError>

Returns the global maximum target units emitted when resetting stream state.

Covers decode-side reset values (encoded to target units) plus encode-side reset units. Most codecs are stateless and return 0 for Codec::MAX_DECODE_RESET_VALUES; in that case this equals the encode reset bound only.

§Returns

Returns the combined decode-reset and encode-reset output bound, or a capacity error on arithmetic overflow.

Source

pub fn max_finish_output_len(&self) -> Result<usize, CapacityError>

Returns the maximum target units emitted by finishing retained state.

The bound covers one possible retained pending value, the global decode-side finish-value bound (encoded to target units), and the global encode-side finish-unit bound. It is independent of whether a pending value currently exists.

§Returns

Returns the combined pending, decode-finish, and encode-finish output bound, or a capacity error on arithmetic overflow.

Source

pub fn max_total_output_len( &self, input_len: usize, ) -> Result<usize, CapacityError>

Returns the maximum target units needed by a complete one-shot conversion.

The returned bound covers conversion reset output, the streaming convert phase for input_len source units, and finish output. Its components are global across transient state. Higher-level complete conversion helpers should use this engine-level bound instead of recomputing capacity from the source or target codec constants, because decode and encode hooks may change streaming or finish output.

§Parameters
  • input_len: Number of source units in the complete stream.
§Returns

Returns the complete-stream target-output bound, or a capacity error on arithmetic overflow.

Source

pub fn reset( &mut self, output: &mut [E::Unit], output_index: usize, ) -> Result<usize, TranscodeConvertErrorOf<D, E>>
where D::Value: Default,

Clears retained conversion state, runs before-reset hooks, and emits stream-start encode output.

Reset clears any retained pending value, resets the target encoder, then drains decode-side reset values through that reset encoder state. The caller must provide enough output capacity for Self::max_reset_output_len.

§Parameters
  • output: Complete output unit slice visible to the converter.
  • output_index: Absolute output index where writing starts.
§Returns

Returns the number of target units written while resetting stream state.

§Errors

Returns a converter error if reset validation or target reset output emission fails. Capacity and index failures occur before converter state is changed. Once reset execution starts, an error poisons the converter until a later reset succeeds.

§Panics

Panics when decode-reset values cannot be encoded within the capacity reserved by Self::max_reset_output_len.

Source

pub fn transcode( &mut self, input: &[D::Unit], input_index: usize, output: &mut [E::Unit], output_index: usize, ) -> Result<TranscodeProgress, TranscodeConvertErrorOf<D, E>>

Converts source units into target units.

The engine drains any retained pending value before consuming new input. Each loop iteration decodes one source value and immediately attempts to encode it. Conversion stops when the input tail is incomplete, when the output buffer cannot hold the next encoded value, or when the visible input is exhausted.

§Parameters
  • input: Complete input unit slice visible to the converter.
  • input_index: Absolute input index where conversion starts.
  • output: Complete output unit slice visible to the converter.
  • output_index: Absolute output index where writing starts.
§Returns

Returns conversion progress describing input units consumed, target units written, and why conversion stopped.

§Errors

Returns hook errors when indices are invalid or concrete conversion fails. Invalid output indices are reported through the encode-side error path. Returns TranscodeFailure::TranscodeBeforeReset when the engine has not completed its first reset. Returns TranscodeFailure::TranscodeAfterFinish when the logical stream was already finished and has not been reset, or TranscodeFailure::LifecyclePoisoned when an earlier reset or finish failed after execution started.

Source

pub fn transcode_eof( &mut self, input: &[D::Unit], input_index: usize, output: &mut [E::Unit], output_index: usize, ) -> Result<TranscodeProgress, TranscodeConvertErrorOf<D, E>>

Converts source units after the caller has established end of input.

Source

pub fn finish( &mut self, output: &mut [E::Unit], output_index: usize, ) -> Result<usize, TranscodeConvertErrorOf<D, E>>
where D::Value: Default,

Finishes retained output after EOF.

Finalization drains a pending decoded value first, then lets the source-side decode hooks emit final values, encodes those values through the target-side encode hooks, and finally finishes target-side encode hook state. The decode-finish value buffer used for this cold path requires D::Value: Default; the normal Self::transcode loop does not.

§Parameters
  • output: Complete output unit slice visible to the converter.
  • output_index: Absolute output index where writing starts.
§Returns

Returns the number of target units written during finalization.

§Errors

Returns a converter error when output capacity checks fail or when hook finalization fails. Returns TranscodeFailure::FinishBeforeReset when the engine has not completed its first reset. Returns TranscodeFailure::FinishAfterFinish when the logical stream was already finished and has not been reset, or TranscodeFailure::LifecyclePoisoned when an earlier reset or finish failed after execution started. Capacity and index failures occur before finish execution and remain retryable; later failures poison the converter until reset succeeds.

§Panics

Panics when a retained pending value or decode-finish value cannot be encoded within the planned finish capacity.

Source

pub fn transcode_complete_into( &mut self, input: &[D::Unit], output: &mut [E::Unit], ) -> Result<usize, TranscodeConvertErrorOf<D, E>>
where D::Value: Default,

Runs a complete one-shot reset -> transcode -> finish conversion.

The complete input is supplied as input, and output starts at index 0 in output. Callers that need subranges should slice their buffers before calling this method. Downstream one-shot converter helpers should call this engine method instead of reproducing the reset, transcode, and finish sequence themselves.

§Parameters
  • input: Complete source unit slice.
  • output: Target unit slice for the whole converted stream.
§Returns

Returns the number of target units written.

§Errors

Returns framework errors for insufficient output, capacity overflow, or an incomplete EOF tail, and domain errors from reset, conversion, or finish.

Trait Implementations§

Source§

impl<D, E, DH, EH> Debug for TranscodeConvertEngine<D, E, DH, EH>
where D: Codec + Debug, E: Codec<Value = D::Value> + Debug, DH: TranscodeDecodeHooks<D> + Debug, EH: TranscodeEncodeHooks<E> + Debug, D::Value: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<D, E, DH, EH> Default for TranscodeConvertEngine<D, E, DH, EH>
where D: Codec + Default, E: Codec<Value = D::Value> + Default, DH: TranscodeDecodeHooks<D> + Default, EH: TranscodeEncodeHooks<E> + Default,

Source§

fn default() -> Self

Creates a default buffered converter engine.

§Returns

Returns a converter engine constructed from default codecs and hooks.

Source§

impl<D, E, DH, EH> TranscodeConverter for TranscodeConvertEngine<D, E, DH, EH>
where D: Codec, E: Codec<Value = D::Value>, D::Value: Default, DH: TranscodeDecodeHooks<D>, EH: TranscodeEncodeHooks<E>,

Source§

type DecodeError = <D as Codec>::DecodeError

Domain error type produced by source decoding.
Source§

type EncodeError = <E as Codec>::EncodeError

Domain error type produced by target encoding.
Source§

type Value = <D as Codec>::Value

Intermediate logical value type converted between source and target.
Source§

impl<D, E, DH, EH> Transcoder for TranscodeConvertEngine<D, E, DH, EH>
where D: Codec, E: Codec<Value = D::Value>, D::Value: Default, DH: TranscodeDecodeHooks<D>, EH: TranscodeEncodeHooks<E>,

Source§

fn max_transcode_output_len( &self, input_len: usize, ) -> Result<usize, CapacityError>

Returns an upper bound for target units produced from input_len units.

Source§

fn max_finish_output_len(&self) -> Result<usize, CapacityError>

Returns an upper bound for target units emitted by finishing retained state.

Source§

fn max_reset_output_len(&self) -> Result<usize, CapacityError>

Returns an upper bound for target units emitted when resetting stream state.

Source§

fn reset( &mut self, output: &mut [E::Unit], output_index: usize, ) -> Result<usize, TranscodeConvertErrorOf<D, E>>

Clears retained conversion state and emits target reset output.

Source§

fn transcode( &mut self, input: &[D::Unit], input_index: usize, output: &mut [E::Unit], output_index: usize, ) -> Result<TranscodeProgress, TranscodeConvertErrorOf<D, E>>

Converts source units into target units.

Source§

fn finish( &mut self, output: &mut [E::Unit], output_index: usize, ) -> Result<usize, TranscodeConvertErrorOf<D, E>>

Finishes retained converter output after EOF.

Source§

type Input = <D as Codec>::Unit

Input unit type accepted by this transcoder.
Source§

type Output = <E as Codec>::Unit

Output unit type produced by this transcoder.
Source§

type Error = TranscodeConvertError<<D as Codec>::DecodeError, <E as Codec>::EncodeError, <D as Codec>::Value>

Complete error type produced by this transcoder.
Source§

fn transcode_eof( &mut self, input: &[D::Unit], input_index: usize, output: &mut [E::Unit], output_index: usize, ) -> Result<TranscodeProgress, TranscodeConvertErrorOf<D, E>>

Converts source units after the caller has established end of input. Read more
Source§

fn max_total_output_len(&self, input_len: usize) -> Result<usize, CapacityError>

Returns an upper bound for a complete reset -> transcode -> finish stream. Read more
Source§

fn transcode_complete_into( &mut self, input: &[Self::Input], output: &mut [Self::Output], ) -> Result<usize, Self::Error>

Runs a complete one-shot reset -> transcode -> finish stream. Read more

Auto Trait Implementations§

§

impl<D, E, DH, EH> Freeze for TranscodeConvertEngine<D, E, DH, EH>
where D: Freeze, DH: Freeze, E: Freeze, EH: Freeze, <D as Codec>::Value: Freeze,

§

impl<D, E, DH, EH> RefUnwindSafe for TranscodeConvertEngine<D, E, DH, EH>

§

impl<D, E, DH, EH> Send for TranscodeConvertEngine<D, E, DH, EH>
where D: Send, DH: Send, E: Send, EH: Send, <D as Codec>::Value: Send,

§

impl<D, E, DH, EH> Sync for TranscodeConvertEngine<D, E, DH, EH>
where D: Sync, DH: Sync, E: Sync, EH: Sync, <D as Codec>::Value: Sync,

§

impl<D, E, DH, EH> Unpin for TranscodeConvertEngine<D, E, DH, EH>
where D: Unpin, DH: Unpin, E: Unpin, EH: Unpin, <D as Codec>::Value: Unpin,

§

impl<D, E, DH, EH> UnsafeUnpin for TranscodeConvertEngine<D, E, DH, EH>

§

impl<D, E, DH, EH> UnwindSafe for TranscodeConvertEngine<D, E, DH, EH>
where D: UnwindSafe, DH: UnwindSafe, E: UnwindSafe, EH: UnwindSafe, <D as Codec>::Value: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.