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
12/// Encodes and decodes one value or codec quantum against a unit buffer.
13///
14/// `Codec` is the lowest-level abstraction in the codec stack. It is intended
15/// for hot paths that have already validated buffer capacity and want to avoid
16/// constructing subslices for every value. Higher-level transcoders and
17/// convenience APIs are responsible for checked buffer management and owned
18/// output allocation.
19///
20/// `min_units_per_value` and `max_units_per_value` describe the representation
21/// width bounds for one value. The minimum is a lower-bound hint for checked
22/// layers: if fewer than this many units are available, no complete value can
23/// exist, so a streaming caller can request more input, report an incomplete
24/// EOF tail. For decoding, this minimum is the smallest safety precondition
25/// checked callers must satisfy before entering
26/// [`decode`](Self::decode). The maximum is a value-independent upper bound
27/// callers can use for coarse capacity planning. For encoding a known value,
28/// checked callers should reserve the exact [`encode_len`](Self::encode_len)
29/// instead of pessimistically reserving the maximum width.
30///
31/// A codec may keep decode-side and encode-side stream state. That state is an
32/// implementation detail owned by the codec. Callers do not snapshot or restore
33/// it; implementations must keep their own state internally consistent across
34/// every public operation, including operations that return `Err`.
35///
36/// # Associated Types
37///
38/// - `Value`: Logical value decoded from or encoded into the buffer. This may
39///   be a scalar such as `u8`, `u16`, `u64`, a `char`, or a fixed quantum such
40///   as `[u8; 3]`. The trait can model other small value objects, but it is
41///   intentionally aimed at copyable value-domain types rather than owned
42///   resource handles or heap-backed aggregates. Implementations must provide
43///   [`Copy`] and [`Default`] so checked adapters can pass values by copy and
44///   allocate flush scratch buffers.
45/// - `Unit`: Buffer unit used by the encoded representation. Implementations
46///   are typically scalar storage units such as `u8`, `u16`, or `char`.
47///   Implementations must provide [`Copy`] and [`Default`] so checked adapters
48///   can allocate output unit buffers and initialize caller-owned scratch
49///   storage.
50///
51/// # Safety
52///
53/// Implementors must uphold the safety contract documented by
54/// [`decode`](Self::decode), [`encode`](Self::encode),
55/// [`encode_reset`](Self::encode_reset), and
56/// [`decode_flush`](Self::decode_flush). In particular, unchecked
57/// implementations must not read or write outside the caller-provided ranges.
58/// Implementations should use `debug_assert!` to state the expected buffer
59/// bounds at the unchecked entry point.
60///
61/// Implementations must also guarantee that
62/// [`min_units_per_value`](Self::min_units_per_value) is less than or equal to
63/// [`max_units_per_value`](Self::max_units_per_value). Both bounds are non-zero
64/// by type, and `max_units_per_value` must be a valid upper bound for one
65/// complete encoded value or codec quantum. Checked adapters assert this
66/// invariant before using codec-provided bounds.
67pub unsafe trait Codec {
68    /// The type of logical values decoded from or encoded into the buffer.
69    type Value: Copy + Default;
70
71    /// The type of buffer units used by the encoded representation.
72    type Unit: Copy + Default;
73
74    /// The type of errors reported when decoding malformed units.
75    type DecodeError;
76
77    /// The type of errors reported when encoding an unsupported value.
78    type EncodeError;
79
80    /// Returns the minimum possible unit count for one encoded value.
81    ///
82    /// This is a lower bound used by checked callers for planning and fast
83    /// impossibility checks. If a streaming decoder has fewer than this many
84    /// readable units, no complete value can be present at the current
85    /// position. If the stream has reached EOF, such a tail is necessarily
86    /// incomplete; otherwise the caller should read more input. Similarly,
87    /// an encoder or transcoder can avoid calling into the codec when the
88    /// remaining output capacity is smaller than this lower bound.
89    ///
90    /// This value does not prove that encoding will fit. For variable-width
91    /// representations, a value may require more units, up to
92    /// [`max_units_per_value`](Self::max_units_per_value). For decoding, this
93    /// is the minimum safety precondition required by
94    /// [`decode`](Self::decode); if fewer units are
95    /// available, a checked caller must request more input or report a closed
96    /// incomplete tail without calling into the unchecked method.
97    ///
98    /// # Returns
99    ///
100    /// Returns a non-zero lower bound for one complete value. Variable-width
101    /// codecs such as LEB128 should return the shortest valid representation
102    /// length. For example, a UTF-16 byte codec can return `2`, while its
103    /// maximum is `4` because a surrogate pair needs four bytes.
104    #[must_use]
105    fn min_units_per_value(&self) -> NonZeroUsize;
106
107    /// Returns the maximum non-zero unit count needed to encode or decode one
108    /// value.
109    ///
110    /// # Returns
111    ///
112    /// Returns an upper bound for one complete value or codec quantum.
113    #[must_use]
114    fn max_units_per_value(&self) -> NonZeroUsize;
115
116    /// Returns whether `value` is in this codec's encodable value domain.
117    ///
118    /// The default implementation returns `true`, which is correct for codecs
119    /// whose [`Value`](Self::Value) type contains only values they can encode.
120    /// Codecs whose logical value type is broader than their representation
121    /// domain, such as an ASCII codec with `Value = char`, must override this
122    /// method.
123    ///
124    /// Checked encoder adapters call this method before querying
125    /// [`encode_len`](Self::encode_len) or entering the unsafe
126    /// [`encode`](Self::encode) method. Direct unsafe callers must do the same.
127    ///
128    /// # Parameters
129    ///
130    /// - `value`: Value whose encodability is queried.
131    ///
132    /// # Returns
133    ///
134    /// Returns `true` when `value` may be passed to
135    /// [`encode_len`](Self::encode_len) and [`encode`](Self::encode).
136    #[inline(always)]
137    #[must_use]
138    fn can_encode_value(&self, _value: &Self::Value) -> bool {
139        true
140    }
141
142    /// Returns the exact non-zero unit count this codec will write when
143    /// encoding `value`.
144    ///
145    /// The default implementation returns
146    /// [`max_units_per_value`](Self::max_units_per_value), which is the
147    /// conservative bound callers can use when no specific value is available.
148    /// Fixed-width codecs do not need to override this method.
149    ///
150    /// Variable-width codecs (LEB128, UTF-8, GB18030, …) should override this
151    /// to report the true encoded length for encodable `value`s. Doing so lets
152    /// buffered adapters and stream writers reserve only what is actually
153    /// needed and enables capacity probing without performing the encode.
154    /// Default codec-backed encoders use this exact value for per-value output
155    /// capacity. The contract requires callers to use this method only when
156    /// [`can_encode_value`](Self::can_encode_value) returned `true` for the
157    /// same `value`. Under that precondition, the returned length must equal
158    /// the unit count [`encode`](Self::encode) writes for the same `value`
159    /// under the same codec state, and must never exceed
160    /// [`max_units_per_value`](Self::max_units_per_value).
161    ///
162    /// # Parameters
163    ///
164    /// - `value`: Value whose encoded length is queried.
165    ///
166    /// # Returns
167    ///
168    /// Returns the non-zero unit count [`encode`](Self::encode) will write for
169    /// an encodable `value`.
170    #[inline(always)]
171    #[must_use]
172    fn encode_len(&self, _value: &Self::Value) -> NonZeroUsize {
173        self.max_units_per_value()
174    }
175
176    /// Returns the maximum unit count emitted when resetting encode state.
177    ///
178    /// Stateful encoders may need a stream-start sequence, such as a byte order
179    /// mark, before the first encoded value. Buffered encoders use this bound
180    /// to reserve output capacity before calling
181    /// [`encode_reset`](Self::encode_reset).
182    ///
183    /// # Returns
184    ///
185    /// Returns the finite reset-output upper bound. Stateless codecs should
186    /// use the default `0`.
187    #[inline(always)]
188    #[must_use]
189    fn max_encode_reset_units(&self) -> usize {
190        0
191    }
192
193    /// Returns the maximum value count emitted when flushing decode state.
194    ///
195    /// Stateful decoders may need to produce final values at EOF from retained
196    /// state. Buffered decoders use this bound to reserve output capacity
197    /// before calling [`decode_flush`](Self::decode_flush).
198    ///
199    /// # Returns
200    ///
201    /// Returns the finite flush-output upper bound. Stateless codecs should
202    /// use the default `0`.
203    #[inline(always)]
204    #[must_use]
205    fn max_decode_flush_values(&self) -> usize {
206        0
207    }
208
209    /// Emits stream-start output and resets encode-side state.
210    ///
211    /// # Parameters
212    ///
213    /// - `output`: Destination unit buffer.
214    /// - `index`: Start index in `output`.
215    ///
216    /// # Returns
217    ///
218    /// Returns the number of reset units written.
219    ///
220    /// # Errors
221    ///
222    /// Returns `Self::EncodeError` when reset output cannot be emitted.
223    /// Implementations must leave their internal state consistent when
224    /// returning an error.
225    ///
226    /// # Safety
227    ///
228    /// The caller must guarantee that the implementation can write up to
229    /// [`max_encode_reset_units`](Self::max_encode_reset_units) units starting
230    /// at `index`.
231    #[inline(always)]
232    #[must_use = "reset output and reset errors must be handled"]
233    unsafe fn encode_reset(
234        &mut self,
235        _output: &mut [Self::Unit],
236        _index: usize,
237    ) -> Result<usize, Self::EncodeError> {
238        Ok(0)
239    }
240
241    /// Encodes one borrowed value into `output` starting at `index`.
242    ///
243    /// # Parameters
244    ///
245    /// - `value`: Value to encode.
246    /// - `output`: Destination unit buffer.
247    /// - `index`: Start index in `output`.
248    ///
249    /// # Returns
250    ///
251    /// Returns the non-zero number of written units. A successful encode
252    /// always emits at least one unit; stateful encoders that need to defer
253    /// output should report that intent through a custom encode error
254    /// instead of returning a zero count.
255    ///
256    /// # Errors
257    ///
258    /// Returns `Self::EncodeError` for encode-side state or representation
259    /// failures other than a value being outside the codec's encodable domain.
260    /// Checked callers reject values for which
261    /// [`can_encode_value`](Self::can_encode_value) returns `false` before
262    /// entering this unsafe method. Implementations must leave their internal
263    /// state consistent when returning an error.
264    ///
265    /// # Safety
266    ///
267    /// The caller must guarantee that
268    /// [`can_encode_value`](Self::can_encode_value) returned `true` for
269    /// `value`, and that the implementation can write at least
270    /// [`encode_len`](Self::encode_len) units for the same `value` and codec
271    /// state starting at `index`. On success, implementations must return that
272    /// exact written unit count, and the count must be no larger than
273    /// [`max_units_per_value`](Self::max_units_per_value).
274    #[must_use = "encoded length and encode errors must be handled"]
275    unsafe fn encode(
276        &mut self,
277        value: &Self::Value,
278        output: &mut [Self::Unit],
279        index: usize,
280    ) -> Result<NonZeroUsize, Self::EncodeError>;
281
282    /// Decodes one value from `input` starting at `index`.
283    ///
284    /// # Parameters
285    ///
286    /// - `input`: Source unit buffer.
287    /// - `index`: Start index in `input`.
288    ///
289    /// # Returns
290    ///
291    /// Returns the decoded value and the non-zero number of consumed units.
292    ///
293    /// # Errors
294    ///
295    /// Returns `Self::DecodeError` when the units are malformed, non-canonical,
296    /// incomplete, or otherwise invalid for this codec. The concrete error type
297    /// carries the codec-specific reason and context. Implementations must
298    /// leave their internal state consistent when returning an error.
299    ///
300    /// # Safety
301    ///
302    /// The caller must guarantee that `index` is a valid boundary in `input`
303    /// and that at least [`min_units_per_value`](Self::min_units_per_value)
304    /// units are readable from `index`. Implementations must not read beyond
305    /// the currently available units under that precondition. They may
306    /// return `Self::DecodeError` when those units are a valid but
307    /// incomplete prefix.
308    ///
309    /// On success, implementations must return a consumed unit count no larger
310    /// than the available input. The return type guarantees that successful
311    /// decoding always consumes at least one unit. Implementations should use
312    /// `debug_assert!` to state these unchecked entry-point assumptions.
313    #[must_use = "decoded value, consumed length, and decode errors must be handled"]
314    unsafe fn decode(
315        &mut self,
316        input: &[Self::Unit],
317        index: usize,
318    ) -> Result<(Self::Value, NonZeroUsize), Self::DecodeError>;
319
320    /// Flushes decode-side EOF state into `output`.
321    ///
322    /// # Parameters
323    ///
324    /// - `output`: Destination value buffer.
325    /// - `index`: Start index in `output`.
326    ///
327    /// # Returns
328    ///
329    /// Returns the number of flushed values written.
330    ///
331    /// # Errors
332    ///
333    /// Returns `Self::DecodeError` when retained decode state is invalid at
334    /// EOF. Implementations must leave their internal state consistent when
335    /// returning an error.
336    ///
337    /// # Safety
338    ///
339    /// The caller must guarantee that the implementation can write up to
340    /// [`max_decode_flush_values`](Self::max_decode_flush_values) values
341    /// starting at `index`.
342    #[inline(always)]
343    #[must_use = "flush output length and flush errors must be handled"]
344    unsafe fn decode_flush(
345        &mut self,
346        _output: &mut [Self::Value],
347        _index: usize,
348    ) -> Result<usize, Self::DecodeError> {
349        Ok(0)
350    }
351}
352
353/// Asserts the public unit-bound invariant required by [`Codec`].
354///
355/// # Type Parameters
356///
357/// - `C`: Codec implementation to validate.
358///
359/// # Returns
360///
361/// Returns unit `()`.
362///
363/// # Panics
364///
365/// Panics when [`Codec::min_units_per_value`] is greater than
366/// [`Codec::max_units_per_value`].
367pub(crate) fn assert_unit_bounds<C>(codec: &C)
368where
369    C: Codec,
370{
371    assert!(
372        codec.min_units_per_value() <= codec.max_units_per_value(),
373        "Codec::min_units_per_value() must not exceed Codec::max_units_per_value()",
374    );
375}