use qubit_codec::prelude::{
BigEndian,
BufferedConvertHooks,
BufferedConverter,
BufferedDecoder,
BufferedEncoder,
ByteOrder,
ByteOrderSpec,
Codec,
CodecBufferedConverter,
CodecBufferedDecoder,
CodecBufferedEncoder,
CodecConvertError,
CodecDecodeError,
CodecEncodeError,
CodecValueDecoder,
CodecValueEncoder,
EncodeContext,
EncodePlan,
FinishError,
TranscodeProgress,
TranscodeStatus,
ValueDecoder,
ValueEncoder,
};
#[derive(Default)]
struct EchoCodec;
impl ValueEncoder<str> for EchoCodec {
type Output = String;
type Error = core::convert::Infallible;
fn encode(&self, input: &str) -> Result<Self::Output, Self::Error> {
Ok(input.to_owned())
}
}
impl ValueDecoder<str> for EchoCodec {
type Output = String;
type Error = core::convert::Infallible;
fn decode(&self, input: &str) -> Result<Self::Output, Self::Error> {
Ok(input.to_owned())
}
}
unsafe impl Codec for EchoCodec {
type Value = u8;
type Unit = u8;
type DecodeError = core::convert::Infallible;
type EncodeError = core::convert::Infallible;
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
}
unsafe fn decode_unchecked(
&self,
input: &[u8],
index: usize,
) -> Result<(u8, core::num::NonZeroUsize), Self::DecodeError> {
debug_assert!(index < input.len());
let value = unsafe { *input.as_ptr().add(index) };
Ok((value, core::num::NonZeroUsize::MIN))
}
unsafe fn encode_unchecked(&self, value: &u8, output: &mut [u8], index: usize) -> Result<usize, Self::EncodeError> {
debug_assert!(index < output.len());
unsafe {
*output.as_mut_ptr().add(index) = *value;
}
Ok(1)
}
}
#[test]
fn test_prelude_imports_core_codec_traits_and_markers() {
fn _accept_buffered_encoder<T: BufferedEncoder<char, u8>>() {}
fn _accept_buffered_decoder<T: BufferedDecoder<u8, char>>() {}
fn _accept_buffered_converter<T: BufferedConverter<u8, u16>>() {}
fn _accept_codec_value_encoder<T: ValueEncoder<u8, Output = Vec<u8>>>() {}
fn _accept_codec_value_decoder<T: ValueDecoder<[u8], Output = u8>>() {}
fn _accept_codec_buffered_encoder<T: BufferedEncoder<u8, u8>>() {}
fn _accept_codec_buffered_decoder<T: BufferedDecoder<u8, u8>>() {}
fn _accept_codec_buffered_converter<T: BufferedConverter<u8, u8>>() {}
fn _accept_buffered_decode_engine<T>() {}
fn _accept_buffered_encode_engine<T>() {}
fn _accept_buffered_convert_engine<T>() {}
fn _accept_buffered_decode_hooks<T: qubit_codec::BufferedDecodeHooks<EchoCodec>>() {}
fn _accept_buffered_encode_hooks<T: qubit_codec::BufferedEncodeHooks<EchoCodec>>() {}
fn _accept_buffered_convert_hooks<T: BufferedConvertHooks<EchoCodec, EchoCodec>>() {}
assert_eq!(ByteOrder::BigEndian, BigEndian::ORDER);
_accept_codec_value_encoder::<CodecValueEncoder<EchoCodec>>();
_accept_codec_value_decoder::<CodecValueDecoder<EchoCodec>>();
_accept_codec_buffered_encoder::<CodecBufferedEncoder<EchoCodec>>();
_accept_codec_buffered_decoder::<CodecBufferedDecoder<EchoCodec>>();
_accept_codec_buffered_converter::<CodecBufferedConverter<EchoCodec, EchoCodec>>();
_accept_buffered_decode_engine::<qubit_codec::BufferedDecodeEngine<EchoCodec, ()>>();
_accept_buffered_encode_engine::<qubit_codec::BufferedEncodeEngine<EchoCodec, ()>>();
let codec = EchoCodec;
let encoded = ValueEncoder::<str>::encode(&codec, "abc").expect("echo encode should be infallible");
let decoded = ValueDecoder::<str>::decode(&codec, &encoded).expect("echo decode should be infallible");
assert_eq!("abc", decoded);
let progress = TranscodeProgress::complete(1, 2);
assert_eq!(TranscodeStatus::Complete, progress.status());
assert_eq!(
FinishError::<core::convert::Infallible>::InvalidOutputIndex { index: 1, len: 0 },
FinishError::invalid_output_index(1, 0),
);
let decode_error = CodecDecodeError::<core::convert::Infallible>::incomplete(0, 2, 1);
assert!(matches!(
decode_error,
CodecDecodeError::Incomplete {
input_index: 0,
required_total: 2,
available: 1,
}
));
let convert_error = CodecConvertError::<core::convert::Infallible, core::convert::Infallible>::decode(decode_error);
assert!(matches!(convert_error, CodecConvertError::Decode { .. }));
let encode_error = CodecEncodeError::<core::convert::Infallible>::invalid_output_index(2, 1);
assert!(matches!(encode_error, CodecEncodeError::InvalidOutputIndex { .. }));
let convert_error = CodecConvertError::<core::convert::Infallible, core::convert::Infallible>::encode(encode_error);
assert!(matches!(
convert_error,
CodecConvertError::Encode {
source: CodecEncodeError::InvalidOutputIndex { .. },
},
));
let mut output = [0_u8; 1];
let context = EncodeContext {
input_value: &1_u8,
input_index: 0,
output: &mut output,
output_index: 0,
};
assert_eq!(0, context.input_index);
assert_eq!(1, context.available_output());
let encode_plan = EncodePlan::new(3, "action");
assert_eq!(3, encode_plan.max_output_units);
assert_eq!("action", encode_plan.action);
let (decoded, consumed) = unsafe { codec.decode_unchecked(&[1], 0) }.expect("decode should be infallible");
assert_eq!((1, 1), (decoded, consumed.get()));
}