Made arrays never encode their length (#625)

* Made arrays with 32 elements or less never encode their length

* Removed `write_fixed_array_length` and `skip_fixed_array_length` as this was based on incorrect assumptions on how serde and bincode 1 works

---------

Co-authored-by: Victor Koenders <victor.koenders@qrtech.se>
This commit is contained in:
Trangar 2023-03-30 15:09:33 +02:00 committed by GitHub
parent af4697e1fb
commit dc468b4bed
14 changed files with 146 additions and 206 deletions

View File

@ -22,18 +22,22 @@ where
// This is what bincode 1 serializes to. This will be our comparison value.
let encoded = bincode_1_options.serialize(t).unwrap();
println!("Encoded {:?} as {:?}", t, encoded);
println!("Encoded {t:?} as {encoded:?}");
// Test bincode 2 encode
let bincode_2_output = bincode_2::encode_to_vec(t, bincode_2_config).unwrap();
assert_eq!(encoded, bincode_2_output, "{:?} serializes differently", t);
assert_eq!(
encoded,
bincode_2_output,
"{t:?} serializes differently\nbincode 2 config {:?}",
core::any::type_name::<C>(),
);
// Test bincode 2 serde serialize
let bincode_2_serde_output = bincode_2::serde::encode_to_vec(t, bincode_2_config).unwrap();
assert_eq!(
encoded, bincode_2_serde_output,
"{:?} serializes differently",
t
"{t:?} serializes differently"
);
// Test bincode 1 deserialize

View File

@ -10,6 +10,83 @@ fn test() {
super::test_same(std::net::Ipv6Addr::LOCALHOST);
}
#[test]
fn test_arrays() {
// serde is known to be weird with arrays
// Arrays of length 32 and less are encoded as tuples, but arrays 33 and up are encoded as slices
// we need to make sure we're compatible with this
super::test_same([0u8; 0]);
super::test_same([1u8; 1]);
super::test_same([1u8, 2]);
super::test_same([1u8, 2, 3]);
super::test_same([1u8, 2, 3, 4]);
super::test_same([1u8, 2, 3, 4, 5]);
super::test_same([1u8, 2, 3, 4, 5, 6]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
super::test_same([1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31,
]);
super::test_same([
1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32,
]);
}
#[derive(
bincode_2::Encode, bincode_2::Decode, serde::Serialize, serde::Deserialize, Debug, PartialEq,
)]

View File

@ -126,7 +126,7 @@ assert_eq!(encoded.as_slice(), &[
# Arrays
Array length is encoded based on the `.write_fixed_array_length` and `.skip_fixed_array_length()` config. When an array length is written, it will be encoded as a `u64`.
Array length is never encoded.
Note that `&[T]` is encoded as a [Collection](#collections).
@ -135,15 +135,9 @@ Note that `&[T]` is encoded as a [Collection](#collections).
let arr: [u8; 5] = [10, 20, 30, 40, 50];
let encoded = bincode::encode_to_vec(arr, bincode::config::legacy()).unwrap();
assert_eq!(encoded.as_slice(), &[
5, 0, 0, 0, 0, 0, 0, 0, // The length, as a u64
10, 20, 30, 40, 50, // the bytes
]);
let encoded = bincode::encode_to_vec(arr, bincode::config::legacy().skip_fixed_array_length()).unwrap();
assert_eq!(encoded.as_slice(), &[
// no length
10, 20, 30, 40, 50, // the bytes
]);
```
This applies to any type `T` that implements `Encode`/`Decode`
@ -168,14 +162,6 @@ let arr: [Foo; 2] = [
let encoded = bincode::encode_to_vec(&arr, bincode::config::legacy()).unwrap();
assert_eq!(encoded.as_slice(), &[
2, 0, 0, 0, 0, 0, 0, 0, // Length of the array
10, 20, // First Foo
30, 40, // Second Foo
]);
let encoded = bincode::encode_to_vec(&arr, bincode::config::legacy().skip_fixed_array_length()).unwrap();
assert_eq!(encoded.as_slice(), &[
// no length
10, 20, // First Foo
30, 40, // Second Foo
]);

View File

@ -11,10 +11,7 @@
//! .with_little_endian()
//! // pick one of:
//! .with_variable_int_encoding()
//! .with_fixed_int_encoding()
//! // pick one of:
//! .skip_fixed_array_length()
//! .write_fixed_array_length();
//! .with_fixed_int_encoding();
//! ```
//!
//! See [Configuration] for more information on the configuration options.
@ -29,20 +26,16 @@ use core::marker::PhantomData;
///
/// - [with_little_endian] and [with_big_endian]
/// - [with_fixed_int_encoding] and [with_variable_int_encoding]
/// - [skip_fixed_array_length] and [write_fixed_array_length]
///
///
/// [with_little_endian]: #method.with_little_endian
/// [with_big_endian]: #method.with_big_endian
/// [with_fixed_int_encoding]: #method.with_fixed_int_encoding
/// [with_variable_int_encoding]: #method.with_variable_int_encoding
/// [skip_fixed_array_length]: #method.skip_fixed_array_length
/// [write_fixed_array_length]: #method.write_fixed_array_length
#[derive(Copy, Clone)]
pub struct Configuration<E = LittleEndian, I = Varint, A = WriteFixedArrayLength, L = NoLimit> {
pub struct Configuration<E = LittleEndian, I = Varint, L = NoLimit> {
_e: PhantomData<E>,
_i: PhantomData<I>,
_a: PhantomData<A>,
_l: PhantomData<L>,
}
@ -59,7 +52,6 @@ pub struct Configuration<E = LittleEndian, I = Varint, A = WriteFixedArrayLength
/// The default config for bincode 2.0. By default this will be:
/// - Little endian
/// - Variable int encoding
/// - Write fixed array length
pub const fn standard() -> Configuration {
generate()
}
@ -67,34 +59,32 @@ pub const fn standard() -> Configuration {
/// Creates the "legacy" default config. This is the default config that was present in bincode 1.0
/// - Little endian
/// - Fixed int length encoding
/// - Write fixed array length
pub const fn legacy() -> Configuration<LittleEndian, Fixint, WriteFixedArrayLength, NoLimit> {
pub const fn legacy() -> Configuration<LittleEndian, Fixint, NoLimit> {
generate()
}
impl<E, I, A, L> Default for Configuration<E, I, A, L> {
impl<E, I, L> Default for Configuration<E, I, L> {
fn default() -> Self {
generate()
}
}
const fn generate<E, I, A, L>() -> Configuration<E, I, A, L> {
const fn generate<E, I, L>() -> Configuration<E, I, L> {
Configuration {
_e: PhantomData,
_i: PhantomData,
_a: PhantomData,
_l: PhantomData,
}
}
impl<E, I, A, L> Configuration<E, I, A, L> {
impl<E, I, L> Configuration<E, I, L> {
/// Makes bincode encode all integer types in big endian.
pub const fn with_big_endian(self) -> Configuration<BigEndian, I, A, L> {
pub const fn with_big_endian(self) -> Configuration<BigEndian, I, L> {
generate()
}
/// Makes bincode encode all integer types in little endian.
pub const fn with_little_endian(self) -> Configuration<LittleEndian, I, A, L> {
pub const fn with_little_endian(self) -> Configuration<LittleEndian, I, L> {
generate()
}
@ -155,7 +145,7 @@ impl<E, I, A, L> Configuration<E, I, A, L> {
///
/// Note that u256 and the like are unsupported by this format; if and when they are added to the
/// language, they may be supported via the extension point given by the 255 byte.
pub const fn with_variable_int_encoding(self) -> Configuration<E, Varint, A, L> {
pub const fn with_variable_int_encoding(self) -> Configuration<E, Varint, L> {
generate()
}
@ -164,51 +154,29 @@ impl<E, I, A, L> Configuration<E, I, A, L> {
/// * Fixed size integers are encoded directly
/// * Enum discriminants are encoded as u32
/// * Lengths and usize are encoded as u64
pub const fn with_fixed_int_encoding(self) -> Configuration<E, Fixint, A, L> {
generate()
}
/// Skip writing the length of fixed size arrays (`[u8; N]`) before writing the array
///
/// **NOTE:** This is not supported if you're using the `bincode::serde::*` functions, the `#[bincode(with_serde)]` attribute, or the `Compat` struct.
pub const fn skip_fixed_array_length(self) -> Configuration<E, I, SkipFixedArrayLength, L> {
generate()
}
/// Write the length of fixed size arrays (`[u8; N]`) before writing the array
pub const fn write_fixed_array_length(self) -> Configuration<E, I, WriteFixedArrayLength, L> {
pub const fn with_fixed_int_encoding(self) -> Configuration<E, Fixint, L> {
generate()
}
/// Sets the byte limit to `limit`.
pub const fn with_limit<const N: usize>(self) -> Configuration<E, I, A, Limit<N>> {
pub const fn with_limit<const N: usize>(self) -> Configuration<E, I, Limit<N>> {
generate()
}
/// Clear the byte limit.
pub const fn with_no_limit(self) -> Configuration<E, I, A, NoLimit> {
pub const fn with_no_limit(self) -> Configuration<E, I, NoLimit> {
generate()
}
}
/// Indicates a type is valid for controlling the bincode configuration
pub trait Config:
InternalEndianConfig
+ InternalArrayLengthConfig
+ InternalIntEncodingConfig
+ InternalLimitConfig
+ Copy
+ Clone
InternalEndianConfig + InternalIntEncodingConfig + InternalLimitConfig + Copy + Clone
{
}
impl<T> Config for T where
T: InternalEndianConfig
+ InternalArrayLengthConfig
+ InternalIntEncodingConfig
+ InternalLimitConfig
+ Copy
+ Clone
T: InternalEndianConfig + InternalIntEncodingConfig + InternalLimitConfig + Copy + Clone
{
}
@ -244,22 +212,6 @@ impl InternalIntEncodingConfig for Varint {
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
}
/// Skip writing the length of fixed size arrays (`[u8; N]`) before writing the array.
#[derive(Copy, Clone)]
pub struct SkipFixedArrayLength {}
impl InternalArrayLengthConfig for SkipFixedArrayLength {
const SKIP_FIXED_ARRAY_LENGTH: bool = true;
}
/// Write the length of fixed size arrays (`[u8; N]`) before writing the array.
#[derive(Copy, Clone)]
pub struct WriteFixedArrayLength {}
impl InternalArrayLengthConfig for WriteFixedArrayLength {
const SKIP_FIXED_ARRAY_LENGTH: bool = false;
}
/// Sets an unlimited byte limit.
#[derive(Copy, Clone)]
pub struct NoLimit {}
@ -281,7 +233,7 @@ mod internal {
const ENDIAN: Endian;
}
impl<E: InternalEndianConfig, I, A, L> InternalEndianConfig for Configuration<E, I, A, L> {
impl<E: InternalEndianConfig, I, L> InternalEndianConfig for Configuration<E, I, L> {
const ENDIAN: Endian = E::ENDIAN;
}
@ -295,9 +247,7 @@ mod internal {
const INT_ENCODING: IntEncoding;
}
impl<E, I: InternalIntEncodingConfig, A, L> InternalIntEncodingConfig
for Configuration<E, I, A, L>
{
impl<E, I: InternalIntEncodingConfig, L> InternalIntEncodingConfig for Configuration<E, I, L> {
const INT_ENCODING: IntEncoding = I::INT_ENCODING;
}
@ -307,21 +257,11 @@ mod internal {
Variable,
}
pub trait InternalArrayLengthConfig {
const SKIP_FIXED_ARRAY_LENGTH: bool;
}
impl<E, I, A: InternalArrayLengthConfig, L> InternalArrayLengthConfig
for Configuration<E, I, A, L>
{
const SKIP_FIXED_ARRAY_LENGTH: bool = A::SKIP_FIXED_ARRAY_LENGTH;
}
pub trait InternalLimitConfig {
const LIMIT: Option<usize>;
}
impl<E, I, A, L: InternalLimitConfig> InternalLimitConfig for Configuration<E, I, A, L> {
impl<E, I, L: InternalLimitConfig> InternalLimitConfig for Configuration<E, I, L> {
const LIMIT: Option<usize> = L::LIMIT;
}
}

View File

@ -3,10 +3,7 @@ use super::{
BorrowDecode, BorrowDecoder, Decode, Decoder,
};
use crate::{
config::{
Endian, IntEncoding, InternalArrayLengthConfig, InternalEndianConfig,
InternalIntEncodingConfig,
},
config::{Endian, IntEncoding, InternalEndianConfig, InternalIntEncodingConfig},
error::{DecodeError, IntegerType},
impl_borrow_decode,
};
@ -448,16 +445,6 @@ where
T: Decode + Sized + 'static,
{
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
if !D::C::SKIP_FIXED_ARRAY_LENGTH {
let length = super::decode_slice_len(decoder)?;
if length != N {
return Err(DecodeError::ArrayLengthMismatch {
found: length,
required: N,
});
}
}
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;
// Optimize for `[u8; N]`
@ -489,16 +476,6 @@ where
T: BorrowDecode<'de> + Sized + 'static,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
if !D::C::SKIP_FIXED_ARRAY_LENGTH {
let length = super::decode_slice_len(decoder)?;
if length != N {
return Err(DecodeError::ArrayLengthMismatch {
found: length,
required: N,
});
}
}
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;
// Optimize for `[u8; N]`

View File

@ -1,9 +1,6 @@
use super::{write::Writer, Encode, Encoder};
use crate::{
config::{
Endian, IntEncoding, InternalArrayLengthConfig, InternalEndianConfig,
InternalIntEncodingConfig,
},
config::{Endian, IntEncoding, InternalEndianConfig, InternalIntEncodingConfig},
error::EncodeError,
};
use core::{
@ -358,9 +355,6 @@ where
T: Encode,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
if !E::C::SKIP_FIXED_ARRAY_LENGTH {
super::encode_slice_len(encoder, N)?;
}
for item in self.iter() {
item.encode(encoder)?;
}

View File

@ -444,6 +444,19 @@ where
}
}
#[test]
fn test_cow_round_trip() {
let start = Cow::Borrowed("Foo");
let encoded = crate::encode_to_vec(&start, crate::config::standard()).unwrap();
let (end, _) =
crate::borrow_decode_from_slice::<Cow<str>, _>(&encoded, crate::config::standard())
.unwrap();
assert_eq!(start, end);
let (end, _) =
crate::decode_from_slice::<Cow<str>, _>(&encoded, crate::config::standard()).unwrap();
assert_eq!(start, end);
}
impl<T> Decode for Rc<T>
where
T: Decode,

View File

@ -13,9 +13,6 @@ where
T: Deserialize<'de>,
C: Config,
{
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeDecodeError::SkipFixedArrayLengthNotSupported.into());
}
let reader = crate::de::read::SliceReader::new(slice);
let mut decoder = crate::de::DecoderImpl::new(reader, config);
let serde_decoder = SerdeDecoder {
@ -35,9 +32,6 @@ where
T: DeserializeSeed<'de>,
C: Config,
{
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeDecodeError::SkipFixedArrayLengthNotSupported.into());
}
let reader = crate::de::read::SliceReader::new(slice);
let mut decoder = crate::de::DecoderImpl::new(reader, config);
let serde_decoder = SerdeDecoder {

View File

@ -16,9 +16,6 @@ where
T: DeserializeOwned,
C: Config,
{
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeDecodeError::SkipFixedArrayLengthNotSupported.into());
}
let reader = crate::de::read::SliceReader::new(slice);
let mut decoder = crate::de::DecoderImpl::new(reader, config);
let serde_decoder = SerdeDecoder { de: &mut decoder };
@ -34,9 +31,6 @@ pub fn decode_from_std_read<D: DeserializeOwned, C: Config, R: std::io::Read>(
src: &mut R,
config: C,
) -> Result<D, DecodeError> {
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeDecodeError::SkipFixedArrayLengthNotSupported.into());
}
let reader = crate::IoReader::new(src);
let mut decoder = crate::de::DecoderImpl::new(reader, config);
let serde_decoder = SerdeDecoder { de: &mut decoder };
@ -52,9 +46,6 @@ pub fn decode_from_reader<D: DeserializeOwned, R: Reader, C: Config>(
reader: R,
config: C,
) -> Result<D, DecodeError> {
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeDecodeError::SkipFixedArrayLengthNotSupported.into());
}
let mut decoder = crate::de::DecoderImpl::<_, C>::new(reader, config);
let serde_decoder = SerdeDecoder { de: &mut decoder };
D::deserialize(serde_decoder)

View File

@ -83,9 +83,6 @@ pub enum DecodeError {
/// Serde tried decoding a borrowed value from an owned reader. Use `serde_decode_borrowed_from_*` instead
CannotBorrowOwnedData,
/// Serde does not support skipping fixed array lengths
SkipFixedArrayLengthNotSupported,
/// Could not allocate data like `String` and `Vec<u8>`
#[cfg(not(feature = "alloc"))]
CannotAllocate,
@ -133,9 +130,6 @@ pub enum EncodeError {
/// Serde provided bincode with a sequence without a length, which is not supported in bincode
SequenceMustHaveLength,
/// Serde does not support skipping fixed array lengths
SkipFixedArrayLengthNotSupported,
/// [Serializer::collect_str] got called but bincode was unable to allocate memory.
#[cfg(not(feature = "alloc"))]
CannotCollectStr,

View File

@ -16,9 +16,6 @@ where
T: Serialize,
C: Config,
{
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeEncodeError::SkipFixedArrayLengthNotSupported.into());
}
let mut encoder = crate::enc::EncoderImpl::new(crate::VecWriter::default(), config);
let serializer = SerdeEncoder { enc: &mut encoder };
t.serialize(serializer)?;
@ -31,9 +28,6 @@ where
T: Serialize,
C: Config,
{
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeEncodeError::SkipFixedArrayLengthNotSupported.into());
}
let mut encoder =
crate::enc::EncoderImpl::new(crate::enc::write::SliceWriter::new(slice), config);
let serializer = SerdeEncoder { enc: &mut encoder };
@ -51,9 +45,6 @@ pub fn encode_into_writer<E: Serialize, W: Writer, C: Config>(
writer: W,
config: C,
) -> Result<(), EncodeError> {
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeEncodeError::SkipFixedArrayLengthNotSupported.into());
}
let mut encoder = crate::enc::EncoderImpl::<_, C>::new(writer, config);
let serializer = SerdeEncoder { enc: &mut encoder };
val.serialize(serializer)?;
@ -71,9 +62,6 @@ pub fn encode_into_std_write<E: Serialize, C: Config, W: std::io::Write>(
dst: &mut W,
config: C,
) -> Result<usize, EncodeError> {
if C::SKIP_FIXED_ARRAY_LENGTH {
return Err(SerdeEncodeError::SkipFixedArrayLengthNotSupported.into());
}
let writer = crate::IoWriter::new(dst);
let mut encoder = crate::enc::EncoderImpl::<_, C>::new(writer, config);
let serializer = SerdeEncoder { enc: &mut encoder };

View File

@ -214,30 +214,25 @@ fn test_array() {
let mut buffer = [0u8; 32];
let input: [u8; 10] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap();
assert_eq!(
&buffer[..11],
&[10, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
);
assert_eq!(&buffer[..10], &[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]);
let (output, len): ([u8; 10], usize) =
bincode::decode_from_slice(&buffer[..11], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, 11);
assert_eq!(len, 10);
let mut buffer = [0u8; 32];
let input: [u8; 1] = [1];
let config = bincode::config::standard()
.write_fixed_array_length()
.with_fixed_int_encoding()
.with_little_endian();
let len = bincode::encode_into_slice(input, &mut buffer, config).unwrap();
assert_eq!(len, 9);
assert_eq!(&buffer[..9], &[1, 0, 0, 0, 0, 0, 0, 0, 1]);
assert_eq!(len, 1);
assert_eq!(&buffer[..1], &[1]);
let (output, len): (&[u8], usize) =
bincode::borrow_decode_from_slice(&buffer[..9], config).unwrap();
let (output, len): ([u8; 1], usize) = bincode::decode_from_slice(&buffer[..9], config).unwrap();
assert_eq!(len, 1);
assert_eq!(input, output);
assert_eq!(len, 9);
}
#[test]

View File

@ -422,7 +422,7 @@ mod zoxide {
#[test]
fn test() {
let dirs = &[
let dirs = vec![
Dir {
path: Cow::Borrowed("Foo"),
rank: 1.23,

View File

@ -37,38 +37,29 @@ where
C: bincode::config::Config,
CMP: Fn(&V, &V) -> bool,
{
use bincode::error::EncodeError;
let mut buffer = [0u8; 2048];
let len = bincode::serde::encode_into_slice(element, &mut buffer, config);
let decoded = bincode::serde::decode_from_slice(&buffer, config);
if !C::SKIP_FIXED_ARRAY_LENGTH {
let len = len.unwrap();
let (decoded, decoded_len): (V, usize) = decoded.unwrap();
println!(
"{:?} ({}): {:?} ({:?})",
element,
core::any::type_name::<V>(),
&buffer[..len],
core::any::type_name::<C>()
);
let len = len.unwrap();
let (decoded, decoded_len): (V, usize) = decoded.unwrap();
println!(
"{:?} ({}): {:?} ({:?})",
element,
core::any::type_name::<V>(),
&buffer[..len],
core::any::type_name::<C>()
);
assert!(
cmp(element, &decoded),
"Comparison failed\nDecoded: {:?}\nExpected: {:?}\nBytes: {:?}",
decoded,
element,
&buffer[..len],
);
assert_eq!(len, decoded_len);
} else {
match len.unwrap_err() {
EncodeError::Serde(bincode::serde::EncodeError::SkipFixedArrayLengthNotSupported) => {}
err => panic!("Unexpected error: {:?}", err),
}
}
assert!(
cmp(element, &decoded),
"Comparison failed\nDecoded: {:?}\nExpected: {:?}\nBytes: {:?}",
decoded,
element,
&buffer[..len],
);
assert_eq!(len, decoded_len);
}
pub fn the_same_with_comparer<V, CMP>(element: V, cmp: CMP)
@ -81,32 +72,28 @@ where
&element,
bincode::config::standard()
.with_little_endian()
.with_fixed_int_encoding()
.skip_fixed_array_length(),
.with_fixed_int_encoding(),
&cmp,
);
the_same_with_config(
&element,
bincode::config::standard()
.with_big_endian()
.with_fixed_int_encoding()
.skip_fixed_array_length(),
.with_fixed_int_encoding(),
&cmp,
);
the_same_with_config(
&element,
bincode::config::standard()
.with_little_endian()
.with_variable_int_encoding()
.skip_fixed_array_length(),
.with_variable_int_encoding(),
&cmp,
);
the_same_with_config(
&element,
bincode::config::standard()
.with_big_endian()
.with_variable_int_encoding()
.skip_fixed_array_length(),
.with_variable_int_encoding(),
&cmp,
);
the_same_with_config(