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::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,
DecodeFailure,
CodecDecodeError,
DecodeInvalidAction,
DecodeContext,
TranscodeStatus,
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: NonZeroUsize = NonZeroUsize::MIN;
const MAX_UNITS_PER_VALUE: NonZeroUsize = NonZeroUsize::MIN;
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<NonZeroUsize, Self::EncodeError> {
output[index] = *value;
Ok(NonZeroUsize::MIN)
}
}
struct ReplacementHooks;
impl TranscodeDecodeHooks<ByteCodec> for ReplacementHooks {
type Error = CodecDecodeError<ByteDecodeError>;
fn handle_invalid_decode(
&mut self,
_codec: &mut ByteCodec,
error: ByteDecodeError,
consumed: Option<NonZeroUsize>,
_context: DecodeContext,
) -> Result<DecodeInvalidAction<u8>, Self::Error> {
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 progress = engine.transcode(&input, 0, &mut output, 0)?;
match progress.status() {
TranscodeStatus::Complete => assert_eq!(&output[..progress.written()], b"a?b"),
TranscodeStatus::NeedInput { input_index, .. } => {
// Keep `input[input_index..]`, append more source units, and resume.
}
TranscodeStatus::NeedOutput { output_index, .. } => {
// Drain `output[..output_index]`, 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>,
impl<C, H> TranscodeDecodeEngine<C, H>where
C: Codec,
H: TranscodeDecodeHooks<C>,
Sourcepub fn new(codec: C, hooks: H) -> Self
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.
§Panics
In debug builds, panics when the supplied codec violates the
Codec::MIN_UNITS_PER_VALUE / Codec::MAX_UNITS_PER_VALUE ordering
invariant. Release builds skip this check because the invariant is the
responsibility of the Codec implementation.
Sourcepub fn max_output_len(&self, input_len: usize) -> Result<usize, CapacityError>
pub fn max_output_len(&self, input_len: usize) -> Result<usize, CapacityError>
Sourcepub fn max_finish_output_len(&self) -> Result<usize, CapacityError>
pub fn max_finish_output_len(&self) -> Result<usize, CapacityError>
Returns the maximum values emitted by flushing codec state and finishing hook-owned state.
§Returns
Returns the sum of Codec::MAX_DECODE_FLUSH_VALUES and the
hook-provided final-output bound. The codec flush portion covers values
written by Codec::decode_flush; hook implementations must not
include that portion in
TranscodeDecodeHooks::max_finish_output_len.
Sourcepub fn max_reset_output_len(&self) -> Result<usize, CapacityError>
pub fn max_reset_output_len(&self) -> Result<usize, CapacityError>
Returns the maximum values emitted when resetting stream state.
Returns Codec::MAX_DECODE_RESET_VALUES for the wrapped codec.
Stateless decoders always return 0.
Sourcepub fn reset(
&mut self,
output: &mut [C::Value],
output_index: usize,
) -> Result<usize, TranscodeError<TranscodeDecodeEngineError<<C as Codec>::DecodeError, <H as TranscodeDecodeHooks<C>>::Error>>>
pub fn reset( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeError<TranscodeDecodeEngineError<<C as Codec>::DecodeError, <H as TranscodeDecodeHooks<C>>::Error>>>
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.
Sourcepub fn transcode(
&mut self,
input: &[C::Unit],
input_index: usize,
output: &mut [C::Value],
output_index: usize,
) -> Result<TranscodeProgress, TranscodeError<TranscodeDecodeEngineError<<C as Codec>::DecodeError, <H as TranscodeDecodeHooks<C>>::Error>>>
pub fn transcode( &mut self, input: &[C::Unit], input_index: usize, output: &mut [C::Value], output_index: usize, ) -> Result<TranscodeProgress, TranscodeError<TranscodeDecodeEngineError<<C as Codec>::DecodeError, <H as TranscodeDecodeHooks<C>>::Error>>>
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.
Sourcepub fn finish(
&mut self,
output: &mut [C::Value],
output_index: usize,
) -> Result<usize, TranscodeError<TranscodeDecodeEngineError<<C as Codec>::DecodeError, <H as TranscodeDecodeHooks<C>>::Error>>>
pub fn finish( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeError<TranscodeDecodeEngineError<<C as Codec>::DecodeError, <H as TranscodeDecodeHooks<C>>::Error>>>
Finishes codec and hook-owned output after EOF.
Finalization first flushes decode-side codec state through
Codec::decode_flush, 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 flush 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 flush or hook finalization fails.
§Panics
Panics when the codec flush writes beyond
Codec::MAX_DECODE_FLUSH_VALUES or when the combined codec and hook
finalization writes beyond
TranscodeDecodeEngine::max_finish_output_len.
Trait Implementations§
Source§impl<C: Default, H: Default> Default for TranscodeDecodeEngine<C, H>
impl<C: Default, H: Default> Default for TranscodeDecodeEngine<C, H>
Source§fn default() -> TranscodeDecodeEngine<C, H>
fn default() -> TranscodeDecodeEngine<C, H>
Source§impl<C, H> Transcoder<<C as Codec>::Unit, <C as Codec>::Value> for TranscodeDecodeEngine<C, H>where
C: Codec,
H: TranscodeDecodeHooks<C>,
impl<C, H> Transcoder<<C as Codec>::Unit, <C as Codec>::Value> for TranscodeDecodeEngine<C, H>where
C: Codec,
H: TranscodeDecodeHooks<C>,
Source§fn max_output_len(&self, input_len: usize) -> Result<usize, CapacityError>
fn max_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>
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>
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, TranscodeError<Self::Error>>
fn reset( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeError<Self::Error>>
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, TranscodeError<Self::Error>>
fn transcode( &mut self, input: &[C::Unit], input_index: usize, output: &mut [C::Value], output_index: usize, ) -> Result<TranscodeProgress, TranscodeError<Self::Error>>
Decodes source units into logical values.
Source§fn finish(
&mut self,
output: &mut [C::Value],
output_index: usize,
) -> Result<usize, TranscodeError<Self::Error>>
fn finish( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, TranscodeError<Self::Error>>
Finishes internally retained output after EOF.