Skip to main content

BufferedEncodeHooks

Trait BufferedEncodeHooks 

Source
pub trait BufferedEncodeHooks<C>
where C: Codec,
{ type Error; type PlanAction; // Required methods fn prepare_encode( &mut self, codec: &C, input_value: &C::Value, input_index: usize, ) -> Result<EncodePlan<Self::PlanAction>, Self::Error>; unsafe fn write_encode( &mut self, codec: &C, context: EncodeContext<'_, C::Value, C::Unit>, plan: EncodePlan<Self::PlanAction>, ) -> Result<usize, Self::Error>; fn invalid_input_index( &mut self, codec: &C, index: usize, input_len: usize, ) -> Self::Error; fn invalid_output_index( &mut self, codec: &C, index: usize, output_len: usize, ) -> Self::Error; // Provided methods fn max_output_len( &self, codec: &C, input_len: usize, ) -> Result<usize, CapacityError> { ... } fn max_finish_output_len(&self, _codec: &C) -> usize { ... } fn finish( &mut self, _codec: &C, _output: &mut [C::Unit], _output_index: usize, ) -> Result<usize, Self::Error> { ... } fn reset(&mut self, _codec: &C) { ... } }
Expand description

Policy hooks for crate::BufferedEncodeEngine.

Hooks own policy state, such as replacement or ignore behavior, but not the codec or engine cursor state. The engine passes the codec into hook methods when policy code needs codec metadata or one-value encode operations.

Implement this trait when a buffered encoder needs policy decisions around individual values while reusing the common engine loop. Examples include rejecting unsupported values with adapter-level context, consuming values without writing output, writing replacement units, or emitting final state in finish.

The engine calls prepare_encode before each value is consumed. The returned EncodePlan states the required output capacity and may carry an action computed by the hook. Only after that capacity is available does the engine call write_encode with the same cursor context and the prepared plan. This split lets the engine stop with crate::TranscodeStatus::NeedOutput without consuming the next input value.

§Example

This hook writes each value with the wrapped codec and uses the codec’s maximum width as the capacity plan.

use core::{
    convert::Infallible,
    num::NonZeroUsize,
};
use qubit_codec::{
    BufferedEncodeHooks,
    Codec,
    CodecEncodeError,
    EncodeContext,
    EncodePlan,
};

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

unsafe impl Codec for ByteCodec {
    type Value = u8;
    type Unit = u8;
    type DecodeError = Infallible;
    type EncodeError = 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> {
        Ok((input[index], NonZeroUsize::MIN))
    }

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

struct StrictHooks;

impl<C> BufferedEncodeHooks<C> for StrictHooks
where
    C: Codec,
{
    type Error = CodecEncodeError<C::EncodeError>;
    type PlanAction = ();

    fn prepare_encode(
        &mut self,
        codec: &C,
        _value: &C::Value,
        _input_index: usize,
    ) -> Result<EncodePlan<()>, Self::Error> {
        Ok(EncodePlan::new(codec.max_units_per_value().get(), ()))
    }

    unsafe fn write_encode(
        &mut self,
        codec: &C,
        context: EncodeContext<'_, C::Value, C::Unit>,
        _plan: EncodePlan<()>,
    ) -> Result<usize, Self::Error> {
        unsafe {
            codec.encode_unchecked(context.input_value, context.output, context.output_index)
        }
        .map_err(|error| CodecEncodeError::encode(error, context.input_index))
    }

    fn invalid_input_index(
        &mut self,
        _codec: &C,
        index: usize,
        input_len: usize,
    ) -> Self::Error {
        CodecEncodeError::invalid_input_index(index, input_len)
    }

    fn invalid_output_index(
        &mut self,
        _codec: &C,
        index: usize,
        output_len: usize,
    ) -> Self::Error {
        CodecEncodeError::invalid_output_index(index, output_len)
    }
}

§Type Parameters

  • C: Low-level codec owned by the engine.

Required Associated Types§

Source

type Error

Error type returned by the buffered encoder.

Source

type PlanAction

Concrete action stored in EncodePlan::action.

Required Methods§

Source

fn prepare_encode( &mut self, codec: &C, input_value: &C::Value, input_index: usize, ) -> Result<EncodePlan<Self::PlanAction>, Self::Error>

Prepares an encoding plan for one input value.

This method must not write output. It decides the output capacity bound needed before write_encode may be called and returns an implementation-specific plan action.

§Parameters
  • codec: Low-level codec owned by the engine.
  • input_value: Input value being encoded.
  • input_index: Absolute input index of value.
§Returns

Returns the write plan for value.

§Errors

Returns Self::Error when this value cannot be encoded under the hook policy.

Source

unsafe fn write_encode( &mut self, codec: &C, context: EncodeContext<'_, C::Value, C::Unit>, plan: EncodePlan<Self::PlanAction>, ) -> Result<usize, Self::Error>

Writes one input value according to a previously prepared plan.

This method is called only after the engine has verified that EncodePlan::max_output_units units from plan are writable from EncodeContext::output_index. Implementations may rely on that capacity guarantee and do not need to report output starvation here. If a value needs more output than the plan declared, fix prepare_encode to return a larger bound.

§Parameters
  • codec: Low-level codec owned by the engine.
  • context: Encode-write context containing the input value, input index, output slice, and output cursor.
  • plan: Prepared plan returned by prepare_encode.
§Returns

Returns the number of output units written.

§Errors

Returns Self::Error when writing fails under the hook policy. Output capacity exhaustion is handled before this method is called and should not be reported as a write error.

§Safety

The caller must guarantee that at least the corresponding EncodePlan::max_output_units units are writable from EncodeContext::output_index in EncodeContext::output.

Source

fn invalid_input_index( &mut self, codec: &C, index: usize, input_len: usize, ) -> Self::Error

Builds an error for a caller-supplied input index outside the input slice.

The engine calls this hook before it reads input. Keeping this construction in the hook lets codec-backed adapters preserve their own concrete error type without a separate public factory trait.

§Parameters
  • codec: Low-level codec owned by the engine.
  • index: Invalid absolute input index supplied by the caller.
  • input_len: Length of the input slice.
§Returns

Returns the hook-specific invalid-input-index error.

Source

fn invalid_output_index( &mut self, codec: &C, index: usize, output_len: usize, ) -> Self::Error

Builds an error for a caller-supplied output index outside the output slice.

The engine calls this hook before it writes output. Keeping this construction in the hook lets codec-backed adapters preserve their own concrete error type without a separate public factory trait.

§Parameters
  • codec: Low-level codec owned by the engine.
  • index: Invalid absolute output index supplied by the caller.
  • output_len: Length of the output slice.
§Returns

Returns the hook-specific invalid-output-index error.

Provided Methods§

Source

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

Returns the maximum output units needed for input_len values.

§Parameters
  • codec: Low-level codec owned by the engine.
  • input_len: Number of input values the caller plans to encode.
§Returns

Returns a conservative upper bound derived from the codec’s Codec::max_units_per_value.

Source

fn max_finish_output_len(&self, _codec: &C) -> usize

Returns an upper bound for units emitted by finishing hook-owned state.

finish never receives more input values. Implementations must only report output derived from hook-owned state that remains after the caller has supplied all input.

§Parameters
  • codec: Low-level codec owned by the engine.
§Returns

Returns the finite final-output upper bound.

Source

fn finish( &mut self, _codec: &C, _output: &mut [C::Unit], _output_index: usize, ) -> Result<usize, Self::Error>

Finishes hook-owned state and writes any retained output units.

The default implementation is a no-op for stateless encode hooks. Stateful hooks may emit final units such as reset sequences, checksums, or trailers. The caller must provide at least BufferedEncodeHooks::max_finish_output_len writable units from output_index. Engines may pass an output slice whose upper bound is capped at output_index + max_finish_output_len, so implementations must not write beyond that declared final-output bound.

§Parameters
  • codec: Low-level codec owned by the engine.
  • output: Output unit slice visible to the hook.
  • output_index: Absolute output unit index where writing starts.
§Returns

Returns the number of units written by finalization. This count must not exceed BufferedEncodeHooks::max_finish_output_len.

§Errors

Returns Self::Error when hook-owned state cannot be finalized.

Source

fn reset(&mut self, _codec: &C)

Resets hook-owned policy state.

§Parameters
  • codec: Low-level codec owned by the engine.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§