Skip to main content

qubit_codec/codec/
codec.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Low-level value codec trait.
9
10use core::num::NonZeroUsize;
11
12use super::decode_failure::DecodeFailure;
13
14/// Encodes and decodes one value or codec quantum against a unit buffer.
15///
16/// `Codec` is the lowest-level abstraction in the codec stack. It is intended
17/// for hot paths that have already validated buffer capacity and want to avoid
18/// constructing subslices for every value. Higher-level transcoders and
19/// convenience APIs are responsible for checked buffer management and owned
20/// output allocation.
21///
22/// `MIN_UNITS_PER_VALUE` and `MAX_DECODE_UNITS_PER_VALUE` describe the readable
23/// representation-width bounds for one decoded value. If fewer than the
24/// minimum units are available, no complete value can exist, so a streaming
25/// caller can request more input or report an incomplete EOF tail. The minimum
26/// is also the smallest safety precondition checked callers must satisfy before
27/// entering [`decode`](Self::decode). The decode maximum bounds successful
28/// consumption and incomplete-input requirements for one value.
29///
30/// `MAX_ENCODE_UNITS_PER_VALUE` is the independent value-agnostic upper bound
31/// for main-phase encode output. Reserving that many units makes encoding safe
32/// for every encodable value. Once a value and encode state are known, callers
33/// may instead reserve the exact [`encode_len`](Self::encode_len), which must
34/// not exceed the encode maximum. Complete-lifecycle adapters that still need
35/// to run [`encode_reset`](Self::encode_reset) must reserve the maximum first
36/// because reset may change the exact width.
37///
38/// A codec may keep decode-side and encode-side stream state. That state is an
39/// implementation detail owned by the codec. Callers do not snapshot or restore
40/// it; implementations must keep their own state internally consistent across
41/// every public operation. A failed decode attempt must not advance decode
42/// state, so callers can retry the same input after refilling their buffer or
43/// applying an invalid-input policy.
44///
45/// Decode operations see only the currently supplied input slice and codec
46/// state. [`decode`](Self::decode) treats that slice as an open stream segment;
47/// [`decode_eof`](Self::decode_eof) receives the same preconditions after the
48/// caller has established that no more units will arrive. Returning
49/// [`DecodeFailure::Incomplete`] from `decode` requests more input for the
50/// current value; it is not itself an EOF error. Codecs that need EOF-aware
51/// maximal-munch parsing or reinterpretation of a trailing prefix can override
52/// `decode_eof` without changing their streaming behavior.
53/// An incomplete failure may also retain codec-specific context through
54/// [`DecodeFailure::incomplete_with_source`]; stream drivers may ignore that
55/// context while retrying and use it for detailed EOF diagnostics.
56///
57/// # Associated Types
58///
59/// - `Value`: Logical value decoded from or encoded into the buffer. This may
60///   be a scalar such as `u8`, `u16`, `u64`, a `char`, a fixed quantum such as
61///   `[u8; 3]`, or an owned value such as `String`/`Vec<u8>`. Adapters that
62///   need scratch initialization add their own bounds at the use site.
63/// - `Unit`: Buffer unit used by the encoded representation. Implementations
64///   are typically scalar storage units such as `u8`, `u16`, or `char`.
65///   Adapters that allocate owned output add their own initialization bounds at
66///   the use site.
67///
68/// Implementors must uphold the safety contract documented by
69/// [`decode`](Self::decode), [`encode`](Self::encode),
70/// [`encode_reset`](Self::encode_reset), and
71/// [`decode_finish`](Self::decode_finish). Unchecked implementations must not
72/// read or write outside the caller-provided ranges. Implementations should use
73/// `debug_assert!` to state the expected buffer bounds at the unchecked entry
74/// point.
75///
76/// Implementations must also guarantee that
77/// [`MIN_UNITS_PER_VALUE`](Self::MIN_UNITS_PER_VALUE) is non-zero and no larger
78/// than [`MAX_DECODE_UNITS_PER_VALUE`](Self::MAX_DECODE_UNITS_PER_VALUE), which
79/// must also be non-zero. `MAX_ENCODE_UNITS_PER_VALUE` may be zero for a codec
80/// that always buffers each accepted value instead of immediately emitting
81/// units. Checked adapters enforce the decode-bound invariants with
82/// compile-time assertions before using codec-provided bounds.
83///
84/// # Why the low-level methods are unchecked
85///
86/// The `unsafe` entry points are intentional: checked adapters validate the
87/// index and capacity preconditions once, then call [`encode`](Self::encode)
88/// and [`decode`](Self::decode) without rebuilding subslices or repeating
89/// bounds checks for every value. The `safe_vs_unchecked` benchmark in
90/// `benches/transcode.rs` compares the same 64 KiB copy loop in release mode.
91/// Its result is workload- and toolchain-specific, so callers should use
92/// checked adapters unless they can establish the documented preconditions at
93/// a trusted boundary. Measure representative codec workloads before choosing
94/// an unchecked entry point. Codec implementations should keep the unchecked
95/// methods small and use `debug_assert!` for those assumptions.
96///
97/// # Examples
98///
99/// A caller can inspect a codec's declared unit bounds before allocating a
100/// buffer:
101///
102/// ```
103/// use qubit_codec::Codec;
104///
105/// fn decode_capacity<C: Codec>() -> usize {
106///     C::MAX_DECODE_UNITS_PER_VALUE
107/// }
108/// ```
109pub trait Codec {
110    /// The type of logical values decoded from or encoded into the buffer.
111    type Value;
112
113    /// The type of buffer units used by the encoded representation.
114    type Unit;
115
116    /// The type of errors reported when decoding malformed units.
117    type DecodeError;
118
119    /// The type of errors reported when encoding an unsupported value.
120    type EncodeError;
121
122    /// The minimum possible non-zero readable unit count for one decoded value.
123    ///
124    /// This is a lower bound used by checked callers for planning and fast
125    /// impossibility checks. If a streaming decoder has fewer than this many
126    /// readable units, no complete value can be present at the current
127    /// position. It is also the denominator used by default decode hooks when
128    /// estimating the maximum number of values that can be produced from an
129    /// input unit count.
130    const MIN_UNITS_PER_VALUE: usize;
131
132    /// The maximum unit count emitted when encoding one value.
133    ///
134    /// This is a value-independent upper bound for the main encode phase. When
135    /// no concrete value is available, reserving this many writable units is
136    /// sufficient for any encodable value, without first calling
137    /// [`encode_len`](Self::encode_len). For a known value, callers may reserve
138    /// only the exact length returned by `encode_len` instead. This bound does
139    /// not include output produced by encode reset or finish phases.
140    ///
141    /// This is also the multiplier used by default encode hooks when estimating
142    /// the maximum number of output units needed for an input value count.
143    ///
144    /// The bound may be zero for a codec that buffers every accepted value and
145    /// emits retained output only during a later lifecycle phase.
146    const MAX_ENCODE_UNITS_PER_VALUE: usize;
147
148    /// The maximum non-zero unit count consumed to decode one value.
149    ///
150    /// This is a value-independent upper bound for one complete encoded value
151    /// or codec quantum on the decode side. Successful decode consumption and
152    /// the `required_total` carried by [`DecodeFailure::Incomplete`] must not
153    /// exceed this bound.
154    const MAX_DECODE_UNITS_PER_VALUE: usize;
155
156    /// The maximum unit count emitted when resetting encode state.
157    ///
158    /// This bound covers only output written by
159    /// [`encode_reset`](Self::encode_reset). It does not include hook-owned
160    /// reset output or any ordinary encoded input values. It must cover every
161    /// reachable pre-reset encode state. Stateless codecs should use the
162    /// default `0`.
163    const MAX_ENCODE_RESET_UNITS: usize = 0;
164
165    /// The maximum unit count emitted when finishing encode state at EOF.
166    ///
167    /// This bound covers only output written by
168    /// [`encode_finish`](Self::encode_finish). It does not include hook-owned
169    /// finish output and must cover every reachable encode state, even when the
170    /// current stream has no pending finish output. Stateless codecs should use
171    /// the default `0`. Codecs that emit a stream trailer (padding, checksum,
172    /// or end-of-stream marker) should override this with the exact maximum
173    /// unit count.
174    const MAX_ENCODE_FINISH_UNITS: usize = 0;
175
176    /// The maximum value count emitted when resetting decode state.
177    ///
178    /// This bound covers only values written by
179    /// [`decode_reset`](Self::decode_reset). It does not include hook-owned
180    /// reset output or values decoded from source units. It must cover every
181    /// reachable pre-reset decode state. Stateless codecs should use the
182    /// default `0`. Codecs that emit a stream-start sentinel or BOM on reset
183    /// should override this.
184    const MAX_DECODE_RESET_VALUES: usize = 0;
185
186    /// The maximum value count emitted when finishing decode state.
187    ///
188    /// This bound covers only values written by
189    /// [`decode_finish`](Self::decode_finish). It does not include hook-owned
190    /// finish output and must cover every reachable decode state, even when the
191    /// current stream has no pending finish output. Stateless codecs should use
192    /// the default `0`.
193    const MAX_DECODE_FINISH_VALUES: usize = 0;
194
195    /// Returns whether `value` is in this codec's encodable value domain.
196    ///
197    /// The default implementation returns `true`, which is correct for codecs
198    /// whose [`Value`](Self::Value) type contains only values they can encode.
199    /// Codecs whose logical value type is broader than their representation
200    /// domain, such as an ASCII codec with `Value = char`, must override this
201    /// method.
202    ///
203    /// Checked encoder adapters call this method in the same codec state used
204    /// to query [`encode_len`](Self::encode_len) and enter the unsafe
205    /// [`encode`](Self::encode) method. Complete-lifecycle adapters do so after
206    /// [`encode_reset`](Self::encode_reset). Direct unsafe callers must uphold
207    /// the same ordering.
208    ///
209    /// # Parameters
210    ///
211    /// - `value`: Value whose encodability is queried.
212    ///
213    /// # Returns
214    ///
215    /// Returns `true` when `value` may be passed to
216    /// [`encode_len`](Self::encode_len) and [`encode`](Self::encode).
217    #[inline(always)]
218    #[must_use]
219    fn can_encode_value(&self, _value: &Self::Value) -> bool {
220        true
221    }
222
223    /// Returns the exact unit count this codec will write when encoding
224    /// `value`.
225    ///
226    /// The default implementation returns
227    /// [`MAX_ENCODE_UNITS_PER_VALUE`](Self::MAX_ENCODE_UNITS_PER_VALUE). This
228    /// default is correct only when every successful main encode writes exactly
229    /// that many units in the relevant codec state, as fixed-width codecs
230    /// normally do.
231    ///
232    /// Variable-width, buffering, or otherwise state-dependent codecs must
233    /// override this method to report the true encoded length for encodable
234    /// `value`s. The return value is never an estimate or an "unknown" marker:
235    /// it must equal the unit count [`encode`](Self::encode) subsequently
236    /// writes for the same `value` under the same codec state. It must also
237    /// never exceed
238    /// [`MAX_ENCODE_UNITS_PER_VALUE`](Self::MAX_ENCODE_UNITS_PER_VALUE).
239    /// Callers that do not yet have a concrete value should use
240    /// `MAX_ENCODE_UNITS_PER_VALUE` directly instead of calling this method.
241    ///
242    /// Default codec-backed encoders use this exact value for per-value output
243    /// capacity. The contract requires callers to use this method only when
244    /// [`can_encode_value`](Self::can_encode_value) returned `true` for the
245    /// same `value`.
246    ///
247    /// # Parameters
248    ///
249    /// - `value`: Value whose encoded length is queried.
250    ///
251    /// # Returns
252    ///
253    /// Returns the unit count [`encode`](Self::encode) will write for an
254    /// encodable `value`.
255    ///
256    /// A return value of `0` is valid for stateful encoders that accept a
257    /// value into internal state without immediately emitting units. Examples
258    /// include codecs that aggregate values into fixed-size quanta, shift-state
259    /// encodings, or framing layers that defer output until enough values have
260    /// been seen or EOF is finalized. Stateless and directly value-to-unit
261    /// codecs should continue returning a positive length.
262    #[inline(always)]
263    #[must_use]
264    fn encode_len(&self, _value: &Self::Value) -> usize {
265        Self::MAX_ENCODE_UNITS_PER_VALUE
266    }
267
268    /// Emits stream-start output and resets encode-side state.
269    ///
270    /// # Parameters
271    ///
272    /// - `output`: Destination unit buffer.
273    /// - `output_index`: Start index in `output`.
274    ///
275    /// # Returns
276    ///
277    /// Returns the number of reset units written.
278    ///
279    /// # Errors
280    ///
281    /// Returns `Self::EncodeError` when reset output cannot be emitted.
282    /// Implementations must leave encode state unchanged when returning an
283    /// error.
284    ///
285    /// # Safety
286    ///
287    /// The caller must guarantee that the implementation can write up to
288    /// [`MAX_ENCODE_RESET_UNITS`](Self::MAX_ENCODE_RESET_UNITS) units starting
289    /// at `output_index`.
290    #[inline(always)]
291    #[must_use = "reset output and reset errors must be handled"]
292    unsafe fn encode_reset(
293        &mut self,
294        _output: &mut [Self::Unit],
295        _output_index: usize,
296    ) -> Result<usize, Self::EncodeError> {
297        Ok(0)
298    }
299
300    /// Encodes one borrowed value into `output` starting at `output_index`.
301    ///
302    /// # Parameters
303    ///
304    /// - `value`: Value to encode.
305    /// - `output`: Destination unit buffer.
306    /// - `output_index`: Start index in `output`.
307    ///
308    /// # Returns
309    ///
310    /// Returns the number of written units.
311    ///
312    /// A successful encode may return `0` when the codec accepted `value` into
313    /// internal encode-side state but intentionally deferred output. This is
314    /// the normal shape for accumulative encoders such as base64-byte
315    /// aggregators, shift-state encodings, or frame builders. In that case
316    /// [`encode_len`](Self::encode_len) for the same `value` and state must
317    /// also return `0`, and the retained output must be emitted by a later
318    /// successful [`encode`](Self::encode),
319    /// [`encode_finish`](Self::encode_finish), or codec-specific facade.
320    ///
321    /// # Errors
322    ///
323    /// Returns `Self::EncodeError` for encode-side state or representation
324    /// failures other than a value being outside the codec's encodable domain.
325    /// Checked callers reject values for which
326    /// [`can_encode_value`](Self::can_encode_value) returns `false` before
327    /// entering this unsafe method. Implementations must leave their internal
328    /// state consistent when returning an error.
329    ///
330    /// # Safety
331    ///
332    /// The caller must guarantee that
333    /// [`can_encode_value`](Self::can_encode_value) returned `true` for
334    /// `value`. Starting at `output_index`, the caller must also provide either
335    /// at least
336    /// [`MAX_ENCODE_UNITS_PER_VALUE`](Self::MAX_ENCODE_UNITS_PER_VALUE)
337    /// writable
338    /// units, which is sufficient for every encodable value, or at least the
339    /// exact [`encode_len`](Self::encode_len) for the same `value` and codec
340    /// state. On success, implementations must return that exact written unit
341    /// count, including `0` for deliberate buffering, and the count must be no
342    /// larger than `MAX_ENCODE_UNITS_PER_VALUE`. Implementations must not write
343    /// beyond the exact `encode_len` capacity on either the success or error
344    /// path.
345    #[must_use = "encoded length and encode errors must be handled"]
346    unsafe fn encode(
347        &mut self,
348        value: &Self::Value,
349        output: &mut [Self::Unit],
350        output_index: usize,
351    ) -> Result<usize, Self::EncodeError>;
352
353    /// Emits EOF trailer output and finishes encode-side state.
354    ///
355    /// This is the encode-side counterpart of
356    /// [`decode_finish`](Self::decode_finish). Codecs that append stream
357    /// trailers (padding, checksums, end-of-stream markers) emit them here.
358    /// Stateless codecs use the default no-op.
359    ///
360    /// # Parameters
361    ///
362    /// - `output`: Destination unit buffer.
363    /// - `output_index`: Start index in `output`.
364    ///
365    /// # Returns
366    ///
367    /// Returns the number of finish units written.
368    ///
369    /// # Errors
370    ///
371    /// Returns `Self::EncodeError` when finish output cannot be emitted.
372    /// Implementations must leave their internal state consistent when
373    /// returning an error.
374    ///
375    /// # Safety
376    ///
377    /// The caller must guarantee that the implementation can write up to
378    /// [`MAX_ENCODE_FINISH_UNITS`](Self::MAX_ENCODE_FINISH_UNITS) units
379    /// starting at `output_index`.
380    #[inline(always)]
381    #[must_use = "finish output and finish errors must be handled"]
382    unsafe fn encode_finish(
383        &mut self,
384        _output: &mut [Self::Unit],
385        _output_index: usize,
386    ) -> Result<usize, Self::EncodeError> {
387        Ok(0)
388    }
389
390    /// Emits stream-start values and resets decode-side state.
391    ///
392    /// This is the decode-side counterpart of
393    /// [`encode_reset`](Self::encode_reset). Codecs that emit a
394    /// stream-start marker or BOM before decoding a new stream emit them
395    /// here. Stateless codecs use the default no-op.
396    ///
397    /// # Parameters
398    ///
399    /// - `output`: Destination value buffer.
400    /// - `output_index`: Start index in `output`.
401    ///
402    /// # Returns
403    ///
404    /// Returns the number of reset values written.
405    ///
406    /// # Errors
407    ///
408    /// Returns `Self::DecodeError` when reset output cannot be emitted.
409    /// Implementations must leave their internal state consistent when
410    /// returning an error.
411    ///
412    /// # Safety
413    ///
414    /// The caller must guarantee that the implementation can write up to
415    /// [`MAX_DECODE_RESET_VALUES`](Self::MAX_DECODE_RESET_VALUES) values
416    /// starting at `output_index`.
417    #[inline(always)]
418    #[must_use = "reset output and reset errors must be handled"]
419    unsafe fn decode_reset(
420        &mut self,
421        _output: &mut [Self::Value],
422        _output_index: usize,
423    ) -> Result<usize, Self::DecodeError> {
424        Ok(0)
425    }
426
427    /// Decodes one value from `input` starting at `input_index`.
428    ///
429    /// # Parameters
430    ///
431    /// - `input`: Source unit buffer.
432    /// - `input_index`: Start index in `input`.
433    ///
434    /// # Returns
435    ///
436    /// Returns the decoded value and the non-zero number of consumed units.
437    ///
438    /// # Errors
439    ///
440    /// Returns [`DecodeFailure::Incomplete`] when the visible input is a
441    /// valid prefix but more units are needed to decide or complete a value.
442    /// This reports a streaming boundary, not a final EOF condition; the
443    /// caller or higher-level adapter decides what an incomplete tail means
444    /// when the upstream source is closed. Codec-specific context may be
445    /// retained in the failure's optional `source` field.
446    /// Returns [`DecodeFailure::Invalid`] when the units are malformed,
447    /// non-canonical, unmappable, or otherwise invalid for this codec and the
448    /// span is known or unknown. Unknown span is represented as
449    /// [`DecodeFailure::Invalid`] with an unknown consumed-unit hint.
450    /// Implementations must leave their internal state consistent when
451    /// returning an error.
452    ///
453    /// # Safety
454    ///
455    /// The caller must guarantee that `input_index` is a valid boundary in
456    /// `input` and that at least
457    /// [`MIN_UNITS_PER_VALUE`](Self::MIN_UNITS_PER_VALUE)
458    /// units are readable from `input_index`. Implementations must not read
459    /// beyond the currently available units under that precondition. They
460    /// may return [`DecodeFailure::Incomplete`] when those units are a
461    /// valid but incomplete prefix.
462    ///
463    /// On success, implementations must return a consumed unit count no larger
464    /// than either the available input or
465    /// [`MAX_DECODE_UNITS_PER_VALUE`](Self::MAX_DECODE_UNITS_PER_VALUE). An
466    /// incomplete result's `required_total` must also not exceed that maximum.
467    /// The return type guarantees that successful decoding always consumes at
468    /// least one unit. Implementations should use `debug_assert!` to state
469    /// these unchecked entry-point assumptions.
470    #[must_use = "decoded value, consumed length, and decode errors must be handled"]
471    unsafe fn decode(
472        &mut self,
473        input: &[Self::Unit],
474        input_index: usize,
475    ) -> Result<(Self::Value, NonZeroUsize), DecodeFailure<Self::DecodeError>>;
476
477    /// Decodes one value after the caller has established end of input.
478    ///
479    /// This method has the same safety and state guarantees as
480    /// [`decode`](Self::decode), but may resolve an otherwise incomplete
481    /// trailing prefix using EOF-aware format rules. The default preserves the
482    /// open-stream behavior by delegating to [`decode`](Self::decode).
483    ///
484    /// # Safety
485    ///
486    /// The caller must satisfy the same input-index and minimum-readable-unit
487    /// preconditions as [`decode`](Self::decode). Implementations must not
488    /// read beyond the currently available units.
489    #[inline(always)]
490    #[must_use = "decoded value, consumed length, and decode errors must be handled"]
491    unsafe fn decode_eof(
492        &mut self,
493        input: &[Self::Unit],
494        input_index: usize,
495    ) -> Result<(Self::Value, NonZeroUsize), DecodeFailure<Self::DecodeError>> {
496        // SAFETY: `decode_eof` has the same preconditions as `decode`.
497        unsafe { self.decode(input, input_index) }
498    }
499
500    /// Finishes decode-side EOF state into `output`.
501    ///
502    /// `decode_finish` receives no source input. Callers must have already
503    /// handled any tail reported by [`DecodeFailure::Incomplete`] before
504    /// finishing decode state. Implementations may emit retained values or
505    /// validate internal EOF state, but they must not depend on re-reading the
506    /// incomplete source tail.
507    ///
508    /// # Parameters
509    ///
510    /// - `output`: Destination value buffer.
511    /// - `output_index`: Start index in `output`.
512    ///
513    /// # Returns
514    ///
515    /// Returns the number of finished values written.
516    ///
517    /// # Errors
518    ///
519    /// Returns `Self::DecodeError` when retained decode state is invalid at
520    /// EOF. Implementations must leave their internal state consistent when
521    /// returning an error.
522    ///
523    /// # Safety
524    ///
525    /// The caller must guarantee that the implementation can write up to
526    /// [`MAX_DECODE_FINISH_VALUES`](Self::MAX_DECODE_FINISH_VALUES) values
527    /// starting at `output_index`.
528    #[inline(always)]
529    #[must_use = "finish output length and finish errors must be handled"]
530    unsafe fn decode_finish(
531        &mut self,
532        _output: &mut [Self::Value],
533        _output_index: usize,
534    ) -> Result<usize, Self::DecodeError> {
535        Ok(0)
536    }
537}
538
539/// Compile-time asserts the public unit-bound invariants required by [`Codec`].
540///
541/// # Type Parameters
542///
543/// - `C`: Codec implementation to validate.
544///
545/// # Returns
546///
547/// Returns unit `()`.
548///
549/// # Panics
550///
551/// Panics at compile time when either decode width bound is zero or when
552/// [`Codec::MIN_UNITS_PER_VALUE`] is greater than
553/// [`Codec::MAX_DECODE_UNITS_PER_VALUE`], because these invariants must hold
554/// for any well-formed [`Codec`] implementation and violating them is always a
555/// bug.
556#[inline(always)]
557pub(crate) fn assert_unit_bounds<C>()
558where
559    C: Codec,
560{
561    const {
562        assert!(
563            C::MIN_UNITS_PER_VALUE > 0,
564            "Codec::MIN_UNITS_PER_VALUE must be non-zero",
565        );
566        assert!(
567            C::MAX_DECODE_UNITS_PER_VALUE > 0,
568            "Codec::MAX_DECODE_UNITS_PER_VALUE must be non-zero",
569        );
570        assert!(
571            C::MIN_UNITS_PER_VALUE <= C::MAX_DECODE_UNITS_PER_VALUE,
572            "Codec::MIN_UNITS_PER_VALUE must not exceed Codec::MAX_DECODE_UNITS_PER_VALUE",
573        );
574    }
575}