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