blob: 4f5eee2544fdd4417df76d8a86aa998dd3896cd4 [file] [log] [blame]
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate serde;
extern crate serde_bytes;
extern crate byteorder;
use std::fmt::Debug;
use std::collections::HashMap;
use std::borrow::Cow;
use bincode::{Bounded, Infinite};
use bincode::{serialized_size, ErrorKind, Result};
use bincode::internal::{deserialize, deserialize_from, serialize};
use bincode::serialize as serialize_little;
use bincode::deserialize as deserialize_little;
use bincode::deserialize_from as deserialize_from_little;
fn the_same<V>(element: V)
where
V: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug + 'static,
{
let size = serialized_size(&element);
{
let encoded = serialize_little(&element, Infinite).unwrap();
let decoded = deserialize_little(&encoded[..]).unwrap();
assert_eq!(element, decoded);
assert_eq!(size, encoded.len() as u64);
}
{
let encoded = serialize::<_, _, byteorder::BigEndian>(&element, Infinite).unwrap();
let decoded = deserialize::<_, byteorder::BigEndian>(&encoded[..]).unwrap();
let decoded_reader =
deserialize_from::<_, _, _, byteorder::BigEndian>(&mut &encoded[..], Infinite).unwrap();
assert_eq!(element, decoded);
assert_eq!(element, decoded_reader);
assert_eq!(size, encoded.len() as u64);
}
}
#[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);
}
#[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)]
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)]
struct Easy {
x: isize,
s: String,
y: usize,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
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)]
struct NewtypeStr(usize);
the_same(NewtypeStr(5));
}
#[test]
fn test_struct_tuple() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
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)]
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_little::<bool>(&vec![0xA][..]).unwrap_err() {
ErrorKind::InvalidBoolEncoding(0xA) => {}
_ => panic!(),
}
match *deserialize_little::<String>(&vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF][..]).unwrap_err() {
ErrorKind::InvalidUtf8Encoding(_) => {}
_ => panic!(),
}
// Out-of-bounds variant
#[derive(Serialize, Deserialize, Debug)]
enum Test {
One,
Two,
};
match *deserialize_little::<Test>(&vec![0, 0, 0, 5][..]).unwrap_err() {
// Error message comes from serde
ErrorKind::Custom(_) => {}
_ => panic!(),
}
match *deserialize_little::<Option<u8>>(&vec![5, 0][..]).unwrap_err() {
ErrorKind::InvalidTagEncoding(_) => {}
_ => panic!(),
}
}
#[test]
fn too_big_deserialize() {
let serialized = vec![0, 0, 0, 3];
let deserialized: Result<u32> =
deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(3));
assert!(deserialized.is_err());
let serialized = vec![0, 0, 0, 3];
let deserialized: Result<u32> =
deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(4));
assert!(deserialized.is_ok());
}
#[test]
fn char_serialization() {
let chars = "Aa\0☺♪";
for c in chars.chars() {
let encoded = serialize_little(&c, Bounded(4)).expect("serializing char failed");
let decoded: char = deserialize_little(&encoded).expect("deserializing failed");
assert_eq!(decoded, c);
}
}
#[test]
fn too_big_char_deserialize() {
let serialized = vec![0x41];
let deserialized: Result<char> =
deserialize_from_little::<_, _, _>(&mut &serialized[..], Bounded(1));
assert!(deserialized.is_ok());
assert_eq!(deserialized.unwrap(), 'A');
}
#[test]
fn too_big_serialize() {
assert!(serialize_little(&0u32, Bounded(3)).is_err());
assert!(serialize_little(&0u32, Bounded(4)).is_ok());
assert!(serialize_little(&"abcde", Bounded(8 + 4)).is_err());
assert!(serialize_little(&"abcde", Bounded(8 + 5)).is_ok());
}
#[test]
fn test_proxy_encoded_size() {
assert!(serialized_size(&0u8) == 1);
assert!(serialized_size(&0u16) == 2);
assert!(serialized_size(&0u32) == 4);
assert!(serialized_size(&0u64) == 8);
// length isize stored as u64
assert!(serialized_size(&"") == 8);
assert!(serialized_size(&"a") == 8 + 1);
assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
}
#[test]
fn test_serialized_size() {
assert!(serialized_size(&0u8) == 1);
assert!(serialized_size(&0u16) == 2);
assert!(serialized_size(&0u32) == 4);
assert!(serialized_size(&0u64) == 8);
// length isize stored as u64
assert!(serialized_size(&"") == 8);
assert!(serialized_size(&"a") == 8 + 1);
assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
}
#[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_little(&Message::M1(Cow::Borrowed(&large_object)), Infinite).unwrap();
let deserialized: Message<'static> =
deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
match deserialized {
Message::M1(b) => assert!(&b.into_owned() == &large_object),
_ => assert!(false),
}
}
// Test 2
{
let serialized =
serialize_little(&Message::M2(Cow::Borrowed(&large_map)), Infinite).unwrap();
let deserialized: Message<'static> =
deserialize_from_little(&mut &serialized[..], Infinite).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_little(&Cow::Borrowed(strx), Infinite).unwrap();
let deserialized: Cow<'static, String> =
deserialize_from_little(&mut &serialized[..], Infinite).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_little(&Cow::Borrowed(&slice[..]), Infinite).unwrap();
println!("{:?}", serialized);
let deserialized: Cow<'static, Vec<u32>> =
deserialize_from_little(&mut &serialized[..], Infinite).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_little(&("foo", "bar", "baz"), Infinite).is_ok());
}
#[test]
fn test_oom_protection() {
use std::io::Cursor;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct FakeVec {
len: u64,
byte: u8,
}
let x = serialize_little(
&FakeVec {
len: 0xffffffffffffffffu64,
byte: 1,
},
Bounded(10),
).unwrap();
let y: Result<Vec<u8>> = deserialize_from_little(&mut Cursor::new(&x[..]), Bounded(10));
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_little(&path, Infinite).unwrap();
let decoded: PathBuf = deserialize_little(&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_little(&data[..], Infinite).unwrap();
let s2 = serialize_little(&Bytes::new(data), Infinite).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_little(&x, Infinite).unwrap();
let big = serialize::<_, _, byteorder::BigEndian>(&x, Infinite).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_little(&f, Infinite).unwrap();
let out: Foo = deserialize_little(&encoded[..]).unwrap();
assert_eq!(out, f);
}
}