pub struct BufferedDecodeEngine<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_unchecked, 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::BufferedDecodeHooks, allowing a policy to request more input,
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; hooks should convert that error into
crate::DecodeAction::NeedInput when the stream may continue.
For strict decoding that wraps codec errors, use
crate::CodecBufferedDecoder. Use BufferedDecodeEngine directly when
invalid input should be repaired, skipped, counted, or otherwise handled by
policy.
§Example
use core::num::NonZeroUsize;
use qubit_codec::{
BufferedDecodeEngine,
BufferedDecodeHooks,
Codec,
DecodeAction,
DecodeContext,
TranscodeStatus,
};
#[derive(Clone, Copy)]
struct ByteCodec;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum ByteDecodeError {
Malformed { consumed: NonZeroUsize },
}
unsafe impl Codec for ByteCodec {
type Value = u8;
type Unit = u8;
type DecodeError = ByteDecodeError;
type EncodeError = core::convert::Infallible;
fn min_units_per_value(&self) -> NonZeroUsize {
NonZeroUsize::MIN
}
fn max_units_per_value(&self) -> NonZeroUsize {
NonZeroUsize::MIN
}
unsafe fn decode_unchecked(
&self,
input: &[u8],
index: usize,
) -> Result<(u8, NonZeroUsize), Self::DecodeError> {
match input[index] {
0xff => Err(ByteDecodeError::Malformed {
consumed: NonZeroUsize::MIN,
}),
value => Ok((value, NonZeroUsize::MIN)),
}
}
unsafe fn encode_unchecked(
&self,
value: &u8,
output: &mut [u8],
index: usize,
) -> Result<usize, Self::EncodeError> {
output[index] = *value;
Ok(1)
}
}
struct ReplacementHooks;
impl BufferedDecodeHooks<ByteCodec> for ReplacementHooks {
type Error = ByteDecodeError;
fn handle_decode_error(
&mut self,
_codec: &ByteCodec,
error: ByteDecodeError,
_context: DecodeContext,
) -> Result<DecodeAction<u8>, Self::Error> {
match error {
ByteDecodeError::Malformed { consumed } => {
Ok(DecodeAction::Emit { value: b'?', consumed })
}
}
}
fn invalid_input_index(
&mut self,
_codec: &ByteCodec,
_index: usize,
_input_len: usize,
) -> Self::Error {
ByteDecodeError::Malformed {
consumed: NonZeroUsize::MIN,
}
}
fn invalid_output_index(
&mut self,
_codec: &ByteCodec,
_index: usize,
_output_len: usize,
) -> Self::Error {
ByteDecodeError::Malformed {
consumed: NonZeroUsize::MIN,
}
}
}
let mut engine = BufferedDecodeEngine::<_, _>::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> BufferedDecodeEngine<C, H>where
C: Codec,
H: BufferedDecodeHooks<C>,
impl<C, H> BufferedDecodeEngine<C, H>where
C: Codec,
H: BufferedDecodeHooks<C>,
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) -> usize
pub fn max_finish_output_len(&self) -> usize
Returns the maximum values emitted by finishing hook-owned state.
§Returns
Returns the hook-provided final output bound.
Sourcepub fn transcode(
&mut self,
input: &[C::Unit],
input_index: usize,
output: &mut [C::Value],
output_index: usize,
) -> Result<TranscodeProgress, H::Error>
pub fn transcode( &mut self, input: &[C::Unit], input_index: usize, output: &mut [C::Value], output_index: usize, ) -> Result<TranscodeProgress, H::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, FinishError<H::Error>>
pub fn finish( &mut self, output: &mut [C::Value], output_index: usize, ) -> Result<usize, FinishError<H::Error>>
Finishes hook-owned output after EOF.
The engine owns no final output state itself. Hook implementations may
finish their own retained state and emit final output after the caller
has handled any incomplete input tail. The caller must provide enough
output capacity for BufferedDecodeEngine::max_finish_output_len.
§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 FinishError when the caller provides invalid or insufficient
output capacity, or when hook finalization fails.
§Panics
Panics when the hook writes or reports more final output values than
BufferedDecodeEngine::max_finish_output_len declared.
Trait Implementations§
Source§impl<C: Clone, H: Clone> Clone for BufferedDecodeEngine<C, H>
impl<C: Clone, H: Clone> Clone for BufferedDecodeEngine<C, H>
Source§fn clone(&self) -> BufferedDecodeEngine<C, H>
fn clone(&self) -> BufferedDecodeEngine<C, H>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<C: Default, H: Default> Default for BufferedDecodeEngine<C, H>
impl<C: Default, H: Default> Default for BufferedDecodeEngine<C, H>
Source§fn default() -> BufferedDecodeEngine<C, H>
fn default() -> BufferedDecodeEngine<C, H>
impl<C: Eq, H: Eq> Eq for BufferedDecodeEngine<C, H>
Source§impl<C: PartialEq, H: PartialEq> PartialEq for BufferedDecodeEngine<C, H>
impl<C: PartialEq, H: PartialEq> PartialEq for BufferedDecodeEngine<C, H>
Source§fn eq(&self, other: &BufferedDecodeEngine<C, H>) -> bool
fn eq(&self, other: &BufferedDecodeEngine<C, H>) -> bool
self and other values to be equal, and is used by ==.