From 0f3896b36cff6bd1580806b3b1d0ca36352d1f94 Mon Sep 17 00:00:00 2001 From: frosch Date: Fri, 26 Apr 2024 22:17:10 +0200 Subject: [PATCH] refactor: speed-up bulk validations by compiling Regexes only once (#13) --- Cargo.lock | 1 + Cargo.toml | 1 + src/parser.rs | 25 +++++++++++++++---------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dceaf75..b8bd53c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,6 +160,7 @@ version = "0.0.0-git" dependencies = [ "clap", "console_error_panic_hook", + "once_cell", "regex", "serde", "serde-wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 9052511..5a5a4f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] clap = { version = "4.5", features = ["derive" ]} console_error_panic_hook = "0.1" +once_cell = "1.19.0" regex = "1.10.4" serde = { version = "1.0", features = ["derive"] } serde-wasm-bindgen = "0.4" diff --git a/src/parser.rs b/src/parser.rs index e39437a..d1ce028 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,3 +1,4 @@ +use once_cell::sync::Lazy; use regex::Regex; #[derive(Debug, PartialEq)] @@ -47,11 +48,12 @@ pub struct ParserError { pub message: String, } +static PAT_COMMAND: Lazy = + Lazy::new(|| Regex::new(r"^\{(?:(\d+):)?(|\{|[A-Z]+[A-Z0-9_]*)(?:\.(\w+))?\}$").unwrap()); + impl StringCommand { fn parse(string: &str) -> Option { - let pat_command = - Regex::new(r"^\{(?:(\d+):)?(|\{|[A-Z]+[A-Z0-9_]*)(?:\.(\w+))?\}$").unwrap(); - let caps = pat_command.captures(string)?; + let caps = PAT_COMMAND.captures(string)?; Some(StringCommand { index: caps.get(1).and_then(|v| v.as_str().parse().ok()), name: String::from(&caps[2]), @@ -73,10 +75,11 @@ impl StringCommand { } } +static PAT_GENDER: Lazy = Lazy::new(|| Regex::new(r"^\{G\s*=\s*(\w+)\}$").unwrap()); + impl GenderDefinition { fn parse(string: &str) -> Option { - let pat_gender = Regex::new(r"^\{G\s*=\s*(\w+)\}$").unwrap(); - let caps = pat_gender.captures(string)?; + let caps = PAT_GENDER.captures(string)?; Some(GenderDefinition { gender: String::from(&caps[1]), }) @@ -87,12 +90,14 @@ impl GenderDefinition { } } +static PAT_CHOICE: Lazy = + Lazy::new(|| Regex::new(r"^\{([PG])(?:\s+(\d+)(?::(\d+))?)?(\s+[^\s0-9].*?)\s*\}$").unwrap()); +static PAT_ITEM: Lazy = + Lazy::new(|| Regex::new(r##"^\s+(?:([^\s"]+)|"([^"]*)")"##).unwrap()); + impl ChoiceList { fn parse(string: &str) -> Option { - let pat_choice = - Regex::new(r"^\{([PG])(?:\s+(\d+)(?::(\d+))?)?(\s+[^\s0-9].*?)\s*\}$").unwrap(); - let pat_item = Regex::new(r##"^\s+(?:([^\s"]+)|"([^"]*)")"##).unwrap(); - let caps = pat_choice.captures(string)?; + let caps = PAT_CHOICE.captures(string)?; let mut result = ChoiceList { name: String::from(&caps[1]), indexref: caps.get(2).and_then(|v| v.as_str().parse().ok()), @@ -101,7 +106,7 @@ impl ChoiceList { }; let mut rest = &caps[4]; while !rest.is_empty() { - let m = pat_item.captures(rest)?; + let m = PAT_ITEM.captures(rest)?; result .choices .push(String::from(m.get(1).or(m.get(2)).unwrap().as_str()));