diff options
author | Markus Unterwaditzer <markus@unterwaditzer.net> | 2015-03-13 20:06:40 +0100 |
---|---|---|
committer | Markus Unterwaditzer <markus@unterwaditzer.net> | 2015-03-13 20:15:17 +0100 |
commit | d5ddd80e03df5b4b207d530c7927f49676ad2c22 (patch) | |
tree | 73957c6c96c1f0e94ba5639da1760a9f589947c5 | |
parent | 72a62476f1e9177ae54683c8397bb4dc95a1c47c (diff) |
Add error type
-rw-r--r-- | src/vobject/lib.rs | 94 | ||||
-rw-r--r-- | tests/lib.rs | 2 |
2 files changed, 90 insertions, 6 deletions
diff --git a/src/vobject/lib.rs b/src/vobject/lib.rs index df7612a..a601783 100644 --- a/src/vobject/lib.rs +++ b/src/vobject/lib.rs @@ -1,11 +1,14 @@ // DOCS -#![feature(plugin,core,collections,std_misc,unicode)] +#![feature(plugin,core,collections,std_misc)] #![plugin(peg_syntax_ext)] use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::borrow::ToOwned; use std::str::FromStr; +use std::fmt; +use std::error::Error; pub struct Property { @@ -94,23 +97,29 @@ impl FromStr for Component { /// Same as `vobject::parse_component`, but without the error messages. fn from_str(s: &str) -> Result<Component, String> { - parse_component(s) + match parse_component(s) { + Ok(x) => Ok(x), + Err(e) => Err(e.into_string()) + } } } /// Parse a component. The error value is a human-readable message. -pub fn parse_component(s: &str) -> Result<Component, String> { +pub fn parse_component(s: &str) -> ParseResult<Component> { // XXX: The unfolding should be worked into the PEG // See feature request: https://github.com/kevinmehall/rust-peg/issues/26 let unfolded = unfold_lines(s); - parser::component(unfolded.as_slice()) + match parser::component(unfolded.as_slice()) { + Ok(x) => Ok(x), + Err(e) => Err(ParseError::from_peg_error(e)) + } } /// Write a component. The error value is a human-readable message. pub fn write_component(c: &Component) -> String { fn inner(buf: &mut String, c: &Component) { buf.push_str("BEGIN:"); - buf.push_str(c.name.as_slice()); + buf.push_str(c.name.as_slice());& buf.push_str("\r\n"); for (prop_name, props) in c.props.iter() { @@ -193,6 +202,81 @@ pub fn fold_line(s: &str) -> String { rv } +#[derive(PartialEq, Eq, Debug)] +pub struct ParseError { + desc: String, + orig: Option<parser::ParseError> +} + +pub type ParseResult<T> = Result<T, ParseError>; + +impl Error for ParseError { + fn description(&self) -> &str { + self.desc.as_slice() + } + + fn cause(&self) -> Option<&Error> { + match self.parser_error() { + Some(x) => Some(&*x), + None => None + } + } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + +impl ParseError { + pub fn new(desc: String, cause: Option<parser::ParseError>) -> Self { + ParseError { + desc: desc, + orig: cause + } + } + + pub fn from_peg_error(e: parser::ParseError) -> Self { + ParseError { + desc: stringify!(e).to_owned(), + orig: Some(e) + } + } + + pub fn into_string(self) -> String { + self.desc + } + + /// Access the underlying parser error. + pub fn parser_error(&self) -> Option<&parser::ParseError> { + self.orig.as_ref() + } + + + /// The line where the error occured. + /// + /// The value might be warped because content lines are unfolded before the parser keeps track + /// of line numbers. + pub fn line(&self) -> Option<&usize> { + match self.parser_error() { + Some(e) => Some(&e.line), + None => None + } + } + + /// The column where the error occured. + /// + /// The value might be warped because content lines are unfolded before the parser keeps track + /// of line numbers. + pub fn column(&self) -> Option<&usize> { + match self.parser_error() { + Some(e) => Some(&e.column), + None => None + } + } +} + peg! parser(r#" use super::{Component,Property}; diff --git a/tests/lib.rs b/tests/lib.rs index 01efced..c6ba331 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,4 +1,4 @@ -#![allow(unstable)] +#![feature(core)] extern crate vobject; use vobject::parse_component; use std::borrow::ToOwned; |