#![deny(missing_docs)]
extern crate serde;
pub use de::Deserializer;
pub use ser::Serializer;
use ser::SizeChecker;
use std::io::Read;
use std::io::Write;
use std::{error, fmt, io, result};
mod ser;
mod de;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
Io(io::Error),
InvalidEncoding {
#[allow(missing_docs)]
desc: &'static str,
#[allow(missing_docs)]
detail: Option<String>,
},
SizeLimit,
SequenceMustHaveLength,
Custom(String),
#[doc(hidden)]
__Nonexhaustive,
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Io(ref err) => error::Error::description(err),
Error::InvalidEncoding { desc, .. } => desc,
Error::SequenceMustHaveLength => "zlo can't encode infinite sequences",
Error::SizeLimit => "the size limit for decoding has been reached",
Error::Custom(ref msg) => msg,
Error::__Nonexhaustive => unreachable!(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::Io(ref err) => Some(err),
Error::InvalidEncoding { .. } => None,
Error::SequenceMustHaveLength => None,
Error::SizeLimit => None,
Error::Custom(_) => None,
Error::__Nonexhaustive => unreachable!(),
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::Io(err).into()
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Io(ref ioerr) => write!(fmt, "Io: {}", ioerr),
Error::InvalidEncoding { desc, detail: None } =>
write!(fmt, "InvalidEncoding: {}", desc),
Error::InvalidEncoding {
desc, detail: Some(ref detail),
} => write!(fmt, "InvalidEncoding: {} ({})", desc, detail),
Error::SequenceMustHaveLength =>
write!(fmt, "zlo can only encode sequences and maps that have \
a knowable size ahead of time."),
Error::SizeLimit => write!(fmt, "SizeLimit"),
Error::Custom(ref s) => s.fmt(fmt),
Error::__Nonexhaustive => unreachable!(),
}
}
}
impl serde::de::Error for Error {
fn custom<T: fmt::Display>(desc: T) -> Error {
Error::Custom(desc.to_string()).into()
}
}
impl serde::ser::Error for Error {
fn custom<T: fmt::Display>(msg: T) -> Self {
Error::Custom(msg.to_string()).into()
}
}
pub fn serialize_into<W, T: ?Sized, S>(
writer: W,
value: &T,
size_limit: S,
) -> Result<()>
where
W: Write,
T: serde::Serialize,
S: SizeLimit,
{
if let Some(limit) = size_limit.limit() {
serialized_size_bounded(value, limit)
.ok_or(Error::SizeLimit)?;
}
let mut serializer = Serializer::<_>::new(writer);
serde::Serialize::serialize(value, &mut serializer)?;
serializer.finish().map_err(|(_, e)| e)?;
Ok(())
}
pub fn serialize<T: ?Sized, S>(value: &T, size_limit: S) -> Result<Vec<u8>>
where
T: serde::Serialize,
S: SizeLimit,
{
let mut writer = match size_limit.limit() {
Some(size_limit) => {
let actual_size = serialized_size_bounded(value, size_limit)
.ok_or(Error::SizeLimit)?;
Vec::with_capacity(actual_size as usize)
}
None => Vec::with_capacity(serialized_size(value) as usize)
};
serialize_into(&mut writer, value, 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(Error::SizeLimit);
}
}
Ok(())
}
fn limit(&self) -> Option<u64> {
unreachable!()
}
}
pub fn serialized_size<T: ?Sized>(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
}
pub fn serialized_size_bounded<T: ?Sized>(value: &T, max: u64) -> Option<u64>
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,
}
}
pub fn deserialize_from<R, T, S>(reader: R, size_limit: S) -> Result<T>
where
R: Read,
T: serde::de::DeserializeOwned,
S: SizeLimit,
{
let mut deserializer = Deserializer::<_, S>::new(reader, size_limit);
serde::Deserialize::deserialize(&mut deserializer)
}
pub fn deserialize<'a, T>(bytes: &'a [u8]) -> Result<T>
where
T: serde::de::Deserialize<'a>,
{
use std::io::Cursor;
let reader = Cursor::new(&bytes);
let mut deserializer = Deserializer::new(reader, Infinite);
serde::Deserialize::deserialize(&mut deserializer)
}
pub trait SizeLimit: private::Sealed {
fn add(&mut self, n: u64) -> Result<()>;
fn limit(&self) -> Option<u64>;
}
#[derive(Copy, Clone)]
pub struct Bounded(u64);
impl Bounded {
pub fn new_bits(lim: u64) -> Self {
Self { 0: lim }
}
pub fn new_bytes(lim: u64) -> Self {
assert!(lim <= ::std::u64::MAX / 8, "lim must be representable \
as bit count in 64 bits");
Self { 0: lim * 8 }
}
}
#[derive(Copy, Clone)]
pub struct Infinite;
struct CountSize {
total: u64,
limit: Option<u64>,
}
impl SizeLimit for Bounded {
#[inline(always)]
fn add(&mut self, n: u64) -> Result<()> {
if self.0 >= n {
self.0 -= n;
Ok(())
} else {
Err(Error::SizeLimit)
}
}
#[inline(always)]
fn limit(&self) -> Option<u64> {
Some(self.0)
}
}
impl SizeLimit for Infinite {
#[inline(always)]
fn add(&mut self, _: u64) -> Result<()> {
Ok(())
}
#[inline(always)]
fn limit(&self) -> Option<u64> {
None
}
}
mod private {
pub trait Sealed {}
impl Sealed for super::Infinite {}
impl Sealed for super::Bounded {}
impl Sealed for super::CountSize {}
}