json_eval_rs/rlogic/evaluator/
arithmetic.rs1use super::{Evaluator, types::*};
2use serde_json::Value;
3use super::super::compiled::CompiledLogic;
4use super::helpers;
5
6impl Evaluator {
7 #[inline(always)]
9 pub(super) fn eval_arithmetic_fast(&self, op: ArithOp, items: &[CompiledLogic], user_data: &Value, internal_context: &Value) -> Option<Value> {
10 if items.len() > 20 || items.iter().any(|i| !matches!(i, CompiledLogic::Number(_) | CompiledLogic::Var(_, None))) {
12 return None;
13 }
14
15 let mut result = 0.0_f64;
16 for (idx, item) in items.iter().enumerate() {
17 let val = match item {
18 CompiledLogic::Number(n) => n.parse::<f64>().unwrap_or(0.0),
19 CompiledLogic::Var(name, _) => {
20 let v = helpers::get_var(internal_context, name)
22 .or_else(|| helpers::get_var(user_data, name));
23 if let Some(value) = v {
24 helpers::to_f64(value)
25 } else {
26 0.0
27 }
28 },
29 _ => return None,
30 };
31
32 if idx == 0 {
33 result = val;
34 } else {
35 result = match op {
36 ArithOp::Add => result + val,
37 ArithOp::Sub => result - val,
38 ArithOp::Mul => result * val,
39 ArithOp::Div => if val != 0.0 { result / val } else { return Some(Value::Null); },
40 };
41 }
42 }
43 Some(self.f64_to_json(result))
44 }
45
46 #[inline]
48 pub(super) fn eval_binary_arith<F>(&self, a: &CompiledLogic, b: &CompiledLogic, f: F, user_data: &Value, internal_context: &Value, depth: usize) -> Result<Value, String>
49 where F: FnOnce(f64, f64) -> Option<f64>
50 {
51 let val_a = self.evaluate_with_context(a, user_data, internal_context, depth + 1)?;
52 let val_b = self.evaluate_with_context(b, user_data, internal_context, depth + 1)?;
53 let num_a = helpers::to_f64(&val_a);
54 let num_b = helpers::to_f64(&val_b);
55 match f(num_a, num_b) {
56 Some(result) => Ok(self.f64_to_json(result)),
57 None => Ok(Value::Null)
58 }
59 }
60
61 #[inline]
63 pub(super) fn eval_array_fold<F>(&self, items: &[CompiledLogic], initial: f64, f: F, user_data: &Value, internal_context: &Value, depth: usize) -> Result<Value, String>
64 where F: Fn(f64, f64) -> Option<f64>
65 {
66 let mut result = initial;
67 for item in items {
68 let val = self.evaluate_with_context(item, user_data, internal_context, depth + 1)?;
69 let num = helpers::to_f64(&val);
70 match f(result, num) {
71 Some(v) => result = v,
72 None => return Ok(Value::Null)
73 }
74 }
75 Ok(self.f64_to_json(result))
76 }
77
78 pub(super) fn flatten_array_values(&self, items: &[CompiledLogic], user_data: &Value, internal_context: &Value, depth: usize) -> Result<Vec<f64>, String> {
80 let mut values = Vec::new();
81 for item in items {
82 let val = self.evaluate_with_context(item, user_data, internal_context, depth + 1)?;
83 if let Value::Array(arr) = val {
84 for elem in arr {
85 values.push(helpers::to_f64(&elem));
86 }
87 } else {
88 values.push(helpers::to_f64(&val));
89 }
90 }
91 Ok(values)
92 }
93}