899 lines
24 KiB
Rust
899 lines
24 KiB
Rust
#[macro_use]
|
|
extern crate serde_derive;
|
|
|
|
extern crate bincode;
|
|
#[macro_use]
|
|
extern crate serde;
|
|
extern crate serde_bytes;
|
|
|
|
use std::borrow::Cow;
|
|
use std::collections::HashMap;
|
|
use std::fmt::{self, Debug};
|
|
use std::result::Result as StdResult;
|
|
|
|
use bincode::{
|
|
deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size,
|
|
DefaultOptions, ErrorKind, Options, Result,
|
|
};
|
|
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
|
|
|
const LEN_SIZE: u64 = 8;
|
|
|
|
fn the_same_impl<V, O>(element: V, options: &mut O)
|
|
where
|
|
V: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug + 'static,
|
|
O: Options,
|
|
{
|
|
let size = options.serialized_size(&element).unwrap();
|
|
|
|
{
|
|
let encoded = options.serialize(&element).unwrap();
|
|
let decoded: V = options.deserialize(&encoded[..]).unwrap();
|
|
let decoded_reader = options.deserialize_from(&mut &encoded[..]).unwrap();
|
|
|
|
assert_eq!(element, decoded);
|
|
assert_eq!(element, decoded_reader);
|
|
assert_eq!(size, encoded.len() as u64);
|
|
}
|
|
}
|
|
|
|
fn the_same<V>(element: V)
|
|
where
|
|
V: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug + Clone + 'static,
|
|
{
|
|
// add a new macro which calls the previous when you add a new option set
|
|
macro_rules! all_endians {
|
|
($element:expr, $options:expr) => {
|
|
the_same_impl($element.clone(), &mut $options.with_native_endian());
|
|
the_same_impl($element.clone(), &mut $options.with_big_endian());
|
|
the_same_impl($element.clone(), &mut $options.with_little_endian());
|
|
};
|
|
}
|
|
|
|
macro_rules! all_integer_encodings {
|
|
($element:expr, $options:expr) => {
|
|
all_endians!($element, $options.with_fixint_encoding());
|
|
all_endians!($element, $options.with_varint_encoding());
|
|
};
|
|
}
|
|
|
|
all_integer_encodings!(element, DefaultOptions::new());
|
|
}
|
|
|
|
#[test]
|
|
fn test_numbers() {
|
|
// unsigned positive
|
|
the_same(5u8);
|
|
the_same(5u16);
|
|
the_same(5u32);
|
|
the_same(5u64);
|
|
the_same(5usize);
|
|
// signed positive
|
|
the_same(5i8);
|
|
the_same(5i16);
|
|
the_same(5i32);
|
|
the_same(5i64);
|
|
the_same(5isize);
|
|
// signed negative
|
|
the_same(-5i8);
|
|
the_same(-5i16);
|
|
the_same(-5i32);
|
|
the_same(-5i64);
|
|
the_same(-5isize);
|
|
// floating
|
|
the_same(-100f32);
|
|
the_same(0f32);
|
|
the_same(5f32);
|
|
the_same(-100f64);
|
|
the_same(5f64);
|
|
}
|
|
|
|
serde_if_integer128! {
|
|
#[test]
|
|
fn test_numbers_128bit() {
|
|
// unsigned positive
|
|
the_same(5u128);
|
|
the_same(u128::max_value());
|
|
// signed positive
|
|
the_same(5i128);
|
|
the_same(i128::max_value());
|
|
// signed negative
|
|
the_same(-5i128);
|
|
the_same(i128::min_value());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_string() {
|
|
the_same("".to_string());
|
|
the_same("a".to_string());
|
|
}
|
|
|
|
#[test]
|
|
fn test_tuple() {
|
|
the_same((1isize,));
|
|
the_same((1isize, 2isize, 3isize));
|
|
the_same((1isize, "foo".to_string(), ()));
|
|
}
|
|
|
|
#[test]
|
|
fn test_basic_struct() {
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
|
struct Easy {
|
|
x: isize,
|
|
s: String,
|
|
y: usize,
|
|
}
|
|
the_same(Easy {
|
|
x: -4,
|
|
s: "foo".to_string(),
|
|
y: 10,
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_nested_struct() {
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
|
struct Easy {
|
|
x: isize,
|
|
s: String,
|
|
y: usize,
|
|
}
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
|
struct Nest {
|
|
f: Easy,
|
|
b: usize,
|
|
s: Easy,
|
|
}
|
|
|
|
the_same(Nest {
|
|
f: Easy {
|
|
x: -1,
|
|
s: "foo".to_string(),
|
|
y: 20,
|
|
},
|
|
b: 100,
|
|
s: Easy {
|
|
x: -100,
|
|
s: "bar".to_string(),
|
|
y: 20,
|
|
},
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_struct_newtype() {
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
|
struct NewtypeStr(usize);
|
|
|
|
the_same(NewtypeStr(5));
|
|
}
|
|
|
|
#[test]
|
|
fn test_struct_tuple() {
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
|
struct TubStr(usize, String, f32);
|
|
|
|
the_same(TubStr(5, "hello".to_string(), 3.2));
|
|
}
|
|
|
|
#[test]
|
|
fn test_option() {
|
|
the_same(Some(5usize));
|
|
the_same(Some("foo bar".to_string()));
|
|
the_same(None::<usize>);
|
|
}
|
|
|
|
#[test]
|
|
fn test_enum() {
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
|
|
enum TestEnum {
|
|
NoArg,
|
|
OneArg(usize),
|
|
Args(usize, usize),
|
|
AnotherNoArg,
|
|
StructLike { x: usize, y: f32 },
|
|
}
|
|
the_same(TestEnum::NoArg);
|
|
the_same(TestEnum::OneArg(4));
|
|
//the_same(TestEnum::Args(4, 5));
|
|
the_same(TestEnum::AnotherNoArg);
|
|
the_same(TestEnum::StructLike { x: 4, y: 3.14159 });
|
|
the_same(vec![
|
|
TestEnum::NoArg,
|
|
TestEnum::OneArg(5),
|
|
TestEnum::AnotherNoArg,
|
|
TestEnum::StructLike { x: 4, y: 1.4 },
|
|
]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_vec() {
|
|
let v: Vec<u8> = vec![];
|
|
the_same(v);
|
|
the_same(vec![1u64]);
|
|
the_same(vec![1u64, 2, 3, 4, 5, 6]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_map() {
|
|
let mut m = HashMap::new();
|
|
m.insert(4u64, "foo".to_string());
|
|
m.insert(0u64, "bar".to_string());
|
|
the_same(m);
|
|
}
|
|
|
|
#[test]
|
|
fn test_bool() {
|
|
the_same(true);
|
|
the_same(false);
|
|
}
|
|
|
|
#[test]
|
|
fn test_unicode() {
|
|
the_same("å".to_string());
|
|
the_same("aåååååååa".to_string());
|
|
}
|
|
|
|
#[test]
|
|
fn test_fixed_size_array() {
|
|
the_same([24u32; 32]);
|
|
the_same([1u64, 2, 3, 4, 5, 6, 7, 8]);
|
|
the_same([0u8; 19]);
|
|
}
|
|
|
|
#[test]
|
|
fn deserializing_errors() {
|
|
match *deserialize::<bool>(&vec![0xA][..]).unwrap_err() {
|
|
ErrorKind::InvalidBoolEncoding(0xA) => {}
|
|
_ => panic!(),
|
|
}
|
|
|
|
let invalid_str = vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF];
|
|
|
|
match *deserialize::<String>(&invalid_str[..]).unwrap_err() {
|
|
ErrorKind::InvalidUtf8Encoding(_) => {}
|
|
_ => panic!(),
|
|
}
|
|
|
|
// Out-of-bounds variant
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
enum Test {
|
|
One,
|
|
Two,
|
|
};
|
|
|
|
let invalid_enum = vec![0, 0, 0, 5];
|
|
|
|
match *deserialize::<Test>(&invalid_enum[..]).unwrap_err() {
|
|
// Error message comes from serde
|
|
ErrorKind::Custom(_) => {}
|
|
_ => panic!(),
|
|
}
|
|
match *deserialize::<Option<u8>>(&vec![5, 0][..]).unwrap_err() {
|
|
ErrorKind::InvalidTagEncoding(_) => {}
|
|
_ => panic!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn trailing_bytes() {
|
|
match DefaultOptions::new()
|
|
.deserialize::<char>(b"1x")
|
|
.map_err(|e| *e)
|
|
{
|
|
Err(ErrorKind::Custom(_)) => {}
|
|
other => panic!("Expecting TrailingBytes, got {:?}", other),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn too_big_deserialize() {
|
|
let serialized = vec![0, 0, 0, 3];
|
|
let deserialized: Result<u32> = DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(3)
|
|
.deserialize_from(&mut &serialized[..]);
|
|
assert!(deserialized.is_err());
|
|
|
|
let serialized = vec![0, 0, 0, 3];
|
|
let deserialized: Result<u32> = DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(4)
|
|
.deserialize_from(&mut &serialized[..]);
|
|
assert!(deserialized.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn char_serialization() {
|
|
let chars = "Aa\0☺♪";
|
|
for c in chars.chars() {
|
|
let encoded = DefaultOptions::new()
|
|
.with_limit(4)
|
|
.serialize(&c)
|
|
.expect("serializing char failed");
|
|
let decoded: char = deserialize(&encoded).expect("deserializing failed");
|
|
assert_eq!(decoded, c);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn too_big_char_deserialize() {
|
|
let serialized = vec![0x41];
|
|
let deserialized: Result<char> = DefaultOptions::new()
|
|
.with_limit(1)
|
|
.deserialize_from(&mut &serialized[..]);
|
|
assert!(deserialized.is_ok());
|
|
assert_eq!(deserialized.unwrap(), 'A');
|
|
}
|
|
|
|
#[test]
|
|
fn too_big_serialize() {
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(3)
|
|
.serialize(&0u32)
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(4)
|
|
.serialize(&0u32)
|
|
.is_ok());
|
|
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(LEN_SIZE + 4)
|
|
.serialize(&"abcde")
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(LEN_SIZE + 5)
|
|
.serialize(&"abcde")
|
|
.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_serialized_size() {
|
|
assert!(serialized_size(&0u8).unwrap() == 1);
|
|
assert!(serialized_size(&0u16).unwrap() == 2);
|
|
assert!(serialized_size(&0u32).unwrap() == 4);
|
|
assert!(serialized_size(&0u64).unwrap() == 8);
|
|
|
|
// length isize stored as u64
|
|
assert!(serialized_size(&"").unwrap() == LEN_SIZE);
|
|
assert!(serialized_size(&"a").unwrap() == LEN_SIZE + 1);
|
|
|
|
assert!(serialized_size(&vec![0u32, 1u32, 2u32]).unwrap() == LEN_SIZE + 3 * (4));
|
|
}
|
|
|
|
#[test]
|
|
fn test_serialized_size_bounded() {
|
|
// JUST RIGHT
|
|
assert!(
|
|
DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(1)
|
|
.serialized_size(&0u8)
|
|
.unwrap()
|
|
== 1
|
|
);
|
|
assert!(
|
|
DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(2)
|
|
.serialized_size(&0u16)
|
|
.unwrap()
|
|
== 2
|
|
);
|
|
assert!(
|
|
DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(4)
|
|
.serialized_size(&0u32)
|
|
.unwrap()
|
|
== 4
|
|
);
|
|
assert!(
|
|
DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(8)
|
|
.serialized_size(&0u64)
|
|
.unwrap()
|
|
== 8
|
|
);
|
|
assert!(
|
|
DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(8)
|
|
.serialized_size(&"")
|
|
.unwrap()
|
|
== LEN_SIZE
|
|
);
|
|
assert!(
|
|
DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(8 + 1)
|
|
.serialized_size(&"a")
|
|
.unwrap()
|
|
== LEN_SIZE + 1
|
|
);
|
|
assert!(
|
|
DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(LEN_SIZE + 3 * 4)
|
|
.serialized_size(&vec![0u32, 1u32, 2u32])
|
|
.unwrap()
|
|
== LEN_SIZE + 3 * 4
|
|
);
|
|
// Below
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(0)
|
|
.serialized_size(&0u8)
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(1)
|
|
.serialized_size(&0u16)
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(3)
|
|
.serialized_size(&0u32)
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(7)
|
|
.serialized_size(&0u64)
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(7)
|
|
.serialized_size(&"")
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(8 + 0)
|
|
.serialized_size(&"a")
|
|
.is_err());
|
|
assert!(DefaultOptions::new()
|
|
.with_fixint_encoding()
|
|
.with_limit(8 + 3 * 4 - 1)
|
|
.serialized_size(&vec![0u32, 1u32, 2u32])
|
|
.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn encode_box() {
|
|
the_same(Box::new(5));
|
|
}
|
|
|
|
#[test]
|
|
fn test_cow_serialize() {
|
|
let large_object = vec![1u32, 2, 3, 4, 5, 6];
|
|
let mut large_map = HashMap::new();
|
|
large_map.insert(1, 2);
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
enum Message<'a> {
|
|
M1(Cow<'a, Vec<u32>>),
|
|
M2(Cow<'a, HashMap<u32, u32>>),
|
|
}
|
|
|
|
// Test 1
|
|
{
|
|
let serialized = serialize(&Message::M1(Cow::Borrowed(&large_object))).unwrap();
|
|
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..]).unwrap();
|
|
|
|
match deserialized {
|
|
Message::M1(b) => assert!(&b.into_owned() == &large_object),
|
|
_ => assert!(false),
|
|
}
|
|
}
|
|
|
|
// Test 2
|
|
{
|
|
let serialized = serialize(&Message::M2(Cow::Borrowed(&large_map))).unwrap();
|
|
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..]).unwrap();
|
|
|
|
match deserialized {
|
|
Message::M2(b) => assert!(&b.into_owned() == &large_map),
|
|
_ => assert!(false),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_strbox_serialize() {
|
|
let strx: &'static str = "hello world";
|
|
let serialized = serialize(&Cow::Borrowed(strx)).unwrap();
|
|
let deserialized: Cow<'static, String> = deserialize_from(&mut &serialized[..]).unwrap();
|
|
let stringx: String = deserialized.into_owned();
|
|
assert!(strx == &stringx[..]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_slicebox_serialize() {
|
|
let slice = [1u32, 2, 3, 4, 5];
|
|
let serialized = serialize(&Cow::Borrowed(&slice[..])).unwrap();
|
|
println!("{:?}", serialized);
|
|
let deserialized: Cow<'static, Vec<u32>> = deserialize_from(&mut &serialized[..]).unwrap();
|
|
{
|
|
let sb: &[u32] = &deserialized;
|
|
assert!(slice == sb);
|
|
}
|
|
let vecx: Vec<u32> = deserialized.into_owned();
|
|
assert!(slice == &vecx[..]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_multi_strings_serialize() {
|
|
assert!(serialize(&("foo", "bar", "baz")).is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_oom_protection() {
|
|
use std::io::Cursor;
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
struct FakeVec {
|
|
len: u64,
|
|
byte: u8,
|
|
}
|
|
let x = DefaultOptions::new()
|
|
.with_limit(10)
|
|
.serialize(&FakeVec {
|
|
len: 0xffffffffffffffffu64,
|
|
byte: 1,
|
|
})
|
|
.unwrap();
|
|
let y: Result<Vec<u8>> = DefaultOptions::new()
|
|
.with_limit(10)
|
|
.deserialize_from(&mut Cursor::new(&x[..]));
|
|
assert!(y.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn path_buf() {
|
|
use std::path::{Path, PathBuf};
|
|
let path = Path::new("foo").to_path_buf();
|
|
let serde_encoded = serialize(&path).unwrap();
|
|
let decoded: PathBuf = deserialize(&serde_encoded).unwrap();
|
|
assert!(path.to_str() == decoded.to_str());
|
|
}
|
|
|
|
#[test]
|
|
fn bytes() {
|
|
use serde_bytes::Bytes;
|
|
|
|
let data = b"abc\0123";
|
|
let s = serialize(&data[..]).unwrap();
|
|
let s2 = serialize(&Bytes::new(data)).unwrap();
|
|
assert_eq!(s[..], s2[..]);
|
|
}
|
|
|
|
#[test]
|
|
fn serde_bytes() {
|
|
use serde_bytes::ByteBuf;
|
|
the_same(ByteBuf::from(vec![1, 2, 3, 4, 5]));
|
|
}
|
|
|
|
#[test]
|
|
fn endian_difference() {
|
|
let x = 10u64;
|
|
let little = serialize(&x).unwrap();
|
|
let big = DefaultOptions::new()
|
|
.with_big_endian()
|
|
.serialize(&x)
|
|
.unwrap();
|
|
assert_ne!(little, big);
|
|
}
|
|
|
|
#[test]
|
|
fn test_zero_copy_parse() {
|
|
#[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 out: Foo = deserialize(&encoded[..]).unwrap();
|
|
assert_eq!(out, f);
|
|
}
|
|
}
|
|
|
|
#[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,
|
|
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(
|
|
SliceReader {
|
|
slice: &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::<Ipv4Addr>() as u64,
|
|
serialized_size(&ip).unwrap()
|
|
);
|
|
}
|
|
|
|
// The example is taken from serde::de::DeserializeSeed.
|
|
struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>);
|
|
|
|
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<D>(self, deserializer: D) -> StdResult<Self::Value, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
// Visitor implementation that will walk an inner array of the JSON
|
|
// input.
|
|
struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
|
|
|
|
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<A>(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 = DefaultOptions::new();
|
|
|
|
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::<Vec<_>>());
|
|
}
|
|
|
|
#[test]
|
|
fn test_big_endian_deserialize_seed() {
|
|
let config = DefaultOptions::new().with_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::<Vec<_>>());
|
|
}
|
|
|
|
#[test]
|
|
fn test_default_deserialize_from_seed() {
|
|
let config = DefaultOptions::new();
|
|
|
|
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_from_seed(seed, &mut &*bytes)
|
|
.expect("Config::deserialize_from_seed failed");
|
|
}
|
|
|
|
assert_eq!(seed_data, (0..100).collect::<Vec<_>>());
|
|
}
|
|
|
|
#[test]
|
|
fn test_big_endian_deserialize_from_seed() {
|
|
let config = DefaultOptions::new().with_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_from_seed(seed, &mut &*bytes)
|
|
.expect("Config::deserialize_from_seed failed");
|
|
}
|
|
|
|
assert_eq!(seed_data, (0..100).collect::<Vec<_>>());
|
|
}
|
|
|
|
#[test]
|
|
fn test_varint_length_prefixes() {
|
|
let a = vec![(); 127]; // should be a single byte
|
|
let b = vec![(); 250]; // also should be a single byte
|
|
let c = vec![(); 251];
|
|
let d = vec![(); u16::max_value() as usize + 1];
|
|
|
|
assert_eq!(
|
|
DefaultOptions::new()
|
|
.with_varint_encoding()
|
|
.serialized_size(&a[..])
|
|
.unwrap(),
|
|
1
|
|
); // 2 ** 7 - 1
|
|
assert_eq!(
|
|
DefaultOptions::new()
|
|
.with_varint_encoding()
|
|
.serialized_size(&b[..])
|
|
.unwrap(),
|
|
1
|
|
); // 250
|
|
assert_eq!(
|
|
DefaultOptions::new()
|
|
.with_varint_encoding()
|
|
.serialized_size(&c[..])
|
|
.unwrap(),
|
|
(1 + std::mem::size_of::<u16>()) as u64
|
|
); // 251
|
|
assert_eq!(
|
|
DefaultOptions::new()
|
|
.with_varint_encoding()
|
|
.serialized_size(&d[..])
|
|
.unwrap(),
|
|
(1 + std::mem::size_of::<u32>()) as u64
|
|
); // 2 ** 16 + 1
|
|
}
|
|
|
|
#[test]
|
|
fn test_byte_vec_struct() {
|
|
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
|
|
struct ByteVecs {
|
|
a: Vec<u8>,
|
|
b: Vec<u8>,
|
|
c: Vec<u8>,
|
|
};
|
|
|
|
let byte_struct = ByteVecs {
|
|
a: vec![2; 20],
|
|
b: vec![3; 30],
|
|
c: vec![1; 10],
|
|
};
|
|
|
|
the_same(byte_struct);
|
|
}
|