diff --git a/benches/eval.rs b/benches/eval.rs index 8071f51..2ae8769 100644 --- a/benches/eval.rs +++ b/benches/eval.rs @@ -2,6 +2,8 @@ extern crate criterion; extern crate loot_condition_interpreter; +use std::str::FromStr; + use criterion::Criterion; use loot_condition_interpreter::{Expression, GameType, State}; @@ -22,7 +24,7 @@ fn generate_plugin_versions() -> Vec<(String, String)> { fn criterion_benchmark(c: &mut Criterion) { c.bench_function("Expression.eval() file(path)", |b| { let state = State::new(GameType::Tes4, ".".into(), ".".into()); - let expression = Expression::parse("file(\"Cargo.toml\")").unwrap().1; + let expression = Expression::from_str("file(\"Cargo.toml\")").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -31,7 +33,7 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("Expression.eval() file(regex)", |b| { let state = State::new(GameType::Tes4, ".".into(), ".".into()); - let expression = Expression::parse("file(\"Cargo.*\")").unwrap().1; + let expression = Expression::from_str("file(\"Cargo.*\")").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -45,7 +47,7 @@ fn criterion_benchmark(c: &mut Criterion) { ".".into(), ).with_active_plugins(&generate_active_plugins()); - let expression = Expression::parse("active(\"Blank.esm\")").unwrap().1; + let expression = Expression::from_str("active(\"Blank.esm\")").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -59,7 +61,7 @@ fn criterion_benchmark(c: &mut Criterion) { ".".into(), ).with_active_plugins(&generate_active_plugins()); - let expression = Expression::parse("active(\"Blank.*\")").unwrap().1; + let expression = Expression::from_str("active(\"Blank.*\")").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -68,7 +70,7 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("Expression.eval() many()", |b| { let state = State::new(GameType::Tes4, ".".into(), ".".into()); - let expression = Expression::parse("many(\"Cargo.*\")").unwrap().1; + let expression = Expression::from_str("many(\"Cargo.*\")").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -82,7 +84,7 @@ fn criterion_benchmark(c: &mut Criterion) { ".".into(), ).with_active_plugins(&generate_active_plugins()); - let expression = Expression::parse("many_active(\"Blank.*\")").unwrap().1; + let expression = Expression::from_str("many_active(\"Blank.*\")").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -95,9 +97,7 @@ fn criterion_benchmark(c: &mut Criterion) { "testing-plugins/Oblivion/Data".into(), ".".into(), ); - let expression = Expression::parse("checksum(\"Blank.esm\", 374E2A6F)") - .unwrap() - .1; + let expression = Expression::from_str("checksum(\"Blank.esm\", 374E2A6F)").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -111,9 +111,7 @@ fn criterion_benchmark(c: &mut Criterion) { ".".into(), ).with_plugin_versions(&generate_plugin_versions()); - let expression = Expression::parse("version(\"Blank.esm\", \"5.0\", ==)") - .unwrap() - .1; + let expression = Expression::from_str("version(\"Blank.esm\", \"5.0\", ==)").unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); @@ -122,10 +120,9 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("Expression.eval() version(executable)", |b| { let state = State::new(GameType::Tes4, ".".into(), ".".into()); - let expression = Expression::parse( + let expression = Expression::from_str( "version(\"loot_api-0.13.8-0-g47797cc_dev-win32/loot_api.dll\", \"0.13.8.0\", ==)", - ).unwrap() - .1; + ).unwrap(); b.iter(|| { assert!(expression.eval(&state).unwrap()); diff --git a/src/lib.rs b/src/lib.rs index 72b465b..85c2092 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,12 +46,6 @@ impl From for Error { } } -impl From for Error { - fn from(_: pelite::resources::FindError) -> Self { - Error::PeParsingError - } -} - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum GameType { Tes4, @@ -148,17 +142,26 @@ impl Expression { } Ok(false) } +} - pub fn parse(input: &str) -> IResult<&str, Expression> { - do_parse!( - input, - compound_conditions: - separated_list_complete!(ws!(tag!("or")), CompoundCondition::parse) - >> (Expression(compound_conditions)) - ) +impl str::FromStr for Expression { + type Err = Error; + + fn from_str(s: &str) -> Result { + parse_expression(s) + .map(|(_, expression)| expression) + .map_err(Error::from) } } +fn parse_expression(input: &str) -> IResult<&str, Expression> { + do_parse!( + input, + compound_conditions: separated_list_complete!(ws!(tag!("or")), CompoundCondition::parse) + >> (Expression(compound_conditions)) + ) +} + impl fmt::Display for Expression { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let strings: Vec = self.0.iter().map(CompoundCondition::to_string).collect(); @@ -223,7 +226,7 @@ impl Condition { preceded!(ws!(tag!("not")), call!(Function::parse)) => { |f| Condition::InvertedFunction(f) } | - delimited!(tag!("("), call!(Expression::parse), tag!(")")) => { + delimited!(tag!("("), call!(parse_expression), tag!(")")) => { |e| Condition::Expression(e) } ) >> (condition) @@ -247,6 +250,7 @@ mod tests { use super::*; use std::fs::create_dir; + use std::str::FromStr; fn state>(data_path: T) -> State { let data_path = data_path.into(); @@ -409,7 +413,7 @@ mod tests { #[test] fn expression_parse_should_handle_a_single_compound_condition() { - let result = Expression::parse("file(\"Cargo.toml\")").unwrap().1; + let result = Expression::from_str("file(\"Cargo.toml\")").unwrap(); match result.0.as_slice() { [CompoundCondition(_)] => {} @@ -419,9 +423,7 @@ mod tests { #[test] fn expression_parse_should_handle_multiple_compound_conditions() { - let result = Expression::parse("file(\"Cargo.toml\") or file(\"Cargo.toml\")") - .unwrap() - .1; + let result = Expression::from_str("file(\"Cargo.toml\") or file(\"Cargo.toml\")").unwrap(); match result.0.as_slice() { [CompoundCondition(_), CompoundCondition(_)] => {} diff --git a/src/version.rs b/src/version.rs index b869af4..a13c2ef 100644 --- a/src/version.rs +++ b/src/version.rs @@ -30,7 +30,8 @@ pub struct Version { impl Version { pub fn read_file_version(file_path: &Path) -> Result { let file_map = FileMap::open(file_path)?; - let version_info = get_pe_version_info(file_map.as_ref())?; + let version_info = + get_pe_version_info(file_map.as_ref()).map_err(|_| Error::PeParsingError)?; if let Some(fixed_file_info) = version_info.fixed() { let version = format!(