Skip to main content

qubit_codec/buffered/
codec_buffered_encoder.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Buffered encoder adapter backed by a low-level codec.
11
12use super::{
13    BufferedEncoder,
14    BufferedTranscoder,
15    FinishError,
16    TranscodeProgress,
17    buffered_encode_engine::BufferedEncodeEngine,
18    codec_buffered_encode_hooks::CodecBufferedEncodeHooks,
19};
20use crate::{
21    CapacityError,
22    Codec,
23    CodecEncodeError,
24};
25
26/// Encodes values into caller-provided output units by using a [`Codec`].
27///
28/// `CodecBufferedEncoder` is the default bridge from the low-level unchecked
29/// [`Codec`] contract to the buffered [`BufferedTranscoder`] and [`BufferedEncoder`]
30/// contracts. It encodes complete values only; when the remaining output
31/// capacity is smaller than `codec.max_units_per_value()`, it stops before
32/// consuming the next input value and reports [`crate::TranscodeStatus::NeedOutput`].
33///
34/// # Type Parameters
35///
36/// - `C`: Low-level codec used to encode values.
37#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
38pub struct CodecBufferedEncoder<C> {
39    /// Common buffered encoding engine.
40    engine: BufferedEncodeEngine<C, CodecBufferedEncodeHooks>,
41}
42
43impl<C> CodecBufferedEncoder<C>
44where
45    C: Codec,
46{
47    /// Creates a buffered encoder backed by `codec`.
48    ///
49    /// # Parameters
50    ///
51    /// - `codec`: Low-level codec used to encode values.
52    ///
53    /// # Returns
54    ///
55    /// Returns a buffered encoder adapter for the supplied codec.
56    #[must_use]
57    #[inline(always)]
58    pub const fn new(codec: C) -> Self {
59        Self {
60            engine: BufferedEncodeEngine::new(codec, CodecBufferedEncodeHooks),
61        }
62    }
63}
64
65impl<C> BufferedTranscoder<C::Value, C::Unit> for CodecBufferedEncoder<C>
66where
67    C: Codec,
68{
69    type Error = CodecEncodeError<C::EncodeError>;
70
71    /// Returns the maximum number of output units needed for `input_len` values.
72    ///
73    /// # Parameters
74    ///
75    /// - `input_len`: Logical input values the caller plans to encode.
76    ///
77    /// # Returns
78    ///
79    /// Returns a conservative upper bound for output units.
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 units emitted by finishing internal state.
86    ///
87    /// # Returns
88    ///
89    /// Returns the number of units that may be emitted by finishing state.
90    #[inline(always)]
91    fn max_finish_output_len(&self) -> Result<usize, CapacityError> {
92        Ok(self.engine.max_finish_output_len())
93    }
94
95    /// Resets hook-owned state.
96    ///
97    /// # Returns
98    ///
99    /// Returns unit `()`.
100    #[inline(always)]
101    fn reset(&mut self) {
102        self.engine.reset();
103    }
104
105    /// Encodes values into the supplied output buffer.
106    ///
107    /// # Parameters
108    ///
109    /// - `input`: Input value slice.
110    /// - `input_index`: Absolute input index where encoding starts.
111    /// - `output`: Destination unit slice.
112    /// - `output_index`: Absolute output index where writing starts.
113    ///
114    /// # Returns
115    ///
116    /// Returns conversion progress for consumed input and produced output units.
117    ///
118    /// # Errors
119    ///
120    /// Returns an encode error when indices are invalid or when encoding cannot
121    /// continue under current policy.
122    #[inline(always)]
123    fn transcode(
124        &mut self,
125        input: &[C::Value],
126        input_index: usize,
127        output: &mut [C::Unit],
128        output_index: usize,
129    ) -> Result<TranscodeProgress, Self::Error> {
130        self.engine.transcode(input, input_index, output, output_index)
131    }
132
133    /// Finishes internally retained output after EOF.
134    ///
135    /// # Parameters
136    ///
137    /// - `output`: Destination unit slice for finalization output.
138    /// - `output_index`: Absolute output index where writing starts.
139    ///
140    /// # Returns
141    ///
142    /// Returns the number of units written by finalization.
143    ///
144    /// # Errors
145    ///
146    /// Returns a finish error if retained output cannot be fully emitted.
147    #[inline(always)]
148    fn finish(&mut self, output: &mut [C::Unit], output_index: usize) -> Result<usize, FinishError<Self::Error>> {
149        self.engine.finish(output, output_index)
150    }
151}
152
153impl<C> BufferedEncoder<C::Value, C::Unit> for CodecBufferedEncoder<C> where C: Codec {}