pub struct BufferedEncodeEngine<C, H> { /* private fields */ }Expand description
Reusable buffered encoding engine for codec-backed encoders.
The engine owns the low-level codec and hook object. It keeps the common
buffered encoding loop private: input-index validation, output-capacity
checks, input consumption, output progress, and crate::TranscodeStatus
reporting.
Use this type to build a streaming encoder over a one-value Codec. The
engine does not allocate output. It repeatedly asks hooks to plan one input
value, verifies that the caller-provided output slice can hold that plan, and
then lets the hooks write the value. If the next value would not fit, the
engine returns crate::TranscodeStatus::NeedOutput without consuming that
value; the caller can provide a larger or fresh output buffer and resume
with the returned input index.
For the common strict policy that simply wraps codec errors, use
crate::CodecBufferedEncoder. Use BufferedEncodeEngine directly when
the encode policy needs custom planning, replacement, skipped values, or
finish-time output.
§Example
use core::{
convert::Infallible,
num::NonZeroUsize,
};
use qubit_codec::{
BufferedEncodeEngine,
BufferedEncodeHooks,
Codec,
CodecEncodeError,
EncodeContext,
EncodePlan,
TranscodeStatus,
};
#[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 BufferedEncodeHooks<ByteCodec> for StrictHooks {
type Error = CodecEncodeError<Infallible>;
type PlanAction = ();
fn prepare_encode(
&mut self,
codec: &ByteCodec,
_value: &u8,
_input_index: usize,
) -> Result<EncodePlan<()>, Self::Error> {
Ok(EncodePlan::new(codec.max_units_per_value().get(), ()))
}
unsafe fn write_encode(
&mut self,
codec: &ByteCodec,
context: EncodeContext<'_, u8, u8>,
_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: &ByteCodec,
index: usize,
input_len: usize,
) -> Self::Error {
CodecEncodeError::invalid_input_index(index, input_len)
}
fn invalid_output_index(
&mut self,
_codec: &ByteCodec,
index: usize,
output_len: usize,
) -> Self::Error {
CodecEncodeError::invalid_output_index(index, output_len)
}
}
let mut engine = BufferedEncodeEngine::new(ByteCodec, StrictHooks);
let input = [1_u8, 2, 3];
let mut output = [0_u8; 2];
let progress = engine.transcode(&input, 0, &mut output, 0)?;
match progress.status() {
TranscodeStatus::Complete => unreachable!("output is intentionally short"),
TranscodeStatus::NeedOutput { output_index, .. } => {
assert_eq!(2, output_index);
assert_eq!([1, 2], output);
// Write out `output[..output_index]`, then resume at
// `progress.read()` with fresh output capacity.
}
TranscodeStatus::NeedInput { .. } => unreachable!("encoders do not read encoded input"),
}§Type Parameters
C: Low-level codec used by the engine.H: Policy hook object used by the engine.
Implementations§
Source§impl<C, H> BufferedEncodeEngine<C, H>where
C: Codec,
H: BufferedEncodeHooks<C>,
impl<C, H> BufferedEncodeEngine<C, H>where
C: Codec,
H: BufferedEncodeHooks<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 output units emitted by finishing hook-owned state.
§Returns
Returns the hook-provided final output bound.
Sourcepub fn transcode(
&mut self,
input: &[C::Value],
input_index: usize,
output: &mut [C::Unit],
output_index: usize,
) -> Result<TranscodeProgress, H::Error>
pub fn transcode( &mut self, input: &[C::Value], input_index: usize, output: &mut [C::Unit], output_index: usize, ) -> Result<TranscodeProgress, H::Error>
Encodes values into a caller-provided output buffer.
The engine stops before consuming the next input value when the current output buffer does not satisfy that value’s planned capacity bound.
§Parameters
input: Complete input value slice visible to the encoder.input_index: Absolute input value index where encoding starts.output: Complete output unit slice visible to the encoder.output_index: Absolute output unit index where writing starts.
§Returns
Returns progress describing input values consumed, output units written, and why encoding stopped.
§Errors
Returns hook errors when input_index is outside input, when
output_index is outside output, or when hook planning or writing
rejects a value.
Sourcepub fn finish(
&mut self,
output: &mut [C::Unit],
output_index: usize,
) -> Result<usize, FinishError<H::Error>>
pub fn finish( &mut self, output: &mut [C::Unit], 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
supplied all input values. The caller must provide enough output capacity
for BufferedEncodeEngine::max_finish_output_len.
§Parameters
output: Complete output unit slice visible to the encoder.output_index: Absolute output unit index where writing starts.
§Returns
Returns the number of units 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 units than
BufferedEncodeEngine::max_finish_output_len declared.
Trait Implementations§
Source§impl<C: Clone, H: Clone> Clone for BufferedEncodeEngine<C, H>
impl<C: Clone, H: Clone> Clone for BufferedEncodeEngine<C, H>
Source§fn clone(&self) -> BufferedEncodeEngine<C, H>
fn clone(&self) -> BufferedEncodeEngine<C, H>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl<C: Copy, H: Copy> Copy for BufferedEncodeEngine<C, H>
Source§impl<C: Default, H: Default> Default for BufferedEncodeEngine<C, H>
impl<C: Default, H: Default> Default for BufferedEncodeEngine<C, H>
Source§fn default() -> BufferedEncodeEngine<C, H>
fn default() -> BufferedEncodeEngine<C, H>
impl<C: Eq, H: Eq> Eq for BufferedEncodeEngine<C, H>
Source§impl<C: PartialEq, H: PartialEq> PartialEq for BufferedEncodeEngine<C, H>
impl<C: PartialEq, H: PartialEq> PartialEq for BufferedEncodeEngine<C, H>
Source§fn eq(&self, other: &BufferedEncodeEngine<C, H>) -> bool
fn eq(&self, other: &BufferedEncodeEngine<C, H>) -> bool
self and other values to be equal, and is used by ==.