Skip to main content

TranscodeDecodeEngine

Struct TranscodeDecodeEngine 

Source
pub struct TranscodeDecodeEngine<C, H> { /* private fields */ }
Expand description

Reusable buffered decoding engine for codec-backed decoders.

The engine owns the low-level codec and hook object. It keeps the common buffered decoding loop private: input-index validation, output-capacity checks, calls to Codec::decode, hook dispatch, and crate::TranscodeStatus reporting. Incomplete input tails are left in the caller-provided input slice; callers own input-buffer refill.

Use this type to build a streaming decoder over a one-value Codec. The engine decodes into a caller-provided output slice and returns TranscodeProgress instead of allocating. On success it writes decoded values directly to output. On codec errors it delegates to crate::engine::TranscodeDecodeHooks, allowing a policy to skip invalid units, emit a replacement value, or fail.

The engine stops before reading an incomplete value when fewer than Codec::MIN_UNITS_PER_VALUE units are available. For variable-width codecs, the codec may still return an incomplete decode error after that minimum is satisfied; the engine converts that failure directly into crate::TranscodeStatus::NeedInput.

For strict decoding that wraps codec errors, use crate::CodecTranscodeDecoder. Use TranscodeDecodeEngine directly when invalid input should be repaired, skipped, counted, or otherwise handled by policy.

§Example

use core::num::NonZeroUsize;
use qubit_codec::{
    Codec,
    TranscodeDecodeErrorOf,
    DecodeFailure,
    TranscodeStatus,
};
use qubit_codec::engine::{
    DecodeContext,
    DecodeInvalidAction,
    TranscodeDecodeEngine,
    TranscodeDecodeHooks,
};

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

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum ByteDecodeError {
    Malformed { consumed: NonZeroUsize },
}

impl Codec for ByteCodec {
    type Value = u8;
    type Unit = u8;
    type DecodeError = ByteDecodeError;
    type EncodeError = core::convert::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>> {
        match input[index] {
            0xff => Err(DecodeFailure::invalid(
                ByteDecodeError::Malformed {
                    consumed: NonZeroUsize::MIN,
                },
                NonZeroUsize::MIN,
            )),
            value => Ok((value, NonZeroUsize::MIN)),
        }
    }

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

struct ReplacementHooks;

impl TranscodeDecodeHooks<ByteCodec> for ReplacementHooks {
    fn handle_invalid_decode(
        &mut self,
        _codec: &mut ByteCodec,
        error: &ByteDecodeError,
        consumed: Option<NonZeroUsize>,
        _context: DecodeContext,
    ) -> Result<DecodeInvalidAction<u8>, TranscodeDecodeErrorOf<ByteCodec>> {
        match error {
            ByteDecodeError::Malformed { .. } => {
                Ok(DecodeInvalidAction::Emit {
                    value: b'?',
                    consumed: consumed.expect("codec reported malformed width"),
                })
            }
        }
    }
}

let mut engine = TranscodeDecodeEngine::<_, _>::new(ByteCodec, ReplacementHooks);
let input = [b'a', 0xff, b'b'];
let mut output = [0_u8; 3];
let mut reset_output = [];
engine.reset(&mut reset_output, 0)?;

let progress = engine.transcode(&input, 0, &mut output, 0)?;
match progress.status() {
    TranscodeStatus::Complete => assert_eq!(&output[..progress.written()], b"a?b"),
    TranscodeStatus::NeedInput { .. } => {
        // Keep `input[input_index + progress.read()..]`, append more source
        // units, and resume.
    }
    TranscodeStatus::NeedOutput { .. } => {
        // Drain `output[..progress.written()]`, then resume with more output
        // room.
    }
}

§Type Parameters

  • C: Low-level codec used by the engine.
  • H: Policy hook object used by the engine.

Implementations§

Source§

impl<C, H> TranscodeDecodeEngine<C, H>
where C: Codec, H: TranscodeDecodeHooks<C>,

Source

pub fn new(codec: C, hooks: H) -> Self

Creates a buffered decoder engine.

§Parameters
  • codec: Low-level codec used for one-value decoding.
  • hooks: Policy hooks used for decode failures.
§Returns

Returns a buffered decoder engine.

§Compile-Time Checks

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

Source

pub const fn codec(&self) -> &C

Returns the wrapped low-level codec.

§Returns

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

Source

pub fn codec_mut(&mut self) -> &mut C

Returns the wrapped low-level codec mutably.

§Returns

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

Source

pub const fn hooks(&self) -> &H

Returns the decode hooks used by this engine.

§Returns

Returns a shared reference to the hook object owned by this engine.

Source

pub fn hooks_mut(&mut self) -> &mut H

Returns the decode hooks mutably.

§Returns

Returns a mutable reference to the hook object owned by this engine.

Source

pub fn into_parts(self) -> (C, H)

Consumes the engine and returns its codec and hooks.

Any lifecycle state owned by the engine is discarded.

§Returns

Returns the wrapped codec followed by the decode hooks.

Source

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

Returns an upper bound for decoded values produced from input_len units.

This bound covers only the streaming decode phase. It is delegated to TranscodeDecodeHooks::max_transcode_output_len, so it includes hook policy and is valid for every reachable transient codec and hook state. Downstream decoders must use this engine-level API for capacity planning instead of recomputing the bound from Codec constants.

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

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

Source

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

Returns the global maximum values emitted by finishing codec state and finishing hook-owned state.

§Returns

Returns the sum of Codec::MAX_DECODE_FINISH_VALUES and the hook-provided final-output bound. The codec finish portion covers values written by Codec::decode_finish; hook implementations must not include that portion in TranscodeDecodeHooks::max_finish_output_len. Both component bounds cover every reachable transient state.

Source

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

Returns the global maximum values emitted when resetting stream state.

Returns Codec::MAX_DECODE_RESET_VALUES for the wrapped codec. Stateless decoders always return 0.

Source

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

Returns the maximum values needed by a complete one-shot decode stream.

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

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

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

Source

pub fn reset( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeDecodeErrorOf<C>>

Resets codec decode state, runs reset hooks, and emits stream-start values.

The sequence is: validate capacity → run reset_hooks → call Codec::decode_reset. Stateless decoders (MAX_DECODE_RESET_VALUES == 0) write nothing and return Ok(0).

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

Returns the number of reset values written.

§Errors

Returns framework errors when the caller provides invalid or insufficient output capacity. Returns domain errors when codec reset or hook reset handling fails. Capacity and index failures occur before any reset state is changed. Once reset execution starts, an error poisons the engine until a later reset succeeds.

Source

pub fn transcode( &mut self, input: &[C::Unit], input_index: usize, output: &mut [C::Value], output_index: usize, ) -> Result<TranscodeProgress, TranscodeDecodeErrorOf<C>>

Decodes source units into caller-provided output values.

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

Returns progress describing input units consumed, output values written, and why decoding stopped.

§Errors

Returns hook errors when input_index is outside input, when output_index is outside output, or when a concrete policy hook rejects a value. 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: &[C::Unit], input_index: usize, output: &mut [C::Value], output_index: usize, ) -> Result<TranscodeProgress, TranscodeDecodeErrorOf<C>>

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

This follows the normal streaming contract, except that codec attempts use Codec::decode_eof. A codec may therefore resolve a trailing prefix that would remain incomplete in an open stream.

Source

pub fn finish( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeDecodeErrorOf<C>>

Finishes codec and hook-owned output after EOF.

Finalization first finishes decode-side codec state through Codec::decode_finish, then lets hook implementations finish their own retained state. The caller must provide enough output capacity for TranscodeDecodeEngine::max_finish_output_len, which includes both the codec finish bound and the hook-owned finish bound.

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

Returns the number of values written by finalization.

§Errors

Returns framework errors when the caller provides invalid or insufficient output capacity. Returns domain errors when codec finish or 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 engine until reset succeeds.

§Panics

Panics when the codec finish writes beyond Codec::MAX_DECODE_FINISH_VALUES or when the combined codec and hook finalization writes beyond TranscodeDecodeEngine::max_finish_output_len.

Source

pub fn transcode_complete_into( &mut self, input: &[C::Unit], output: &mut [C::Value], ) -> Result<usize, TranscodeDecodeErrorOf<C>>

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

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 decoder helpers should call this engine method instead of reproducing the reset, transcode, and finish sequence themselves.

§Parameters
  • input: Complete source unit slice.
  • output: Output value slice for the whole decoded stream.
§Returns

Returns the number of output values written.

§Errors

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

Trait Implementations§

Source§

impl<C: Debug, H: Debug> Debug for TranscodeDecodeEngine<C, H>

Source§

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

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

impl<C: Default, H: Default> Default for TranscodeDecodeEngine<C, H>

Source§

fn default() -> TranscodeDecodeEngine<C, H>

Returns the “default value” for a type. Read more
Source§

impl<C, H> TranscodeDecoder for TranscodeDecodeEngine<C, H>
where C: Codec, H: TranscodeDecodeHooks<C>,

Source§

type DecodeError = <C as Codec>::DecodeError

Domain error type produced by decode internals.
Source§

impl<C, H> Transcoder for TranscodeDecodeEngine<C, H>
where C: Codec, H: TranscodeDecodeHooks<C>,

Source§

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

Returns an upper bound for decoded values produced from input_len units.

Source§

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

Returns an upper bound for values produced by finishing codec and hook state.

Source§

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

Returns an upper bound for values emitted when resetting stream state.

Source§

fn reset( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeDecodeErrorOf<C>>

Runs hook-owned cleanup before a logical decoder reset.

Source§

fn transcode( &mut self, input: &[C::Unit], input_index: usize, output: &mut [C::Value], output_index: usize, ) -> Result<TranscodeProgress, TranscodeDecodeErrorOf<C>>

Decodes source units into logical values.

Source§

fn transcode_eof( &mut self, input: &[C::Unit], input_index: usize, output: &mut [C::Value], output_index: usize, ) -> Result<TranscodeProgress, TranscodeDecodeErrorOf<C>>

Decodes source units after end of input is known.

Source§

fn finish( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeDecodeErrorOf<C>>

Finishes internally retained output after EOF.

Source§

type Input = <C as Codec>::Unit

Input unit type accepted by this transcoder.
Source§

type Output = <C as Codec>::Value

Output unit type produced by this transcoder.
Source§

type Error = TranscodeDecodeError<<C as Codec>::DecodeError>

Complete error type produced by this transcoder.
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<C, H> Freeze for TranscodeDecodeEngine<C, H>
where C: Freeze, H: Freeze,

§

impl<C, H> RefUnwindSafe for TranscodeDecodeEngine<C, H>

§

impl<C, H> Send for TranscodeDecodeEngine<C, H>
where C: Send, H: Send,

§

impl<C, H> Sync for TranscodeDecodeEngine<C, H>
where C: Sync, H: Sync,

§

impl<C, H> Unpin for TranscodeDecodeEngine<C, H>
where C: Unpin, H: Unpin,

§

impl<C, H> UnsafeUnpin for TranscodeDecodeEngine<C, H>
where C: UnsafeUnpin, H: UnsafeUnpin,

§

impl<C, H> UnwindSafe for TranscodeDecodeEngine<C, H>
where C: UnwindSafe, H: 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.