Skip to main content

BufferedDecodeEngine

Struct BufferedDecodeEngine 

Source
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>,

Source

pub const 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.

Source

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

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

§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) -> usize

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

§Returns

Returns the hook-provided final output bound.

Source

pub fn reset(&mut self)

Resets hook-owned state.

§Parameters
  • self: Decoder instance whose hook state is reset.
§Returns

Returns unit ().

Source

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.

Source

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>

Source§

fn clone(&self) -> BufferedDecodeEngine<C, H>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<C: Debug, H: Debug> Debug for BufferedDecodeEngine<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 BufferedDecodeEngine<C, H>

Source§

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

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

impl<C: Eq, H: Eq> Eq for BufferedDecodeEngine<C, H>

Source§

impl<C: Hash, H: Hash> Hash for BufferedDecodeEngine<C, H>

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<C: PartialEq, H: PartialEq> PartialEq for BufferedDecodeEngine<C, H>

Source§

fn eq(&self, other: &BufferedDecodeEngine<C, H>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<C, H> StructuralPartialEq for BufferedDecodeEngine<C, H>

Auto Trait Implementations§

§

impl<C, H> Freeze for BufferedDecodeEngine<C, H>
where C: Freeze, H: Freeze,

§

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

§

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

§

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

§

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

§

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

§

impl<C, H> UnwindSafe for BufferedDecodeEngine<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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.