//! A collection of serialization and deserialization functions //! that use the `serde` crate for the serializable and deserializable //! implementation. use std::io::{self, Write, Read}; use std::{error, fmt, result}; use std::str::Utf8Error; use {CountSize, SizeLimit}; use byteorder::ByteOrder; use std::error::Error as StdError; pub use super::de::Deserializer; pub use super::ser::Serializer; use super::ser::SizeChecker; use serde_crate as serde; /// The result of a serialization or deserialization operation. pub type Result = result::Result; /// An error that can be produced during (de)serializing. pub type Error = Box; /// The kind of error that can be produced during a serialization or deserialization. #[derive(Debug)] pub enum ErrorKind { /// If the error stems from the reader/writer that is being used /// during (de)serialization, that error will be stored and returned here. Io(io::Error), /// Returned if the deserializer attempts to deserialize a string that is not valid utf8 InvalidUtf8Encoding(Utf8Error), /// Returned if the deserializer attempts to deserialize a bool that was /// not encoded as either a 1 or a 0 InvalidBoolEncoding(u8), /// Returned if the deserializer attempts to deserialize a char that is not in the correct format. InvalidCharEncoding, /// Returned if the deserializer attempts to deserialize the tag of an enum that is /// not in the expected ranges InvalidTagEncoding(usize), /// Serde has a deserialize_any method that lets the format hint to the /// object which route to take in deserializing. DeserializeAnyNotSupported, /// If (de)serializing a message takes more than the provided size limit, this /// error is returned. SizeLimit, /// Bincode can not encode sequences of unknown length (like iterators). SequenceMustHaveLength, /// A custom error message from Serde. Custom(String), } impl StdError for ErrorKind { fn description(&self) -> &str { match *self { ErrorKind::Io(ref err) => error::Error::description(err), ErrorKind::InvalidUtf8Encoding(_) => "string is not valid utf8", ErrorKind::InvalidBoolEncoding(_) => "invalid u8 while decoding bool", ErrorKind::InvalidCharEncoding => "char is not valid", ErrorKind::InvalidTagEncoding(_) => "tag for enum is not valid", ErrorKind::SequenceMustHaveLength => "bincode can only encode sequences and maps that have a knowable size ahead of time", ErrorKind::DeserializeAnyNotSupported => { "bincode doesn't support serde::Deserializer::deserialize_any" } ErrorKind::SizeLimit => "the size limit has been reached", ErrorKind::Custom(ref msg) => msg, } } fn cause(&self) -> Option<&error::Error> { match *self { ErrorKind::Io(ref err) => Some(err), ErrorKind::InvalidUtf8Encoding(_) => None, ErrorKind::InvalidBoolEncoding(_) => None, ErrorKind::InvalidCharEncoding => None, ErrorKind::InvalidTagEncoding(_) => None, ErrorKind::SequenceMustHaveLength => None, ErrorKind::DeserializeAnyNotSupported => None, ErrorKind::SizeLimit => None, ErrorKind::Custom(_) => None, } } } impl From for Error { fn from(err: io::Error) -> Error { ErrorKind::Io(err).into() } } impl fmt::Display for ErrorKind { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { ErrorKind::Io(ref ioerr) => write!(fmt, "io error: {}", ioerr), ErrorKind::InvalidUtf8Encoding(ref e) => write!(fmt, "{}: {}", self.description(), e), ErrorKind::InvalidBoolEncoding(b) => { write!(fmt, "{}, expected 0 or 1, found {}", self.description(), b) } ErrorKind::InvalidCharEncoding => write!(fmt, "{}", self.description()), ErrorKind::InvalidTagEncoding(tag) => { write!(fmt, "{}, found {}", self.description(), tag) } ErrorKind::SequenceMustHaveLength => { write!(fmt, "{}", self.description()) } ErrorKind::SizeLimit => write!(fmt, "{}", self.description()), ErrorKind::DeserializeAnyNotSupported => { write!( fmt, "bincode does not support the serde::Deserializer::deserialize_any method" ) } ErrorKind::Custom(ref s) => s.fmt(fmt), } } } impl serde::de::Error for Error { fn custom(desc: T) -> Error { ErrorKind::Custom(desc.to_string()).into() } } impl serde::ser::Error for Error { fn custom(msg: T) -> Self { ErrorKind::Custom(msg.to_string()).into() } } /// Serializes an object directly into a `Writer`. /// /// If the serialization would take more bytes than allowed by `size_limit`, an error /// is returned and *no bytes* will be written into the `Writer`. /// /// If this returns an `Error` (other than SizeLimit), assume that the /// writer is in an invalid state, as writing could bail out in the middle of /// serializing. pub fn serialize_into(writer: W, value: &T, size_limit: S) -> Result<()> where W: Write, T: serde::Serialize, S: SizeLimit, E: ByteOrder, { if let Some(limit) = size_limit.limit() { try!(serialized_size_bounded(value, limit).ok_or( ErrorKind::SizeLimit, )); } let mut serializer = Serializer::<_, E>::new(writer); serde::Serialize::serialize(value, &mut serializer) } /// Serializes a serializable object into a `Vec` of bytes. /// /// If the serialization would take more bytes than allowed by `size_limit`, /// an error is returned. pub fn serialize(value: &T, size_limit: S) -> Result> where T: serde::Serialize, S: SizeLimit, E: ByteOrder, { let mut writer = match size_limit.limit() { Some(size_limit) => { let actual_size = try!(serialized_size_bounded(value, size_limit).ok_or( ErrorKind::SizeLimit, )); Vec::with_capacity(actual_size as usize) } None => { let size = serialized_size(value) as usize; Vec::with_capacity(size) } }; try!(serialize_into::<_, _, _, E>( &mut writer, value, super::Infinite, )); Ok(writer) } impl SizeLimit for CountSize { fn add(&mut self, c: u64) -> Result<()> { self.total += c; if let Some(limit) = self.limit { if self.total > limit { return Err(Box::new(ErrorKind::SizeLimit)); } } Ok(()) } fn limit(&self) -> Option { unreachable!(); } } /// Returns the size that an object would be if serialized using bincode. /// /// This is used internally as part of the check for encode_into, but it can /// be useful for preallocating buffers if thats your style. pub fn serialized_size(value: &T) -> u64 where T: serde::Serialize, { let mut size_counter = SizeChecker { size_limit: CountSize { total: 0, limit: None, }, }; value.serialize(&mut size_counter).ok(); size_counter.size_limit.total } /// Given a maximum size limit, check how large an object would be if it /// were to be serialized. /// /// If it can be serialized in `max` or fewer bytes, that number will be returned /// inside `Some`. If it goes over bounds, then None is returned. pub fn serialized_size_bounded(value: &T, max: u64) -> Option where T: serde::Serialize, { let mut size_counter = SizeChecker { size_limit: CountSize { total: 0, limit: Some(max), }, }; match value.serialize(&mut size_counter) { Ok(_) => Some(size_counter.size_limit.total), Err(_) => None, } } /// Deserializes an object directly from a `Read`er. /// /// If the provided `SizeLimit` is reached, the deserialization will bail immediately. /// A SizeLimit can help prevent an attacker from flooding your server with /// a neverending stream of values that runs your server out of memory. /// /// If this returns an `Error`, assume that the buffer that you passed /// in is in an invalid state, as the error could be returned during any point /// in the reading. pub fn deserialize_from(reader: R, size_limit: S) -> Result where R: Read, T: serde::de::DeserializeOwned, S: SizeLimit, E: ByteOrder, { let reader = ::de::read::IoReader::new(reader); let mut deserializer = Deserializer::<_, S, E>::new(reader, size_limit); serde::Deserialize::deserialize(&mut deserializer) } /// Deserializes a slice of bytes into an object. /// /// This method does not have a size-limit because if you already have the bytes /// in memory, then you don't gain anything by having a limiter. pub fn deserialize<'a, T, E: ByteOrder>(bytes: &'a [u8]) -> Result where T: serde::de::Deserialize<'a>, { let reader = ::de::read::SliceReader::new(bytes); let mut deserializer = Deserializer::<_, _, E>::new(reader, super::Infinite); serde::Deserialize::deserialize(&mut deserializer) }