imag/src/storage/parser.rs

173 lines
4.7 KiB
Rust
Raw Normal View History

2015-10-30 13:44:41 +00:00
use regex::Regex;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;
2015-10-30 13:44:41 +00:00
use super::file::{FileHeaderSpec, FileHeaderData};
2015-10-30 13:44:41 +00:00
pub struct ParserError {
summary: String,
parsertext: String,
index: i32,
explanation: Option<String>,
2015-12-04 12:12:17 +00:00
caused_by: Option<Box<Error>>,
2015-10-30 13:44:41 +00:00
}
impl ParserError {
2015-11-09 15:02:21 +00:00
pub fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
2015-10-30 13:44:41 +00:00
ParserError {
summary: String::from(sum),
parsertext: text,
index: idx,
explanation: Some(String::from(expl)),
2015-12-04 12:12:17 +00:00
caused_by: None,
2015-10-30 13:44:41 +00:00
}
}
pub fn short(sum: &str, text: String, idx: i32) -> ParserError {
2015-10-30 13:44:41 +00:00
ParserError {
summary: String::from(sum),
parsertext: text,
index: idx,
2015-12-04 12:12:17 +00:00
explanation: None,
caused_by: None,
2015-10-30 13:44:41 +00:00
}
}
2015-12-04 12:12:17 +00:00
pub fn with_cause(mut self, e: Box<Error>) -> ParserError {
self.caused_by = Some(e);
self
}
2015-10-30 13:44:41 +00:00
}
impl Error for ParserError {
fn description(&self) -> &str {
&self.summary[..]
}
2015-12-04 12:12:17 +00:00
fn cause(&self) -> Option<&Error> {
self.caused_by.as_ref().map(|e| &**e)
}
}
impl Debug for ParserError {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "ParserError: {}\n\n", self.summary);
if let Some(ref e) = self.explanation {
write!(fmt, "{}\n\n", e);
}
write!(fmt, "On position {}\nin\n{}", self.index, self.parsertext);
Ok(())
}
}
impl Display for ParserError {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "ParserError: {}", self.summary);
if let Some(ref e) = self.explanation {
write!(fmt, "\n\n{}", e);
}
Ok(())
}
}
2015-12-02 10:28:21 +00:00
pub trait FileHeaderParser : Sized {
2015-10-30 13:44:41 +00:00
fn read(&self, string: Option<String>) -> Result<FileHeaderData, ParserError>;
fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
}
type TextTpl = (Option<String>, Option<String>);
pub struct Parser<HP>
2015-10-30 13:44:41 +00:00
{
headerp : HP,
}
2015-12-02 10:28:21 +00:00
impl<HP> Parser<HP> where
HP: FileHeaderParser,
2015-10-30 13:44:41 +00:00
{
2015-12-02 10:28:21 +00:00
pub fn new(headerp: HP) -> Parser<HP> {
2015-10-30 13:44:41 +00:00
Parser {
headerp: headerp,
}
}
pub fn read(&self, s: String) -> Result<(FileHeaderData, String), ParserError>
2015-10-30 13:44:41 +00:00
{
debug!("Reading into internal datastructure: '{}'", s);
let divided = self.divide_text(&s);
2015-10-30 13:44:41 +00:00
if divided.is_err() {
debug!("Error reading into internal datastructure");
let mut p = ParserError::new("Dividing text failed",
s, 0,
"Dividing text with divide_text() failed");
return Err(p.with_cause(Box::new(divided.err().unwrap())));
2015-10-30 13:44:41 +00:00
}
let (header, data) = divided.ok().unwrap();
debug!("Header = '{:?}'", header);
debug!("Data = '{:?}'", data);
2015-10-30 13:44:41 +00:00
2015-11-01 17:01:32 +00:00
let h_parseres = try!(self.headerp.read(header));
debug!("Success parsing header");
2015-10-30 13:44:41 +00:00
Ok((h_parseres, data.unwrap_or(String::new())))
2015-10-30 13:44:41 +00:00
}
2015-11-24 09:27:34 +00:00
pub fn write(&self, tpl : (FileHeaderData, String)) -> Result<String, ParserError>
2015-10-30 13:44:41 +00:00
{
debug!("Parsing internal datastructure to String");
2015-10-30 13:44:41 +00:00
let (header, data) = tpl;
2015-11-01 17:02:40 +00:00
let h_text = try!(self.headerp.write(&header));
debug!("Success translating header");
2015-10-30 13:44:41 +00:00
let text = format!("---\n{}\n---\n{}", h_text, data);
Ok(text)
2015-10-30 13:44:41 +00:00
}
fn divide_text(&self, text: &String) -> Result<TextTpl, ParserError> {
2015-12-04 20:47:14 +00:00
let re = Regex::new(r"(?sm)^---$(.*)^---$(.*)").unwrap();
debug!("Splitting: '{}'", text);
debug!(" regex = {:?}", re);
2015-12-04 20:47:14 +00:00
re.captures(text).map(|captures| {
2015-10-30 13:44:41 +00:00
2015-12-04 20:47:14 +00:00
if captures.len() != 3 {
debug!("Unexpected amount of captures");
return Err(ParserError::new("Unexpected Regex output",
text.clone(), 0,
"The regex to divide text into header and content had an unexpected output."))
}
2015-12-04 20:47:14 +00:00
let header = captures.at(1).map(|s| String::from(s));
let content = captures.at(2).map(|s| String::from(s));
debug!("Splitted, Header = '{:?}'", header.clone().unwrap_or("NONE".into()));
debug!("Splitted, Data = '{:?}'", content.clone().unwrap_or("NONE".into()));
Ok((header, content))
}).or_else(|| {
debug!("Cannot capture from text");
let e = ParserError::new("Cannot run regex on text",
text.clone(), 0,
"Cannot run regex on text to divide it into header and content.");
Some(Err(e))
}).unwrap()
2015-10-30 13:44:41 +00:00
}
}