@@ -194,16 +194,29 @@ impl PatternOf<u64> for CoinPattern {
194194 }
195195}
196196
197- #[ derive( Serialize , Deserialize , Clone , Debug , PartialEq ) ]
197+ #[ derive( Serialize , Deserialize , Clone , Debug ) ]
198+ #[ serde( rename_all = "lowercase" ) ]
198199pub enum TextPattern {
199200 Exact ( String ) ,
200- // TODO: Regex
201+ #[ serde( with = "serde_ext::regex_pattern" ) ]
202+ Regex ( regex:: Regex ) ,
203+ }
204+
205+ impl PartialEq for TextPattern {
206+ fn eq ( & self , other : & Self ) -> bool {
207+ match ( self , other) {
208+ ( TextPattern :: Exact ( a) , TextPattern :: Exact ( b) ) => a. eq ( b) ,
209+ ( TextPattern :: Regex ( a) , TextPattern :: Regex ( b) ) => a. as_str ( ) == b. as_str ( ) ,
210+ _ => false ,
211+ }
212+ }
201213}
202214
203215impl PatternOf < & str > for TextPattern {
204216 fn is_match ( & self , subject : & str ) -> MatchOutcome {
205217 match self {
206- TextPattern :: Exact ( x) => MatchOutcome :: if_equal ( x. as_str ( ) , subject) ,
218+ TextPattern :: Exact ( x) => MatchOutcome :: if_true ( x. eq ( subject) ) ,
219+ TextPattern :: Regex ( x) => MatchOutcome :: if_true ( x. is_match ( subject) ) ,
207220 }
208221 }
209222}
@@ -221,9 +234,17 @@ impl PatternOf<&[u8]> for TextPattern {
221234
222235impl PatternOf < & Metadatum > for TextPattern {
223236 fn is_match ( & self , subject : & Metadatum ) -> MatchOutcome {
237+ use pallas:: interop:: utxorpc:: spec:: cardano:: metadatum:: Metadatum as M ;
238+
224239 match subject. metadatum . as_ref ( ) {
225- Some ( pallas:: interop:: utxorpc:: spec:: cardano:: metadatum:: Metadatum :: Text ( subject) ) => {
226- self . is_match ( subject. as_str ( ) )
240+ Some ( M :: Text ( text) ) => self . is_match ( text. as_str ( ) ) ,
241+ Some ( M :: Array ( array) ) => self . is_any_match ( array. items . iter ( ) ) ,
242+ Some ( M :: Map ( map) ) => {
243+ let key_matches =
244+ self . is_any_match ( map. pairs . iter ( ) . filter_map ( |p| p. key . as_ref ( ) ) ) ;
245+ let value_matches =
246+ self . is_any_match ( map. pairs . iter ( ) . filter_map ( |p| p. value . as_ref ( ) ) ) ;
247+ key_matches + value_matches
227248 }
228249 _ => MatchOutcome :: Negative ,
229250 }
@@ -642,6 +663,48 @@ mod tests {
642663 assert ! ( matches!( pattern, Pattern :: Metadata ( ..) ) ) ;
643664 }
644665
666+ /// Tests PartialEq implementation for TextPattern.
667+ #[ test]
668+ fn text_pattern_equality ( ) {
669+ use regex:: Regex ;
670+
671+ let pattern1 = TextPattern :: Regex ( Regex :: new ( r"test" ) . unwrap ( ) ) ;
672+ let pattern2 = TextPattern :: Regex ( Regex :: new ( r"test" ) . unwrap ( ) ) ;
673+ let pattern3 = TextPattern :: Regex ( Regex :: new ( r"different" ) . unwrap ( ) ) ;
674+ let pattern4 = TextPattern :: Exact ( "test" . to_string ( ) ) ;
675+ let pattern5 = TextPattern :: Exact ( "test" . to_string ( ) ) ;
676+
677+ assert_eq ! ( pattern1, pattern2) ;
678+ assert_ne ! ( pattern1, pattern3) ;
679+ assert_eq ! ( pattern4, pattern5) ;
680+ assert_ne ! ( pattern1, pattern4) ;
681+ }
682+
683+ #[ test]
684+ fn text_pattern_exact_match ( ) {
685+ let pattern = TextPattern :: Exact ( "hello" . to_string ( ) ) ;
686+
687+ assert_eq ! ( pattern. is_match( "hello" ) , MatchOutcome :: Positive ) ;
688+ assert_eq ! ( pattern. is_match( "hello world" ) , MatchOutcome :: Negative ) ;
689+ }
690+
691+ /// Tests TextPattern matching against UTF-8 and invalid byte slices.
692+ #[ test]
693+ fn text_pattern_matches_utf8_bytes ( ) {
694+ use regex:: Regex ;
695+
696+ let pattern = TextPattern :: Regex ( Regex :: new ( r"hello" ) . unwrap ( ) ) ;
697+
698+ let utf8_bytes = b"hello world" ;
699+ assert_eq ! ( pattern. is_match( & utf8_bytes[ ..] ) , MatchOutcome :: Positive ) ;
700+
701+ let utf8_no_match = b"goodbye" ;
702+ assert_eq ! ( pattern. is_match( & utf8_no_match[ ..] ) , MatchOutcome :: Negative ) ;
703+
704+ let invalid_utf8 = vec ! [ 0xFF , 0xFE , 0xFD ] ;
705+ assert_eq ! ( pattern. is_match( & invalid_utf8[ ..] ) , MatchOutcome :: Uncertain ) ;
706+ }
707+
645708 #[ test]
646709 fn deser_predicate ( ) {
647710 serde_json:: from_str :: < StringOrStruct < Predicate > > ( "\" addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3n0d3vllmyqwsx5wktcd8cc3sq835lu7drv2xwl2wywfgse35a3x\" " ) . unwrap ( ) ;
0 commit comments