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.

§Examples

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.

§Errors

Returns CapacityError when a component bound or their sum overflows usize.

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.

§Errors

Returns CapacityError when a component bound or their sum overflows usize.

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.

§Errors

Returns CapacityError when a component bound or their sum overflows usize.

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.

§Errors

Returns CapacityError when a component bound or their sum overflows usize.

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.

§Parameters
  • input: Source units visible to this call.
  • input_index: Starting index in input.
  • output: Destination for target units.
  • output_index: Starting index in output.
§Returns

Consumed source units, written target units, and the stopping reason.

§Errors

Returns an error for invalid indices, a missing reset, a finished or poisoned stream, or codec/hook conversion failure.

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.

§Panics

Panics if codec/hook lifecycle output exceeds its declared capacity bound.

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

Source codec failures retained in conversion errors.

Source§

type EncodeError = <E as Codec>::EncodeError

Target codec failures retained in conversion errors.

Source§

type Value = <D as Codec>::Value

Shared logical value transferred between the two codecs.

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§

type Input = <D as Codec>::Unit

Source representation units accepted by the decoder.

Source§

type Output = <E as Codec>::Unit

Target representation units emitted by the encoder.

Source§

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

Source, target, contract, and capacity failures in the pipeline.

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.

§Parameters
  • input_len: Number of source units to include in capacity planning.
§Returns

The target-unit capacity bound, including the applicable retained state.

§Errors

Returns CapacityError when a component bound or their sum overflows usize.

Source§

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

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

§Returns

The target-unit capacity bound, including the applicable retained state.

§Errors

Returns CapacityError when a component bound or their sum overflows usize.

Source§

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

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

§Returns

The target-unit capacity bound, including the applicable retained state.

§Errors

Returns CapacityError when a component bound or their sum overflows usize.

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.

§Parameters
  • output: Destination for lifecycle output units.
  • output_index: Starting index in output.
§Returns

The number of lifecycle output units written.

§Errors

Returns the engine error for invalid indices, insufficient capacity, an invalid lifecycle transition, or codec/hook failure. See the inherent TranscodeConvertEngine::reset method for retry and poisoning semantics.

§Panics

Panics if a codec/hook output bound fails to reserve enough space for emitted values.

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.

§Parameters
  • input: Source units visible to this call.
  • input_index: Starting index in input.
  • output: Destination for target units.
  • output_index: Starting index in output.
§Returns

Consumed source units, written target units, and the stopping reason.

§Errors

Returns an error for invalid indices, a missing reset, a finished or poisoned stream, or codec/hook conversion failure.

Source§

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

Transcodes an input segment while marking it as the end of the stream.

This forwarding implementation delegates to the engine’s EOF-aware operation so the decoder can resolve trailing input using EOF rules. Call finish separately to drain retained lifecycle output.

§Parameters
  • input: Source units visible to this call.
  • input_index: Starting index in input.
  • output: Destination for target units.
  • output_index: Starting index in output.
§Returns

Consumed source units, written target units, and the stopping reason.

§Errors

Returns an error for invalid indices, a missing reset, a finished or poisoned stream, or codec/hook conversion failure.

Source§

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

Finishes retained converter output after EOF.

§Parameters
  • output: Destination for lifecycle output units.
  • output_index: Starting index in output.
§Returns

The number of lifecycle output units written.

§Errors

Returns the engine error for invalid indices, insufficient capacity, an invalid lifecycle transition, or codec/hook failure. See the inherent TranscodeConvertEngine::finish method for retry and poisoning semantics.

§Panics

Panics if a codec/hook output bound fails to reserve enough space for emitted values.

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 TranscodeDecodeEngine<D, DH>: Freeze, TranscodeEncodeEngine<E, EH>: Freeze, PendingValueSlot<<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 TranscodeDecodeEngine<D, DH>: Send, TranscodeEncodeEngine<E, EH>: Send, PendingValueSlot<<D as Codec>::Value>: Send,

§

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

§

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

§

impl<D, E, DH, EH> UnsafeUnpin for TranscodeConvertEngine<D, E, DH, EH>
where TranscodeDecodeEngine<D, DH>: UnsafeUnpin, TranscodeEncodeEngine<E, EH>: UnsafeUnpin, PendingValueSlot<<D as Codec>::Value>: UnsafeUnpin,

§

impl<D, E, DH, EH> UnwindSafe for TranscodeConvertEngine<D, E, DH, EH>
where TranscodeDecodeEngine<D, DH>: UnwindSafe, TranscodeEncodeEngine<E, EH>: UnwindSafe, PendingValueSlot<<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 = !

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

fn try_from(value: U) -> Result<T, !>

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.