Skip to content

Commit 198f373

Browse files
committed
Fixes from PR review
1 parent 9d14ab9 commit 198f373

File tree

1 file changed

+205
-23
lines changed

1 file changed

+205
-23
lines changed

primitives/src/targeting/eval.rs

Lines changed: 205 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,14 @@ pub enum Function {
112112
In(Box<Rule>, Box<Rule>),
113113
NotIn(Box<Rule>, Box<Rule>),
114114
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
116116
Between(Box<Rule>, Box<Rule>, Box<Rule>),
117117
Split(Box<Rule>, Box<Rule>),
118118
StartsWith(Box<Rule>, Box<Rule>),
119119
EndsWith(Box<Rule>, Box<Rule>),
120120
OnlyShowIf(Box<Rule>),
121121
Intersects(Box<Rule>, Box<Rule>),
122+
Do(Box<Rule>),
122123
Get(String),
123124
/// Output variables can be set any number of times by different rules, except `show`
124125
/// 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>
549550
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
550551
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
551552

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)
555571
}
556572
Function::Lte(first_rule, second_rule) => {
557573
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
558574
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
559575

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)
563594
}
564595
Function::Gt(first_rule, second_rule) => {
565596
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
566597
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
567598

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)
571617
}
572618
Function::Gte(first_rule, second_rule) => {
573619
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
574620
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
575621

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)
579640
}
580641
Function::Equals(first_rule, second_rule) => {
581642
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
582643
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
583644

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)
587677
}
588678
Function::NotEquals(first_rule, second_rule) => {
589679
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
590680
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
591681

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)
595714
}
596715
Function::Intersects(first_rule, second_rule) => {
597716
let a = eval(input, output, first_rule)?
@@ -631,7 +750,7 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
631750
Some(Value::Bool(value.ge(&start) && value.le(&end)))
632751
}
633752
Function::At(first_rule, second_rule) => {
634-
let first_eval = first_rule
753+
let mut first_eval = first_rule
635754
.eval(input, output)?
636755
.ok_or(Error::TypeError)?
637756
.try_array()?;
@@ -641,9 +760,14 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
641760
.try_number()?
642761
.as_u64()
643762
.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)
647771
}
648772
Function::Split(first_rule, second_rule) => {
649773
let first_eval = first_rule
@@ -691,6 +815,9 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
691815
output,
692816
&Rule::Function(Function::Set(String::from("show"), first_rule.clone())),
693817
)?,
818+
Function::Do(first_rule) => {
819+
eval(input, output, first_rule)?
820+
}
694821
Function::Set(key, rule) => {
695822
// Output variables can be set any number of times by different rules, except `show`
696823
// 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 {
755882
Min,
756883
}
757884

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+
758940
fn handle_u64(lhs: u64, rhs: u64, ops: MathOperator) -> Result<Number, Error> {
759941
match ops {
760942
MathOperator::Division => {

0 commit comments

Comments
 (0)