Last active
October 29, 2015 23:25
-
-
Save matthiasbeyer/ab71460066b6366ef2f6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use runtime::Runtime; | |
use std::error::Error; | |
use std::fmt::Formatter; | |
use std::fmt::Result as FMTResult; | |
use std::fmt::Display; | |
use std::path::Path; | |
use std::result::Result; | |
use module::todo::TodoModule; | |
mod todo; | |
#[derive(Debug)] | |
pub struct ModuleError { | |
desc: String, | |
} | |
impl ModuleError { | |
fn mk(desc: &'static str) -> ModuleError { | |
ModuleError { | |
desc: desc.to_owned().to_string(), | |
} | |
} | |
} | |
impl Error for ModuleError { | |
fn description(&self) -> &str { | |
&self.desc[..] | |
} | |
fn cause(&self) -> Option<&Error> { | |
None | |
} | |
} | |
impl Display for ModuleError { | |
fn fmt(&self, f: &mut Formatter) -> FMTResult { | |
write!(f, "ModuleError: {}", self.description()) | |
} | |
} | |
pub type ModuleResult = Result<(), ModuleError>; | |
pub trait Module { | |
fn new(rt : &Runtime) -> Self; | |
fn callnames() -> &'static [&'static str]; | |
fn name(&self) -> &'static str; | |
fn execute(&self, rt : &Runtime) -> ModuleResult; | |
fn shutdown(&self, rt : &Runtime) -> ModuleResult; | |
} | |
pub mod file { | |
use regex::Regex; | |
extern crate core; | |
use self::core::marker::Sized; | |
pub struct ParserError { | |
summary: String, | |
parsertext: String, | |
index: i32, | |
explanation: Option<String>, | |
} | |
impl ParserError { | |
fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError { | |
ParserError { | |
summary: String::from(sum), | |
parsertext: text, | |
index: idx, | |
explanation: Some(String::from(expl)), | |
} | |
} | |
fn short(sum: &'static str, text: String, idx: i32) -> ParserError { | |
ParserError { | |
summary: String::from(sum), | |
parsertext: text, | |
index: idx, | |
explanation: None | |
} | |
} | |
} | |
pub enum FileHeaderSpec { | |
Null, | |
Bool, | |
Integer, | |
UInteger, | |
Float, | |
Text, | |
Key { name: String, value_type: Box<FileHeaderSpec> }, | |
Array { allowed_types: Box<Vec<FileHeaderSpec>> }, | |
} | |
pub enum FileHeaderData { | |
Null, | |
Bool(bool), | |
Integer(i64), | |
UInteger(u64), | |
Float(f64), | |
Text(String), | |
Key { name: String, value: Box<FileHeaderData> }, | |
Array { values: Box<Vec<FileHeaderData>> }, | |
} | |
pub trait FileHeaderParser : Sized { | |
fn new(spec: &FileHeaderSpec) -> Self; | |
fn read(&self, string: Option<String>) -> Result<FileHeaderData, ParserError>; | |
fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>; | |
} | |
pub trait FileData : core::marker::Sized { | |
fn get_fulltext(&self) -> String; | |
fn get_abbrev(&self) -> String; | |
} | |
pub trait FileDataParser<FD> : Sized { | |
fn new() -> Self; | |
fn read(&self, string: Option<String>) -> Result<FD, ParserError>; | |
fn write(&self, data: &FileData) -> Result<String, ParserError>; | |
} | |
type TextTpl = (Option<String>, Option<String>); | |
pub struct Parser<HP, DP, FD> where | |
FD: FileData, | |
HP: FileHeaderParser, | |
DP: FileDataParser<FD>, | |
{ | |
headerp : HP, | |
datap : DP, | |
} | |
impl<HP, DP, FD> Parser<HP, DP, FD> { | |
fn new(headerp: HP, datap: DP) -> Parser<HP, DP, FD> { | |
Parser { | |
headerp: headerp, | |
datap: datap, | |
} | |
} | |
fn read(&self, s: String) -> Result<(FileHeaderData, FD), ParserError> { | |
let divided = divide_text(&s); | |
if divided.is_err() { | |
return Err(divided.err().unwrap()); | |
} | |
let (header, data) = divided.ok().unwrap(); | |
let h_parseres = self.headerp.read(header); | |
let d_parseres = self.datap.read(data); | |
if h_parseres.is_err() { | |
return Err(h_parseres.err().unwrap()); | |
} | |
if d_parseres.is_err() { | |
return Err(d_parseres.err().unwrap()); | |
} | |
Ok(h_parseres.ok().unwrap(), d_parseres.ok().unwrap()) | |
} | |
} | |
fn divide_text(text: &String) -> Result<TextTpl, ParserError> { | |
let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap(); | |
let captures = re.captures(&text[..]).unwrap_or( | |
return Err(ParserError::new("Cannot run regex on text", | |
text.clone(), 0, | |
"Cannot run regex on text to divide it into header and content.")) | |
); | |
if captures.len() != 2 { | |
return Err(ParserError::new("Unexpected Regex output", | |
text.clone(), 0, | |
"The regex to divide text into header and content had an unexpected output.")) | |
} | |
let header = captures.at(0).map(|s| String::from(s)); | |
let content = captures.at(1).map(|s| String::from(s)); | |
Ok((header, content)) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use runtime::Runtime; | |
use std::error::Error; | |
use std::fmt::Formatter; | |
use std::fmt::Result as FMTResult; | |
use std::fmt::Display; | |
use std::path::Path; | |
use std::result::Result; | |
use module::todo::TodoModule; | |
mod todo; | |
#[derive(Debug)] | |
pub struct ModuleError { | |
desc: String, | |
} | |
impl ModuleError { | |
fn mk(desc: &'static str) -> ModuleError { | |
ModuleError { | |
desc: desc.to_owned().to_string(), | |
} | |
} | |
} | |
impl Error for ModuleError { | |
fn description(&self) -> &str { | |
&self.desc[..] | |
} | |
fn cause(&self) -> Option<&Error> { | |
None | |
} | |
} | |
impl Display for ModuleError { | |
fn fmt(&self, f: &mut Formatter) -> FMTResult { | |
write!(f, "ModuleError: {}", self.description()) | |
} | |
} | |
pub type ModuleResult = Result<(), ModuleError>; | |
pub trait Module { | |
fn new(rt : &Runtime) -> Self; | |
fn callnames() -> &'static [&'static str]; | |
fn name(&self) -> &'static str; | |
fn execute(&self, rt : &Runtime) -> ModuleResult; | |
fn shutdown(&self, rt : &Runtime) -> ModuleResult; | |
} | |
pub mod file { | |
use regex::Regex; | |
extern crate core; | |
use self::core::marker::Sized; | |
pub struct ParserError { | |
summary: String, | |
parsertext: String, | |
index: i32, | |
explanation: Option<String>, | |
} | |
impl ParserError { | |
fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError { | |
ParserError { | |
summary: String::from(sum), | |
parsertext: text, | |
index: idx, | |
explanation: Some(String::from(expl)), | |
} | |
} | |
fn short(sum: &'static str, text: String, idx: i32) -> ParserError { | |
ParserError { | |
summary: String::from(sum), | |
parsertext: text, | |
index: idx, | |
explanation: None | |
} | |
} | |
} | |
pub enum FileHeaderSpec { | |
Null, | |
Bool, | |
Integer, | |
UInteger, | |
Float, | |
Text, | |
Key { name: String, value_type: Box<FileHeaderSpec> }, | |
Array { allowed_types: Box<Vec<FileHeaderSpec>> }, | |
} | |
pub enum FileHeaderData { | |
Null, | |
Bool(bool), | |
Integer(i64), | |
UInteger(u64), | |
Float(f64), | |
Text(String), | |
Key { name: String, value: Box<FileHeaderData> }, | |
Array { values: Box<Vec<FileHeaderData>> }, | |
} | |
pub trait FileHeaderParser : Sized { | |
fn new(spec: &FileHeaderSpec) -> Self; | |
fn read(&self, string: Option<String>) -> Result<FileHeaderData, ParserError>; | |
fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>; | |
} | |
pub trait FileData : core::marker::Sized { | |
fn get_fulltext(&self) -> String; | |
fn get_abbrev(&self) -> String; | |
} | |
pub trait FileDataParser : Sized { | |
fn new() -> FileDataParser; | |
fn read<T>(&self, string: Option<String>) -> Result<T, ParserError> | |
where T: FileData; | |
fn write(&self, data: &FileData) -> Result<String, ParserError>; | |
} | |
type TextTpl = (Option<String>, Option<String>); | |
pub struct Parser { | |
headerp : FileHeaderParser, | |
datap : FileDataParser, | |
} | |
impl Parser { | |
fn new(headerp: FileHeaderParser, datap: FileDataParser) -> Parser { | |
Parser { | |
headerp: headerp, | |
datap: datap, | |
} | |
} | |
fn read<FHP: FileHeaderParser>(&self, s: String) -> Result<(FHP, FileData), ParserError> { | |
let divided = divide_text(s); | |
if divided.is_err() { | |
return Err(divided.err().unwrap()); | |
} | |
let (header, data) = divided.ok().unwrap(); | |
let h_parseres = self.headerp.read(header); | |
let d_parseres = self.datap.read(data); | |
if h_parseres.is_err() { | |
return Err(h_parseres.err().unwrap()); | |
} | |
if d_parseres.is_err() { | |
return Err(d_parseres.err().unwrap()); | |
} | |
Ok(h_parseres.ok().unwrap(), d_parseres.ok().unwrap()) | |
} | |
} | |
fn divide_text(text: &String) -> Result<TextTpl, ParserError> { | |
let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap(); | |
let captures = re.captures(&text[..]).unwrap_or( | |
return Err(ParserError::new("Cannot run regex on text", | |
text.clone(), 0, | |
"Cannot run regex on text to divide it into header and content.")) | |
); | |
if captures.len() != 2 { | |
return Err(ParserError::new("Unexpected Regex output", | |
text.clone(), 0, | |
"The regex to divide text into header and content had an unexpected output.")) | |
} | |
let header = captures.at(0).map(|s| String::from(s)); | |
let content = captures.at(1).map(|s| String::from(s)); | |
Ok((header, content)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment