use core::fmt;
use qubit_utils::try_reserve_vec;
use super::ValueEncoder;
use crate::CapacityError;
use crate::Codec;
use crate::TranscodeEncodeErrorOf;
use crate::TranscodeFailure;
use crate::codec::assert_unit_bounds;
use crate::value::codec_value_lifecycle::encode_complete_value_into_reserved;
use crate::value::codec_value_lifecycle::max_complete_encode_units;
pub struct CodecValueEncoder<C> {
codec: C,
}
impl<C> CodecValueEncoder<C>
where
C: Codec,
{
#[inline]
#[must_use]
pub fn new(codec: C) -> Self {
assert_unit_bounds::<C>();
Self { codec }
}
#[inline]
#[must_use = "use the reference to inspect the wrapped codec"]
pub const fn codec(&self) -> &C {
&self.codec
}
#[inline]
#[must_use = "use the reference to update the wrapped codec"]
pub fn codec_mut(&mut self) -> &mut C {
&mut self.codec
}
#[inline]
#[must_use]
pub fn into_codec(self) -> C {
self.codec
}
pub fn encode_into(
&mut self,
input: &C::Value,
output: &mut Vec<C::Unit>,
) -> Result<usize, TranscodeEncodeErrorOf<C>>
where
C::Unit: Default,
{
let units = max_complete_encode_units::<C>()?;
let original_len = output.len();
let target_len = original_len
.checked_add(units)
.ok_or(CapacityError::OutputLengthOverflow)?;
try_reserve_vec(output, units).map_err(|_| TranscodeFailure::allocation_failed())?;
output.resize_with(target_len, C::Unit::default);
match encode_complete_value_into_reserved(&mut self.codec, input, output, original_len, units) {
Ok(written) => {
output.truncate(original_len + written);
Ok(written)
}
Err(error) => {
output.truncate(original_len);
Err(error)
}
}
}
}
impl<C> ValueEncoder<C::Value> for CodecValueEncoder<C>
where
C: Codec,
C::Unit: Default,
{
type Output = Vec<C::Unit>;
type Error = TranscodeEncodeErrorOf<C>;
fn encode(&mut self, input: &C::Value) -> Result<Self::Output, Self::Error> {
let mut output = Vec::new();
self.encode_into(input, &mut output)?;
Ok(output)
}
}
impl<C> fmt::Debug for CodecValueEncoder<C>
where
C: Codec + fmt::Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("CodecValueEncoder")
.field("codec", &self.codec)
.finish()
}
}
impl<C> Default for CodecValueEncoder<C>
where
C: Codec + Default,
{
#[inline]
fn default() -> Self {
Self::new(C::default())
}
}