mirror of https://git.sr.ht/~stygianentity/bincode
move to custom read implementation for deserialize_in_place
This commit is contained in:
parent
68ca894b81
commit
76b7662dcd
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue