[Breaking change] Made all `decode_from_slice` also return the number of bytes read (#445)

This commit is contained in:
Trangar 2021-12-11 15:51:50 +01:00 committed by GitHub
parent 63f4607992
commit 404946f12b
14 changed files with 89 additions and 43 deletions

View File

@ -53,9 +53,10 @@ fn main() {
// The 4 floats are encoded in 4 bytes each. // The 4 floats are encoded in 4 bytes each.
assert_eq!(encoded.len(), 1 + 4 * 4); assert_eq!(encoded.len(), 1 + 4 * 4);
let decoded: World = bincode::decode_from_slice(&encoded[..], config).unwrap(); let (decoded, len): (World, usize) = bincode::decode_from_slice(&encoded[..], config).unwrap();
assert_eq!(world, decoded); assert_eq!(world, decoded);
assert_eq!(len, encoded.len()); // read all bytes
} }
``` ```

View File

@ -14,7 +14,7 @@ fn slice_varint_u8(c: &mut Criterion) {
c.bench_function("slice_varint_u8", |b| { c.bench_function("slice_varint_u8", |b| {
b.iter(|| { b.iter(|| {
let _: Vec<u8> = bincode::decode_from_slice(&bytes, config).unwrap(); let _: (Vec<u8>, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
}) })
}); });
} }
@ -30,7 +30,7 @@ fn slice_varint_u16(c: &mut Criterion) {
c.bench_function("slice_varint_u16", |b| { c.bench_function("slice_varint_u16", |b| {
b.iter(|| { b.iter(|| {
let _: Vec<u16> = bincode::decode_from_slice(&bytes, config).unwrap(); let _: (Vec<u8>, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
}) })
}); });
} }
@ -46,7 +46,7 @@ fn slice_varint_u32(c: &mut Criterion) {
c.bench_function("slice_varint_u32", |b| { c.bench_function("slice_varint_u32", |b| {
b.iter(|| { b.iter(|| {
let _: Vec<u32> = bincode::decode_from_slice(&bytes, config).unwrap(); let _: (Vec<u16>, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
}) })
}); });
} }
@ -62,7 +62,7 @@ fn slice_varint_u64(c: &mut Criterion) {
c.bench_function("slice_varint_u64", |b| { c.bench_function("slice_varint_u64", |b| {
b.iter(|| { b.iter(|| {
let _: Vec<u64> = bincode::decode_from_slice(&bytes, config).unwrap(); let _: (Vec<u64>, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
}) })
}); });
} }

View File

@ -122,6 +122,7 @@ impl Generics {
} }
#[derive(Debug)] #[derive(Debug)]
#[allow(clippy::enum_variant_names)]
enum Generic { enum Generic {
Lifetime(Lifetime), Lifetime(Lifetime),
Simple(SimpleGeneric), Simple(SimpleGeneric),

View File

@ -1,4 +1,5 @@
#![allow(unused_unsafe)] #![allow(unused_unsafe)]
#![allow(clippy::needless_borrow)]
//! Contains implementations for rust core that have not been stabilized //! Contains implementations for rust core that have not been stabilized
//! //!

View File

@ -61,7 +61,7 @@ pub trait BorrowReader<'storage>: Reader {
/// A reader type for `&[u8]` slices. Implements both [Reader] and [BorrowReader], and thus can be used for borrowed data. /// A reader type for `&[u8]` slices. Implements both [Reader] and [BorrowReader], and thus can be used for borrowed data.
pub struct SliceReader<'storage> { pub struct SliceReader<'storage> {
slice: &'storage [u8], pub(crate) slice: &'storage [u8],
} }
impl<'storage> SliceReader<'storage> { impl<'storage> SliceReader<'storage> {

View File

@ -5,12 +5,12 @@ use crate::{
}; };
use serde_incl::de::*; use serde_incl::de::*;
/// Decode an owned type from the given slice. /// Decode an owned type from the given slice. Will return the decoded type `T` as well as the amount of bytes that were read.
/// ///
/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [decode_borrowed_from_slice]. /// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [decode_borrowed_from_slice].
/// ///
/// [decode_borrowed_from_slice]: fn.decode_borrowed_from_slice.html /// [decode_borrowed_from_slice]: fn.decode_borrowed_from_slice.html
pub fn decode_from_slice<T, C>(slice: &[u8], config: C) -> Result<T, DecodeError> pub fn decode_from_slice<T, C>(slice: &[u8], config: C) -> Result<(T, usize), DecodeError>
where where
T: DeserializeOwned, T: DeserializeOwned,
C: Config, C: Config,
@ -18,7 +18,9 @@ where
let reader = crate::de::read::SliceReader::new(slice); let reader = crate::de::read::SliceReader::new(slice);
let mut decoder = crate::de::DecoderImpl::new(reader, config); let mut decoder = crate::de::DecoderImpl::new(reader, config);
let serde_decoder = SerdeDecoder { de: &mut decoder }; let serde_decoder = SerdeDecoder { de: &mut decoder };
T::deserialize(serde_decoder) let result = T::deserialize(serde_decoder)?;
let bytes_read = slice.len() - decoder.reader().slice.len();
Ok((result, bytes_read))
} }
pub(crate) struct SerdeDecoder<'a, DE: Decoder> { pub(crate) struct SerdeDecoder<'a, DE: Decoder> {

View File

@ -49,7 +49,7 @@
//! //!
//! // Decoding works the same as encoding. //! // Decoding works the same as encoding.
//! // The trait used is `de::Decode`, and can also be automatically implemented with the `derive` feature. //! // The trait used is `de::Decode`, and can also be automatically implemented with the `derive` feature.
//! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode::decode_from_slice(slice, Configuration::standard()).unwrap(); //! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode::decode_from_slice(slice, Configuration::standard()).unwrap().0;
//! //!
//! assert_eq!(decoded, input); //! assert_eq!(decoded, input);
//! ``` //! ```
@ -67,7 +67,7 @@ mod features;
pub(crate) mod utils; pub(crate) mod utils;
pub(crate) mod varint; pub(crate) mod varint;
use de::read::Reader; use de::{read::Reader, Decoder};
use enc::write::Writer; use enc::write::Writer;
pub use features::*; pub use features::*;
@ -120,10 +120,12 @@ pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
pub fn decode_from_slice<'a, D: de::BorrowDecode<'a>, C: Config>( pub fn decode_from_slice<'a, D: de::BorrowDecode<'a>, C: Config>(
src: &'a [u8], src: &'a [u8],
config: C, config: C,
) -> Result<D, error::DecodeError> { ) -> Result<(D, usize), error::DecodeError> {
let reader = de::read::SliceReader::new(src); let reader = de::read::SliceReader::new(src);
let mut decoder = de::DecoderImpl::<_, C>::new(reader, config); let mut decoder = de::DecoderImpl::<_, C>::new(reader, config);
D::borrow_decode(&mut decoder) let result = D::borrow_decode(&mut decoder)?;
let bytes_read = src.len() - decoder.reader().slice.len();
Ok((result, bytes_read))
} }
/// Attempt to decode a given type `D` from the given [Reader]. /// Attempt to decode a given type `D` from the given [Reader].

View File

@ -44,9 +44,11 @@ fn test_vec() {
let vec = bincode::encode_to_vec(Foo { a: 5, b: 10 }, Configuration::standard()).unwrap(); let vec = bincode::encode_to_vec(Foo { a: 5, b: 10 }, Configuration::standard()).unwrap();
assert_eq!(vec, &[5, 10]); assert_eq!(vec, &[5, 10]);
let foo: Foo = bincode::decode_from_slice(&vec, Configuration::standard()).unwrap(); let (foo, len): (Foo, usize) =
bincode::decode_from_slice(&vec, Configuration::standard()).unwrap();
assert_eq!(foo.a, 5); assert_eq!(foo.a, 5);
assert_eq!(foo.b, 10); assert_eq!(foo.b, 10);
assert_eq!(len, 2);
} }
#[test] #[test]

View File

@ -136,9 +136,10 @@ fn test_slice() {
bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap(); bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap();
assert_eq!(&buffer[..8], &[7, 1, 2, 3, 4, 5, 6, 7]); assert_eq!(&buffer[..8], &[7, 1, 2, 3, 4, 5, 6, 7]);
let output: &[u8] = let (output, len): (&[u8], usize) =
bincode::decode_from_slice(&mut buffer[..8], Configuration::standard()).unwrap(); bincode::decode_from_slice(&mut buffer[..8], Configuration::standard()).unwrap();
assert_eq!(input, output); assert_eq!(input, output);
assert_eq!(len, 8);
} }
#[test] #[test]
@ -148,18 +149,20 @@ fn test_option_slice() {
let n = bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap(); let n = bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap();
assert_eq!(&buffer[..n], &[1, 7, 1, 2, 3, 4, 5, 6, 7]); assert_eq!(&buffer[..n], &[1, 7, 1, 2, 3, 4, 5, 6, 7]);
let output: Option<&[u8]> = let (output, len): (Option<&[u8]>, usize) =
bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap(); bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap();
assert_eq!(input, output); assert_eq!(input, output);
assert_eq!(len, n);
let mut buffer = [0u8; 32]; let mut buffer = [0u8; 32];
let input: Option<&[u8]> = None; let input: Option<&[u8]> = None;
let n = bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap(); let n = bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap();
assert_eq!(&buffer[..n], &[0]); assert_eq!(&buffer[..n], &[0]);
let output: Option<&[u8]> = let (output, len): (Option<&[u8]>, usize) =
bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap(); bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap();
assert_eq!(input, output); assert_eq!(input, output);
assert_eq!(len, n);
} }
#[test] #[test]
@ -172,9 +175,10 @@ fn test_str() {
&[11, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100] &[11, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
); );
let output: &str = let (output, len): (&str, usize) =
bincode::decode_from_slice(&mut buffer[..12], Configuration::standard()).unwrap(); bincode::decode_from_slice(&mut buffer[..12], Configuration::standard()).unwrap();
assert_eq!(input, output); assert_eq!(input, output);
assert_eq!(len, 12);
} }
#[test] #[test]
@ -187,18 +191,20 @@ fn test_option_str() {
&[1, 11, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100] &[1, 11, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
); );
let output: Option<&str> = let (output, len): (Option<&str>, usize) =
bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap(); bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap();
assert_eq!(input, output); assert_eq!(input, output);
assert_eq!(len, n);
let mut buffer = [0u8; 32]; let mut buffer = [0u8; 32];
let input: Option<&str> = None; let input: Option<&str> = None;
let n = bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap(); let n = bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap();
assert_eq!(&buffer[..n], &[0]); assert_eq!(&buffer[..n], &[0]);
let output: Option<&str> = let (output, len): (Option<&str>, usize) =
bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap(); bincode::decode_from_slice(&buffer[..n], Configuration::standard()).unwrap();
assert_eq!(input, output); assert_eq!(input, output);
assert_eq!(len, n);
} }
#[test] #[test]
@ -208,7 +214,8 @@ fn test_array() {
bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap(); bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap();
assert_eq!(&buffer[..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: [u8; 10] = let (output, len): ([u8; 10], usize) =
bincode::decode_from_slice(&mut buffer[..10], Configuration::standard()).unwrap(); bincode::decode_from_slice(&mut buffer[..10], Configuration::standard()).unwrap();
assert_eq!(input, output); assert_eq!(input, output);
assert_eq!(len, 10);
} }

View File

@ -64,8 +64,10 @@ fn test_decode() {
c: 1024u32, c: 1024u32,
}; };
let slice = [5, 10, 251, 0, 4]; let slice = [5, 10, 251, 0, 4];
let result: Test2<u32> = bincode::decode_from_slice(&slice, Configuration::standard()).unwrap(); let (result, len): (Test2<u32>, usize) =
bincode::decode_from_slice(&slice, Configuration::standard()).unwrap();
assert_eq!(result, start); assert_eq!(result, start);
assert_eq!(len, 5);
} }
#[test] #[test]
@ -79,8 +81,11 @@ fn test_encode_decode_str() {
let mut slice = [0u8; 100]; let mut slice = [0u8; 100];
let len = bincode::encode_into_slice(&start, &mut slice, Configuration::standard()).unwrap(); let len = bincode::encode_into_slice(&start, &mut slice, Configuration::standard()).unwrap();
let end: Test3 = bincode::decode_from_slice(&slice[..len], Configuration::standard()).unwrap(); assert_eq!(len, 21);
let (end, len): (Test3, usize) =
bincode::decode_from_slice(&slice[..len], Configuration::standard()).unwrap();
assert_eq!(end, start); assert_eq!(end, start);
assert_eq!(len, 21);
} }
#[test] #[test]
@ -97,9 +102,10 @@ fn test_encode_tuple() {
fn test_decode_tuple() { fn test_decode_tuple() {
let start = TestTupleStruct(5, 10, 1024); let start = TestTupleStruct(5, 10, 1024);
let mut slice = [5, 10, 251, 0, 4]; let mut slice = [5, 10, 251, 0, 4];
let result: TestTupleStruct = let (result, len): (TestTupleStruct, usize) =
bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap(); bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap();
assert_eq!(result, start); assert_eq!(result, start);
assert_eq!(len, 5);
} }
#[test] #[test]
@ -116,9 +122,10 @@ fn test_encode_enum_struct_variant() {
fn test_decode_enum_struct_variant() { fn test_decode_enum_struct_variant() {
let start = TestEnum::Bar { name: 5u32 }; let start = TestEnum::Bar { name: 5u32 };
let mut slice = [1, 5]; let mut slice = [1, 5];
let result: TestEnum = let (result, len): (TestEnum, usize) =
bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap(); bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap();
assert_eq!(result, start); assert_eq!(result, start);
assert_eq!(len, 2);
} }
#[test] #[test]
@ -135,9 +142,10 @@ fn test_encode_enum_tuple_variant() {
fn test_decode_enum_unit_variant() { fn test_decode_enum_unit_variant() {
let start = TestEnum::Foo; let start = TestEnum::Foo;
let mut slice = [0]; let mut slice = [0];
let result: TestEnum = let (result, len): (TestEnum, usize) =
bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap(); bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap();
assert_eq!(result, start); assert_eq!(result, start);
assert_eq!(len, 1);
} }
#[test] #[test]
@ -154,9 +162,10 @@ fn test_encode_enum_unit_variant() {
fn test_decode_enum_tuple_variant() { fn test_decode_enum_tuple_variant() {
let start = TestEnum::Baz(5, 10, 1024); let start = TestEnum::Baz(5, 10, 1024);
let mut slice = [2, 5, 10, 251, 0, 4]; let mut slice = [2, 5, 10, 251, 0, 4];
let result: TestEnum = let (result, len): (TestEnum, usize) =
bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap(); bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap();
assert_eq!(result, start); assert_eq!(result, start);
assert_eq!(len, 6);
} }
#[derive(bincode::Decode, bincode::Encode, PartialEq, Eq, Debug)] #[derive(bincode::Decode, bincode::Encode, PartialEq, Eq, Debug)]
@ -185,7 +194,9 @@ fn test_c_style_enum() {
assert_eq!(ser(CStyleEnum::E), 6); assert_eq!(ser(CStyleEnum::E), 6);
fn de(num: u8) -> Result<CStyleEnum, bincode::error::DecodeError> { fn de(num: u8) -> Result<CStyleEnum, bincode::error::DecodeError> {
bincode::decode_from_slice(&[num], Configuration::standard()) let (result, len) = bincode::decode_from_slice(&[num], Configuration::standard())?;
assert_eq!(len, 1);
Ok(result)
} }
fn expected_err(idx: u32) -> Result<CStyleEnum, bincode::error::DecodeError> { fn expected_err(idx: u32) -> Result<CStyleEnum, bincode::error::DecodeError> {

View File

@ -26,7 +26,9 @@ fn test() {
}; };
let vec = bincode::encode_to_vec(&t, Configuration::standard()).unwrap(); let vec = bincode::encode_to_vec(&t, Configuration::standard()).unwrap();
let decoded: T<String> = bincode::decode_from_slice(&vec, Configuration::standard()).unwrap(); let (decoded, len): (T<String>, usize) =
bincode::decode_from_slice(&vec, Configuration::standard()).unwrap();
assert_eq!(t, decoded); assert_eq!(t, decoded);
assert_eq!(len, 12);
} }

View File

@ -28,10 +28,11 @@ fn test_serde_round_trip() {
let bytes = let bytes =
bincode::encode_to_vec(SerdeRoundtrip { a: 15, b: 15 }, Configuration::standard()).unwrap(); bincode::encode_to_vec(SerdeRoundtrip { a: 15, b: 15 }, Configuration::standard()).unwrap();
assert_eq!(bytes, &[15, 15]); assert_eq!(bytes, &[15, 15]);
let result: SerdeRoundtrip = let (result, len): (SerdeRoundtrip, usize) =
bincode::decode_from_slice(&bytes, Configuration::standard()).unwrap(); bincode::decode_from_slice(&bytes, Configuration::standard()).unwrap();
assert_eq!(result.a, 15); assert_eq!(result.a, 15);
assert_eq!(result.b, 15); assert_eq!(result.b, 15);
assert_eq!(len, 2);
} }
#[derive(Serialize, Deserialize, PartialEq, Debug)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
@ -115,7 +116,7 @@ fn test_serialize_deserialize_owned_data() {
assert_eq!(result, expected); assert_eq!(result, expected);
let output: SerdeWithOwnedData = let (output, len): (SerdeWithOwnedData, usize) =
bincode::serde::decode_from_slice(&result, Configuration::standard()).unwrap(); bincode::serde::decode_from_slice(&result, Configuration::standard()).unwrap();
assert_eq!( assert_eq!(
SerdeWithOwnedData { SerdeWithOwnedData {
@ -124,6 +125,7 @@ fn test_serialize_deserialize_owned_data() {
}, },
output output
); );
assert_eq!(len, 13);
} }
#[cfg(feature = "derive")] #[cfg(feature = "derive")]
@ -154,24 +156,33 @@ mod derive {
#[test] #[test]
fn test_serde_derive() { fn test_serde_derive() {
fn test_encode_decode<T>(start: T) fn test_encode_decode<T>(start: T, expected_len: usize)
where where
T: bincode::Encode + bincode::Decode + PartialEq + core::fmt::Debug, T: bincode::Encode + bincode::Decode + PartialEq + core::fmt::Debug,
{ {
let mut slice = [0u8; 100]; let mut slice = [0u8; 100];
let len = let len =
bincode::encode_into_slice(&start, &mut slice, Configuration::standard()).unwrap(); bincode::encode_into_slice(&start, &mut slice, Configuration::standard()).unwrap();
assert_eq!(len, expected_len);
let slice = &slice[..len]; let slice = &slice[..len];
let result: T = bincode::decode_from_slice(&slice, Configuration::standard()).unwrap(); let (result, len): (T, usize) =
bincode::decode_from_slice(&slice, Configuration::standard()).unwrap();
assert_eq!(start, result); assert_eq!(start, result);
assert_eq!(len, expected_len);
} }
test_encode_decode(StructWithSerde { test_encode_decode(
StructWithSerde {
serde: SerdeType { a: 5 }, serde: SerdeType { a: 5 },
}); },
test_encode_decode(EnumWithSerde::Unit(SerdeType { a: 5 })); 1,
test_encode_decode(EnumWithSerde::Struct { );
test_encode_decode(EnumWithSerde::Unit(SerdeType { a: 5 }), 2);
test_encode_decode(
EnumWithSerde::Struct {
serde: SerdeType { a: 5 }, serde: SerdeType { a: 5 },
}); },
2,
);
} }
} }

View File

@ -106,12 +106,16 @@ fn test_std_commons() {
// &CStr // &CStr
let cstr = CStr::from_bytes_with_nul(b"Hello world\0").unwrap(); let cstr = CStr::from_bytes_with_nul(b"Hello world\0").unwrap();
let len = bincode::encode_into_slice(cstr, &mut buffer, config).unwrap(); let len = bincode::encode_into_slice(cstr, &mut buffer, config).unwrap();
let decoded: &CStr = bincode::decode_from_slice(&mut buffer[..len], config).unwrap(); let (decoded, len): (&CStr, usize) =
bincode::decode_from_slice(&mut buffer[..len], config).unwrap();
assert_eq!(cstr, decoded); assert_eq!(cstr, decoded);
assert_eq!(len, 13);
// Path // Path
let path = Path::new("C:/Program Files/Foo"); let path = Path::new("C:/Program Files/Foo");
let len = bincode::encode_into_slice(path, &mut buffer, config).unwrap(); let len = bincode::encode_into_slice(path, &mut buffer, config).unwrap();
let decoded: &Path = bincode::decode_from_slice(&mut buffer[..len], config).unwrap(); let (decoded, len): (&Path, usize) =
bincode::decode_from_slice(&mut buffer[..len], config).unwrap();
assert_eq!(path, decoded); assert_eq!(path, decoded);
assert_eq!(len, 21);
} }

View File

@ -15,7 +15,8 @@ where
&buffer[..len], &buffer[..len],
core::any::type_name::<C>() core::any::type_name::<C>()
); );
let decoded: V = bincode::decode_from_slice(&mut buffer, config).unwrap(); let (decoded, decoded_len): (V, usize) =
bincode::decode_from_slice(&mut buffer, config).unwrap();
assert!( assert!(
cmp(&element, &decoded), cmp(&element, &decoded),
@ -24,6 +25,7 @@ where
element, element,
&buffer[..len], &buffer[..len],
); );
assert_eq!(len, decoded_len);
} }
pub fn the_same_with_comparer<V, CMP>(element: V, cmp: CMP) pub fn the_same_with_comparer<V, CMP>(element: V, cmp: CMP)