@@ -112,13 +112,14 @@ pub enum Function {
112
112
In ( Box < Rule > , Box < Rule > ) ,
113
113
NotIn ( Box < Rule > , Box < Rule > ) ,
114
114
At ( Box < Rule > , Box < Rule > ) ,
115
- // Note: this is inclusive of the start and end value
115
+ /// Note: this is inclusive of the start and end value
116
116
Between ( Box < Rule > , Box < Rule > , Box < Rule > ) ,
117
117
Split ( Box < Rule > , Box < Rule > ) ,
118
118
StartsWith ( Box < Rule > , Box < Rule > ) ,
119
119
EndsWith ( Box < Rule > , Box < Rule > ) ,
120
120
OnlyShowIf ( Box < Rule > ) ,
121
121
Intersects ( Box < Rule > , Box < Rule > ) ,
122
+ Do ( Box < Rule > ) ,
122
123
Get ( String ) ,
123
124
/// Output variables can be set any number of times by different rules, except `show`
124
125
/// if `show` is at any point set to `false`, we stop executing rules and don't show the ad.
@@ -549,49 +550,167 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
549
550
let first_eval = first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
550
551
let second_eval = second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
551
552
552
- let lhs = BigNum :: try_from ( first_eval) ?;
553
- let rhs = BigNum :: try_from ( second_eval) ?;
554
- Some ( Value :: Bool ( lhs. lt ( & rhs) ) )
553
+ let value = match ( first_eval, second_eval) {
554
+ ( Value :: BigNum ( bignum) , rhs_value) => {
555
+ let rhs_bignum = BigNum :: try_from ( rhs_value) ?;
556
+
557
+ Value :: Bool ( bignum. lt ( & rhs_bignum) )
558
+ }
559
+ ( lhs_value, Value :: BigNum ( rhs_bignum) ) => {
560
+ let lhs_bignum = BigNum :: try_from ( lhs_value) ?;
561
+
562
+ Value :: Bool ( lhs_bignum. lt ( & rhs_bignum) )
563
+ }
564
+ ( Value :: Number ( lhs) , Value :: Number ( rhs) ) => {
565
+ Value :: Bool ( compare_numbers ( lhs, rhs, ComparisonOperator :: Lt ) ?)
566
+ }
567
+ _ => return Err ( Error :: TypeError ) ,
568
+ } ;
569
+
570
+ Some ( value)
555
571
}
556
572
Function :: Lte ( first_rule, second_rule) => {
557
573
let first_eval = first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
558
574
let second_eval = second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
559
575
560
- let lhs = BigNum :: try_from ( first_eval) ?;
561
- let rhs = BigNum :: try_from ( second_eval) ?;
562
- Some ( Value :: Bool ( lhs. le ( & rhs) ) )
576
+ let value = match ( first_eval, second_eval) {
577
+ ( Value :: BigNum ( bignum) , rhs_value) => {
578
+ let rhs_bignum = BigNum :: try_from ( rhs_value) ?;
579
+
580
+ Value :: Bool ( bignum. le ( & rhs_bignum) )
581
+ }
582
+ ( lhs_value, Value :: BigNum ( rhs_bignum) ) => {
583
+ let lhs_bignum = BigNum :: try_from ( lhs_value) ?;
584
+
585
+ Value :: Bool ( lhs_bignum. le ( & rhs_bignum) )
586
+ }
587
+ ( Value :: Number ( lhs) , Value :: Number ( rhs) ) => {
588
+ Value :: Bool ( compare_numbers ( lhs, rhs, ComparisonOperator :: Lte ) ?)
589
+ }
590
+ _ => return Err ( Error :: TypeError ) ,
591
+ } ;
592
+
593
+ Some ( value)
563
594
}
564
595
Function :: Gt ( first_rule, second_rule) => {
565
596
let first_eval = first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
566
597
let second_eval = second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
567
598
568
- let lhs = BigNum :: try_from ( first_eval) ?;
569
- let rhs = BigNum :: try_from ( second_eval) ?;
570
- Some ( Value :: Bool ( lhs. gt ( & rhs) ) )
599
+ let value = match ( first_eval, second_eval) {
600
+ ( Value :: BigNum ( bignum) , rhs_value) => {
601
+ let rhs_bignum = BigNum :: try_from ( rhs_value) ?;
602
+
603
+ Value :: Bool ( bignum. gt ( & rhs_bignum) )
604
+ }
605
+ ( lhs_value, Value :: BigNum ( rhs_bignum) ) => {
606
+ let lhs_bignum = BigNum :: try_from ( lhs_value) ?;
607
+
608
+ Value :: Bool ( lhs_bignum. gt ( & rhs_bignum) )
609
+ }
610
+ ( Value :: Number ( lhs) , Value :: Number ( rhs) ) => {
611
+ Value :: Bool ( compare_numbers ( lhs, rhs, ComparisonOperator :: Gt ) ?)
612
+ }
613
+ _ => return Err ( Error :: TypeError ) ,
614
+ } ;
615
+
616
+ Some ( value)
571
617
}
572
618
Function :: Gte ( first_rule, second_rule) => {
573
619
let first_eval = first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
574
620
let second_eval = second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
575
621
576
- let lhs = BigNum :: try_from ( first_eval) ?;
577
- let rhs = BigNum :: try_from ( second_eval) ?;
578
- Some ( Value :: Bool ( lhs. ge ( & rhs) ) )
622
+ let value = match ( first_eval, second_eval) {
623
+ ( Value :: BigNum ( bignum) , rhs_value) => {
624
+ let rhs_bignum = BigNum :: try_from ( rhs_value) ?;
625
+
626
+ Value :: Bool ( bignum. ge ( & rhs_bignum) )
627
+ }
628
+ ( lhs_value, Value :: BigNum ( rhs_bignum) ) => {
629
+ let lhs_bignum = BigNum :: try_from ( lhs_value) ?;
630
+
631
+ Value :: Bool ( lhs_bignum. ge ( & rhs_bignum) )
632
+ }
633
+ ( Value :: Number ( lhs) , Value :: Number ( rhs) ) => {
634
+ Value :: Bool ( compare_numbers ( lhs, rhs, ComparisonOperator :: Gte ) ?)
635
+ }
636
+ _ => return Err ( Error :: TypeError ) ,
637
+ } ;
638
+
639
+ Some ( value)
579
640
}
580
641
Function :: Equals ( first_rule, second_rule) => {
581
642
let first_eval = first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
582
643
let second_eval = second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
583
644
584
- let lhs = BigNum :: try_from ( first_eval) ?;
585
- let rhs = BigNum :: try_from ( second_eval) ?;
586
- Some ( Value :: Bool ( lhs. eq ( & rhs) ) )
645
+ let value = match ( first_eval, second_eval) {
646
+ ( Value :: BigNum ( bignum) , rhs_value) => {
647
+ let rhs_bignum = BigNum :: try_from ( rhs_value) ?;
648
+
649
+ Value :: Bool ( bignum. eq ( & rhs_bignum) )
650
+ }
651
+ ( lhs_value, Value :: BigNum ( rhs_bignum) ) => {
652
+ let lhs_bignum = BigNum :: try_from ( lhs_value) ?;
653
+
654
+ Value :: Bool ( lhs_bignum. eq ( & rhs_bignum) )
655
+ }
656
+ ( Value :: Number ( lhs) , Value :: Number ( rhs) ) => {
657
+ Value :: Bool ( compare_numbers ( lhs, rhs, ComparisonOperator :: Equals ) ?)
658
+ }
659
+ ( Value :: Bool ( lhs) , Value :: Bool ( rhs) ) => {
660
+ Value :: Bool ( lhs == rhs)
661
+ }
662
+ ( Value :: String ( lhs) , Value :: String ( rhs) ) => {
663
+ Value :: Bool ( lhs == rhs)
664
+ }
665
+ ( Value :: Array ( lhs) , Value :: Array ( rhs) ) => {
666
+ if lhs. len ( ) != rhs. len ( ) {
667
+ Value :: Bool ( false )
668
+ } else {
669
+ let are_same = lhs. iter ( ) . zip ( rhs. iter ( ) ) . all ( |( a, b) | a == b) ;
670
+ Value :: Bool ( are_same)
671
+ }
672
+ }
673
+ _ => return Err ( Error :: TypeError ) ,
674
+ } ;
675
+
676
+ Some ( value)
587
677
}
588
678
Function :: NotEquals ( first_rule, second_rule) => {
589
679
let first_eval = first_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
590
680
let second_eval = second_rule. eval ( input, output) ?. ok_or ( Error :: TypeError ) ?;
591
681
592
- let lhs = BigNum :: try_from ( first_eval) ?;
593
- let rhs = BigNum :: try_from ( second_eval) ?;
594
- Some ( Value :: Bool ( lhs. ne ( & rhs) ) )
682
+ let value = match ( first_eval, second_eval) {
683
+ ( Value :: BigNum ( bignum) , rhs_value) => {
684
+ let rhs_bignum = BigNum :: try_from ( rhs_value) ?;
685
+
686
+ Value :: Bool ( bignum. ne ( & rhs_bignum) )
687
+ }
688
+ ( lhs_value, Value :: BigNum ( rhs_bignum) ) => {
689
+ let lhs_bignum = BigNum :: try_from ( lhs_value) ?;
690
+
691
+ Value :: Bool ( lhs_bignum. ne ( & rhs_bignum) )
692
+ }
693
+ ( Value :: Number ( lhs) , Value :: Number ( rhs) ) => {
694
+ Value :: Bool ( compare_numbers ( lhs, rhs, ComparisonOperator :: NotEquals ) ?)
695
+ }
696
+ ( Value :: Bool ( lhs) , Value :: Bool ( rhs) ) => {
697
+ Value :: Bool ( lhs != rhs)
698
+ }
699
+ ( Value :: String ( lhs) , Value :: String ( rhs) ) => {
700
+ Value :: Bool ( lhs != rhs)
701
+ }
702
+ ( Value :: Array ( lhs) , Value :: Array ( rhs) ) => {
703
+ if lhs. len ( ) != rhs. len ( ) {
704
+ Value :: Bool ( true )
705
+ } else {
706
+ let are_same = lhs. iter ( ) . zip ( rhs. iter ( ) ) . all ( |( a, b) | a == b) ;
707
+ Value :: Bool ( !are_same)
708
+ }
709
+ }
710
+ _ => return Err ( Error :: TypeError ) ,
711
+ } ;
712
+
713
+ Some ( value)
595
714
}
596
715
Function :: Intersects ( first_rule, second_rule) => {
597
716
let a = eval ( input, output, first_rule) ?
@@ -631,7 +750,7 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
631
750
Some ( Value :: Bool ( value. ge ( & start) && value. le ( & end) ) )
632
751
}
633
752
Function :: At ( first_rule, second_rule) => {
634
- let first_eval = first_rule
753
+ let mut first_eval = first_rule
635
754
. eval ( input, output) ?
636
755
. ok_or ( Error :: TypeError ) ?
637
756
. try_array ( ) ?;
@@ -641,9 +760,14 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
641
760
. try_number ( ) ?
642
761
. as_u64 ( )
643
762
. ok_or ( Error :: TypeError ) ?;
644
- let index = second_eval as usize ;
645
- let value = & first_eval[ index] ;
646
- Some ( value. clone ( ) )
763
+ let index = usize:: try_from ( second_eval) . unwrap ( ) ;
764
+ let value = if first_eval. get ( index) . is_none ( ) {
765
+ None
766
+ } else {
767
+ Some ( first_eval. swap_remove ( index) )
768
+ } ;
769
+ let value = value. ok_or ( Error :: TypeError ) ?;
770
+ Some ( value)
647
771
}
648
772
Function :: Split ( first_rule, second_rule) => {
649
773
let first_eval = first_rule
@@ -691,6 +815,9 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
691
815
output,
692
816
& Rule :: Function ( Function :: Set ( String :: from ( "show" ) , first_rule. clone ( ) ) ) ,
693
817
) ?,
818
+ Function :: Do ( first_rule) => {
819
+ eval ( input, output, first_rule) ?
820
+ }
694
821
Function :: Set ( key, rule) => {
695
822
// Output variables can be set any number of times by different rules, except `show`
696
823
// if `show` is at any point set to `false`, we stop executing rules and don't show the ad.
@@ -755,6 +882,61 @@ enum MathOperator {
755
882
Min ,
756
883
}
757
884
885
+ enum ComparisonOperator {
886
+ Gt ,
887
+ Gte ,
888
+ Lt ,
889
+ Lte ,
890
+ Equals ,
891
+ NotEquals ,
892
+ }
893
+
894
+ fn compare_numbers ( lhs : Number , rhs : Number , ops : ComparisonOperator ) -> Result < bool , Error > {
895
+ match ( lhs. as_u64 ( ) , rhs. as_u64 ( ) ) {
896
+ ( Some ( lhs) , Some ( rhs) ) => handle_comparisons ( lhs, rhs, ops) ,
897
+ _ => match ( lhs. as_i64 ( ) , rhs. as_i64 ( ) ) {
898
+ ( Some ( lhs) , Some ( rhs) ) => handle_comparisons ( lhs, rhs, ops) ,
899
+ _ => match ( lhs. as_f64 ( ) , rhs. as_f64 ( ) ) {
900
+ ( Some ( lhs) , Some ( rhs) ) => handle_comparisons ( lhs, rhs, ops) ,
901
+ _ => Err ( Error :: TypeError ) ,
902
+ } ,
903
+ } ,
904
+ }
905
+ }
906
+
907
+ fn handle_comparisons < T : PartialOrd > (
908
+ lhs : T ,
909
+ rhs : T ,
910
+ ops : ComparisonOperator ,
911
+ ) -> Result < bool , Error > {
912
+ match ops {
913
+ ComparisonOperator :: Lt => {
914
+ let is_lt = lhs < rhs;
915
+ Ok ( is_lt)
916
+ }
917
+ ComparisonOperator :: Lte => {
918
+ let is_lte = lhs <= rhs;
919
+ Ok ( is_lte)
920
+ }
921
+ ComparisonOperator :: Gt => {
922
+ let is_gt = lhs > rhs;
923
+ Ok ( is_gt)
924
+ }
925
+ ComparisonOperator :: Gte => {
926
+ let is_gte = lhs >= rhs;
927
+ Ok ( is_gte)
928
+ }
929
+ ComparisonOperator :: Equals => {
930
+ let is_equal = lhs == rhs;
931
+ Ok ( is_equal)
932
+ }
933
+ ComparisonOperator :: NotEquals => {
934
+ let is_not_equal = lhs != rhs;
935
+ Ok ( is_not_equal)
936
+ }
937
+ }
938
+ }
939
+
758
940
fn handle_u64 ( lhs : u64 , rhs : u64 , ops : MathOperator ) -> Result < Number , Error > {
759
941
match ops {
760
942
MathOperator :: Division => {
0 commit comments