1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
use super::*; #[derive(Debug, Display, From)] pub enum Error { Regex(fancy_regex::Error), } #[derive(Debug)] pub struct Matcher { regex: fancy_regex::Regex, device_replacement: Option<String>, brand_replacement: Option<String>, model_replacement: Option<String>, } impl SubParser for Matcher { type Item = Device; fn try_parse(&self, text: &str) -> Option<Self::Item> { if let Ok(Some(captures)) = self.regex.captures(text) { let family: String = if let Some(device_replacement) = &self.device_replacement { replace(&device_replacement, &captures) } else { captures .get(1) .map(|x| x.as_str()) .and_then(none_if_empty) .map(ToString::to_string)? }; let brand: Option<String> = if let Some(brand_replacement) = &self.brand_replacement { none_if_empty(replace(&brand_replacement, &captures)) } else { None }; let model: Option<String> = if let Some(model_replacement) = &self.model_replacement { none_if_empty(replace(&model_replacement, &captures)) } else { captures .get(1) .map(|x| x.as_str()) .and_then(none_if_empty) .map(ToString::to_string) }; Some(Device { family, brand, model, }) } else { None } } } impl Matcher { pub fn try_from(entry: DeviceParserEntry) -> Result<Matcher, Error> { let regex_with_flags = if !entry.regex_flag.as_ref().map_or(true, String::is_empty) { format!("(?{}){}", entry.regex_flag.unwrap_or_default(), entry.regex) } else { entry.regex.to_owned() }; let regex = fancy_regex::RegexBuilder::new(®ex_with_flags) .delegate_size_limit(20 * (1 << 20)) .build(); Ok(Matcher { regex: regex?, device_replacement: entry.device_replacement, brand_replacement: entry.brand_replacement, model_replacement: entry.model_replacement, }) } }