From 0d6b8a48b69daae6b01e4636afd79dc60433b1f7 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 1 Jul 2015 20:19:34 -0700 Subject: [PATCH] Get serde working --- Cargo.toml | 1 + src/lib.rs | 9 + src/reader_serde.rs | 599 ++++++++++++++++++++++++++++++++++++++++++++ src/refbox.rs | 83 ++++++ tests/test.rs | 2 + tests/test_serde.rs | 178 +++++++++++-- 6 files changed, 850 insertions(+), 22 deletions(-) create mode 100644 src/reader_serde.rs diff --git a/Cargo.toml b/Cargo.toml index 1f5fa37..89a7844 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,6 @@ description = "A binary serialization / deserialization strategy and implementat [dependencies] rustc-serialize = "0.3.*" byteorder = "0.3.*" +num = "*" serde = "*" serde_macros = "*" diff --git a/src/lib.rs b/src/lib.rs index bcea473..49cc137 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ extern crate rustc_serialize; extern crate byteorder; +extern crate num; extern crate serde; use rustc_serialize::{Encodable, Decodable}; @@ -40,6 +41,13 @@ pub use refbox::{RefBox, StrBox, SliceBox}; pub use writer::{EncoderWriter, EncodingResult, EncodingError}; pub use reader::{DecoderReader, DecodingResult, DecodingError}; use writer::SizeChecker; +pub use reader_serde::{ + Deserializer, + DeserializeResult, + DeserializeError, + from_reader, + from_slice, +}; pub use writer_serde::{ Serializer, SerializeResult, @@ -56,6 +64,7 @@ mod writer; mod reader; mod refbox; mod writer_serde; +mod reader_serde; /// A limit on the amount of bytes that can be read or written. /// diff --git a/src/reader_serde.rs b/src/reader_serde.rs new file mode 100644 index 0000000..8f53322 --- /dev/null +++ b/src/reader_serde.rs @@ -0,0 +1,599 @@ +use std::io; +use std::io::Read; +use std::io::Error as IoError; +use std::error::Error; +use std::fmt; +use std::convert::From; + +use byteorder::Error as ByteOrderError; +use byteorder::{BigEndian, ReadBytesExt}; +use num; +use serde; +use serde::de::value::ValueDeserializer; + +use super::SizeLimit; + +#[derive(Eq, PartialEq, Clone, Debug)] +pub struct InvalidEncoding { + desc: &'static str, + detail: Option, +} + +impl fmt::Display for InvalidEncoding { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + InvalidEncoding { detail: None, desc } => + write!(fmt, "{}", desc), + InvalidEncoding { detail: Some(ref detail), desc } => + write!(fmt, "{} ({})", desc, detail) + } + } +} + +/// An error that can be produced during decoding. +/// +/// If decoding from a Buffer, assume that the buffer has been left +/// in an invalid state. +#[derive(Debug)] +pub enum DeserializeError { + /// If the error stems from the reader that is being used + /// during decoding, that error will be stored and returned here. + IoError(IoError), + /// If the bytes in the reader are not decodable because of an invalid + /// encoding, this error will be returned. This error is only possible + /// if a stream is corrupted. A stream produced from `encode` or `encode_into` + /// should **never** produce an InvalidEncoding error. + InvalidEncoding(InvalidEncoding), + /// If decoding a message takes more than the provided size limit, this + /// error is returned. + SizeLimit, + SyntaxError, + EndOfStreamError, + UnknownFieldError, + MissingFieldError, +} + +impl Error for DeserializeError { + fn description(&self) -> &str { + match *self { + DeserializeError::IoError(ref err) => Error::description(err), + DeserializeError::InvalidEncoding(ref ib) => ib.desc, + DeserializeError::SizeLimit => "the size limit for decoding has been reached", + DeserializeError::SyntaxError => "syntax error", + DeserializeError::EndOfStreamError => "Unexpected EOF while reading a multi-byte number", + DeserializeError::UnknownFieldError => "unknown field error", + DeserializeError::MissingFieldError => "missing field error", + } + } + + fn cause(&self) -> Option<&Error> { + match *self { + DeserializeError::IoError(ref err) => err.cause(), + DeserializeError::InvalidEncoding(_) => None, + DeserializeError::SizeLimit => None, + DeserializeError::SyntaxError => None, + DeserializeError::EndOfStreamError => None, + DeserializeError::UnknownFieldError => None, + DeserializeError::MissingFieldError => None, + } + } +} + +impl From for DeserializeError { + fn from(err: IoError) -> DeserializeError { + DeserializeError::IoError(err) + } +} + +impl From for DeserializeError { + fn from(err: ByteOrderError) -> DeserializeError { + match err { + ByteOrderError::Io(ioe) => DeserializeError::IoError(ioe), + ByteOrderError::UnexpectedEOF => DeserializeError::EndOfStreamError, + } + } +} + +impl From for DeserializeError { + fn from(err: serde::de::value::Error) -> DeserializeError { + use serde::de::value::Error; + + match err { + Error::SyntaxError => DeserializeError::SyntaxError, + Error::EndOfStreamError => { + DeserializeError::EndOfStreamError + } + Error::UnknownFieldError(_) => DeserializeError::UnknownFieldError, + Error::MissingFieldError(_) => DeserializeError::MissingFieldError, + } + } +} + +impl fmt::Display for DeserializeError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + DeserializeError::IoError(ref ioerr) => + write!(fmt, "IoError: {}", ioerr), + DeserializeError::InvalidEncoding(ref ib) => + write!(fmt, "InvalidEncoding: {}", ib), + DeserializeError::SizeLimit => + write!(fmt, "SizeLimit"), + DeserializeError::SyntaxError => + write!(fmt, "SyntaxError"), + DeserializeError::EndOfStreamError => + write!(fmt, "EndOfStreamError"), + DeserializeError::UnknownFieldError => + write!(fmt, "UnknownFieldError"), + DeserializeError::MissingFieldError => + write!(fmt, "MissingFieldError"), + } + } +} + +impl serde::de::Error for DeserializeError { + fn syntax_error() -> DeserializeError { + DeserializeError::SyntaxError + } + + fn end_of_stream_error() -> DeserializeError { + DeserializeError::EndOfStreamError + } + + fn unknown_field_error(_field: &str) -> DeserializeError { + DeserializeError::UnknownFieldError + } + + fn missing_field_error(_field: &'static str) -> DeserializeError { + DeserializeError::MissingFieldError + } +} + +pub type DeserializeResult = Result; + + +/// A Deserializer that reads bytes from a buffer. +/// +/// This struct should rarely be used. +/// In most cases, prefer the `decode_from` function. +pub struct Deserializer<'a, R: 'a> { + reader: &'a mut R, + size_limit: SizeLimit, + read: u64 +} + +impl<'a, R: Read> Deserializer<'a, R> { + pub fn new(r: &'a mut R, size_limit: SizeLimit) -> Deserializer<'a, R> { + Deserializer { + reader: r, + size_limit: size_limit, + read: 0 + } + } + + /// Returns the number of bytes read from the contained Reader. + pub fn bytes_read(&self) -> u64 { + self.read + } +} + +impl <'a, A> Deserializer<'a, A> { + fn read_bytes(&mut self, count: u64) -> Result<(), DeserializeError> { + self.read += count; + match self.size_limit { + SizeLimit::Infinite => Ok(()), + SizeLimit::Bounded(x) if self.read <= x => Ok(()), + SizeLimit::Bounded(_) => Err(DeserializeError::SizeLimit) + } + } + + fn read_type(&mut self) -> Result<(), DeserializeError> { + use std::mem::size_of; + self.read_bytes(size_of::() as u64) + } +} + +macro_rules! impl_nums { + ($ty:ty, $visitor_method:ident, $reader_method:ident) => { + #[inline] + fn $visitor_method(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + try!(self.read_type::<$ty>()); + let value = try!(self.reader.$reader_method::()); + visitor.$visitor_method(value) + } + } +} + + +impl<'a, R: Read> serde::Deserializer for Deserializer<'a, R> { + type Error = DeserializeError; + + #[inline] + fn visit(&mut self, _visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + Err(serde::de::Error::syntax_error()) + } + + fn visit_bool(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + let value: u8 = try!(serde::Deserialize::deserialize(self)); + match value { + 1 => visitor.visit_bool(true), + 0 => visitor.visit_bool(false), + value => { + Err(DeserializeError::InvalidEncoding(InvalidEncoding { + desc: "invalid u8 when decoding bool", + detail: Some(format!("Expected 0 or 1, got {}", value)) + })) + } + } + } + + #[inline] + fn visit_u8(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + try!(self.read_type::()); + visitor.visit_u8(try!(self.reader.read_u8())) + } + + impl_nums!(u16, visit_u16, read_u16); + impl_nums!(u32, visit_u32, read_u32); + impl_nums!(u64, visit_u64, read_u64); + + #[inline] + fn visit_usize(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + try!(self.read_type::()); + let value = try!(self.reader.read_u64::()); + match num::cast(value) { + Some(value) => visitor.visit_usize(value), + None => Err(serde::de::Error::syntax_error()), + } + } + + #[inline] + fn visit_i8(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + try!(self.read_type::()); + visitor.visit_i8(try!(self.reader.read_i8())) + } + + impl_nums!(i16, visit_i16, read_i16); + impl_nums!(i32, visit_i32, read_i32); + impl_nums!(i64, visit_i64, read_i64); + + #[inline] + fn visit_isize(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + try!(self.read_type::()); + let value = try!(self.reader.read_i64::()); + match num::cast(value) { + Some(value) => visitor.visit_isize(value), + None => Err(serde::de::Error::syntax_error()), + } + } + + impl_nums!(f32, visit_f32, read_f32); + impl_nums!(f64, visit_f64, read_f64); + + fn visit_unit(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + visitor.visit_unit() + } + + fn visit_char(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + use std::str; + + let error = DeserializeError::InvalidEncoding(InvalidEncoding { + desc: "Invalid char encoding", + detail: None + }); + + let mut buf = [0]; + + let _ = try!(self.reader.read(&mut buf[..])); + let first_byte = buf[0]; + let width = utf8_char_width(first_byte); + if width == 1 { return visitor.visit_char(first_byte as char) } + if width == 0 { return Err(error)} + + let mut buf = [first_byte, 0, 0, 0]; + { + let mut start = 1; + while start < width { + match try!(self.reader.read(&mut buf[start .. width])) { + n if n == width - start => break, + n if n < width - start => { start += n; } + _ => return Err(error) + } + } + } + + let res = try!(match str::from_utf8(&buf[..width]).ok() { + Some(s) => Ok(s.chars().next().unwrap()), + None => Err(error) + }); + + try!(self.read_bytes(res.len_utf8() as u64)); + visitor.visit_char(res) + } + + fn visit_string(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + let len = try!(serde::Deserialize::deserialize(self)); + try!(self.read_bytes(len)); + + let mut buffer = Vec::new(); + try!(self.reader.by_ref().take(len as u64).read_to_end(&mut buffer)); + + match String::from_utf8(buffer) { + Ok(s) => visitor.visit_string(s), + Err(err) => Err(DeserializeError::InvalidEncoding(InvalidEncoding { + desc: "error while decoding utf8 string", + detail: Some(format!("Deserialize error: {}", err)) + })), + } + } + + fn visit_enum(&mut self, _enum: &str, mut visitor: V) -> Result + where V: serde::de::EnumVisitor, + { + visitor.visit(self) + } + + fn visit_tuple(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + struct TupleVisitor<'a, 'b: 'a, R: Read + 'b>(&'a mut Deserializer<'b, R>); + + impl<'a, 'b: 'a, R: Read + 'b> serde::de::SeqVisitor for TupleVisitor<'a, 'b, R> { + type Error = DeserializeError; + + fn visit(&mut self) -> Result, Self::Error> + where T: serde::de::Deserialize, + { + let value = try!(serde::Deserialize::deserialize(self.0)); + Ok(Some(value)) + } + + fn end(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } + + visitor.visit_seq(TupleVisitor(self)) + } + + fn visit_named_seq(&mut self, _name: &str, visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + self.visit_tuple(visitor) + } + + fn visit_option(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + let value: u8 = try!(serde::de::Deserialize::deserialize(self)); + match value { + 0 => visitor.visit_none(), + 1 => visitor.visit_some(self), + _ => Err(DeserializeError::InvalidEncoding(InvalidEncoding { + desc: "invalid tag when decoding Option", + detail: Some(format!("Expected 0 or 1, got {}", value)) + })), + } + } + + fn visit_seq(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + struct SeqVisitor<'a, 'b: 'a, R: Read + 'b> { + deserializer: &'a mut Deserializer<'b, R>, + len: usize, + } + + impl<'a, 'b: 'a, R: Read + 'b> serde::de::SeqVisitor for SeqVisitor<'a, 'b, R> { + type Error = DeserializeError; + + fn visit(&mut self) -> Result, Self::Error> + where T: serde::de::Deserialize, + { + if self.len > 0 { + self.len -= 1; + let value = try!(serde::Deserialize::deserialize(self.deserializer)); + Ok(Some(value)) + } else { + Ok(None) + } + } + + fn end(&mut self) -> Result<(), Self::Error> { + if self.len == 0 { + Ok(()) + } else { + Err(serde::de::Error::syntax_error()) + } + } + } + + let len = try!(serde::Deserialize::deserialize(self)); + + visitor.visit_seq(SeqVisitor { deserializer: self, len: len }) + } + + fn visit_map(&mut self, mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + struct MapVisitor<'a, 'b: 'a, R: Read + 'b> { + deserializer: &'a mut Deserializer<'b, R>, + len: usize, + } + + impl<'a, 'b: 'a, R: Read + 'b> serde::de::MapVisitor for MapVisitor<'a, 'b, R> { + type Error = DeserializeError; + + fn visit_key(&mut self) -> Result, Self::Error> + where K: serde::de::Deserialize, + { + if self.len > 0 { + self.len -= 1; + let key = try!(serde::Deserialize::deserialize(self.deserializer)); + Ok(Some(key)) + } else { + Ok(None) + } + } + + fn visit_value(&mut self) -> Result + where V: serde::de::Deserialize, + { + let value = try!(serde::Deserialize::deserialize(self.deserializer)); + Ok(value) + } + + fn end(&mut self) -> Result<(), Self::Error> { + if self.len == 0 { + Ok(()) + } else { + Err(serde::de::Error::syntax_error()) + } + } + } + + let len = try!(serde::Deserialize::deserialize(self)); + + visitor.visit_map(MapVisitor { deserializer: self, len: len }) + } + + fn visit_named_map(&mut self, + _name: &str, + fields: &'static [&'static str], + mut visitor: V) -> DeserializeResult + where V: serde::de::Visitor, + { + struct StructVisitor<'a, 'b: 'a, R: Read + 'b> { + deserializer: &'a mut Deserializer<'b, R>, + index: usize, + fields: &'static [&'static str], + } + + impl<'a, 'b: 'a, R: Read + 'b> serde::de::MapVisitor for StructVisitor<'a, 'b, R> { + type Error = DeserializeError; + + fn visit_key(&mut self) -> Result, Self::Error> + where K: serde::de::Deserialize, + { + if self.index < self.fields.len() { + let mut deserializer = self.index.into_deserializer(); + self.index += 1; + + let key = try!(serde::Deserialize::deserialize(&mut deserializer)); + Ok(Some(key)) + } else { + Ok(None) + } + } + + fn visit_value(&mut self) -> Result + where V: serde::de::Deserialize, + { + let value = try!(serde::Deserialize::deserialize(self.deserializer)); + Ok(value) + } + + fn end(&mut self) -> Result<(), Self::Error> { + if self.index < self.fields.len() { + Err(serde::de::Error::missing_field_error(self.fields[self.index])) + } else { + Ok(()) + } + } + } + + visitor.visit_map(StructVisitor { + deserializer: self, + index: 0, + fields: fields, + }) + } +} + +impl<'a, R: Read> serde::de::VariantVisitor for Deserializer<'a, R> { + type Error = DeserializeError; + + fn visit_variant(&mut self) -> Result + where V: serde::Deserialize, + { + let index: u32 = try!(serde::Deserialize::deserialize(self)); + let mut deserializer = (index as usize).into_deserializer(); + Ok(try!(serde::Deserialize::deserialize(&mut deserializer))) + } + + fn visit_unit(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + + fn visit_seq(&mut self, visitor: V) -> Result + where V: serde::de::Visitor, + { + serde::de::Deserializer::visit_named_seq(self, "", visitor) + } + + fn visit_map(&mut self, + fields: &'static [&'static str], + visitor: V) -> Result + where V: serde::de::Visitor, + { + serde::de::Deserializer::visit_named_map(self, "", fields, visitor) + } + +} + +pub fn from_reader(reader: &mut R, size_limit: SizeLimit) -> DeserializeResult + where R: io::Read, + T: serde::Deserialize, +{ + let mut deserializer = Deserializer::new(reader, size_limit); + serde::Deserialize::deserialize(&mut deserializer) +} + +pub fn from_slice(bytes: &[u8], size_limit: SizeLimit) -> DeserializeResult + where T: serde::Deserialize, +{ + let mut reader = bytes; + from_reader(&mut reader, size_limit) +} + +static UTF8_CHAR_WIDTH: [u8; 256] = [ +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF +0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF +4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF +]; + +fn utf8_char_width(b: u8) -> usize { + UTF8_CHAR_WIDTH[b as usize] as usize +} diff --git a/src/refbox.rs b/src/refbox.rs index 9cd921a..5bcf6cf 100644 --- a/src/refbox.rs +++ b/src/refbox.rs @@ -4,6 +4,8 @@ use std::ops::Deref; use rustc_serialize::{Encodable, Encoder}; use rustc_serialize::{Decodable, Decoder}; +use serde; + /// A struct for encoding nested reference types. /// /// Encoding large objects by reference is really handy. For example, @@ -151,6 +153,25 @@ impl Decodable for RefBox<'static, T> { } } +impl<'a, T> serde::Serialize for RefBox<'a, T> + where T: serde::Serialize, +{ + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + serde::Serialize::serialize(&self.inner, serializer) + } +} + +impl serde::Deserialize for RefBox<'static, T> { + fn deserialize(deserializer: &mut D) -> Result + where D: serde::Deserializer + { + let inner = try!(serde::Deserialize::deserialize(deserializer)); + Ok(RefBox{ inner: inner }) + } +} + impl<'a> StrBox<'a> { /// Creates a new StrBox that looks at a borrowed value. pub fn new(s: &'a str) -> StrBox<'a> { @@ -226,6 +247,23 @@ impl Decodable for StrBox<'static> { } } +impl<'a> serde::Serialize for StrBox<'a> { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + serde::Serialize::serialize(&self.inner, serializer) + } +} + +impl serde::Deserialize for StrBox<'static> { + fn deserialize(deserializer: &mut D) -> Result + where D: serde::Deserializer + { + let inner = try!(serde::Deserialize::deserialize(deserializer)); + Ok(StrBox{ inner: inner }) + } +} + // // SliceBox // @@ -296,6 +334,25 @@ impl Decodable for SliceBox<'static, T> { } } +impl<'a, T> serde::Serialize for SliceBox<'a, T> + where T: serde::Serialize, +{ + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + serde::Serialize::serialize(&self.inner, serializer) + } +} + +impl serde::Deserialize for SliceBox<'static, T> { + fn deserialize(deserializer: &mut D) -> Result + where D: serde::Deserializer + { + let inner = try!(serde::Deserialize::deserialize(deserializer)); + Ok(SliceBox{ inner: inner }) + } +} + impl <'a, A: Encodable + ?Sized, B: Encodable> Encodable for RefBoxInner<'a, A, B> { fn encode(&self, s: &mut S) -> Result<(), S::Error> { match self { @@ -305,6 +362,21 @@ impl <'a, A: Encodable + ?Sized, B: Encodable> Encodable for RefBoxInner<'a, A, } } +impl<'a, A: ?Sized, B> serde::Serialize for RefBoxInner<'a, A, B> + where A: serde::Serialize, + B: serde::Serialize, +{ + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer + { + match self { + &RefBoxInner::Ref(ref r) => serde::Serialize::serialize(r, serializer), + &RefBoxInner::Box(ref b) => serde::Serialize::serialize(b, serializer), + } + } +} + + impl Decodable for RefBoxInner<'static, A, B> { fn decode(d: &mut D) -> Result, D::Error> { let decoded = try!(Decodable::decode(d)); @@ -312,6 +384,17 @@ impl Decodable for RefBoxInner<'static, A, B> { } } +impl serde::Deserialize for RefBoxInner<'static, A, B> + where B: serde::Deserialize, +{ + fn deserialize(deserializer: &mut D) -> Result + where D: serde::Deserializer + { + let deserialized = try!(serde::Deserialize::deserialize(deserializer)); + Ok(RefBoxInner::Box(deserialized)) + } +} + impl <'a, T> Deref for RefBox<'a, T> { type Target = T; diff --git a/tests/test.rs b/tests/test.rs index f3f8580..e6ebd19 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,3 +1,4 @@ +/* extern crate bincode; extern crate rustc_serialize; @@ -326,3 +327,4 @@ fn test_slicebox() { fn test_multi_strings() { assert!(encode(&("foo", "bar", "baz"), Infinite).is_ok()); } +*/ diff --git a/tests/test_serde.rs b/tests/test_serde.rs index 4888908..fb8911d 100644 --- a/tests/test_serde.rs +++ b/tests/test_serde.rs @@ -18,6 +18,8 @@ use bincode::{ encoded_size, DecodingError, DecodingResult, + DeserializeError, + DeserializeResult, RefBox, StrBox, SliceBox, @@ -26,9 +28,8 @@ use bincode::{ use bincode::SizeLimit::{Infinite, Bounded}; fn the_same(element: V) - where V: Encodable+Decodable+serde::Serialize+PartialEq+Debug+'static + where V: Encodable+Decodable+serde::Serialize+serde::Deserialize+PartialEq+Debug+'static { - // Make sure that the bahavior isize correct when wrapping with a RefBox. fn ref_box_correct(v: &V) -> bool where V: Encodable+Decodable+PartialEq+Debug+'static @@ -48,9 +49,13 @@ fn the_same(element: V) assert_eq!(size, encoded.len() as u64); assert!(ref_box_correct(&element)); - let size = bincode::serialized_size(&element); let serialized = bincode::to_vec(&element, Infinite).unwrap(); assert_eq!(encoded, serialized); + + let deserialized = bincode::from_slice(&serialized[..], Infinite).unwrap(); + assert_eq!(element, deserialized); + + let size = bincode::serialized_size(&element); assert_eq!(size, serialized.len() as u64); } @@ -61,16 +66,19 @@ fn test_numbers() { 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); @@ -94,7 +102,7 @@ fn test_tuple() { #[test] fn test_basic_struct() { - #[derive(RustcEncodable, RustcDecodable, Serialize, PartialEq, Debug)] + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, PartialEq, Debug)] struct Easy { x: isize, s: String, @@ -105,13 +113,13 @@ fn test_basic_struct() { #[test] fn test_nested_struct() { - #[derive(RustcEncodable, RustcDecodable, Serialize, PartialEq, Debug)] + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, PartialEq, Debug)] struct Easy { x: isize, s: String, y: usize } - #[derive(RustcEncodable, RustcDecodable, Serialize, PartialEq, Debug)] + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, PartialEq, Debug)] struct Nest { f: Easy, b: usize, @@ -127,22 +135,22 @@ fn test_nested_struct() { #[test] fn test_struct_tuple() { - #[derive(RustcEncodable, RustcDecodable, Serialize, PartialEq, Debug)] + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, PartialEq, Debug)] struct TubStr(usize, String, f32); the_same(TubStr(5, "hello".to_string(), 3.2)); } #[test] -fn option() { +fn test_option() { the_same(Some(5usize)); the_same(Some("foo bar".to_string())); the_same(None::); } #[test] -fn enm() { - #[derive(RustcEncodable, RustcDecodable, Serialize, PartialEq, Debug)] +fn test_enum() { + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, PartialEq, Debug)] enum TestEnum { NoArg, OneArg(usize), @@ -153,10 +161,9 @@ fn enm() { the_same(TestEnum::AnotherNoArg); } - #[test] -fn struct_enum() { - #[derive(RustcEncodable, RustcDecodable, Serialize, PartialEq, Debug)] +fn test_struct_enum() { + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, PartialEq, Debug)] enum TestEnum { NoArg, OneArg(usize), @@ -172,7 +179,7 @@ fn struct_enum() { } #[test] -fn many() { +fn test_vec() { let v: Vec = vec![]; the_same(v); the_same(vec![1u64]); @@ -180,7 +187,7 @@ fn many() { } #[test] -fn map() { +fn test_map() { let mut m = HashMap::new(); m.insert(4u64, "foo".to_string()); m.insert(0u64, "bar".to_string()); @@ -188,18 +195,17 @@ fn map() { } #[test] -fn boole() { +fn test_bool() { the_same(true); the_same(false); } #[test] -fn unicode() { +fn test_unicode() { the_same("å".to_string()); the_same("aåååååååa".to_string()); } - #[test] fn decoding_errors() { fn isize_invalid_encoding(res: DecodingResult) { @@ -223,6 +229,28 @@ fn decoding_errors() { isize_invalid_encoding(decode::>(&vec![5, 0][..])); } +#[test] +fn deserializing_errors() { + fn isize_invalid_deserialize(res: DeserializeResult) { + match res { + Err(DeserializeError::InvalidEncoding(_)) => {}, + Err(DeserializeError::SyntaxError) => {}, + _ => panic!("Expecting InvalidEncoding, got {:?}", res), + } + } + + isize_invalid_deserialize(bincode::from_slice::(&vec![0xA][..], Infinite)); + isize_invalid_deserialize(bincode::from_slice::(&vec![0, 0, 0, 0, 0, 0, 0, 1, 0xFF][..], Infinite)); + // Out-of-bounds variant + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, Debug)] + enum Test { + One, + Two, + }; + isize_invalid_deserialize(bincode::from_slice::(&vec![0, 0, 0, 5][..], Infinite)); + isize_invalid_deserialize(bincode::from_slice::>(&vec![5, 0][..], Infinite)); +} + #[test] fn too_big_decode() { let encoded = vec![0,0,0,3]; @@ -236,6 +264,17 @@ fn too_big_decode() { assert!(decoded.is_ok()); } +#[test] +fn too_big_deserialize() { + let serialized = vec![0,0,0,3]; + let deserialized: Result = bincode::from_slice(&serialized[..], Bounded(3)); + assert!(deserialized.is_err()); + + let serialized = vec![0,0,0,3]; + let deserialized: Result = bincode::from_slice(&serialized[..], Bounded(4)); + assert!(deserialized.is_ok()); +} + #[test] fn too_big_char_decode() { let encoded = vec![0x41]; @@ -245,6 +284,14 @@ fn too_big_char_decode() { assert_eq!(decoded.unwrap(), 'A'); } +#[test] +fn too_big_char_deserialize() { + let serialized = vec![0x41]; + let deserialized: Result = bincode::from_slice(&serialized[..], Bounded(1)); + assert!(deserialized.is_ok()); + assert_eq!(deserialized.unwrap(), 'A'); +} + #[test] fn too_big_encode() { assert!(encode(&0u32, Bounded(3)).is_err()); @@ -254,6 +301,15 @@ fn too_big_encode() { assert!(encode(&"abcde", Bounded(8 + 5)).is_ok()); } +#[test] +fn too_big_serialize() { + assert!(bincode::to_vec(&0u32, Bounded(3)).is_err()); + assert!(bincode::to_vec(&0u32, Bounded(4)).is_ok()); + + assert!(bincode::to_vec(&"abcde", Bounded(8 + 4)).is_err()); + assert!(bincode::to_vec(&"abcde", Bounded(8 + 5)).is_ok()); +} + #[test] fn test_encoded_size() { assert!(encoded_size(&0u8) == 1); @@ -266,6 +322,21 @@ fn test_encoded_size() { assert!(encoded_size(&"a") == 8 + 1); assert!(encoded_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4)) + +} + +#[test] +fn test_serialized_size() { + assert!(bincode::serialized_size(&0u8) == 1); + assert!(bincode::serialized_size(&0u16) == 2); + assert!(bincode::serialized_size(&0u32) == 4); + assert!(bincode::serialized_size(&0u64) == 8); + + // length isize stored as u64 + assert!(bincode::serialized_size(&"") == 8); + assert!(bincode::serialized_size(&"a") == 8 + 1); + + assert!(bincode::serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4)) } #[test] @@ -274,7 +345,7 @@ fn encode_box() { } #[test] -fn test_refbox() { +fn test_refbox_encode() { let large_object = vec![1u32,2,3,4,5,6]; let mut large_map = HashMap::new(); large_map.insert(1, 2); @@ -310,7 +381,43 @@ fn test_refbox() { } #[test] -fn test_strbox() { +fn test_refbox_serialize() { + let large_object = vec![1u32,2,3,4,5,6]; + let mut large_map = HashMap::new(); + large_map.insert(1, 2); + + + #[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, Debug)] + enum Message<'a> { + M1(RefBox<'a, Vec>), + M2(RefBox<'a, HashMap>) + } + + // Test 1 + { + let serialized = bincode::to_vec(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap(); + let deserialized: Message<'static> = bincode::from_slice(&serialized[..], Infinite).unwrap(); + + match deserialized { + Message::M1(b) => assert!(b.take().deref() == &large_object), + _ => assert!(false) + } + } + + // Test 2 + { + let serialized = bincode::to_vec(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap(); + let deserialized: Message<'static> = bincode::from_slice(&serialized[..], Infinite).unwrap(); + + match deserialized { + Message::M2(b) => assert!(b.take().deref() == &large_map), + _ => assert!(false) + } + } +} + +#[test] +fn test_strbox_encode() { let strx: &'static str = "hello world"; let encoded = encode(&StrBox::new(strx), Infinite).unwrap(); let decoded: StrBox<'static> = decode(&encoded[..]).unwrap(); @@ -319,7 +426,16 @@ fn test_strbox() { } #[test] -fn test_slicebox() { +fn test_strbox_serialize() { + let strx: &'static str = "hello world"; + let serialized = bincode::to_vec(&StrBox::new(strx), Infinite).unwrap(); + let deserialized: StrBox<'static> = bincode::from_slice(&serialized[..], Infinite).unwrap(); + let stringx: String = deserialized.take(); + assert!(strx == &stringx[..]); +} + +#[test] +fn test_slicebox_encode() { let slice = [1u32, 2, 3 ,4, 5]; let encoded = encode(&SliceBox::new(&slice), Infinite).unwrap(); let decoded: SliceBox<'static, u32> = decode(&encoded[..]).unwrap(); @@ -332,6 +448,24 @@ fn test_slicebox() { } #[test] -fn test_multi_strings() { +fn test_slicebox_serialize() { + let slice = [1u32, 2, 3 ,4, 5]; + let serialized = bincode::to_vec(&SliceBox::new(&slice), Infinite).unwrap(); + let deserialized: SliceBox<'static, u32> = bincode::from_slice(&serialized[..], Infinite).unwrap(); + { + let sb: &[u32] = &deserialized; + assert!(slice == sb); + } + let vecx: Vec = deserialized.take(); + assert!(slice == &vecx[..]); +} + +#[test] +fn test_multi_strings_encode() { assert!(encode(&("foo", "bar", "baz"), Infinite).is_ok()); } + +#[test] +fn test_multi_strings_serialize() { + assert!(bincode::to_vec(&("foo", "bar", "baz"), Infinite).is_ok()); +}