qubit_codec/value/codec_value_decoder.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//! Value decoder adapter backed by a low-level codec.
9
10use core::fmt;
11
12use qubit_utils::try_reserve_vec;
13
14use super::DecodeLifecycleOutput;
15use super::DecodeLifecycleProgress;
16use super::ValueDecoder;
17use crate::Codec;
18use crate::TranscodeDecodeErrorOf;
19use crate::TranscodeFailure;
20use crate::codec::assert_unit_bounds;
21use crate::value::codec_value_lifecycle::decode_exact_complete_value;
22
23/// Decodes one encoded unit slice into one owned value by using a [`Codec`].
24///
25/// `CodecValueDecoder` is the default bridge from the low-level unchecked
26/// [`Codec`] contract to the convenience-layer [`ValueDecoder`] contract. The
27/// supplied input slice must contain exactly one encoded value. The adapter
28/// runs the complete decode lifecycle, including [`Codec::decode_finish`],
29/// before returning the decoded value.
30///
31/// # Type Parameters
32///
33/// - `C`: Low-level codec used to decode one value.
34///
35/// # Examples
36///
37/// ```
38/// use std::convert::Infallible;
39/// use std::num::NonZeroUsize;
40///
41/// use qubit_codec::Codec;
42/// use qubit_codec::CodecValueDecoder;
43/// use qubit_codec::DecodeFailure;
44///
45/// struct Identity;
46/// impl Codec for Identity {
47/// type Value = u8;
48/// type Unit = u8;
49/// type DecodeError = Infallible;
50/// type EncodeError = Infallible;
51/// const MIN_UNITS_PER_VALUE: usize = 1;
52/// const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
53/// const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
54/// unsafe fn decode(&mut self, input: &[u8], index: usize)
55/// -> Result<(u8, NonZeroUsize), DecodeFailure<Infallible>> {
56/// Ok((input[index], NonZeroUsize::new(1).unwrap()))
57/// }
58/// unsafe fn encode(&mut self, value: &u8, output: &mut [u8], index: usize)
59/// -> Result<usize, Infallible> {
60/// output[index] = *value;
61/// Ok(1)
62/// }
63/// }
64/// let mut decoder = CodecValueDecoder::new(Identity);
65/// assert_eq!(decoder.decode(&[7]).unwrap(), 7);
66/// ```
67pub struct CodecValueDecoder<C>
68where
69 C: Codec,
70{
71 /// Low-level codec used for one-value decoding.
72 codec: C,
73}
74
75impl<C> CodecValueDecoder<C>
76where
77 C: Codec,
78{
79 /// Creates a decoder backed by `codec`.
80 ///
81 /// # Parameters
82 ///
83 /// - `codec`: Low-level codec used to decode one value.
84 ///
85 /// # Returns
86 ///
87 /// Returns a value decoder adapter for the supplied codec.
88 ///
89 /// # Panics
90 ///
91 /// Fails at compile time if codec decode bounds are zero or the minimum
92 /// exceeds the maximum.
93 #[inline]
94 #[must_use]
95 pub fn new(codec: C) -> Self {
96 assert_unit_bounds::<C>();
97 Self { codec }
98 }
99
100 /// Returns a shared reference to the wrapped codec.
101 ///
102 /// # Returns
103 ///
104 /// The codec borrowed for as long as the adapter is borrowed.
105 #[inline]
106 #[must_use]
107 pub const fn codec(&self) -> &C {
108 &self.codec
109 }
110
111 /// Returns a mutable reference to the wrapped codec.
112 ///
113 /// The next value operation starts a fresh codec lifecycle, so mutations
114 /// are applied to the following operation.
115 ///
116 /// # Returns
117 ///
118 /// An exclusive borrow of the codec without allocating.
119 #[inline]
120 #[must_use]
121 pub fn codec_mut(&mut self) -> &mut C {
122 &mut self.codec
123 }
124
125 /// Consumes the adapter and returns its wrapped codec.
126 ///
127 /// # Returns
128 ///
129 /// The owned codec, preserving its most recent lifecycle state.
130 #[inline]
131 #[must_use]
132 pub fn into_codec(self) -> C {
133 self.codec
134 }
135
136 /// Decodes exactly one encoded value from `input`.
137 ///
138 /// # Parameters
139 ///
140 /// - `input`: Encoded units for exactly one value.
141 ///
142 /// # Returns
143 ///
144 /// Returns the decoded value.
145 ///
146 /// Codecs that may emit decode reset or finish values must use
147 /// [`Self::decode_lifecycle`] or [`Self::decode_lifecycle_with_scratch`].
148 ///
149 /// # Errors
150 ///
151 /// Returns [`crate::TranscodeFailure::UnsupportedDecodeLifecycleOutput`]
152 /// before inspecting `input` or running codec hooks when reset or finish
153 /// may emit values. Returns
154 /// [`crate::TranscodeFailure::IncompleteInput`] when fewer than
155 /// [`Codec::MIN_UNITS_PER_VALUE`] units are available or when
156 /// [`crate::DecodeFailure::Incomplete`] is reported by the codec. In this
157 /// one-shot API, incomplete input is a terminal error rather than a
158 /// resumable streaming status. Returns a domain error when the wrapped
159 /// codec rejects or cannot finish the input. Returns
160 /// [`crate::TranscodeFailure::TrailingInput`] when a value is decoded but
161 /// extra input remains.
162 ///
163 /// # Panics
164 ///
165 /// Panics when the wrapped codec reports a consumed unit count larger than
166 /// the input slice length or [`Codec::MAX_DECODE_UNITS_PER_VALUE`].
167 pub fn decode(&mut self, input: &[C::Unit]) -> Result<C::Value, TranscodeDecodeErrorOf<C>> {
168 TranscodeFailure::ensure_no_decode_lifecycle_output::<C>()?;
169 let (value, reset_written, finish_written) =
170 decode_exact_complete_value(&mut self.codec, input, &mut [], &mut [])?;
171 debug_assert_eq!(0, reset_written);
172 debug_assert_eq!(0, finish_written);
173 Ok(value)
174 }
175
176 /// Decodes exactly one value and preserves all lifecycle output.
177 ///
178 /// # Parameters
179 ///
180 /// - `input`: Encoded units for exactly one value.
181 ///
182 /// # Returns
183 ///
184 /// Returns reset values, the main decoded value, and finish values in
185 /// separate owned buffers.
186 ///
187 /// # Errors
188 ///
189 /// Returns a framework error when input is incomplete or has trailing
190 /// units. Returns a phase-aware domain error when reset, decode, or finish
191 /// fails. Returns an allocation failure when either lifecycle buffer cannot
192 /// reserve its declared capacity.
193 ///
194 /// # Panics
195 ///
196 /// Panics when the wrapped codec violates its declared reset, decode, or
197 /// finish bounds.
198 pub fn decode_lifecycle(
199 &mut self,
200 input: &[C::Unit],
201 ) -> Result<DecodeLifecycleOutput<C::Value>, TranscodeDecodeErrorOf<C>>
202 where
203 C::Value: Default,
204 {
205 let mut reset = Vec::new();
206 try_reserve_vec(&mut reset, C::MAX_DECODE_RESET_VALUES).map_err(|_| TranscodeFailure::allocation_failed())?;
207 reset.resize_with(C::MAX_DECODE_RESET_VALUES, C::Value::default);
208 let mut finish = Vec::new();
209 try_reserve_vec(&mut finish, C::MAX_DECODE_FINISH_VALUES).map_err(|_| TranscodeFailure::allocation_failed())?;
210 finish.resize_with(C::MAX_DECODE_FINISH_VALUES, C::Value::default);
211 let (value, reset_written, finish_written) = self
212 .decode_lifecycle_with_scratch(input, &mut reset, &mut finish)?
213 .into_parts();
214 reset.truncate(reset_written);
215 finish.truncate(finish_written);
216 Ok(DecodeLifecycleOutput::new(reset, value, finish))
217 }
218
219 /// Decodes exactly one value into separate lifecycle output buffers.
220 ///
221 /// # Parameters
222 ///
223 /// - `input`: Encoded units for exactly one value.
224 /// - `reset_output`: Destination for values emitted by decode reset.
225 /// - `finish_output`: Destination for values emitted by decode finish.
226 ///
227 /// # Returns
228 ///
229 /// Returns the main decoded value and the initialized lengths of both
230 /// lifecycle output buffers.
231 ///
232 /// # Errors
233 ///
234 /// Returns a framework error before running any lifecycle hook when either
235 /// output buffer is shorter than its corresponding codec bound. Also
236 /// returns incomplete-input, trailing-input, or phase-aware domain errors.
237 ///
238 /// # Panics
239 ///
240 /// Panics when the wrapped codec violates its declared reset, decode, or
241 /// finish bounds.
242 pub fn decode_lifecycle_with_scratch(
243 &mut self,
244 input: &[C::Unit],
245 reset_output: &mut [C::Value],
246 finish_output: &mut [C::Value],
247 ) -> Result<DecodeLifecycleProgress<C::Value>, TranscodeDecodeErrorOf<C>> {
248 let (value, reset_written, finish_written) =
249 decode_exact_complete_value(&mut self.codec, input, reset_output, finish_output)?;
250 Ok(DecodeLifecycleProgress::new(value, reset_written, finish_written))
251 }
252}
253
254impl<C> ValueDecoder<[C::Unit]> for CodecValueDecoder<C>
255where
256 C: Codec,
257{
258 /// Owned value returned after the complete decode lifecycle.
259 type Output = C::Value;
260 /// Framework or phase-aware codec failure from one-value decoding.
261 type Error = TranscodeDecodeErrorOf<C>;
262
263 /// Decodes one value through the owned-value adapter.
264 ///
265 /// # Parameters
266 ///
267 /// - `input`: Complete encoded representation of exactly one value.
268 ///
269 /// # Returns
270 ///
271 /// The owned decoded value after finishing the codec lifecycle.
272 ///
273 /// # Errors
274 ///
275 /// Returns the same unsupported-lifecycle, incomplete-input,
276 /// trailing-input, and codec errors as [`Self::decode`].
277 ///
278 /// # Panics
279 ///
280 /// Panics if the codec reports consumption beyond its bounds or the input.
281 fn decode(&mut self, input: &[C::Unit]) -> Result<Self::Output, Self::Error> {
282 self.decode(input)
283 }
284}
285
286impl<C> fmt::Debug for CodecValueDecoder<C>
287where
288 C: Codec + fmt::Debug,
289{
290 /// Formats the decoder without requiring finished values to be printable.
291 ///
292 /// # Parameters
293 ///
294 /// - `formatter`: Destination and formatting options.
295 ///
296 /// # Returns
297 ///
298 /// Unit on successful formatting.
299 ///
300 /// # Errors
301 ///
302 /// Returns the formatter error if writing the codec representation fails.
303 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
304 formatter
305 .debug_struct("CodecValueDecoder")
306 .field("codec", &self.codec)
307 .finish()
308 }
309}
310
311impl<C> Default for CodecValueDecoder<C>
312where
313 C: Codec + Default,
314{
315 /// Creates a decoder from the default codec.
316 ///
317 /// # Returns
318 ///
319 /// An adapter owning `C::default()`.
320 ///
321 /// # Panics
322 ///
323 /// Fails at compile time for invalid codec decode bounds, as [`Self::new`].
324 /// May panic if the codec's own default constructor panics.
325 fn default() -> Self {
326 Self::new(C::default())
327 }
328}