diff --git a/benches/varint.rs b/benches/varint.rs index 6f18bfc0..ce584191 100644 --- a/benches/varint.rs +++ b/benches/varint.rs @@ -14,7 +14,7 @@ fn slice_varint_u8(c: &mut Criterion) { c.bench_function("slice_varint_u8", |b| { b.iter(|| { - let _: Vec = bincode::decode_from_slice(&bytes, config).unwrap(); + let _: (Vec, 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| { b.iter(|| { - let _: Vec = bincode::decode_from_slice(&bytes, config).unwrap(); + let _: (Vec, 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| { b.iter(|| { - let _: Vec = bincode::decode_from_slice(&bytes, config).unwrap(); + let _: (Vec, 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| { b.iter(|| { - let _: Vec = bincode::decode_from_slice(&bytes, config).unwrap(); + let _: (Vec, usize) = bincode::decode_from_slice(&bytes, config).unwrap(); }) }); } diff --git a/derive/src/derive_struct.rs b/derive/src/derive_struct.rs index 27b9e54b..d75c54fd 100644 --- a/derive/src/derive_struct.rs +++ b/derive/src/derive_struct.rs @@ -25,14 +25,14 @@ impl DeriveStruct { fn_body .push_parsed(format!( "bincode::Encode::encode(&bincode::serde::Compat(&self.{}), &mut encoder)?;", - field.to_string() + field )) .unwrap(); } else { fn_body .push_parsed(format!( "bincode::enc::Encode::encode(&self.{}, &mut encoder)?;", - field.to_string() + field )) .unwrap(); } @@ -72,14 +72,14 @@ impl DeriveStruct { struct_body .push_parsed(format!( "{}: ( as bincode::Decode>::decode(&mut decoder)?).0,", - field.to_string() + field )) .unwrap(); } else { struct_body .push_parsed(format!( "{}: bincode::Decode::decode(&mut decoder)?,", - field.to_string() + field )) .unwrap(); } @@ -114,14 +114,14 @@ impl DeriveStruct { struct_body .push_parsed(format!( "{}: ( as bincode::de::BorrowDecode>::borrow_decode(&mut decoder)?).0,", - field.to_string() + field )) .unwrap(); } else { struct_body .push_parsed(format!( "{}: bincode::de::BorrowDecode::borrow_decode(&mut decoder)?,", - field.to_string() + field )) .unwrap(); } diff --git a/derive/src/parse/generics.rs b/derive/src/parse/generics.rs index b574a00a..0b832ead 100644 --- a/derive/src/parse/generics.rs +++ b/derive/src/parse/generics.rs @@ -122,6 +122,7 @@ impl Generics { } #[derive(Debug)] +#[allow(clippy::enum_variant_names)] enum Generic { Lifetime(Lifetime), Generic(SimpleGeneric), diff --git a/readme.md b/readme.md index 5e321d9a..cb198f15 100644 --- a/readme.md +++ b/readme.md @@ -53,9 +53,10 @@ fn main() { // The 4 floats are encoded in 4 bytes each. 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!(len, encoded.len()); // read all bytes } ``` diff --git a/src/de/impl_core.rs b/src/de/impl_core.rs index a5dc4c49..7d9909e3 100644 --- a/src/de/impl_core.rs +++ b/src/de/impl_core.rs @@ -1,4 +1,5 @@ #![allow(unused_unsafe)] +#![allow(clippy::needless_borrow)] //! Contains implementations for rust core that have not been stabilized //! diff --git a/src/de/read.rs b/src/de/read.rs index b0f6cc38..33dcee66 100644 --- a/src/de/read.rs +++ b/src/de/read.rs @@ -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. pub struct SliceReader<'storage> { - slice: &'storage [u8], + pub(crate) slice: &'storage [u8], } impl<'storage> SliceReader<'storage> { diff --git a/src/enc/write.rs b/src/enc/write.rs index 76188303..2796888f 100644 --- a/src/enc/write.rs +++ b/src/enc/write.rs @@ -51,7 +51,7 @@ impl<'storage> Writer for SliceWriter<'storage> { if bytes.len() > self.slice.len() { return Err(EncodeError::UnexpectedEnd); } - let (a, b) = core::mem::replace(&mut self.slice, &mut []).split_at_mut(bytes.len()); + let (a, b) = core::mem::take(&mut self.slice).split_at_mut(bytes.len()); a.copy_from_slice(bytes); self.slice = b; diff --git a/src/features/serde/de_owned.rs b/src/features/serde/de_owned.rs index 29a575c2..45c13d37 100644 --- a/src/features/serde/de_owned.rs +++ b/src/features/serde/de_owned.rs @@ -5,12 +5,12 @@ use crate::{ }; 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]. /// /// [decode_borrowed_from_slice]: fn.decode_borrowed_from_slice.html -pub fn decode_from_slice(slice: &[u8], config: C) -> Result +pub fn decode_from_slice(slice: &[u8], config: C) -> Result<(T, usize), DecodeError> where T: DeserializeOwned, C: Config, @@ -18,7 +18,9 @@ where let reader = crate::de::read::SliceReader::new(slice); let mut decoder = crate::de::DecoderImpl::new(reader, config); 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> { diff --git a/src/lib.rs b/src/lib.rs index c4358dda..33b42221 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,7 @@ //! //! // Decoding works the same as encoding. //! // 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); //! ``` @@ -57,7 +57,6 @@ #![doc(html_root_url = "https://docs.rs/bincode/2.0.0-alpha.1")] #![crate_name = "bincode"] #![crate_type = "rlib"] -#![crate_type = "dylib"] #[cfg(feature = "alloc")] extern crate alloc; @@ -68,7 +67,7 @@ mod features; pub(crate) mod utils; pub(crate) mod varint; -use de::read::Reader; +use de::{read::Reader, Decoder}; use enc::write::Writer; pub use features::*; @@ -121,10 +120,12 @@ pub fn encode_into_writer( pub fn decode_from_slice<'a, D: de::BorrowDecode<'a>, C: Config>( src: &'a [u8], config: C, -) -> Result { +) -> Result<(D, usize), error::DecodeError> { let reader = de::read::SliceReader::new(src); 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]. diff --git a/tests/alloc.rs b/tests/alloc.rs index 1a2c457b..647d60a1 100644 --- a/tests/alloc.rs +++ b/tests/alloc.rs @@ -44,9 +44,11 @@ fn test_vec() { let vec = bincode::encode_to_vec(Foo { a: 5, b: 10 }, Configuration::standard()).unwrap(); 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.b, 10); + assert_eq!(len, 2); } #[test] diff --git a/tests/basic_types.rs b/tests/basic_types.rs index 8b8d4e8f..7d7b66db 100644 --- a/tests/basic_types.rs +++ b/tests/basic_types.rs @@ -136,9 +136,10 @@ fn test_slice() { bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap(); 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(); assert_eq!(input, output); + assert_eq!(len, 8); } #[test] @@ -151,9 +152,10 @@ fn test_str() { &[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(); assert_eq!(input, output); + assert_eq!(len, 12); } #[test] @@ -163,7 +165,8 @@ fn test_array() { bincode::encode_into_slice(input, &mut buffer, Configuration::standard()).unwrap(); 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(); assert_eq!(input, output); + assert_eq!(len, 10); } diff --git a/tests/derive.rs b/tests/derive.rs index 13e52bc9..47cc836b 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -63,8 +63,10 @@ fn test_decode() { c: 1024u32, }; let slice = [5, 10, 251, 0, 4]; - let result: Test2 = bincode::decode_from_slice(&slice, Configuration::standard()).unwrap(); + let (result, len): (Test2, usize) = + bincode::decode_from_slice(&slice, Configuration::standard()).unwrap(); assert_eq!(result, start); + assert_eq!(len, 5); } #[test] @@ -77,8 +79,11 @@ fn test_encode_decode_str() { let mut slice = [0u8; 100]; 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, 12); + let (end, len): (Test3, usize) = + bincode::decode_from_slice(&slice[..len], Configuration::standard()).unwrap(); assert_eq!(end, start); + assert_eq!(len, 12); } #[test] @@ -95,9 +100,10 @@ fn test_encode_tuple() { fn test_decode_tuple() { let start = TestTupleStruct(5, 10, 1024); 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(); assert_eq!(result, start); + assert_eq!(len, 5); } #[test] @@ -114,9 +120,10 @@ fn test_encode_enum_struct_variant() { fn test_decode_enum_struct_variant() { let start = TestEnum::Bar { name: 5u32 }; let mut slice = [1, 5]; - let result: TestEnum = + let (result, len): (TestEnum, usize) = bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap(); assert_eq!(result, start); + assert_eq!(len, 2); } #[test] @@ -133,9 +140,10 @@ fn test_encode_enum_tuple_variant() { fn test_decode_enum_unit_variant() { let start = TestEnum::Foo; let mut slice = [0]; - let result: TestEnum = + let (result, len): (TestEnum, usize) = bincode::decode_from_slice(&mut slice, Configuration::standard()).unwrap(); assert_eq!(result, start); + assert_eq!(len, 1); } #[test] @@ -152,9 +160,10 @@ fn test_encode_enum_unit_variant() { fn test_decode_enum_tuple_variant() { let start = TestEnum::Baz(5, 10, 1024); 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(); assert_eq!(result, start); + assert_eq!(len, 6); } #[derive(bincode::Decode, bincode::Encode, PartialEq, Eq, Debug)] @@ -183,7 +192,9 @@ fn test_c_style_enum() { assert_eq!(ser(CStyleEnum::E), 6); fn de(num: u8) -> Result { - 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 { diff --git a/tests/issues/issue_431.rs b/tests/issues/issue_431.rs index cd4537f2..8756957d 100644 --- a/tests/issues/issue_431.rs +++ b/tests/issues/issue_431.rs @@ -26,7 +26,9 @@ fn test() { }; let vec = bincode::encode_to_vec(&t, Configuration::standard()).unwrap(); - let decoded: T = bincode::decode_from_slice(&vec, Configuration::standard()).unwrap(); + let (decoded, len): (T, usize) = + bincode::decode_from_slice(&vec, Configuration::standard()).unwrap(); assert_eq!(t, decoded); + assert_eq!(len, 12); } diff --git a/tests/serde.rs b/tests/serde.rs index 55061e66..9cf2066a 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -28,10 +28,11 @@ fn test_serde_round_trip() { let bytes = bincode::encode_to_vec(SerdeRoundtrip { a: 15, b: 15 }, Configuration::standard()).unwrap(); assert_eq!(bytes, &[15, 15]); - let result: SerdeRoundtrip = + let (result, len): (SerdeRoundtrip, usize) = bincode::decode_from_slice(&bytes, Configuration::standard()).unwrap(); assert_eq!(result.a, 15); assert_eq!(result.b, 15); + assert_eq!(len, 2); } #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -115,7 +116,7 @@ fn test_serialize_deserialize_owned_data() { assert_eq!(result, expected); - let output: SerdeWithOwnedData = + let (output, len): (SerdeWithOwnedData, usize) = bincode::serde::decode_from_slice(&result, Configuration::standard()).unwrap(); assert_eq!( SerdeWithOwnedData { @@ -124,6 +125,7 @@ fn test_serialize_deserialize_owned_data() { }, output ); + assert_eq!(len, 13); } #[cfg(feature = "derive")] @@ -154,24 +156,33 @@ mod derive { #[test] fn test_serde_derive() { - fn test_encode_decode(start: T) + fn test_encode_decode(start: T, expected_len: usize) where T: bincode::Encode + bincode::Decode + PartialEq + core::fmt::Debug, { let mut slice = [0u8; 100]; let len = bincode::encode_into_slice(&start, &mut slice, Configuration::standard()).unwrap(); + assert_eq!(len, expected_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!(len, expected_len); } - test_encode_decode(StructWithSerde { - serde: SerdeType { a: 5 }, - }); - test_encode_decode(EnumWithSerde::Unit(SerdeType { a: 5 })); - test_encode_decode(EnumWithSerde::Struct { - serde: SerdeType { a: 5 }, - }); + test_encode_decode( + StructWithSerde { + serde: SerdeType { a: 5 }, + }, + 1, + ); + test_encode_decode(EnumWithSerde::Unit(SerdeType { a: 5 }), 2); + test_encode_decode( + EnumWithSerde::Struct { + serde: SerdeType { a: 5 }, + }, + 2, + ); } } diff --git a/tests/std.rs b/tests/std.rs index 14fc7dde..1da4aa2b 100644 --- a/tests/std.rs +++ b/tests/std.rs @@ -106,12 +106,16 @@ fn test_std_commons() { // &CStr let cstr = CStr::from_bytes_with_nul(b"Hello world\0").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!(len, 13); // Path let path = Path::new("C:/Program Files/Foo"); 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!(len, 21); } diff --git a/tests/utils.rs b/tests/utils.rs index 7a64ad72..dbbbee05 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -15,7 +15,8 @@ where &buffer[..len], core::any::type_name::() ); - 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!( cmp(&element, &decoded), @@ -24,6 +25,7 @@ where element, &buffer[..len], ); + assert_eq!(len, decoded_len); } pub fn the_same_with_comparer(element: V, cmp: CMP)