use qubit_codec::{
EncodeContext,
EncodePlan,
TranscodeEncodeHooks,
};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct UnitCodec;
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
#[error("encode failed")]
struct UnitEncodeError;
unsafe impl qubit_codec::Codec for UnitCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = UnitEncodeError;
fn min_units_per_value(&self) -> core::num::NonZeroUsize {
core::num::NonZeroUsize::MIN
}
fn max_units_per_value(&self) -> core::num::NonZeroUsize {
core::num::NonZeroUsize::MIN
}
fn max_encode_reset_units(&self) -> usize {
1
}
unsafe fn decode(
&mut self,
input: &[u8],
index: usize,
) -> Result<(u8, core::num::NonZeroUsize), Self::DecodeError> {
Ok((input[index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
index: usize,
) -> Result<core::num::NonZeroUsize, Self::EncodeError> {
output[index] = *value;
Ok(qubit_io::nz!(1))
}
unsafe fn encode_reset(
&mut self,
_output: &mut [u8],
_index: usize,
) -> Result<usize, Self::EncodeError> {
Err(UnitEncodeError)
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
struct DefaultOnlyHooks;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
struct DefaultResetHooks;
impl TranscodeEncodeHooks<UnitCodec> for DefaultOnlyHooks {
type Error = UnitEncodeError;
type PlanAction = ();
fn prepare_encode(
&mut self,
_codec: &mut UnitCodec,
_input_value: &u8,
_input_index: usize,
) -> Result<EncodePlan<Self::PlanAction>, Self::Error> {
Ok(EncodePlan::new(1, ()))
}
unsafe fn write_encode(
&mut self,
_codec: &mut UnitCodec,
context: EncodeContext<'_, u8, u8>,
_plan: EncodePlan<Self::PlanAction>,
) -> Result<usize, Self::Error> {
context.output[context.output_index] = *context.input_value;
Ok(1)
}
}
impl TranscodeEncodeHooks<UnitCodec> for DefaultResetHooks {
type Error = UnitEncodeError;
type PlanAction = ();
fn prepare_encode(
&mut self,
_codec: &mut UnitCodec,
_input_value: &u8,
_input_index: usize,
) -> Result<EncodePlan<Self::PlanAction>, Self::Error> {
Ok(EncodePlan::new(1, ()))
}
fn map_encode_reset_error(
&mut self,
_codec: &mut UnitCodec,
error: UnitEncodeError,
) -> Self::Error {
error
}
unsafe fn write_encode(
&mut self,
_codec: &mut UnitCodec,
context: EncodeContext<'_, u8, u8>,
_plan: EncodePlan<Self::PlanAction>,
) -> Result<usize, Self::Error> {
context.output[context.output_index] = *context.input_value;
Ok(1)
}
}
#[test]
#[should_panic(
expected = "TranscodeEncodeHooks::map_encode_reset_error must be implemented for fallible reset codecs"
)]
fn test_transcode_encode_hooks_default_map_encode_reset_error_panics() {
let mut hooks = DefaultOnlyHooks;
let mut codec = UnitCodec;
let _ = TranscodeEncodeHooks::<UnitCodec>::map_encode_reset_error(
&mut hooks,
&mut codec,
UnitEncodeError,
);
}
#[test]
fn test_transcode_encode_hooks_default_write_encode_reset_maps_errors() {
let mut hooks = DefaultResetHooks;
let mut codec = UnitCodec;
let mut output = [0_u8; 1];
let error = unsafe {
TranscodeEncodeHooks::<UnitCodec>::write_encode_reset(
&mut hooks,
&mut codec,
&mut output,
0,
)
}
.expect_err("default reset writer should map codec reset errors");
assert_eq!(UnitEncodeError, error);
}
#[test]
fn test_transcode_encode_hooks_default_finish_is_noop() {
let mut hooks = DefaultOnlyHooks;
let mut codec = UnitCodec;
let mut output = [0_u8; 1];
let written = TranscodeEncodeHooks::<UnitCodec>::finish(
&mut hooks,
&mut codec,
&mut output,
0,
)
.expect("default finish should be a no-op");
assert_eq!(0, written);
}