diff --git a/Cargo.toml b/Cargo.toml index 564c3b6..e6ec407 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,9 +18,9 @@ description = "A binary serialization / deserialization strategy that uses Serde [dependencies] byteorder = "1.2.0" -serde = "1.0.16" +serde = "1.0.27" [dev-dependencies] -serde_bytes = "0.10.*" -serde_derive = "1.0.16" +serde_bytes = "0.10.3" +serde_derive = "1.0.27" diff --git a/src/config.rs b/src/config.rs index 90bcce9..1d19dd9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -255,6 +255,13 @@ impl Config { config_map!(self, opts => ::internal::deserialize(bytes, opts)) } + /// TODO: document + #[doc(hidden)] + #[inline(always)] + pub fn deserialize_in_place<'a, T: serde::de::Deserialize<'a>>(&self, reader: &'a [u8], place: &mut T) -> Result<()> { + config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place)) + } + /// Deserializes an object directly from a `Read`er using this configuration /// /// If this returns an `Error`, `reader` may be in an invalid state. diff --git a/src/internal.rs b/src/internal.rs index 66cae64..990c7de 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -93,6 +93,21 @@ where serde::Deserialize::deserialize(&mut deserializer) } +pub(crate) fn deserialize_in_place<'a, T, O>( + bytes: &'a [u8], + options: O, + place: &mut T, +) -> Result<()> +where + T: serde::de::Deserialize<'a>, + O: Options, +{ + let reader = ::de::read::SliceReader::new(bytes); + let options = ::config::WithOtherLimit::new(options, Infinite); + let mut deserializer = ::de::Deserializer::<_, _>::new(reader, options); + serde::Deserialize::deserialize_in_place(&mut deserializer, place) +} + pub(crate) fn deserialize<'a, T, O>(bytes: &'a [u8], options: O) -> Result where T: serde::de::Deserialize<'a>, diff --git a/src/lib.rs b/src/lib.rs index 6623d83..418be38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,6 +112,15 @@ where config().deserialize_from_custom(reader) } +/// TODO: document +#[doc(hidden)] +pub fn deserialize_in_place<'a, T>(bytes: &'a[u8], place: &mut T) -> Result<()> +where + T: serde::de::Deserialize<'a>, +{ + config().deserialize_in_place(bytes, place) +} + /// Deserializes a slice of bytes into an instance of `T` using the default configuration. pub fn deserialize<'a, T>(bytes: &'a [u8]) -> Result where diff --git a/tests/test.rs b/tests/test.rs index 440be46..474b3e2 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -10,7 +10,8 @@ use std::fmt::Debug; use std::collections::HashMap; use std::borrow::Cow; -use bincode::{config, deserialize, deserialize_from, serialize, serialized_size, ErrorKind, Result}; +use bincode::{config, deserialize, deserialize_from, deserialize_in_place, serialize, + serialized_size, ErrorKind, Result}; fn the_same(element: V) where @@ -315,7 +316,9 @@ fn test_serialized_size_bounded() { assert!( config() .limit(8 + 3 * 4 - 1) - .serialized_size(&vec![0u32, 1u32, 2u32]).is_err()); + .serialized_size(&vec![0u32, 1u32, 2u32]) + .is_err() + ); } #[test] @@ -461,11 +464,38 @@ fn test_zero_copy_parse() { } } +#[test] +fn test_zero_copy_parse_deserialize_into() { + #[derive(Serialize, Deserialize, Eq, PartialEq, Debug)] + struct Foo<'a> { + borrowed_str: &'a str, + borrowed_bytes: &'a [u8], + } + + let f = Foo { + borrowed_str: "hi", + borrowed_bytes: &[0, 1, 2, 3], + }; + + { + let encoded = serialize(&f).unwrap(); + let mut target = Foo { + borrowed_str: "hello", + borrowed_bytes: &[10, 11, 12, 13], + }; + deserialize_in_place(&encoded[..], &mut target).unwrap(); + assert_eq!(target, f); + } +} + #[test] fn not_human_readable() { use std::net::Ipv4Addr; let ip = Ipv4Addr::new(1, 2, 3, 4); the_same(ip); assert_eq!(&ip.octets()[..], &serialize(&ip).unwrap()[..]); - assert_eq!(::std::mem::size_of::() as u64, serialized_size(&ip).unwrap()); + assert_eq!( + ::std::mem::size_of::() as u64, + serialized_size(&ip).unwrap() + ); }