@@ -23,12 +23,14 @@ use std::sync::atomic::{AtomicU32, Ordering};
2323#[ serde( untagged) ]
2424pub enum Rule {
2525 Numeric ( NumericRule ) ,
26+ String ( StringRule ) ,
2627}
2728
2829impl Rule {
2930 pub ( super ) fn resolves ( & self , event : & serde_json:: Value ) -> bool {
3031 match self {
3132 Rule :: Numeric ( rule) => rule. resolves ( event) ,
33+ Rule :: String ( rule) => rule. resolves ( event) ,
3234 }
3335 }
3436
@@ -51,6 +53,10 @@ impl Rule {
5153 ) ,
5254 None => false ,
5355 } ,
56+ Rule :: String ( StringRule { column, .. } ) => match schema. column_with_name ( column) {
57+ Some ( ( _, column) ) => matches ! ( column. data_type( ) , arrow_schema:: DataType :: Utf8 ) ,
58+ None => false ,
59+ } ,
5460 }
5561 }
5662
@@ -88,6 +94,19 @@ impl Rule {
8894 column, value, repeats
8995 ) ,
9096 } ,
97+ Rule :: String ( StringRule {
98+ column,
99+ operator,
100+ value,
101+ ..
102+ } ) => match operator {
103+ StringOperator :: Exact => format ! ( "{} column value is {}" , column, value) ,
104+ StringOperator :: NotExact => format ! ( "{} column value is not {}" , column, value) ,
105+ StringOperator :: Contains => format ! ( "{} column contains {}" , column, value) ,
106+ StringOperator :: NotContains => {
107+ format ! ( "{} column does not contains {}" , column, value)
108+ }
109+ } ,
91110 }
92111 }
93112}
@@ -149,6 +168,44 @@ impl NumericRule {
149168 }
150169}
151170
171+ #[ derive( Debug , Serialize , Deserialize ) ]
172+ #[ serde( rename_all = "camelCase" ) ]
173+ pub struct StringRule {
174+ pub column : String ,
175+ #[ serde( default ) ]
176+ pub operator : StringOperator ,
177+ pub ignore_case : Option < bool > ,
178+ pub value : String ,
179+ }
180+
181+ impl StringRule {
182+ pub fn resolves ( & self , event : & serde_json:: Value ) -> bool {
183+ let string = match event. get ( & self . column ) . expect ( "column exists" ) {
184+ serde_json:: Value :: String ( s) => s,
185+ _ => unreachable ! ( "right rule is set for right column type" ) ,
186+ } ;
187+
188+ if self . ignore_case . unwrap_or_default ( ) {
189+ match self . operator {
190+ StringOperator :: Exact => string. eq_ignore_ascii_case ( & self . value ) ,
191+ StringOperator :: NotExact => !string. eq_ignore_ascii_case ( & self . value ) ,
192+ StringOperator :: Contains => string
193+ . to_ascii_lowercase ( )
194+ . contains ( & self . value . to_ascii_lowercase ( ) ) ,
195+ StringOperator :: NotContains => !string
196+ . to_ascii_lowercase ( )
197+ . contains ( & self . value . to_ascii_lowercase ( ) ) ,
198+ }
199+ } else {
200+ match self . operator {
201+ StringOperator :: Exact => string. eq ( & self . value ) ,
202+ StringOperator :: NotExact => !string. eq ( & self . value ) ,
203+ StringOperator :: Contains => string. contains ( & self . value ) ,
204+ StringOperator :: NotContains => !string. contains ( & self . value ) ,
205+ }
206+ }
207+ }
208+ }
152209// Operator for comparing values
153210
154211#[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
@@ -173,3 +230,20 @@ impl Default for NumericOperator {
173230 Self :: EqualTo
174231 }
175232}
233+
234+ #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
235+ #[ serde( rename_all = "camelCase" ) ]
236+ pub enum StringOperator {
237+ #[ serde( alias = "=" ) ]
238+ Exact ,
239+ #[ serde( alias = "!=" ) ]
240+ NotExact ,
241+ Contains ,
242+ NotContains ,
243+ }
244+
245+ impl Default for StringOperator {
246+ fn default ( ) -> Self {
247+ Self :: Contains
248+ }
249+ }
0 commit comments