move to custom read implementation for deserialize_in_place

This commit is contained in:
Ty Overby 2018-02-07 19:39:21 -08:00
parent 68ca894b81
commit 76b7662dcd
5 changed files with 93 additions and 14 deletions

View File

@ -18,9 +18,9 @@ description = "A binary serialization / deserialization strategy that uses Serde
[dependencies]
byteorder = "1.2.0"
serde = "1.0.27"
serde = "^1.0.27"
[dev-dependencies]
serde_bytes = "0.10.3"
serde_derive = "1.0.27"
serde_bytes = "^0.10.3"
serde_derive = "^1.0.27"

View File

@ -258,7 +258,11 @@ impl Config {
/// 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<()> {
pub fn deserialize_in_place<'a, R, T: >(&self, reader: R, place: &mut T) -> Result<()>
where
R: BincodeRead<'a>,
T: serde::de::Deserialize<'a>
{
config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place))
}

View File

@ -93,17 +93,12 @@ where
serde::Deserialize::deserialize(&mut deserializer)
}
pub(crate) fn deserialize_in_place<'a, T, O>(
bytes: &'a [u8],
options: O,
place: &mut T,
) -> Result<()>
pub(crate) fn deserialize_in_place<'a, R, T, O>(reader: R, options: O, place: &mut T) -> Result<()>
where
R: BincodeRead<'a>,
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)
}

View File

@ -114,11 +114,12 @@ where
/// TODO: document
#[doc(hidden)]
pub fn deserialize_in_place<'a, T>(bytes: &'a[u8], place: &mut T) -> Result<()>
pub fn deserialize_in_place<'a, R, T>(reader: R, place: &mut T) -> Result<()>
where
T: serde::de::Deserialize<'a>,
R: BincodeRead<'a>
{
config().deserialize_in_place(bytes, place)
config().deserialize_in_place(reader, place)
}
/// Deserializes a slice of bytes into an instance of `T` using the default configuration.

View File

@ -466,6 +466,80 @@ fn test_zero_copy_parse() {
#[test]
fn test_zero_copy_parse_deserialize_into() {
use bincode::BincodeRead;
use std::io;
/// A BincodeRead implementation for byte slices
pub struct SliceReader<'storage> {
slice: &'storage [u8],
}
impl<'storage> SliceReader<'storage> {
#[inline(always)]
fn unexpected_eof() -> Box<::ErrorKind> {
return Box::new(::ErrorKind::Io(
io::Error::new(io::ErrorKind::UnexpectedEof, ""),
));
}
}
impl<'storage> io::Read for SliceReader<'storage> {
#[inline(always)]
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
(&mut self.slice).read(out)
}
#[inline(always)]
fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> {
(&mut self.slice).read_exact(out)
}
}
impl<'storage> BincodeRead<'storage> for SliceReader<'storage> {
#[inline(always)]
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
use ErrorKind;
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let string = match ::std::str::from_utf8(&self.slice[..length]) {
Ok(s) => s,
Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()),
};
let r = visitor.visit_borrowed_str(string);
self.slice = &self.slice[length..];
r
}
#[inline(always)]
fn get_byte_buffer(&mut self, length: usize) -> Result<Vec<u8>> {
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let r = &self.slice[..length];
self.slice = &self.slice[length..];
Ok(r.to_vec())
}
#[inline(always)]
fn forward_read_bytes<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where
V: serde::de::Visitor<'storage>,
{
if length > self.slice.len() {
return Err(SliceReader::unexpected_eof());
}
let r = visitor.visit_borrowed_bytes(&self.slice[..length]);
self.slice = &self.slice[length..];
r
}
}
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
struct Foo<'a> {
borrowed_str: &'a str,
@ -483,7 +557,12 @@ fn test_zero_copy_parse_deserialize_into() {
borrowed_str: "hello",
borrowed_bytes: &[10, 11, 12, 13],
};
deserialize_in_place(&encoded[..], &mut target).unwrap();
deserialize_in_place(
SliceReader {
slice: &encoded[..],
},
&mut target,
).unwrap();
assert_eq!(target, f);
}
}