#[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); | |
} |