Skip to main content

qubit_codec/transcode/adapter/
codec_transcode_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//! Buffered decoder adapter backed by a low-level codec.
9
10use super::super::engine::TranscodeDecodeEngine;
11use super::CodecTranscodeDecodeHooks;
12use crate::CapacityError;
13use crate::Codec;
14use crate::TranscodeDecodeErrorOf;
15use crate::TranscodeDecoder;
16use crate::TranscodeProgress;
17use crate::Transcoder;
18
19/// Decodes encoded units into caller-provided value buffers by using a
20/// [`Codec`].
21///
22/// `CodecTranscodeDecoder` is a policy-free bridge from the low-level unchecked
23/// [`Codec`] contract to [`Transcoder`] and [`TranscodeDecoder`]. It
24/// leaves incomplete input tails in the caller-provided input slice while the
25/// stream remains open. Call [`Transcoder::transcode_eof`] after upstream EOF
26/// so codecs can apply their [`Codec::decode_eof`] policy to a trailing prefix.
27///
28/// # Type Parameters
29///
30/// - `C`: Low-level codec used to decode values.
31#[derive(Debug, Default)]
32pub struct CodecTranscodeDecoder<C> {
33    /// Common buffered decoding engine.
34    engine: TranscodeDecodeEngine<C, CodecTranscodeDecodeHooks>,
35}
36
37impl<C> CodecTranscodeDecoder<C>
38where
39    C: Codec,
40{
41    /// Creates a buffered decoder backed by `codec`.
42    ///
43    /// # Parameters
44    ///
45    /// - `codec`: Low-level codec used to decode values.
46    ///
47    /// # Returns
48    ///
49    /// Returns a buffered decoder adapter for the supplied codec.
50    #[inline]
51    #[must_use]
52    pub fn new(codec: C) -> Self {
53        Self {
54            engine: TranscodeDecodeEngine::new(codec, CodecTranscodeDecodeHooks),
55        }
56    }
57
58    /// Returns a shared reference to the wrapped codec.
59    #[inline(always)]
60    #[must_use]
61    pub fn codec(&self) -> &C {
62        self.engine.codec()
63    }
64
65    /// Returns a mutable reference to the wrapped codec.
66    ///
67    /// Mutating a codec during an active stream can invalidate that stream's
68    /// assumptions; reset the adapter before continuing with the new codec
69    /// configuration.
70    #[inline(always)]
71    #[must_use]
72    pub fn codec_mut(&mut self) -> &mut C {
73        self.engine.codec_mut()
74    }
75
76    /// Consumes the adapter and returns its wrapped codec.
77    ///
78    /// Any buffered lifecycle state and internal hooks are discarded.
79    #[inline(always)]
80    #[must_use]
81    pub fn into_codec(self) -> C {
82        self.engine.into_parts().0
83    }
84}
85
86impl<C> Transcoder for CodecTranscodeDecoder<C>
87where
88    C: Codec,
89{
90    type Input = C::Unit;
91    type Output = C::Value;
92    type Error = TranscodeDecodeErrorOf<C>;
93
94    /// Returns an upper bound for decoded values produced from `input_len`
95    /// units.
96    ///
97    /// # Parameters
98    ///
99    /// - `input_len`: Source units the caller plans to decode.
100    ///
101    /// # Returns
102    ///
103    /// Returns a conservative upper bound for decoded values.
104    #[inline(always)]
105    fn max_transcode_output_len(&self, input_len: usize) -> Result<usize, CapacityError> {
106        self.engine.max_transcode_output_len(input_len)
107    }
108
109    /// Returns the global maximum values emitted by finishing internal state.
110    ///
111    /// # Returns
112    ///
113    /// Returns the number of values that may still be emitted by finishing
114    /// state.
115    #[inline(always)]
116    fn max_finish_output_len(&self) -> Result<usize, CapacityError> {
117        self.engine.max_finish_output_len()
118    }
119
120    /// Returns the global maximum values emitted when resetting internal state.
121    #[inline(always)]
122    fn max_reset_output_len(&self) -> Result<usize, CapacityError> {
123        self.engine.max_reset_output_len()
124    }
125
126    /// Runs before-reset cleanup for decoder state.
127    #[inline(always)]
128    fn reset(&mut self, output: &mut [C::Value], output_index: usize) -> Result<usize, TranscodeDecodeErrorOf<C>> {
129        self.engine.reset(output, output_index)
130    }
131
132    /// Decodes source units into logical values.
133    ///
134    /// # Parameters
135    ///
136    /// - `input`: Source unit slice.
137    /// - `input_index`: Absolute source index where decoding starts.
138    /// - `output`: Destination value slice.
139    /// - `output_index`: Absolute output value index where writing starts.
140    ///
141    /// # Returns
142    ///
143    /// Returns conversion progress for consumed and written counters.
144    ///
145    /// # Errors
146    ///
147    /// Returns a decode error when indices are invalid or when conversion fails
148    /// under hook policy.
149    #[inline(always)]
150    fn transcode(
151        &mut self,
152        input: &[C::Unit],
153        input_index: usize,
154        output: &mut [C::Value],
155        output_index: usize,
156    ) -> Result<TranscodeProgress, TranscodeDecodeErrorOf<C>> {
157        self.engine.transcode(input, input_index, output, output_index)
158    }
159
160    #[inline(always)]
161    fn transcode_eof(
162        &mut self,
163        input: &[C::Unit],
164        input_index: usize,
165        output: &mut [C::Value],
166        output_index: usize,
167    ) -> Result<TranscodeProgress, TranscodeDecodeErrorOf<C>> {
168        self.engine.transcode_eof(input, input_index, output, output_index)
169    }
170
171    /// Finishes internally retained output after EOF.
172    ///
173    /// # Parameters
174    ///
175    /// - `output`: Destination value slice for final retained values.
176    /// - `output_index`: Absolute output value index where writing starts.
177    ///
178    /// # Returns
179    ///
180    /// Returns the number of values written by finalization.
181    ///
182    /// # Errors
183    ///
184    /// Returns a finish error if finalization cannot complete.
185    #[inline(always)]
186    fn finish(&mut self, output: &mut [C::Value], output_index: usize) -> Result<usize, TranscodeDecodeErrorOf<C>> {
187        self.engine.finish(output, output_index)
188    }
189}
190
191impl<C> TranscodeDecoder for CodecTranscodeDecoder<C>
192where
193    C: Codec,
194{
195    type DecodeError = C::DecodeError;
196}