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