Skip to main content

qubit_codec/value/
codec_value_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//! Value encoder adapter backed by a low-level codec.
11
12use super::ValueEncoder;
13use crate::{
14    Codec,
15    codec::assert_unit_bounds,
16};
17
18/// Encodes one borrowed value into owned units by using a [`Codec`].
19///
20/// `CodecValueEncoder` is the default bridge from the low-level unchecked
21/// [`Codec`] contract to the convenience-layer [`ValueEncoder`] contract. It
22/// allocates `codec.max_units_per_value()` output units, calls
23/// [`Codec::encode_unchecked`] with the borrowed value, then truncates the owned
24/// output to the number of units actually written.
25///
26/// # Type Parameters
27///
28/// - `C`: Low-level codec used to encode one value.
29#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
30pub struct CodecValueEncoder<C> {
31    /// Low-level codec used for one-value encoding.
32    codec: C,
33}
34
35impl<C> CodecValueEncoder<C> {
36    /// Creates an encoder backed by `codec`.
37    ///
38    /// # Parameters
39    ///
40    /// - `codec`: Low-level codec used to encode one value.
41    ///
42    /// # Returns
43    ///
44    /// Returns a value encoder adapter for the supplied codec.
45    #[must_use]
46    #[inline(always)]
47    pub const fn new(codec: C) -> Self {
48        Self { codec }
49    }
50}
51
52impl<C> ValueEncoder<C::Value> for CodecValueEncoder<C>
53where
54    C: Codec,
55    C::Unit: Default,
56{
57    type Output = Vec<C::Unit>;
58    type Error = C::EncodeError;
59
60    /// Encodes one borrowed value into owned units.
61    ///
62    /// # Parameters
63    ///
64    /// - `input`: Value to encode.
65    ///
66    /// # Returns
67    ///
68    /// Returns the units written by the wrapped codec.
69    ///
70    /// # Errors
71    ///
72    /// Returns the wrapped codec's encode error when `input` cannot be
73    /// represented.
74    ///
75    /// # Panics
76    ///
77    /// Panics when the wrapped codec reports more written units than its
78    /// declared [`Codec::max_units_per_value`] bound.
79    fn encode(&self, input: &C::Value) -> Result<Self::Output, Self::Error> {
80        assert_unit_bounds::<C>(&self.codec);
81        let mut output = vec![C::Unit::default(); self.codec.max_units_per_value().get()];
82        // SAFETY: The output buffer is allocated to the codec's declared maximum
83        // width, which is the safety precondition for one-value encoding.
84        let written = unsafe { self.codec.encode_unchecked(input, &mut output, 0) }?;
85        assert!(
86            written <= output.len(),
87            "Codec::encode_unchecked wrote beyond allocated output",
88        );
89        output.truncate(written);
90        Ok(output)
91    }
92}