use qubit_codec::{
Codec,
CodecValueEncoder,
TranscodeEncodeError,
ValueEncoder,
};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct PairByteCodec;
impl Codec for PairByteCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 2;
const MAX_DECODE_UNITS_PER_VALUE: usize = 2;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
debug_assert!(input_index < input.len());
let value = unsafe { *input.as_ptr().add(input_index) };
Ok((value, core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
debug_assert!(output_index + 2 <= output.len());
unsafe {
*output.as_mut_ptr().add(output_index) = *value;
*output.as_mut_ptr().add(output_index + 1) = value.wrapping_add(1);
}
Ok(2)
}
}
#[test]
fn test_codec_value_encoder_exposes_codec_accessors() {
let mut encoder = CodecValueEncoder::new(PairByteCodec);
assert_eq!(&PairByteCodec, encoder.codec());
*encoder.codec_mut() = PairByteCodec;
assert_eq!(PairByteCodec, encoder.into_codec());
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct RejectOddCodec;
impl Codec for RejectOddCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = &'static str;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
fn can_encode_value(&self, value: &u8) -> bool {
value.is_multiple_of(2)
}
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
debug_assert!(input_index < input.len());
let value = unsafe { *input.as_ptr().add(input_index) };
Ok((value, core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
debug_assert!(self.can_encode_value(value));
debug_assert!(output_index < output.len());
unsafe {
*output.as_mut_ptr().add(output_index) = *value;
}
Ok(1)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct OverreportingEncodeCodec;
impl Codec for OverreportingEncodeCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
debug_assert!(input_index < input.len());
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
debug_assert!(output_index < output.len());
output[output_index] = *value;
Ok(2)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct FailingEncodeCodec;
impl Codec for FailingEncodeCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = &'static str;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
if *value == 7 {
Err("encode failed")
} else {
output[output_index] = *value;
Ok(1)
}
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct AppendOverflowCodec;
impl Codec for AppendOverflowCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_RESET_UNITS: usize = usize::MAX - 1;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = *value;
Ok(1)
}
}
#[derive(Debug, Default, Eq, PartialEq)]
struct NonCloneValue {
value: u8,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct NonCloneValueCodec;
impl Codec for NonCloneValueCodec {
type Value = NonCloneValue;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(NonCloneValue, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
debug_assert!(input_index < input.len());
let value = unsafe { *input.as_ptr().add(input_index) };
Ok((NonCloneValue { value }, core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &NonCloneValue,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
debug_assert!(output_index < output.len());
unsafe {
*output.as_mut_ptr().add(output_index) = value.value;
}
Ok(1)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct ResetFailLifecycleCodec {
fail_reset: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
#[error("reset failed")]
struct ResetFailError;
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct FinishFailLifecycleCodec {
fail_finish: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
#[error("finish failed")]
struct FinishFailError;
impl Codec for ResetFailLifecycleCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = ResetFailError;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_RESET_UNITS: usize = 1;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = *value;
Ok(1)
}
unsafe fn encode_reset(
&mut self,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
if self.fail_reset {
Err(ResetFailError)
} else {
output[output_index] = 0xfe;
Ok(1)
}
}
}
impl Codec for FinishFailLifecycleCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = FinishFailError;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_FINISH_UNITS: usize = 1;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = *value;
Ok(1)
}
unsafe fn encode_finish(
&mut self,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
if self.fail_finish {
Err(FinishFailError)
} else {
output[output_index] = 0xff;
Ok(1)
}
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct OverflowEncodeBoundCodec;
impl Codec for OverflowEncodeBoundCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_RESET_UNITS: usize = usize::MAX;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = *value;
Ok(1)
}
}
#[derive(Debug, Default)]
struct ResetWidthCodec {
reset: bool,
}
impl Codec for ResetWidthCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 2;
const MAX_DECODE_UNITS_PER_VALUE: usize = 2;
fn encode_len(&self, _value: &u8) -> usize {
if self.reset { 2 } else { 1 }
}
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
assert!(self.reset, "encode must observe reset state");
output[output_index] = *value;
output[output_index + 1] = value.wrapping_add(1);
Ok(2)
}
unsafe fn encode_reset(
&mut self,
_output: &mut [u8],
_output_index: usize,
) -> Result<usize, Self::EncodeError> {
self.reset = true;
Ok(0)
}
unsafe fn encode_finish(
&mut self,
_output: &mut [u8],
_output_index: usize,
) -> Result<usize, Self::EncodeError> {
self.reset = false;
Ok(0)
}
}
#[derive(Debug, Default)]
struct OversizedResetWidthCodec;
impl Codec for OversizedResetWidthCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_RESET_UNITS: usize = 1;
fn encode_len(&self, _value: &u8) -> usize {
2
}
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = *value;
output[output_index + 1] = value.wrapping_add(1);
Ok(2)
}
}
#[derive(Debug, Default)]
struct ResetDomainCodec {
reset: bool,
}
impl Codec for ResetDomainCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
fn can_encode_value(&self, _value: &u8) -> bool {
self.reset
}
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
assert!(self.reset, "encode must observe reset domain");
output[output_index] = *value;
Ok(1)
}
unsafe fn encode_reset(
&mut self,
_output: &mut [u8],
_output_index: usize,
) -> Result<usize, Self::EncodeError> {
self.reset = true;
Ok(0)
}
unsafe fn encode_finish(
&mut self,
_output: &mut [u8],
_output_index: usize,
) -> Result<usize, Self::EncodeError> {
self.reset = false;
Ok(0)
}
}
#[derive(Default)]
struct StatefulLifecycleCodec {
encode_state: usize,
}
impl Codec for StatefulLifecycleCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
const MIN_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
const MAX_ENCODE_RESET_UNITS: usize = 1;
const MAX_ENCODE_FINISH_UNITS: usize = 1;
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<
(u8, core::num::NonZeroUsize),
qubit_codec::DecodeFailure<Self::DecodeError>,
> {
Ok((input[input_index], core::num::NonZeroUsize::MIN))
}
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = value.wrapping_add(self.encode_state as u8);
self.encode_state += 1;
Ok(1)
}
unsafe fn encode_reset(
&mut self,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = 0xfe;
self.encode_state = 1;
Ok(1)
}
unsafe fn encode_finish(
&mut self,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
output[output_index] = self.encode_state as u8;
self.encode_state = 0;
Ok(1)
}
}
#[test]
fn test_codec_value_encoder_runs_complete_encode_lifecycle() {
let mut encoder = CodecValueEncoder::<StatefulLifecycleCodec>::new(
StatefulLifecycleCodec::default(),
);
let output = ValueEncoder::<u8>::encode(&mut encoder, &41)
.expect("encoding should be infallible");
assert_eq!(vec![0xfe, 42, 2], output);
}
#[test]
fn test_codec_value_encoder_resets_stream_state_on_each_call() {
let mut encoder = CodecValueEncoder::<StatefulLifecycleCodec>::new(
StatefulLifecycleCodec::default(),
);
let first = ValueEncoder::<u8>::encode(&mut encoder, &41)
.expect("first encoding should be infallible");
let second = ValueEncoder::<u8>::encode(&mut encoder, &41)
.expect("second encoding should be infallible");
assert_eq!(vec![0xfe, 42, 2], first);
assert_eq!(vec![0xfe, 42, 2], second);
}
#[test]
fn test_codec_value_encoder_queries_width_after_reset() {
let mut encoder =
CodecValueEncoder::<ResetWidthCodec>::new(ResetWidthCodec::default());
let output = ValueEncoder::<u8>::encode(&mut encoder, &41)
.expect("reset-state width should be reserved");
assert_eq!(vec![41, 42], output);
}
#[test]
#[should_panic(
expected = "Codec::encode_len exceeded Codec::MAX_ENCODE_UNITS_PER_VALUE"
)]
fn test_codec_value_encoder_rejects_reset_state_width_beyond_maximum() {
let mut encoder = CodecValueEncoder::<OversizedResetWidthCodec>::new(
OversizedResetWidthCodec,
);
let _ = ValueEncoder::<u8>::encode(&mut encoder, &41);
}
#[test]
fn test_codec_value_encoder_checks_domain_after_reset() {
let mut encoder =
CodecValueEncoder::<ResetDomainCodec>::new(ResetDomainCodec::default());
let output = ValueEncoder::<u8>::encode(&mut encoder, &41)
.expect("reset-state domain should accept the value");
assert_eq!(vec![41], output);
}
#[test]
fn test_codec_value_encoder_default_and_debug() {
let encoder = CodecValueEncoder::<PairByteCodec>::default();
let debug = format!("{encoder:?}");
assert!(debug.contains("CodecValueEncoder"));
assert!(debug.contains("codec"));
}
#[test]
fn test_codec_value_encoder_encodes_one_value_to_owned_units() {
let mut encoder = CodecValueEncoder::<PairByteCodec>::new(PairByteCodec);
let output = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect("encoding should be infallible");
assert_eq!(vec![7, 8], output);
}
#[test]
fn test_codec_value_encoder_encode_into_appends_to_existing_vec() {
let mut encoder = CodecValueEncoder::<PairByteCodec>::new(PairByteCodec);
let mut output = vec![0xaa];
let written = encoder
.encode_into(&7, &mut output)
.expect("encoding into caller Vec should be infallible");
assert_eq!(2, written);
assert_eq!(vec![0xaa, 7, 8], output);
}
#[test]
fn test_codec_value_encoder_accepts_non_clone_values() {
let mut encoder =
CodecValueEncoder::<NonCloneValueCodec>::new(NonCloneValueCodec);
let output = ValueEncoder::<NonCloneValue>::encode(
&mut encoder,
&NonCloneValue { value: 11 },
)
.expect("encoding should not require cloning the value");
assert_eq!(vec![11], output);
}
#[test]
fn test_codec_value_encoder_propagates_encode_error() {
let mut encoder = CodecValueEncoder::<RejectOddCodec>::new(RejectOddCodec);
let output = ValueEncoder::<u8>::encode(&mut encoder, &8)
.expect("even value should be encoded");
assert_eq!(vec![8], output);
let error = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect_err("odd value should be rejected");
assert_eq!(TranscodeEncodeError::unencodable_without_context(0), error,);
}
#[test]
fn test_codec_value_encoder_truncates_output_after_encode_error() {
let mut encoder =
CodecValueEncoder::<FailingEncodeCodec>::new(FailingEncodeCodec);
let mut output = vec![0xaa];
let error = encoder
.encode_into(&7, &mut output)
.expect_err("codec encode error should be propagated");
assert!(matches!(
error,
TranscodeEncodeError::Domain(qubit_codec::TranscodeDomainError::Main {
source: "encode failed",
input_index: 0,
input_consumed: None
})
),);
assert_eq!(vec![0xaa], output);
let written = encoder
.encode_into(&8, &mut output)
.expect("non-failing value should be appended");
assert_eq!(1, written);
assert_eq!(vec![0xaa, 8], output);
}
#[test]
fn test_codec_value_encoder_rejects_output_length_overflow() {
let mut encoder = CodecValueEncoder::<OverflowEncodeBoundCodec>::new(
OverflowEncodeBoundCodec,
);
let error = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect_err("reset plus value bound should overflow");
assert_eq!(
qubit_codec::TranscodeEncodeError::Failure(
qubit_codec::TranscodeFailure::output_length_overflow()
),
error
);
}
#[test]
fn test_codec_value_encoder_encode_into_rejects_bound_overflow() {
let mut encoder = CodecValueEncoder::<OverflowEncodeBoundCodec>::new(
OverflowEncodeBoundCodec,
);
let mut output = vec![0xaa];
let error = encoder
.encode_into(&7, &mut output)
.expect_err("reset plus value bound should overflow");
assert_eq!(
qubit_codec::TranscodeEncodeError::Failure(
qubit_codec::TranscodeFailure::output_length_overflow()
),
error
);
assert_eq!(vec![0xaa], output);
}
#[test]
fn test_codec_value_encoder_reports_allocation_failure() {
let mut encoder =
CodecValueEncoder::<AppendOverflowCodec>::new(AppendOverflowCodec);
let error = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect_err("unrepresentable allocation should be reported");
assert_eq!(
qubit_codec::TranscodeEncodeError::Failure(
qubit_codec::TranscodeFailure::allocation_failed()
),
error
);
}
#[test]
fn test_codec_value_encoder_encode_into_rejects_target_len_overflow() {
let mut encoder =
CodecValueEncoder::<AppendOverflowCodec>::new(AppendOverflowCodec);
let mut output = vec![0xaa];
let error = encoder
.encode_into(&7, &mut output)
.expect_err("appending encoded units should report length overflow");
assert_eq!(
qubit_codec::TranscodeEncodeError::Failure(
qubit_codec::TranscodeFailure::output_length_overflow()
),
error
);
assert_eq!(vec![0xaa], output);
}
#[test]
#[should_panic(
expected = "Codec::encode wrote a different length than Codec::encode_len"
)]
fn test_codec_value_encoder_panics_when_codec_reports_wrong_value_width() {
let mut encoder = CodecValueEncoder::<OverreportingEncodeCodec>::new(
OverreportingEncodeCodec,
);
let _ = ValueEncoder::<u8>::encode(&mut encoder, &7);
}
#[test]
fn test_codec_value_encoder_propagates_encode_reset_error() {
let mut encoder = CodecValueEncoder::<ResetFailLifecycleCodec>::new(
ResetFailLifecycleCodec { fail_reset: true },
);
let error = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect_err("encode reset failure should propagate");
assert_eq!(TranscodeEncodeError::domain_reset(ResetFailError), error,);
let mut encoder = CodecValueEncoder::<ResetFailLifecycleCodec>::new(
ResetFailLifecycleCodec { fail_reset: false },
);
let output = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect("successful reset mode should encode");
assert_eq!(vec![0xfe, 7], output);
}
#[test]
fn test_codec_value_encoder_propagates_encode_finish_error() {
let mut encoder = CodecValueEncoder::<FinishFailLifecycleCodec>::new(
FinishFailLifecycleCodec { fail_finish: true },
);
let error = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect_err("encode finish failure should propagate");
assert_eq!(TranscodeEncodeError::domain_finish(FinishFailError), error,);
let mut encoder = CodecValueEncoder::<FinishFailLifecycleCodec>::new(
FinishFailLifecycleCodec { fail_finish: false },
);
let output = ValueEncoder::<u8>::encode(&mut encoder, &7)
.expect("successful finish mode should encode");
assert_eq!(vec![7, 0xff], output);
}