Skip to content

Commit 8045b6b

Browse files
authored
Merge pull request #304 from AdExNetwork/issue-302-math-functions
Math functions from AIP#31
2 parents 46ad390 + 1ed6f06 commit 8045b6b

File tree

1 file changed

+264
-27
lines changed

1 file changed

+264
-27
lines changed

primitives/src/targeting/eval.rs

Lines changed: 264 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
use crate::BigNum;
22
use serde::{Deserialize, Serialize};
33
use serde_json::{value::Value as SerdeValue, Number};
4-
use std::{convert::TryFrom, fmt, ops::Div, str::FromStr};
4+
use std::{
5+
convert::TryFrom,
6+
fmt,
7+
ops::{Add, Div, Mul, Rem, Sub},
8+
str::FromStr,
9+
};
510

611
pub type Map = serde_json::value::Map<String, SerdeValue>;
712

@@ -83,8 +88,14 @@ impl TryFrom<SerdeValue> for Value {
8388
#[serde(rename_all = "camelCase")]
8489
// TODO: https://github.com/AdExNetwork/adex-validator-stack-rust/issues/296
8590
pub enum Function {
86-
/// Math `div`
91+
MulDiv(Box<Rule>, Box<Rule>, Box<Rule>),
8792
Div(Box<Rule>, Box<Rule>),
93+
Mul(Box<Rule>, Box<Rule>),
94+
Mod(Box<Rule>, Box<Rule>),
95+
Add(Box<Rule>, Box<Rule>),
96+
Sub(Box<Rule>, Box<Rule>),
97+
Max(Box<Rule>, Box<Rule>),
98+
Min(Box<Rule>, Box<Rule>),
8899
If(Box<Rule>, Box<Rule>),
89100
And(Box<Rule>, Box<Rule>),
90101
Intersects(Box<Rule>, Box<Rule>),
@@ -193,17 +204,31 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
193204

194205
// basic operators
195206
let value = match function {
207+
Function::MulDiv(first_rule, second_rule, third_rule) => {
208+
let product = eval(
209+
input,
210+
output,
211+
&Rule::Function(Function::Mul(first_rule.clone(), second_rule.clone())),
212+
)?
213+
.ok_or(Error::TypeError)?;
214+
let product_rule = Rule::Value(product);
215+
let boxed_rule = Box::new(product_rule);
216+
eval(
217+
input,
218+
output,
219+
&Rule::Function(Function::Div(boxed_rule, third_rule.clone())),
220+
)?
221+
}
196222
Function::Div(first_rule, second_rule) => {
197223
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
198224
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
199225

200-
201226
let value = match (first_eval, second_eval) {
202227
(Value::BigNum(bignum), second_value) => {
203228
let second_bignum = BigNum::try_from(second_value)?;
204229

205230
Value::BigNum(bignum.div(second_bignum))
206-
},
231+
}
207232
(lhs_value, Value::BigNum(rhs_bignum)) => {
208233
let lhs_bignum = BigNum::try_from(lhs_value)?;
209234

@@ -217,6 +242,144 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
217242

218243
Some(value)
219244
}
245+
Function::Mul(first_rule, second_rule) => {
246+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
247+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
248+
249+
let value = match (first_eval, second_eval) {
250+
(Value::BigNum(bignum), rhs_value) => {
251+
let rhs_bignum = BigNum::try_from(rhs_value)?;
252+
253+
Value::BigNum(bignum.mul(rhs_bignum))
254+
}
255+
(lhs_value, Value::BigNum(rhs_bignum)) => {
256+
let lhs_bignum = BigNum::try_from(lhs_value)?;
257+
258+
Value::BigNum(lhs_bignum.mul(rhs_bignum))
259+
}
260+
(Value::Number(lhs), Value::Number(rhs)) => {
261+
Value::Number(math_operator(lhs, rhs, MathOperator::Multiplication)?)
262+
}
263+
_ => return Err(Error::TypeError),
264+
};
265+
266+
Some(value)
267+
}
268+
Function::Mod(first_rule, second_rule) => {
269+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
270+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
271+
272+
let value = match (first_eval, second_eval) {
273+
(Value::BigNum(bignum), rhs_value) => {
274+
let rhs_bignum = BigNum::try_from(rhs_value)?;
275+
276+
Value::BigNum(bignum.rem(rhs_bignum))
277+
}
278+
(lhs_value, Value::BigNum(rhs_bignum)) => {
279+
let lhs_bignum = BigNum::try_from(lhs_value)?;
280+
281+
Value::BigNum(lhs_bignum.rem(rhs_bignum))
282+
}
283+
(Value::Number(lhs), Value::Number(rhs)) => {
284+
Value::Number(math_operator(lhs, rhs, MathOperator::Modulus)?)
285+
}
286+
_ => return Err(Error::TypeError),
287+
};
288+
289+
Some(value)
290+
}
291+
Function::Add(first_rule, second_rule) => {
292+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
293+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
294+
295+
let value = match (first_eval, second_eval) {
296+
(Value::BigNum(bignum), rhs_value) => {
297+
let rhs_bignum = BigNum::try_from(rhs_value)?;
298+
299+
Value::BigNum(bignum.add(rhs_bignum))
300+
}
301+
(lhs_value, Value::BigNum(rhs_bignum)) => {
302+
let lhs_bignum = BigNum::try_from(lhs_value)?;
303+
304+
Value::BigNum(lhs_bignum.add(rhs_bignum))
305+
}
306+
(Value::Number(lhs), Value::Number(rhs)) => {
307+
Value::Number(math_operator(lhs, rhs, MathOperator::Addition)?)
308+
}
309+
_ => return Err(Error::TypeError),
310+
};
311+
312+
Some(value)
313+
}
314+
Function::Sub(first_rule, second_rule) => {
315+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
316+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
317+
318+
let value = match (first_eval, second_eval) {
319+
(Value::BigNum(bignum), rhs_value) => {
320+
let rhs_bignum = BigNum::try_from(rhs_value)?;
321+
322+
Value::BigNum(bignum.sub(rhs_bignum))
323+
}
324+
(lhs_value, Value::BigNum(rhs_bignum)) => {
325+
let lhs_bignum = BigNum::try_from(lhs_value)?;
326+
327+
Value::BigNum(lhs_bignum.sub(rhs_bignum))
328+
}
329+
(Value::Number(lhs), Value::Number(rhs)) => {
330+
Value::Number(math_operator(lhs, rhs, MathOperator::Subtraction)?)
331+
}
332+
_ => return Err(Error::TypeError),
333+
};
334+
335+
Some(value)
336+
}
337+
Function::Max(first_rule, second_rule) => {
338+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
339+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
340+
341+
let value = match (first_eval, second_eval) {
342+
(Value::BigNum(bignum), rhs_value) => {
343+
let rhs_bignum = BigNum::try_from(rhs_value)?;
344+
345+
Value::BigNum(bignum.max(rhs_bignum))
346+
}
347+
(lhs_value, Value::BigNum(rhs_bignum)) => {
348+
let lhs_bignum = BigNum::try_from(lhs_value)?;
349+
350+
Value::BigNum(lhs_bignum.max(rhs_bignum))
351+
}
352+
(Value::Number(lhs), Value::Number(rhs)) => {
353+
Value::Number(math_operator(lhs, rhs, MathOperator::Max)?)
354+
}
355+
_ => return Err(Error::TypeError),
356+
};
357+
358+
Some(value)
359+
}
360+
Function::Min(first_rule, second_rule) => {
361+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
362+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
363+
364+
let value = match (first_eval, second_eval) {
365+
(Value::BigNum(bignum), rhs_value) => {
366+
let rhs_bignum = BigNum::try_from(rhs_value)?;
367+
368+
Value::BigNum(bignum.min(rhs_bignum))
369+
}
370+
(lhs_value, Value::BigNum(rhs_bignum)) => {
371+
let lhs_bignum = BigNum::try_from(lhs_value)?;
372+
373+
Value::BigNum(lhs_bignum.min(rhs_bignum))
374+
}
375+
(Value::Number(lhs), Value::Number(rhs)) => {
376+
Value::Number(math_operator(lhs, rhs, MathOperator::Min)?)
377+
}
378+
_ => return Err(Error::TypeError),
379+
};
380+
381+
Some(value)
382+
}
220383
Function::If(first_rule, second_rule) => {
221384
let eval_if = eval(input, output, first_rule)?
222385
.ok_or(Error::TypeError)?
@@ -303,16 +466,46 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
303466
}
304467

305468
enum MathOperator {
306-
Division
469+
Division,
470+
Multiplication,
471+
Modulus,
472+
Addition,
473+
Subtraction,
474+
Max,
475+
Min,
307476
}
308477

309478
fn handle_u64(lhs: u64, rhs: u64, ops: MathOperator) -> Result<Number, Error> {
310-
match ops {
311-
MathOperator::Division => {
312-
let divided = lhs.checked_div(rhs).ok_or(Error::TypeError)?;
313-
Ok(divided.into())
314-
}
479+
match ops {
480+
MathOperator::Division => {
481+
let divided = lhs.checked_div(rhs).ok_or(Error::TypeError)?;
482+
Ok(divided.into())
483+
}
484+
MathOperator::Multiplication => {
485+
let multiplied = lhs.checked_mul(rhs).ok_or(Error::TypeError)?;
486+
Ok(multiplied.into())
315487
}
488+
MathOperator::Modulus => {
489+
let modulus = lhs.checked_rem(rhs).ok_or(Error::TypeError)?;
490+
Ok(modulus.into())
491+
}
492+
MathOperator::Addition => {
493+
let added = lhs.checked_add(rhs).ok_or(Error::TypeError)?;
494+
Ok(added.into())
495+
}
496+
MathOperator::Subtraction => {
497+
let subtracted = lhs.checked_sub(rhs).ok_or(Error::TypeError)?;
498+
Ok(subtracted.into())
499+
}
500+
MathOperator::Max => {
501+
let max = lhs.max(rhs);
502+
Ok(max.into())
503+
}
504+
MathOperator::Min => {
505+
let min = lhs.min(rhs);
506+
Ok(min.into())
507+
}
508+
}
316509
}
317510

318511
fn handle_i64(lhs: i64, rhs: i64, ops: MathOperator) -> Result<Number, Error> {
@@ -321,32 +514,76 @@ fn handle_i64(lhs: i64, rhs: i64, ops: MathOperator) -> Result<Number, Error> {
321514
let divided = lhs.checked_div(rhs).ok_or(Error::TypeError)?;
322515
Ok(divided.into())
323516
}
517+
MathOperator::Multiplication => {
518+
let multiplied = lhs.checked_mul(rhs).ok_or(Error::TypeError)?;
519+
Ok(multiplied.into())
520+
}
521+
MathOperator::Modulus => {
522+
let modulus = lhs.checked_rem(rhs).ok_or(Error::TypeError)?;
523+
Ok(modulus.into())
524+
}
525+
MathOperator::Addition => {
526+
let added = lhs.checked_add(rhs).ok_or(Error::TypeError)?;
527+
Ok(added.into())
528+
}
529+
MathOperator::Subtraction => {
530+
let subtracted = lhs.checked_sub(rhs).ok_or(Error::TypeError)?;
531+
Ok(subtracted.into())
532+
}
533+
MathOperator::Max => {
534+
let max = lhs.max(rhs);
535+
Ok(max.into())
536+
}
537+
MathOperator::Min => {
538+
let min = lhs.min(rhs);
539+
Ok(min.into())
540+
}
324541
}
325542
}
326543

327-
fn handle_f64(lhs: f64, rhs: f64, ops:MathOperator) -> Result<Number, Error> {
328-
match ops {
329-
MathOperator::Division => {
330-
let divided = lhs.div(rhs);
331-
Ok(Number::from_f64(divided).ok_or(Error::TypeError)?)
332-
}
544+
fn handle_f64(lhs: f64, rhs: f64, ops: MathOperator) -> Result<Number, Error> {
545+
match ops {
546+
MathOperator::Division => {
547+
let divided = lhs.div(rhs);
548+
Ok(Number::from_f64(divided).ok_or(Error::TypeError)?)
549+
}
550+
MathOperator::Multiplication => {
551+
let multiplied = lhs.mul(rhs);
552+
Ok(Number::from_f64(multiplied).ok_or(Error::TypeError)?)
553+
}
554+
MathOperator::Modulus => {
555+
let modulus = lhs.rem(rhs);
556+
Ok(Number::from_f64(modulus).ok_or(Error::TypeError)?)
333557
}
558+
MathOperator::Addition => {
559+
let added = lhs.add(rhs);
560+
Ok(Number::from_f64(added).ok_or(Error::TypeError)?)
561+
}
562+
MathOperator::Subtraction => {
563+
let subtracted = lhs.sub(rhs);
564+
Ok(Number::from_f64(subtracted).ok_or(Error::TypeError)?)
565+
}
566+
MathOperator::Max => {
567+
let max = lhs.max(rhs);
568+
Ok(Number::from_f64(max).ok_or(Error::TypeError)?)
569+
}
570+
MathOperator::Min => {
571+
let min = lhs.min(rhs);
572+
Ok(Number::from_f64(min).ok_or(Error::TypeError)?)
573+
}
574+
}
334575
}
335576

336577
fn math_operator(lhs: Number, rhs: Number, ops: MathOperator) -> Result<Number, Error> {
337578
match (lhs.as_u64(), rhs.as_u64()) {
338579
(Some(lhs), Some(rhs)) => handle_u64(lhs, rhs, ops),
339-
_ => {
340-
match (lhs.as_i64(), rhs.as_i64()) {
341-
(Some(lhs), Some(rhs)) => handle_i64(lhs, rhs, ops),
342-
_ => {
343-
match (lhs.as_f64(), rhs.as_f64()) {
344-
(Some(lhs), Some(rhs)) => handle_f64(lhs, rhs, ops),
345-
_ => Err(Error::TypeError)
346-
}
347-
}
348-
}
349-
}
580+
_ => match (lhs.as_i64(), rhs.as_i64()) {
581+
(Some(lhs), Some(rhs)) => handle_i64(lhs, rhs, ops),
582+
_ => match (lhs.as_f64(), rhs.as_f64()) {
583+
(Some(lhs), Some(rhs)) => handle_f64(lhs, rhs, ops),
584+
_ => Err(Error::TypeError),
585+
},
586+
},
350587
}
351588
}
352589

0 commit comments

Comments
 (0)