Skip to main content

qubit_codec/transcode/adapter/
codec_transcode_encoder.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 encoder adapter backed by a low-level codec.
9
10use super::super::engine::TranscodeEncodeEngine;
11use super::CodecTranscodeEncodeHooks;
12use crate::CapacityError;
13use crate::Codec;
14use crate::TranscodeEncodeErrorOf;
15use crate::TranscodeEncoder;
16use crate::TranscodeProgress;
17use crate::Transcoder;
18
19/// Encodes values into caller-provided output units by using a [`Codec`].
20///
21/// `CodecTranscodeEncoder` is the default bridge from the low-level unchecked
22/// [`Codec`] contract to the buffered [`Transcoder`] and
23/// [`TranscodeEncoder`] contracts. It encodes complete values only; when the
24/// remaining output capacity is smaller than `codec.encode_len(value)`, it
25/// stops before consuming that input value and reports
26/// [`crate::TranscodeStatus::NeedOutput`].
27///
28/// # Type Parameters
29///
30/// - `C`: Low-level codec used to encode values.
31#[derive(Debug)]
32pub struct CodecTranscodeEncoder<C> {
33    /// Common buffered encoding engine.
34    engine: TranscodeEncodeEngine<C, CodecTranscodeEncodeHooks>,
35}
36
37impl<C> CodecTranscodeEncoder<C>
38where
39    C: Codec,
40{
41    /// Creates a buffered encoder backed by `codec`.
42    ///
43    /// # Parameters
44    ///
45    /// - `codec`: Low-level codec used to encode values.
46    ///
47    /// # Returns
48    ///
49    /// Returns a buffered encoder adapter for the supplied codec.
50    #[inline]
51    #[must_use]
52    pub fn new(codec: C) -> Self {
53        Self {
54            engine: TranscodeEncodeEngine::new(codec, CodecTranscodeEncodeHooks),
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 CodecTranscodeEncoder<C>
87where
88    C: Codec,
89{
90    type Input = C::Value;
91    type Output = C::Unit;
92    type Error = TranscodeEncodeErrorOf<C>;
93
94    /// Gets the maximum number of output units needed for `input_len`
95    /// values.
96    ///
97    /// # Parameters
98    ///
99    /// - `input_len`: Logical input values the caller plans to encode.
100    ///
101    /// # Returns
102    ///
103    /// a conservative upper bound for output units.
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    /// Gets the global maximum units emitted when resetting internal state.
110    ///
111    /// # Returns
112    ///
113    /// the maximum units emitted when resetting internal state.
114    #[inline(always)]
115    fn max_reset_output_len(&self) -> Result<usize, CapacityError> {
116        self.engine.max_reset_output_len()
117    }
118
119    /// Gets the global maximum units emitted by finishing internal state.
120    ///
121    /// # Returns
122    ///
123    /// the number of units that may be emitted by finishing state.
124    #[inline(always)]
125    fn max_finish_output_len(&self) -> Result<usize, CapacityError> {
126        self.engine.max_finish_output_len()
127    }
128
129    /// Runs before-reset cleanup and emits stream-start output.
130    #[inline(always)]
131    fn reset(&mut self, output: &mut [C::Unit], output_index: usize) -> Result<usize, TranscodeEncodeErrorOf<C>> {
132        self.engine.reset(output, output_index)
133    }
134
135    /// Encodes values into the supplied output buffer.
136    ///
137    /// # Parameters
138    ///
139    /// - `input`: Input value slice.
140    /// - `input_index`: Absolute input index where encoding starts.
141    /// - `output`: Destination unit slice.
142    /// - `output_index`: Absolute output index where writing starts.
143    ///
144    /// # Returns
145    ///
146    /// Returns conversion progress for consumed input and produced output
147    /// units.
148    ///
149    /// # Errors
150    ///
151    /// Returns an encode error when indices are invalid or when encoding cannot
152    /// continue under current policy.
153    #[inline(always)]
154    fn transcode(
155        &mut self,
156        input: &[C::Value],
157        input_index: usize,
158        output: &mut [C::Unit],
159        output_index: usize,
160    ) -> Result<TranscodeProgress, TranscodeEncodeErrorOf<C>> {
161        self.engine.transcode(input, input_index, output, output_index)
162    }
163
164    /// Finishes internally retained output after EOF.
165    ///
166    /// # Parameters
167    ///
168    /// - `output`: Destination unit slice for finalization output.
169    /// - `output_index`: Absolute output index where writing starts.
170    ///
171    /// # Returns
172    ///
173    /// Returns the number of units written by finalization.
174    ///
175    /// # Errors
176    ///
177    /// Returns a finish error if retained output cannot be fully emitted.
178    #[inline(always)]
179    fn finish(&mut self, output: &mut [C::Unit], output_index: usize) -> Result<usize, TranscodeEncodeErrorOf<C>> {
180        self.engine.finish(output, output_index)
181    }
182}
183
184impl<C> TranscodeEncoder for CodecTranscodeEncoder<C>
185where
186    C: Codec,
187{
188    type EncodeError = C::EncodeError;
189}
190
191impl<C> Default for CodecTranscodeEncoder<C>
192where
193    C: Codec + Default,
194{
195    /// Creates a default codec-backed buffered encoder.
196    ///
197    /// # Returns
198    ///
199    /// Returns an encoder backed by `C::default()`.
200    #[inline(always)]
201    fn default() -> Self {
202        Self::new(C::default())
203    }
204}