From d5b7b5925781f2deafc5d7c8a8b33a0fde846606 Mon Sep 17 00:00:00 2001 From: qjerome Date: Wed, 13 Nov 2024 07:43:51 +0100 Subject: [PATCH] feat: support bool match --- gene/src/rules/grammars/match.pest | 2 +- gene/src/rules/matcher.rs | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/gene/src/rules/grammars/match.pest b/gene/src/rules/grammars/match.pest index a11a028..e74930e 100644 --- a/gene/src/rules/grammars/match.pest +++ b/gene/src/rules/grammars/match.pest @@ -5,7 +5,7 @@ field_path = ${ sep ~ ("\"" ~ segment_with_ws ~ "\"" | segment) ~ field_pat value_dq = _{ "\"" ~ (!("\"") ~ ANY)* ~ "\"" } value_sq = _{ "'" ~ (!("'") ~ ANY)* ~ "'" } -value = @{ (value_dq | value_sq | "none" | "some") } +value = @{ (value_dq | value_sq | "none" | "some" | "true" | "false") } // the order in which operators are evaluated is important op = _{ eq | lte | lt | gte | gt | rex | flag } diff --git a/gene/src/rules/matcher.rs b/gene/src/rules/matcher.rs index 5f69a3c..a876e28 100644 --- a/gene/src/rules/matcher.rs +++ b/gene/src/rules/matcher.rs @@ -61,6 +61,7 @@ pub(crate) enum MatchValue { Number(Number), StringOrNumber(String, Number), Regex(Regex), + Bool(bool), Some, None, } @@ -72,6 +73,7 @@ impl MatchValue { Self::Number(_) => "number", Self::StringOrNumber(_, _) => "string_or_number", Self::Regex(_) => "regex", + Self::Bool(_) => "bool", Self::Some => "some", Self::None => "none", } @@ -226,11 +228,13 @@ impl FromStr for DirectMatch { let rule_op = inner_pairs.next().unwrap().as_rule(); - // easier to trim quotes here rather than walking parsed items let str_value = inner_pairs.next().unwrap().as_str(); let is_none = str_value == "none"; let is_some = str_value == "some"; + let is_bool_true = str_value.to_lowercase() == "true"; + let is_bool_false = str_value.to_lowercase() == "false"; + // easier to trim quotes here rather than walking parsed items let sanit_value = str_value.trim_matches('\'').trim_matches('"'); let (op, value) = match rule_op { @@ -239,6 +243,10 @@ impl FromStr for DirectMatch { MatchValue::None } else if is_some { MatchValue::Some + } else if is_bool_true { + MatchValue::Bool(true) + } else if is_bool_false { + MatchValue::Bool(false) } else if let Ok(i) = Number::from_str(sanit_value) { // handle the case where string can also be an // integer. Number::from_str manages hex prefix @@ -277,6 +285,7 @@ macro_rules! cmp_values { } impl DirectMatch { + #[inline] pub(crate) fn match_event(&self, event: &E) -> Result { if let Some(fvalue) = event.get_from_path(&self.field_path) { return self @@ -292,6 +301,7 @@ impl DirectMatch { )) } + #[inline] pub(crate) fn match_value(&self, tgt: &FieldValue) -> Result { // we handle a special case where we expect to match a number and the field is a string // in this case we attempt to convert the string value into a number. Mostly because @@ -333,6 +343,13 @@ impl DirectMatch { Err(()) }, ) + .or( + if let (FieldValue::Bool(fvb), MatchValue::Bool(mvb)) = (&fv, &(self.value)) { + Ok(fvb == mvb) + } else { + Err(()) + }, + ) .or( // we return Ok only if we want to match some if matches!(self.value, MatchValue::Some) { @@ -431,6 +448,16 @@ mod test { .match_value(&FieldValue::None) .unwrap()); + assert!(DirectMatch::from_str(r#".data is true"#) + .unwrap() + .match_value(&FieldValue::Bool(true)) + .unwrap()); + + assert!(DirectMatch::from_str(r#".data is false"#) + .unwrap() + .match_value(&FieldValue::Bool(false)) + .unwrap()); + // we try to match None against a string so we must return an error assert!(DirectMatch::from_str(r#".data is 'toast'"#) .unwrap()