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::CodecTranscodeDecodeHooks;
11use crate::{
12    CapacityError,
13    Codec,
14    CodecDecodeError,
15    TranscodeDecodeEngine,
16    TranscodeDecoder,
17    TranscodeError,
18    TranscodeProgress,
19    Transcoder,
20};
21
22/// Decodes encoded units into caller-provided value buffers by using a
23/// [`Codec`].
24///
25/// `CodecTranscodeDecoder` is a policy-free bridge from the low-level unchecked
26/// [`Codec`] contract to [`Transcoder`] and [`TranscodeDecoder`]. It
27/// leaves incomplete input tails in the caller-provided input slice; callers
28/// own input-buffer refill and EOF incomplete-tail policy.
29///
30/// # Type Parameters
31///
32/// - `C`: Low-level codec used to decode values.
33#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
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    #[must_use]
53    #[inline]
54    pub fn new(codec: C) -> Self {
55        Self {
56            engine: TranscodeDecodeEngine::new(
57                codec,
58                CodecTranscodeDecodeHooks,
59            ),
60        }
61    }
62}
63
64impl<C> Transcoder<C::Unit, C::Value> for CodecTranscodeDecoder<C>
65where
66    C: Codec,
67{
68    type Error = CodecDecodeError<C::DecodeError>;
69
70    /// Returns an upper bound for decoded values produced from `input_len`
71    /// units.
72    ///
73    /// # Parameters
74    ///
75    /// - `input_len`: Source units the caller plans to decode.
76    ///
77    /// # Returns
78    ///
79    /// Returns a conservative upper bound for decoded values.
80    #[inline(always)]
81    fn max_output_len(&self, input_len: usize) -> Result<usize, CapacityError> {
82        self.engine.max_output_len(input_len)
83    }
84
85    /// Returns the maximum values emitted by finishing internal state.
86    ///
87    /// # Returns
88    ///
89    /// Returns the number of values that may still be emitted by finishing
90    /// state.
91    #[inline(always)]
92    fn max_finish_output_len(&self) -> Result<usize, CapacityError> {
93        self.engine.max_finish_output_len()
94    }
95
96    /// Returns the maximum values emitted when resetting internal state.
97    #[inline(always)]
98    fn max_reset_output_len(&self) -> Result<usize, CapacityError> {
99        Ok(self.engine.max_reset_output_len())
100    }
101
102    /// Resets codec decode state and hook-owned state.
103    #[inline(always)]
104    fn reset(
105        &mut self,
106        output: &mut [C::Value],
107        output_index: usize,
108    ) -> Result<usize, TranscodeError<Self::Error>> {
109        self.engine.reset(output, output_index)
110    }
111
112    /// Decodes source units into logical values.
113    ///
114    /// # Parameters
115    ///
116    /// - `input`: Source unit slice.
117    /// - `input_index`: Absolute source index where decoding starts.
118    /// - `output`: Destination value slice.
119    /// - `output_index`: Absolute output value index where writing starts.
120    ///
121    /// # Returns
122    ///
123    /// Returns conversion progress for consumed and written counters.
124    ///
125    /// # Errors
126    ///
127    /// Returns a decode error when indices are invalid or when conversion fails
128    /// under hook policy.
129    #[inline(always)]
130    fn transcode(
131        &mut self,
132        input: &[C::Unit],
133        input_index: usize,
134        output: &mut [C::Value],
135        output_index: usize,
136    ) -> Result<TranscodeProgress, TranscodeError<Self::Error>> {
137        self.engine
138            .transcode(input, input_index, output, output_index)
139    }
140
141    /// Finishes internally retained output after EOF.
142    ///
143    /// # Parameters
144    ///
145    /// - `output`: Destination value slice for final retained values.
146    /// - `output_index`: Absolute output value index where writing starts.
147    ///
148    /// # Returns
149    ///
150    /// Returns the number of values written by finalization.
151    ///
152    /// # Errors
153    ///
154    /// Returns a finish error if finalization cannot complete.
155    #[inline(always)]
156    fn finish(
157        &mut self,
158        output: &mut [C::Value],
159        output_index: usize,
160    ) -> Result<usize, TranscodeError<Self::Error>> {
161        self.engine.finish(output, output_index)
162    }
163}
164
165impl<C> TranscodeDecoder<C::Unit, C::Value> for CodecTranscodeDecoder<C> where
166    C: Codec
167{
168}