Skip to content

Commit 9d14ab9

Browse files
committed
All other DSL functions
1 parent 1ed6f06 commit 9d14ab9

File tree

1 file changed

+280
-0
lines changed

1 file changed

+280
-0
lines changed

primitives/src/targeting/eval.rs

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,27 @@ pub enum Function {
9797
Max(Box<Rule>, Box<Rule>),
9898
Min(Box<Rule>, Box<Rule>),
9999
If(Box<Rule>, Box<Rule>),
100+
IfNot(Box<Rule>, Box<Rule>),
101+
IfElse(Box<Rule>, Box<Rule>, Box<Rule>),
100102
And(Box<Rule>, Box<Rule>),
103+
Or(Box<Rule>, Box<Rule>),
104+
Xor(Box<Rule>, Box<Rule>),
105+
Not(Box<Rule>),
106+
Lt(Box<Rule>, Box<Rule>),
107+
Lte(Box<Rule>, Box<Rule>),
108+
Gt(Box<Rule>, Box<Rule>),
109+
Gte(Box<Rule>, Box<Rule>),
110+
Equals(Box<Rule>, Box<Rule>),
111+
NotEquals(Box<Rule>, Box<Rule>),
112+
In(Box<Rule>, Box<Rule>),
113+
NotIn(Box<Rule>, Box<Rule>),
114+
At(Box<Rule>, Box<Rule>),
115+
// Note: this is inclusive of the start and end value
116+
Between(Box<Rule>, Box<Rule>, Box<Rule>),
117+
Split(Box<Rule>, Box<Rule>),
118+
StartsWith(Box<Rule>, Box<Rule>),
119+
EndsWith(Box<Rule>, Box<Rule>),
120+
OnlyShowIf(Box<Rule>),
101121
Intersects(Box<Rule>, Box<Rule>),
102122
Get(String),
103123
/// Output variables can be set any number of times by different rules, except `show`
@@ -124,14 +144,82 @@ impl Function {
124144
Self::If(Box::new(condition.into()), Box::new(then.into()))
125145
}
126146

147+
pub fn new_if_not(condition: impl Into<Rule>, then: impl Into<Rule>) -> Self {
148+
Self::IfNot(Box::new(condition.into()), Box::new(then.into()))
149+
}
150+
151+
pub fn new_if_else(
152+
condition: impl Into<Rule>,
153+
then: impl Into<Rule>,
154+
otherwise: impl Into<Rule>,
155+
) -> Self {
156+
Self::IfElse(
157+
Box::new(condition.into()),
158+
Box::new(then.into()),
159+
Box::new(otherwise.into()),
160+
)
161+
}
162+
127163
pub fn new_and(lhs: impl Into<Rule>, rhs: impl Into<Rule>) -> Self {
128164
Self::And(Box::new(lhs.into()), Box::new(rhs.into()))
129165
}
130166

167+
pub fn new_or(lhs: impl Into<Rule>, rhs: impl Into<Rule>) -> Self {
168+
Self::Or(Box::new(lhs.into()), Box::new(rhs.into()))
169+
}
170+
171+
pub fn new_xor(lhs: impl Into<Rule>, rhs: impl Into<Rule>) -> Self {
172+
Self::Xor(Box::new(lhs.into()), Box::new(rhs.into()))
173+
}
174+
175+
pub fn new_not(statement: impl Into<Rule>) -> Self {
176+
Self::Not(Box::new(statement.into()))
177+
}
178+
131179
pub fn new_intersects(lhs: impl Into<Rule>, rhs: impl Into<Rule>) -> Self {
132180
Self::Intersects(Box::new(lhs.into()), Box::new(rhs.into()))
133181
}
134182

183+
pub fn new_in(lhs: impl Into<Rule>, rhs: impl Into<Rule>) -> Self {
184+
Self::In(Box::new(lhs.into()), Box::new(rhs.into()))
185+
}
186+
187+
pub fn new_not_in(lhs: impl Into<Rule>, rhs: impl Into<Rule>) -> Self {
188+
Self::NotIn(Box::new(lhs.into()), Box::new(rhs.into()))
189+
}
190+
191+
pub fn new_between(
192+
value: impl Into<Rule>,
193+
start: impl Into<Rule>,
194+
end: impl Into<Rule>,
195+
) -> Self {
196+
Self::Between(
197+
Box::new(value.into()),
198+
Box::new(start.into()),
199+
Box::new(end.into()),
200+
)
201+
}
202+
203+
pub fn new_split(string: impl Into<Rule>, separator: impl Into<Rule>) -> Self {
204+
Self::Split(Box::new(string.into()), Box::new(separator.into()))
205+
}
206+
207+
pub fn new_starts_with(string: impl Into<Rule>, start: impl Into<Rule>) -> Self {
208+
Self::StartsWith(Box::new(string.into()), Box::new(start.into()))
209+
}
210+
211+
pub fn new_ends_with(string: impl Into<Rule>, end: impl Into<Rule>) -> Self {
212+
Self::EndsWith(Box::new(string.into()), Box::new(end.into()))
213+
}
214+
215+
pub fn new_at(array: impl Into<Rule>, position: impl Into<Rule>) -> Self {
216+
Self::At(Box::new(array.into()), Box::new(position.into()))
217+
}
218+
219+
pub fn new_only_show_if(condition: impl Into<Rule>) -> Self {
220+
Self::OnlyShowIf(Box::new(condition.into()))
221+
}
222+
135223
pub fn new_get(key: &str) -> Self {
136224
Self::Get(key.to_string())
137225
}
@@ -153,6 +241,13 @@ impl Value {
153241
}
154242
}
155243

244+
pub fn try_string(self) -> Result<String, Error> {
245+
match self {
246+
Self::String(s) => Ok(s),
247+
_ => Err(Error::TypeError),
248+
}
249+
}
250+
156251
pub fn try_array(self) -> Result<Vec<Value>, Error> {
157252
match self {
158253
Self::Array(array) => Ok(array),
@@ -391,6 +486,28 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
391486
None
392487
}
393488
}
489+
Function::IfNot(first_rule, second_rule) => {
490+
let eval_if = eval(input, output, first_rule)?
491+
.ok_or(Error::TypeError)?
492+
.try_bool()?;
493+
494+
if !eval_if {
495+
eval(input, output, second_rule)?
496+
} else {
497+
None
498+
}
499+
}
500+
Function::IfElse(first_rule, second_rule, third_rule) => {
501+
let eval_if = eval(input, output, first_rule)?
502+
.ok_or(Error::TypeError)?
503+
.try_bool()?;
504+
505+
if eval_if {
506+
eval(input, output, second_rule)?
507+
} else {
508+
eval(input, output, third_rule)?
509+
}
510+
}
394511
Function::And(first_rule, second_rule) => {
395512
let a = eval(input, output, first_rule)?
396513
.ok_or(Error::TypeError)?
@@ -401,6 +518,81 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
401518

402519
Some(Value::Bool(a && b))
403520
}
521+
Function::Or(first_rule, second_rule) => {
522+
let a = eval(input, output, first_rule)?
523+
.ok_or(Error::TypeError)?
524+
.try_bool()?;
525+
let b = eval(input, output, second_rule)?
526+
.ok_or(Error::TypeError)?
527+
.try_bool()?;
528+
529+
Some(Value::Bool(a || b))
530+
}
531+
Function::Xor(first_rule, second_rule) => {
532+
let a = eval(input, output, first_rule)?
533+
.ok_or(Error::TypeError)?
534+
.try_bool()?;
535+
let b = eval(input, output, second_rule)?
536+
.ok_or(Error::TypeError)?
537+
.try_bool()?;
538+
539+
Some(Value::Bool((a && !b) || (!a && b)))
540+
}
541+
Function::Not(first_rule) => {
542+
let a = eval(input, output, first_rule)?
543+
.ok_or(Error::TypeError)?
544+
.try_bool()?;
545+
546+
Some(Value::Bool(!a))
547+
}
548+
Function::Lt(first_rule, second_rule) => {
549+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
550+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
551+
552+
let lhs = BigNum::try_from(first_eval)?;
553+
let rhs = BigNum::try_from(second_eval)?;
554+
Some(Value::Bool(lhs.lt(&rhs)))
555+
}
556+
Function::Lte(first_rule, second_rule) => {
557+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
558+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
559+
560+
let lhs = BigNum::try_from(first_eval)?;
561+
let rhs = BigNum::try_from(second_eval)?;
562+
Some(Value::Bool(lhs.le(&rhs)))
563+
}
564+
Function::Gt(first_rule, second_rule) => {
565+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
566+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
567+
568+
let lhs = BigNum::try_from(first_eval)?;
569+
let rhs = BigNum::try_from(second_eval)?;
570+
Some(Value::Bool(lhs.gt(&rhs)))
571+
}
572+
Function::Gte(first_rule, second_rule) => {
573+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
574+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
575+
576+
let lhs = BigNum::try_from(first_eval)?;
577+
let rhs = BigNum::try_from(second_eval)?;
578+
Some(Value::Bool(lhs.ge(&rhs)))
579+
}
580+
Function::Equals(first_rule, second_rule) => {
581+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
582+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
583+
584+
let lhs = BigNum::try_from(first_eval)?;
585+
let rhs = BigNum::try_from(second_eval)?;
586+
Some(Value::Bool(lhs.eq(&rhs)))
587+
}
588+
Function::NotEquals(first_rule, second_rule) => {
589+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
590+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
591+
592+
let lhs = BigNum::try_from(first_eval)?;
593+
let rhs = BigNum::try_from(second_eval)?;
594+
Some(Value::Bool(lhs.ne(&rhs)))
595+
}
404596
Function::Intersects(first_rule, second_rule) => {
405597
let a = eval(input, output, first_rule)?
406598
.ok_or(Error::TypeError)?
@@ -411,6 +603,94 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
411603

412604
Some(Value::Bool(a.iter().any(|x| b.contains(x))))
413605
}
606+
Function::In(first_rule, second_rule) => {
607+
let a = eval(input, output, first_rule)?.ok_or(Error::TypeError)?;
608+
let b = eval(input, output, second_rule)?
609+
.ok_or(Error::TypeError)?
610+
.try_array()?;
611+
612+
Some(Value::Bool(b.contains(&a)))
613+
}
614+
Function::NotIn(first_rule, second_rule) => {
615+
let a = eval(input, output, first_rule)?.ok_or(Error::TypeError)?;
616+
let b = eval(input, output, second_rule)?
617+
.ok_or(Error::TypeError)?
618+
.try_array()?;
619+
620+
Some(Value::Bool(!b.contains(&a)))
621+
}
622+
Function::Between(first_rule, second_rule, third_rule) => {
623+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
624+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
625+
let third_eval = third_rule.eval(input, output)?.ok_or(Error::TypeError)?;
626+
627+
let value = BigNum::try_from(first_eval)?;
628+
let start = BigNum::try_from(second_eval)?;
629+
let end = BigNum::try_from(third_eval)?;
630+
631+
Some(Value::Bool(value.ge(&start) && value.le(&end)))
632+
}
633+
Function::At(first_rule, second_rule) => {
634+
let first_eval = first_rule
635+
.eval(input, output)?
636+
.ok_or(Error::TypeError)?
637+
.try_array()?;
638+
let second_eval = second_rule
639+
.eval(input, output)?
640+
.ok_or(Error::TypeError)?
641+
.try_number()?
642+
.as_u64()
643+
.ok_or(Error::TypeError)?;
644+
let index = second_eval as usize;
645+
let value = &first_eval[index];
646+
Some(value.clone())
647+
}
648+
Function::Split(first_rule, second_rule) => {
649+
let first_eval = first_rule
650+
.eval(input, output)?
651+
.ok_or(Error::TypeError)?
652+
.try_string()?;
653+
let second_eval = second_rule
654+
.eval(input, output)?
655+
.ok_or(Error::TypeError)?
656+
.try_string()?;
657+
658+
let after_split: Vec<&str> = first_eval.split(&second_eval).collect();
659+
let mapped_to_value = after_split
660+
.into_iter()
661+
.map(|x| Value::new_string(x))
662+
.collect();
663+
Some(Value::Array(mapped_to_value))
664+
}
665+
Function::StartsWith(first_rule, second_rule) => {
666+
let first_eval = first_rule
667+
.eval(input, output)?
668+
.ok_or(Error::TypeError)?
669+
.try_string()?;
670+
let second_eval = second_rule
671+
.eval(input, output)?
672+
.ok_or(Error::TypeError)?
673+
.try_string()?;
674+
675+
Some(Value::Bool(first_eval.starts_with(&second_eval)))
676+
}
677+
Function::EndsWith(first_rule, second_rule) => {
678+
let first_eval = first_rule
679+
.eval(input, output)?
680+
.ok_or(Error::TypeError)?
681+
.try_string()?;
682+
let second_eval = second_rule
683+
.eval(input, output)?
684+
.ok_or(Error::TypeError)?
685+
.try_string()?;
686+
687+
Some(Value::Bool(first_eval.ends_with(&second_eval)))
688+
}
689+
Function::OnlyShowIf(first_rule) => eval(
690+
input,
691+
output,
692+
&Rule::Function(Function::Set(String::from("show"), first_rule.clone())),
693+
)?,
414694
Function::Set(key, rule) => {
415695
// Output variables can be set any number of times by different rules, except `show`
416696
// if `show` is at any point set to `false`, we stop executing rules and don't show the ad.

0 commit comments

Comments
 (0)