From 1a2e40f65317022a4217b56a3e32b9c0087259eb Mon Sep 17 00:00:00 2001 From: boxdot Date: Mon, 3 Sep 2018 11:40:25 +0200 Subject: [PATCH 1/2] Introduce `Config::deserialize_seed` for exposing serde's statefull deser. --- src/config.rs | 6 ++++++ src/internal.rs | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/config.rs b/src/config.rs index cebd0be6..73a44236 100644 --- a/src/config.rs +++ b/src/config.rs @@ -266,6 +266,12 @@ impl Config { config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place)) } + /// Deserializes a slice of bytes with state `seed` using this configuration. + #[inline(always)] + pub fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(&self, seed: T, bytes: &'a [u8]) -> Result { + config_map!(self, opts => ::internal::deserialize_seed(seed, bytes, opts)) + } + /// 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 bab4a285..42417846 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -115,6 +115,17 @@ where } +pub(crate) fn deserialize_seed<'a, T, O>(seed: T, bytes: &'a [u8], options: O) -> Result +where + T: serde::de::DeserializeSeed<'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); + seed.deserialize(&mut deserializer) +} + pub(crate) trait SizeLimit: Clone { /// Tells the SizeLimit that a certain number of bytes has been /// read or written. Returns Err if the limit has been exceeded. From 1c6c3303bcb0279731c62de8455999065e0f32e8 Mon Sep 17 00:00:00 2001 From: boxdot Date: Tue, 4 Sep 2018 09:55:37 +0200 Subject: [PATCH 2/2] Add tests for `Config::deserialize_seed`. --- tests/test.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/tests/test.rs b/tests/test.rs index 39e39601..2df15275 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -6,12 +6,16 @@ extern crate byteorder; extern crate serde; extern crate serde_bytes; -use std::fmt::Debug; -use std::collections::HashMap; use std::borrow::Cow; +use std::collections::HashMap; +use std::fmt::{self, Debug}; +use std::result::Result as StdResult; -use bincode::{config, deserialize, deserialize_from, deserialize_in_place, serialize, - serialized_size, ErrorKind, Result}; +use bincode::{ + config, deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size, + ErrorKind, Result, +}; +use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor}; fn the_same(element: V) where @@ -592,3 +596,87 @@ fn not_human_readable() { serialized_size(&ip).unwrap() ); } + +// The example is taken from serde::de::DeserializeSeed. +struct ExtendVec<'a, T: 'a>(&'a mut Vec); + +impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T> +where + T: Deserialize<'de>, +{ + // The return type of the `deserialize` method. This implementation + // appends onto an existing vector but does not create any new data + // structure, so the return type is (). + type Value = (); + + fn deserialize(self, deserializer: D) -> StdResult + where + D: Deserializer<'de>, + { + // Visitor implementation that will walk an inner array of the JSON + // input. + struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec); + + impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T> + where + T: Deserialize<'de>, + { + type Value = (); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "an array of integers") + } + + fn visit_seq(self, mut seq: A) -> StdResult<(), A::Error> + where + A: SeqAccess<'de>, + { + // Visit each element in the inner array and push it onto + // the existing vector. + while let Some(elem) = seq.next_element()? { + self.0.push(elem); + } + Ok(()) + } + } + + deserializer.deserialize_seq(ExtendVecVisitor(self.0)) + } +} + +#[test] +fn test_default_deserialize_seed() { + let config = config(); + + let data: Vec<_> = (10..100).collect(); + let bytes = config.serialize(&data).expect("Config::serialize failed"); + + let mut seed_data: Vec<_> = (0..10).collect(); + { + let seed = ExtendVec(&mut seed_data); + config + .deserialize_seed(seed, &bytes) + .expect("Config::deserialize_seed failed"); + } + + assert_eq!(seed_data, (0..100).collect::>()); +} + +#[test] +fn test_big_endian_deserialize_seed() { + let mut config = config(); + config.big_endian(); + + let data: Vec<_> = (10..100).collect(); + let bytes = config.serialize(&data).expect("Config::serialize failed"); + + let mut seed_data: Vec<_> = (0..10).collect(); + { + let seed = ExtendVec(&mut seed_data); + config + .deserialize_seed(seed, &bytes) + .expect("Config::deserialize_seed failed"); + } + + assert_eq!(seed_data, (0..100).collect::>()); +}