use combine:: { parser, Parser, ParseError };
use combine::primitives:: { Stream };
use record:: { LCOVRecord };
use combinator:: { record, report };
use std::io:: { Read };
use std::fs:: { File };
use std::result:: { Result };
use std::path:: { Path };
use std::convert:: { From };
use std::fmt:: { Display, Formatter, Result as FormatResult };
use std::error::Error;
pub type ParseResult<T> = Result<T, RecordParseError>;
#[derive(PartialEq, Debug)]
pub struct RecordParseError {
pub line: i32,
pub column: i32,
pub message: String
}
pub struct LCOVParser {
report: String
}
impl LCOVParser {
pub fn new(report: &str) -> Self {
LCOVParser { report: report.to_string() }
}
pub fn parse(&self) -> ParseResult<Vec<LCOVRecord>> {
let value = self.report.as_str();
let records = try!(parse_report(value));
Ok(records)
}
}
impl<P: AsRef<Path>> From<P> for LCOVParser {
fn from(path: P) -> Self {
let mut file = File::open(path).unwrap();
let mut buffer = String::new();
let _ = file.read_to_string(&mut buffer);
LCOVParser::new(buffer.as_str())
}
}
impl<'a, P: Stream<Item=char, Range=&'a str>> From<ParseError<P>> for RecordParseError {
fn from(error: ParseError<P>) -> Self {
let line = error.position.line;
let column = error.position.column;
RecordParseError { line: line, column: column, message: format!("{}", error) }
}
}
impl Display for RecordParseError {
fn fmt(&self, f: &mut Formatter) -> FormatResult {
write!(f, "{}", self.message)
}
}
impl Error for RecordParseError {
fn description(&self) -> &str {
&self.message[..]
}
}
#[inline]
pub fn parse_record(input: &str) -> ParseResult<LCOVRecord> {
let (record, _) = try!(parser(record).parse(input));
Ok(record)
}
#[inline]
pub fn parse_report(input: &str) -> ParseResult<Vec<LCOVRecord>> {
let (records, _) = try!(parser(report).parse(input));
Ok(records)
}