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_UNITS_PER_VALUE` describe the representation
23/// width bounds for one value. The minimum is a lower-bound hint for checked
24/// layers: if fewer than this many units are available, no complete value can
25/// exist, so a streaming caller can request more input, report an incomplete
26/// EOF tail. For decoding, this minimum is the smallest safety precondition
27/// checked callers must satisfy before entering
28/// [`decode`](Self::decode). The maximum is a value-independent upper bound
29/// callers can use for coarse capacity planning. For encoding a known value,
30/// checked callers should reserve the exact [`encode_len`](Self::encode_len)
31/// instead of pessimistically reserving the maximum width.
32///
33/// A codec may keep decode-side and encode-side stream state. That state is an
34/// implementation detail owned by the codec. Callers do not snapshot or restore
35/// it; implementations must keep their own state internally consistent across
36/// every public operation, including operations that return `Err`.
37///
38/// Decode operations see only the currently supplied input slice and codec
39/// state. They do not receive an explicit EOF marker and they cannot look past
40/// the visible input. Returning [`DecodeFailure::Incomplete`] requests
41/// more input for the current value; it is not itself an EOF error. The default
42/// codec-backed streaming adapters therefore fit formats whose value boundary
43/// is locally decidable from the visible prefix plus codec state. Formats that
44/// require EOF-aware maximal-munch parsing, delayed boundary decisions, or
45/// reinterpretation of an incomplete tail at EOF should put that policy in a
46/// custom [`crate::Transcoder`] or value-level facade instead of relying on the
47/// default `Codec` bridge.
48///
49/// # Associated Types
50///
51/// - `Value`: Logical value decoded from or encoded into the buffer. This may
52///   be a scalar such as `u8`, `u16`, `u64`, a `char`, a fixed quantum such as
53///   `[u8; 3]`, or an owned value such as `String`/`Vec<u8>`. Adapters that
54///   need scratch initialization add their own bounds at the use site.
55/// - `Unit`: Buffer unit used by the encoded representation. Implementations
56///   are typically scalar storage units such as `u8`, `u16`, or `char`.
57///   Adapters that allocate owned output add their own initialization bounds at
58///   the use site.
59///
60/// Implementors must uphold the safety contract documented by
61/// [`decode`](Self::decode), [`encode`](Self::encode),
62/// [`encode_reset`](Self::encode_reset), and
63/// [`decode_flush`](Self::decode_flush). Unchecked implementations must not
64/// read or write outside the caller-provided ranges. Implementations should use
65/// `debug_assert!` to state the expected buffer bounds at the unchecked entry
66/// point.
67///
68/// Implementations must also guarantee that
69/// [`MIN_UNITS_PER_VALUE`](Self::MIN_UNITS_PER_VALUE) is less than or equal to
70/// [`MAX_UNITS_PER_VALUE`](Self::MAX_UNITS_PER_VALUE). Both bounds are non-zero
71/// by type, and `MAX_UNITS_PER_VALUE` must be a valid upper bound for one
72/// complete encoded value or codec quantum. Checked adapters assert this
73/// invariant before using codec-provided bounds.
74pub trait Codec {
75    /// The type of logical values decoded from or encoded into the buffer.
76    type Value;
77
78    /// The type of buffer units used by the encoded representation.
79    type Unit;
80
81    /// The type of errors reported when decoding malformed units.
82    type DecodeError;
83
84    /// The type of errors reported when encoding an unsupported value.
85    type EncodeError;
86
87    /// The minimum possible unit count for one encoded value.
88    ///
89    /// This is a lower bound used by checked callers for planning and fast
90    /// impossibility checks. If a streaming decoder has fewer than this many
91    /// readable units, no complete value can be present at the current
92    /// position.
93    const MIN_UNITS_PER_VALUE: NonZeroUsize = NonZeroUsize::MIN;
94
95    /// The maximum non-zero unit count needed to encode or decode one value.
96    ///
97    /// This is a value-independent upper bound for one complete encoded value
98    /// or codec quantum.
99    const MAX_UNITS_PER_VALUE: NonZeroUsize = NonZeroUsize::MIN;
100
101    /// The maximum unit count emitted when resetting encode state.
102    ///
103    /// Stateless codecs should use the default `0`.
104    const MAX_ENCODE_RESET_UNITS: usize = 0;
105
106    /// The maximum unit count emitted when flushing encode state at EOF.
107    ///
108    /// Stateless codecs should use the default `0`. Codecs that emit a
109    /// stream trailer (padding, checksum, or end-of-stream marker) should
110    /// override this with the exact maximum unit count.
111    const MAX_ENCODE_FLUSH_UNITS: usize = 0;
112
113    /// The maximum value count emitted when resetting decode state.
114    ///
115    /// Stateless codecs should use the default `0`. Codecs that emit a
116    /// stream-start sentinel or BOM on reset should override this.
117    const MAX_DECODE_RESET_VALUES: usize = 0;
118
119    /// The maximum value count emitted when flushing decode state.
120    ///
121    /// Stateless codecs should use the default `0`.
122    const MAX_DECODE_FLUSH_VALUES: usize = 0;
123
124    /// Returns whether `value` is in this codec's encodable value domain.
125    ///
126    /// The default implementation returns `true`, which is correct for codecs
127    /// whose [`Value`](Self::Value) type contains only values they can encode.
128    /// Codecs whose logical value type is broader than their representation
129    /// domain, such as an ASCII codec with `Value = char`, must override this
130    /// method.
131    ///
132    /// Checked encoder adapters call this method before querying
133    /// [`encode_len`](Self::encode_len) or entering the unsafe
134    /// [`encode`](Self::encode) method. Direct unsafe callers must do the same.
135    ///
136    /// # Parameters
137    ///
138    /// - `value`: Value whose encodability is queried.
139    ///
140    /// # Returns
141    ///
142    /// Returns `true` when `value` may be passed to
143    /// [`encode_len`](Self::encode_len) and [`encode`](Self::encode).
144    #[inline(always)]
145    #[must_use]
146    fn can_encode_value(&self, _value: &Self::Value) -> bool {
147        true
148    }
149
150    /// Returns the exact non-zero unit count this codec will write when
151    /// encoding `value`.
152    ///
153    /// The default implementation returns
154    /// [`MAX_UNITS_PER_VALUE`](Self::MAX_UNITS_PER_VALUE), which is the
155    /// conservative bound callers can use when no specific value is available.
156    /// Fixed-width codecs do not need to override this method.
157    ///
158    /// Variable-width codecs (LEB128, UTF-8, GB18030, …) should override this
159    /// to report the true encoded length for encodable `value`s. Doing so lets
160    /// buffered adapters and stream writers reserve only what is actually
161    /// needed and enables capacity probing without performing the encode.
162    /// Default codec-backed encoders use this exact value for per-value output
163    /// capacity. The contract requires callers to use this method only when
164    /// [`can_encode_value`](Self::can_encode_value) returned `true` for the
165    /// same `value`. Under that precondition, the returned length must equal
166    /// the unit count [`encode`](Self::encode) writes for the same `value`
167    /// under the same codec state, and must never exceed
168    /// [`MAX_UNITS_PER_VALUE`](Self::MAX_UNITS_PER_VALUE).
169    ///
170    /// # Parameters
171    ///
172    /// - `value`: Value whose encoded length is queried.
173    ///
174    /// # Returns
175    ///
176    /// Returns the non-zero unit count [`encode`](Self::encode) will write for
177    /// an encodable `value`.
178    #[inline(always)]
179    #[must_use]
180    fn encode_len(&self, _value: &Self::Value) -> NonZeroUsize {
181        Self::MAX_UNITS_PER_VALUE
182    }
183
184    /// Emits stream-start output and resets encode-side state.
185    ///
186    /// # Parameters
187    ///
188    /// - `output`: Destination unit buffer.
189    /// - `output_index`: Start index in `output`.
190    ///
191    /// # Returns
192    ///
193    /// Returns the number of reset units written.
194    ///
195    /// # Errors
196    ///
197    /// Returns `Self::EncodeError` when reset output cannot be emitted.
198    /// Implementations must leave their internal state consistent when
199    /// returning an error.
200    ///
201    /// # Safety
202    ///
203    /// The caller must guarantee that the implementation can write up to
204    /// [`MAX_ENCODE_RESET_UNITS`](Self::MAX_ENCODE_RESET_UNITS) units starting
205    /// at `output_index`.
206    #[inline(always)]
207    #[must_use = "reset output and reset errors must be handled"]
208    unsafe fn encode_reset(
209        &mut self,
210        _output: &mut [Self::Unit],
211        _output_index: usize,
212    ) -> Result<usize, Self::EncodeError> {
213        Ok(0)
214    }
215
216    /// Encodes one borrowed value into `output` starting at `output_index`.
217    ///
218    /// # Parameters
219    ///
220    /// - `value`: Value to encode.
221    /// - `output`: Destination unit buffer.
222    /// - `output_index`: Start index in `output`.
223    ///
224    /// # Returns
225    ///
226    /// Returns the non-zero number of written units. A successful encode
227    /// always emits at least one unit; stateful encoders that need to defer
228    /// output should report that intent through a custom encode error
229    /// instead of returning a zero count.
230    ///
231    /// # Errors
232    ///
233    /// Returns `Self::EncodeError` for encode-side state or representation
234    /// failures other than a value being outside the codec's encodable domain.
235    /// Checked callers reject values for which
236    /// [`can_encode_value`](Self::can_encode_value) returns `false` before
237    /// entering this unsafe method. Implementations must leave their internal
238    /// state consistent when returning an error.
239    ///
240    /// # Safety
241    ///
242    /// The caller must guarantee that
243    /// [`can_encode_value`](Self::can_encode_value) returned `true` for
244    /// `value`, and that the implementation can write at least
245    /// [`encode_len`](Self::encode_len) units for the same `value` and codec
246    /// state starting at `output_index`. On success, implementations must
247    /// return that exact written unit count, and the count must be no
248    /// larger than [`MAX_UNITS_PER_VALUE`](Self::MAX_UNITS_PER_VALUE).
249    #[must_use = "encoded length and encode errors must be handled"]
250    unsafe fn encode(
251        &mut self,
252        value: &Self::Value,
253        output: &mut [Self::Unit],
254        output_index: usize,
255    ) -> Result<NonZeroUsize, Self::EncodeError>;
256
257    /// Emits EOF trailer output and flushes encode-side state.
258    ///
259    /// This is the encode-side counterpart of
260    /// [`decode_flush`](Self::decode_flush). Codecs that append stream
261    /// trailers (padding, checksums, end-of-stream markers) emit them here.
262    /// Stateless codecs use the default no-op.
263    ///
264    /// # Parameters
265    ///
266    /// - `output`: Destination unit buffer.
267    /// - `output_index`: Start index in `output`.
268    ///
269    /// # Returns
270    ///
271    /// Returns the number of flush units written.
272    ///
273    /// # Errors
274    ///
275    /// Returns `Self::EncodeError` when flush output cannot be emitted.
276    /// Implementations must leave their internal state consistent when
277    /// returning an error.
278    ///
279    /// # Safety
280    ///
281    /// The caller must guarantee that the implementation can write up to
282    /// [`MAX_ENCODE_FLUSH_UNITS`](Self::MAX_ENCODE_FLUSH_UNITS) units starting
283    /// at `output_index`.
284    #[inline(always)]
285    #[must_use = "flush output and flush errors must be handled"]
286    unsafe fn encode_flush(
287        &mut self,
288        _output: &mut [Self::Unit],
289        _output_index: usize,
290    ) -> Result<usize, Self::EncodeError> {
291        Ok(0)
292    }
293
294    /// Emits stream-start values and resets decode-side state.
295    ///
296    /// This is the decode-side counterpart of
297    /// [`encode_reset`](Self::encode_reset). Codecs that emit a
298    /// stream-start marker or BOM before decoding a new stream emit them
299    /// here. Stateless codecs use the default no-op.
300    ///
301    /// # Parameters
302    ///
303    /// - `output`: Destination value buffer.
304    /// - `output_index`: Start index in `output`.
305    ///
306    /// # Returns
307    ///
308    /// Returns the number of reset values written.
309    ///
310    /// # Errors
311    ///
312    /// Returns `Self::DecodeError` when reset output cannot be emitted.
313    /// Implementations must leave their internal state consistent when
314    /// returning an error.
315    ///
316    /// # Safety
317    ///
318    /// The caller must guarantee that the implementation can write up to
319    /// [`MAX_DECODE_RESET_VALUES`](Self::MAX_DECODE_RESET_VALUES) values
320    /// starting at `output_index`.
321    #[inline(always)]
322    #[must_use = "reset output and reset errors must be handled"]
323    unsafe fn decode_reset(
324        &mut self,
325        _output: &mut [Self::Value],
326        _output_index: usize,
327    ) -> Result<usize, Self::DecodeError> {
328        Ok(0)
329    }
330
331    /// Decodes one value from `input` starting at `input_index`.
332    ///
333    /// # Parameters
334    ///
335    /// - `input`: Source unit buffer.
336    /// - `input_index`: Start index in `input`.
337    ///
338    /// # Returns
339    ///
340    /// Returns the decoded value and the non-zero number of consumed units.
341    ///
342    /// # Errors
343    ///
344    /// Returns [`DecodeFailure::Incomplete`] when the visible input is a
345    /// valid prefix but more units are needed to decide or complete a value.
346    /// This reports a streaming boundary, not a final EOF condition; the
347    /// caller or higher-level adapter decides what an incomplete tail means
348    /// when the upstream source is closed.
349    /// Returns [`DecodeFailure::Invalid`] when the units are malformed,
350    /// non-canonical, unmappable, or otherwise invalid for this codec. The
351    /// concrete error type carries only codec-domain invalidity.
352    /// Implementations must leave their internal state consistent when
353    /// returning an error.
354    ///
355    /// # Safety
356    ///
357    /// The caller must guarantee that `input_index` is a valid boundary in
358    /// `input` and that at least
359    /// [`MIN_UNITS_PER_VALUE`](Self::MIN_UNITS_PER_VALUE)
360    /// units are readable from `input_index`. Implementations must not read
361    /// beyond the currently available units under that precondition. They
362    /// may return [`DecodeFailure::Incomplete`] when those units are a
363    /// valid but incomplete prefix.
364    ///
365    /// On success, implementations must return a consumed unit count no larger
366    /// than the available input. The return type guarantees that successful
367    /// decoding always consumes at least one unit. Implementations should use
368    /// `debug_assert!` to state these unchecked entry-point assumptions.
369    #[must_use = "decoded value, consumed length, and decode errors must be handled"]
370    unsafe fn decode(
371        &mut self,
372        input: &[Self::Unit],
373        input_index: usize,
374    ) -> Result<(Self::Value, NonZeroUsize), DecodeFailure<Self::DecodeError>>;
375
376    /// Flushes decode-side EOF state into `output`.
377    ///
378    /// `decode_flush` receives no source input. Callers must have already
379    /// handled any tail reported by [`DecodeFailure::Incomplete`] before
380    /// flushing decode state. Implementations may emit retained values or
381    /// validate internal EOF state, but they must not depend on re-reading the
382    /// incomplete source tail.
383    ///
384    /// # Parameters
385    ///
386    /// - `output`: Destination value buffer.
387    /// - `output_index`: Start index in `output`.
388    ///
389    /// # Returns
390    ///
391    /// Returns the number of flushed values written.
392    ///
393    /// # Errors
394    ///
395    /// Returns `Self::DecodeError` when retained decode state is invalid at
396    /// EOF. Implementations must leave their internal state consistent when
397    /// returning an error.
398    ///
399    /// # Safety
400    ///
401    /// The caller must guarantee that the implementation can write up to
402    /// [`MAX_DECODE_FLUSH_VALUES`](Self::MAX_DECODE_FLUSH_VALUES) values
403    /// starting at `output_index`.
404    #[inline(always)]
405    #[must_use = "flush output length and flush errors must be handled"]
406    unsafe fn decode_flush(
407        &mut self,
408        _output: &mut [Self::Value],
409        _output_index: usize,
410    ) -> Result<usize, Self::DecodeError> {
411        Ok(0)
412    }
413}
414
415/// Compile-time asserts the public unit-bound invariant required by [`Codec`].
416///
417/// # Type Parameters
418///
419/// - `C`: Codec implementation to validate.
420///
421/// # Returns
422///
423/// Returns unit `()`.
424///
425/// # Panics
426///
427/// Panics at compile time when [`Codec::MIN_UNITS_PER_VALUE`] is greater than
428/// [`Codec::MAX_UNITS_PER_VALUE`], because the invariant must hold for any
429/// well-formed [`Codec`] implementation and violating it is always a bug.
430#[inline(always)]
431pub(crate) fn assert_unit_bounds<C>()
432where
433    C: Codec,
434{
435    const {
436        assert!(
437            C::MIN_UNITS_PER_VALUE.get() <= C::MAX_UNITS_PER_VALUE.get(),
438            "Codec::MIN_UNITS_PER_VALUE must not exceed Codec::MAX_UNITS_PER_VALUE",
439        );
440    }
441}