qubit_codec/codec.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Low-level value codec trait.
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 convenience
17/// APIs are responsible for checked buffer management, partial-input reporting,
18/// and owned 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, or avoid attempting an encode when the output buffer is too small.
25/// It is not a safety precondition for unchecked methods. The maximum is the
26/// conservative bound callers normally use to prove that unchecked reads and
27/// writes stay inside the provided buffers.
28///
29/// # Type Parameters
30///
31/// - `Value`: Logical value decoded from or encoded into the buffer. This may be
32/// a scalar such as `u64`, a `char`, or a fixed quantum such as `[u8; 3]`.
33/// - `Unit`: Buffer unit used by the encoded representation.
34///
35/// # Safety
36///
37/// Implementors must uphold the safety contract documented by
38/// [`decode_unchecked`](Self::decode_unchecked) and
39/// [`encode_unchecked`](Self::encode_unchecked). In particular, unchecked
40/// implementations must not read or write outside the caller-provided ranges.
41/// Implementations should use `debug_assert!` to state the expected buffer
42/// bounds at the unchecked entry point.
43pub unsafe trait Codec<Value, Unit: Copy> {
44 /// Error reported when decoding malformed units.
45 type DecodeError;
46
47 /// Error reported when encoding an unsupported value.
48 type EncodeError;
49
50 /// Returns the minimum possible unit count for one encoded value.
51 ///
52 /// This is a lower bound used by checked callers for planning and fast
53 /// impossibility checks. If a streaming decoder has fewer than this many
54 /// readable units, no complete value can be present at the current position.
55 /// If the stream has reached EOF, such a tail is necessarily incomplete;
56 /// otherwise the caller should read more input. Similarly, an encoder or
57 /// transcoder can avoid calling into the codec when the remaining output
58 /// capacity is smaller than this lower bound.
59 ///
60 /// This value does not prove that decoding or encoding will fit. For
61 /// variable-width representations, a value may require more units, up to
62 /// [`max_units_per_value`](Self::max_units_per_value). Callers must not use
63 /// this method as the safety precondition for
64 /// [`decode_unchecked`](Self::decode_unchecked) or
65 /// [`encode_unchecked`](Self::encode_unchecked).
66 ///
67 /// # Returns
68 ///
69 /// Returns a lower bound for one complete value. Variable-width codecs such
70 /// as LEB128 should return the shortest valid representation length. For
71 /// example, a UTF-16 byte codec can return `2`, while its maximum is `4`
72 /// because a surrogate pair needs four bytes.
73 #[must_use]
74 fn min_units_per_value(&self) -> usize;
75
76 /// Returns the maximum unit count needed to encode or decode one value.
77 ///
78 /// # Returns
79 ///
80 /// Returns an upper bound for one complete value or codec quantum.
81 #[must_use]
82 fn max_units_per_value(&self) -> usize;
83
84 /// Decodes one value from `input` starting at `index`.
85 ///
86 /// # Parameters
87 ///
88 /// - `input`: Source unit buffer.
89 /// - `index`: Start index in `input`.
90 ///
91 /// # Returns
92 ///
93 /// Returns the decoded value and the number of consumed units.
94 ///
95 /// # Errors
96 ///
97 /// Returns `Self::DecodeError` when the units are malformed for this codec.
98 ///
99 /// # Safety
100 ///
101 /// The caller must guarantee that the implementation can read enough units
102 /// for one complete value starting at `index`. For fixed-width codecs this
103 /// means at least [`max_units_per_value`](Self::max_units_per_value) units.
104 /// For variable-width codecs this means either a valid terminator appears
105 /// before that maximum, or the full maximum-width range is readable.
106 unsafe fn decode_unchecked(&self, input: &[Unit], index: usize) -> Result<(Value, usize), Self::DecodeError>;
107
108 /// Encodes one value into `output` starting at `index`.
109 ///
110 /// # Parameters
111 ///
112 /// - `value`: Value to encode.
113 /// - `output`: Destination unit buffer.
114 /// - `index`: Start index in `output`.
115 ///
116 /// # Returns
117 ///
118 /// Returns the number of written units.
119 ///
120 /// # Errors
121 ///
122 /// Returns `Self::EncodeError` when `value` cannot be represented by this
123 /// codec.
124 ///
125 /// # Safety
126 ///
127 /// The caller must guarantee that the implementation can write up to
128 /// [`max_units_per_value`](Self::max_units_per_value) units starting at
129 /// `index`.
130 unsafe fn encode_unchecked(
131 &self,
132 value: Value,
133 output: &mut [Unit],
134 index: usize,
135 ) -> Result<usize, Self::EncodeError>;
136}