@@ -10,6 +10,7 @@ use crate::{
1010 DimensionInfo ,
1111} ;
1212
13+ #[ inline]
1314fn apply_logic (
1415 condition : & Map < String , Value > ,
1516 context : & Map < String , Value > ,
@@ -37,15 +38,42 @@ fn apply_logic(
3738 true
3839}
3940
41+ /// Core context application logic - checks if all dimensions in condition are satisfied by context
42+ /// Only exact matches are considered valid, except for "variantIds" dimension where containment is checked
43+ /// Returns true if condition is satisfied by context, false otherwise
4044pub fn apply ( condition : & Map < String , Value > , context : & Map < String , Value > ) -> bool {
4145 apply_logic ( condition, context, false )
4246}
4347
48+ /// Filtering logic that allows partial matching of context
49+ /// For dimensions present in context, performs the same checks as `apply`
50+ /// For dimensions absent in context, skips the check (allows partial matching)
51+ /// This is useful for matching contexts that may not have all dimensions defined
52+ /// For array context values, checks for containment - added behaviour over `apply`
53+ /// Returns false if there is a mismatch, true otherwise
4454pub fn partial_apply (
4555 condition : & Map < String , Value > ,
4656 context : & Map < String , Value > ,
4757) -> bool {
48- apply_logic ( condition, context, true )
58+ for ( dimension, value) in condition {
59+ let Some ( context_value) = context. get ( dimension) else {
60+ continue ; // Skip dimensions not in context (partial matching)
61+ } ;
62+
63+ // For array context values, check containment
64+ if let Value :: Array ( context_values) = context_value {
65+ if !context_values. contains ( value) {
66+ return false ;
67+ }
68+ } else if dimension == "variantIds" {
69+ // variantIds must always be an array - fail if scalar
70+ return false ;
71+ } else if * context_value != * value {
72+ // For non-array values, check equality
73+ return false ;
74+ }
75+ }
76+ true
4977}
5078
5179fn _evaluate_local_cohort_dimension (
0 commit comments