Skip to content
This repository has been archived by the owner on Aug 15, 2021. It is now read-only.

Commit

Permalink
Update serde to 0.7. Rework errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
pyfisch committed Mar 15, 2016
1 parent 713ad3c commit 68f9daa
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 217 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "serde_cbor"
version = "0.2.1"
version = "0.3.0"
authors = ["Pyfisch <[email protected]>"]
repository = "https://github.com/pyfisch/cbor"
documentation = "http://pyfisch.github.io/cbor/serde_cbor/index.html"
Expand All @@ -12,7 +12,7 @@ keywords = ["serde", "cbor", "serialization"]
[dependencies]
byteorder = "0.3"
libc = "0.2.6"
serde = "0.6.11"
serde = "0.7.0"

[features]
unstable = []
58 changes: 23 additions & 35 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@ use byteorder::{BigEndian, ReadBytesExt};
use serde::de::{self, Visitor, Deserialize};
use serde::bytes::ByteBuf;

use super::read::PositionReader;
use super::error::{Error, ErrorCode, Result};
use super::error::{Error, Result};

const MAX_SEQ_LEN: u64 = 524288;

/// A structure that deserializes CBOR into Rust values.
pub struct Deserializer<R: Read> {
reader: PositionReader<R>,
reader: R,
}

impl<R: Read> Deserializer<R> {
/// Creates the CBOR parser from an `std::io::Read`.
#[inline]
pub fn new(reader: R) -> Deserializer<R> {
Deserializer { reader: PositionReader::new(reader) }
Deserializer { reader: reader }
}

/// The `Deserializer::end` method should be called after a value has been fully deserialized.
Expand All @@ -30,20 +29,10 @@ impl<R: Read> Deserializer<R> {
if try!(self.read(&mut [0; 1])) == 0 {
Ok(())
} else {
Err(self.error(ErrorCode::TrailingBytes))
Err(Error::TrailingBytes)
}
}

#[inline]
fn error(&mut self, reason: ErrorCode) -> Error {
Error::SyntaxError(reason, self.reader.position())
}

#[inline]
fn read_bytes(&mut self, n: usize) -> Result<Vec<u8>> {
self.reader.read_bytes(n)
}

#[inline]
fn parse_value<V: Visitor>(&mut self, visitor: V) -> Result<V::Value> {
let first = try!(self.read_u8());
Expand All @@ -69,14 +58,14 @@ impl<R: Read> Deserializer<R> {
26 => try!(self.read_u32::<BigEndian>()) as u64,
27 => try!(self.read_u64::<BigEndian>()) as u64,
31 => return Ok(None),
_ => return Err(self.error(ErrorCode::UnknownByte(first))),
_ => return Err(Error::Syntax),
}))
}

fn parse_size_information(&mut self, first: u8) -> Result<Option<usize>> {
let n = try!(self.parse_additional_information(first));
match n {
Some(n) if n > MAX_SEQ_LEN => return Err(self.error(ErrorCode::TooLarge)),
Some(n) if n > MAX_SEQ_LEN => return Err(Error::Syntax),
_ => (),
}
Ok(n.map(|x| x as usize))
Expand All @@ -90,7 +79,7 @@ impl<R: Read> Deserializer<R> {
25 => visitor.visit_u16(try!(self.read_u16::<BigEndian>())),
26 => visitor.visit_u32(try!(self.read_u32::<BigEndian>())),
27 => visitor.visit_u64(try!(self.read_u64::<BigEndian>())),
_ => Err(self.error(ErrorCode::UnknownByte(first))),
_ => Err(Error::Syntax),
}
}

Expand All @@ -102,7 +91,7 @@ impl<R: Read> Deserializer<R> {
25 => visitor.visit_i32(-1 - try!(self.read_u16::<BigEndian>()) as i32),
26 => visitor.visit_i64(-1 - try!(self.read_u32::<BigEndian>()) as i64),
27 => visitor.visit_i64(-1 - try!(self.read_u64::<BigEndian>()) as i64),
_ => Err(self.error(ErrorCode::UnknownByte(first))),
_ => Err(Error::Syntax),
}
}

Expand All @@ -116,13 +105,15 @@ impl<R: Read> Deserializer<R> {
}
}
if let Some(n) = try!(self.parse_size_information(first)) {
visitor.visit_byte_buf(try!(self.read_bytes(n)))
let mut buf = vec![0; n];
try!(self.reader.read_exact(&mut buf));
visitor.visit_byte_buf(buf)
} else {
let mut bytes = Vec::new();
loop {
match ByteBuf::deserialize(self) {
Ok(value) => append(&mut bytes, &*value),
Err(Error::SyntaxError(ErrorCode::StopCode, _)) => break,
Err(Error::StopCode) => break,
Err(e) => return Err(e),
}
}
Expand All @@ -133,13 +124,15 @@ impl<R: Read> Deserializer<R> {
#[inline]
fn parse_string<V: Visitor>(&mut self, first: u8, mut visitor: V) -> Result<V::Value> {
if let Some(n) = try!(self.parse_size_information(first)) {
visitor.visit_string(try!(String::from_utf8(try!(self.read_bytes(n)))))
let mut buf = vec![0; n];
try!(self.reader.read_exact(&mut buf));
visitor.visit_string(try!(String::from_utf8(buf)))
} else {
let mut string = String::new();
loop {
match String::deserialize(self) {
Ok(value) => string.push_str(&value[..]),
Err(Error::SyntaxError(ErrorCode::StopCode, _)) => break,
Err(Error::StopCode) => break,
Err(e) => return Err(e),
}
}
Expand Down Expand Up @@ -207,8 +200,8 @@ impl<R: Read> Deserializer<R> {
25 => visitor.visit_f32(decode_f16(try!(self.read_u16::<BigEndian>()))),
26 => visitor.visit_f32(try!(self.read_f32::<BigEndian>())),
27 => visitor.visit_f64(try!(self.read_f64::<BigEndian>())),
31 => Err(self.error(ErrorCode::StopCode)),
_ => Err(self.error(ErrorCode::UnknownByte(first))),
31 => Err(Error::StopCode),
_ => Err(Error::Syntax),
}
}
}
Expand All @@ -217,14 +210,9 @@ impl<R: Read> de::Deserializer for Deserializer<R> {
type Error = Error;

#[inline]
fn visit<V: Visitor>(&mut self, visitor: V) -> Result<V::Value> {
fn deserialize<V: Visitor>(&mut self, visitor: V) -> Result<V::Value> {
self.parse_value(visitor)
}

#[inline]
fn format() -> &'static str {
"cbor"
}
}

impl<R: Read> Read for Deserializer<R> {
Expand Down Expand Up @@ -262,7 +250,7 @@ impl<'a, R: Read> de::SeqVisitor for SeqVisitor<'a, R> {
};
match Deserialize::deserialize(self.de) {
Ok(value) => Ok(Some(value)),
Err(Error::SyntaxError(ErrorCode::StopCode, _)) => {
Err(Error::StopCode) => {
self.items = Some(0);
Ok(None)
}
Expand All @@ -275,7 +263,7 @@ impl<'a, R: Read> de::SeqVisitor for SeqVisitor<'a, R> {
if let Some(0) = self.items {
Ok(())
} else {
Err(self.de.error(ErrorCode::TrailingBytes))
Err(Error::TrailingBytes)
}
}

Expand Down Expand Up @@ -313,7 +301,7 @@ impl<'a, R: Read> de::MapVisitor for MapVisitor<'a, R> {
};
match Deserialize::deserialize(self.de) {
Ok(value) => Ok(Some(value)),
Err(Error::SyntaxError(ErrorCode::StopCode, _)) => {
Err(Error::StopCode) => {
self.items = Some(0);
Ok(None)
}
Expand All @@ -331,7 +319,7 @@ impl<'a, R: Read> de::MapVisitor for MapVisitor<'a, R> {
if let Some(0) = self.items {
Ok(())
} else {
Err(self.de.error(ErrorCode::TrailingBytes))
Err(Error::TrailingBytes)
}
}

Expand Down
97 changes: 33 additions & 64 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,126 +6,95 @@ use std::io;
use std::string::FromUtf8Error;

use serde::de;
use serde::ser;
use byteorder::Error as ByteorderError;

/// The errors that can arise while parsing a CBOR stream.
#[derive(Clone, PartialEq)]
pub enum ErrorCode {
/// The data source contains trailing bytes after all values were read.
TrailingBytes,
/// The data source contains not enough bytes to parse a value.
UnexpectedEOF,
/// Break stop code encountered.
StopCode,
/// Too large sequence or map.
TooLarge,
/// Invalid Byte at the beginning of a new value detected.
UnknownByte(u8),
/// Unknown field in struct.
UnknownField(String),
/// Struct is missing a field.
MissingField(&'static str),
/// General error required by serde.
InvalidSyntax(String),
}

impl fmt::Debug for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::fmt::Debug;

match *self {
ErrorCode::UnexpectedEOF => "EOF while parsing a value".fmt(f),
ErrorCode::StopCode => "break stop code outside indefinite length item".fmt(f),
ErrorCode::TooLarge => "too large array or map found".fmt(f),
ErrorCode::UnknownField(ref field) => write!(f, "unknown field \"{}\"", field),
ErrorCode::MissingField(ref field) => write!(f, "missing field \"{}\"", field),
ErrorCode::TrailingBytes => "trailing bytes".fmt(f),
ErrorCode::UnknownByte(byte) => write!(f, "unknown start byte b'\\x{0:x}'", byte),
ErrorCode::InvalidSyntax(ref msg) => write!(f, "invalid syntax: \"{}\"", msg),
}
}
}

/// Represents all possible errors that can occur when serializing or deserializing a value.
#[derive(Debug)]
pub enum Error {
/// The CBOR value had a syntactic error.
SyntaxError(ErrorCode, usize),
Syntax,
/// Some IO error occured when processing a value.
IoError(io::Error),
Io(io::Error),
/// Some error occured while converting a string.
FromUtf8Error(FromUtf8Error),
FromUtf8(FromUtf8Error),
/// A custom error provided by serde occured.
Custom(String),
/// The data source contains not enough bytes to parse a value.
Eof,
/// Break stop code encountered.
StopCode,
/// The data source contains trailing bytes after all values were read.
TrailingBytes,
#[doc(hidden)]
__Nonexhaustive,
}

impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::SyntaxError(..) => "syntax error",
Error::IoError(ref error) => error::Error::description(error),
Error::FromUtf8Error(ref error) => error.description(),
Error::Syntax => "syntax error",
Error::Io(ref error) => error::Error::description(error),
Error::FromUtf8(ref error) => error.description(),
_ => "unknown error",
}
}

fn cause(&self) -> Option<&error::Error> {
match *self {
Error::IoError(ref error) => Some(error),
Error::FromUtf8Error(ref error) => Some(error),
Error::Io(ref error) => Some(error),
Error::FromUtf8(ref error) => Some(error),
_ => None,
}
}
}

impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::SyntaxError(ref code, pos) => write!(fmt, "{:?} at byte position {}", code, pos),
Error::IoError(ref error) => fmt::Display::fmt(error, fmt),
Error::FromUtf8Error(ref error) => fmt::Display::fmt(error, fmt),
_ => fmt.write_str("unknown error"),
Error::Syntax => f.write_str("syntax error"),
Error::Io(ref error) => fmt::Display::fmt(error, f),
Error::FromUtf8(ref error) => fmt::Display::fmt(error, f),
_ => f.write_str("unknown error"),
}
}
}


impl From<io::Error> for Error {
fn from(error: io::Error) -> Error {
Error::IoError(error)
Error::Io(error)
}
}

impl From<FromUtf8Error> for Error {
fn from(error: FromUtf8Error) -> Error {
Error::FromUtf8Error(error)
Error::FromUtf8(error)
}
}

impl From<ByteorderError> for Error {
fn from(error: ByteorderError) -> Error {
match error {
ByteorderError::UnexpectedEOF => Error::SyntaxError(ErrorCode::UnexpectedEOF, 0),
ByteorderError::Io(e) => Error::IoError(e),
ByteorderError::UnexpectedEOF => Error::Eof,
ByteorderError::Io(e) => Error::Io(e),
}
}
}

impl de::Error for Error {
fn syntax(s: &str) -> Error {
Error::SyntaxError(ErrorCode::InvalidSyntax(s.to_owned()), 0)
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}

fn end_of_stream() -> Error {
Error::SyntaxError(ErrorCode::UnexpectedEOF, 0)
}

fn unknown_field(field: &str) -> Error {
Error::SyntaxError(ErrorCode::UnknownField(String::from(field)), 0)
Error::Eof
}
}

fn missing_field(field: &'static str) -> Error {
Error::SyntaxError(ErrorCode::MissingField(field), 0)
impl ser::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,11 @@ extern crate libc;
extern crate serde;

pub use de::{from_slice, from_reader};
pub use error::{Error, ErrorCode, Result};
pub use error::{Error, Result};
pub use ser::{to_vec, to_writer, to_vec_sd, to_writer_sd};
pub use value::{Value, ObjectKey};

pub mod de;
pub mod error;
pub mod read;
pub mod ser;
pub mod value;
Loading

0 comments on commit 68f9daa

Please sign in to comment.