nodedb_query/expr/
binary.rs1use nodedb_types::Value;
4
5use crate::value_ops::{
6 coerced_eq, compare_values, is_truthy, to_value_number, value_to_display_string, value_to_f64,
7};
8
9use super::types::BinaryOp;
10
11pub(super) fn eval_binary_op(left: &Value, op: BinaryOp, right: &Value) -> Value {
12 match op {
13 BinaryOp::Add => match (value_to_f64(left, true), value_to_f64(right, true)) {
14 (Some(a), Some(b)) => to_value_number(a + b),
15 _ => Value::Null,
16 },
17 BinaryOp::Sub => match (value_to_f64(left, true), value_to_f64(right, true)) {
18 (Some(a), Some(b)) => to_value_number(a - b),
19 _ => Value::Null,
20 },
21 BinaryOp::Mul => match (value_to_f64(left, true), value_to_f64(right, true)) {
22 (Some(a), Some(b)) => to_value_number(a * b),
23 _ => Value::Null,
24 },
25 BinaryOp::Div => match (value_to_f64(left, true), value_to_f64(right, true)) {
26 (Some(a), Some(b)) => {
27 if b == 0.0 {
28 Value::Null
29 } else {
30 to_value_number(a / b)
31 }
32 }
33 _ => Value::Null,
34 },
35 BinaryOp::Mod => match (value_to_f64(left, true), value_to_f64(right, true)) {
36 (Some(a), Some(b)) => {
37 if b == 0.0 {
38 Value::Null
39 } else {
40 to_value_number(a % b)
41 }
42 }
43 _ => Value::Null,
44 },
45 BinaryOp::Concat => {
46 let ls = value_to_display_string(left);
47 let rs = value_to_display_string(right);
48 Value::String(format!("{ls}{rs}"))
49 }
50 BinaryOp::Eq => Value::Bool(coerced_eq(left, right)),
51 BinaryOp::NotEq => Value::Bool(!coerced_eq(left, right)),
52 BinaryOp::Gt => Value::Bool(compare_values(left, right) == std::cmp::Ordering::Greater),
53 BinaryOp::GtEq => {
54 let c = compare_values(left, right);
55 Value::Bool(c == std::cmp::Ordering::Greater || c == std::cmp::Ordering::Equal)
56 }
57 BinaryOp::Lt => Value::Bool(compare_values(left, right) == std::cmp::Ordering::Less),
58 BinaryOp::LtEq => {
59 let c = compare_values(left, right);
60 Value::Bool(c == std::cmp::Ordering::Less || c == std::cmp::Ordering::Equal)
61 }
62 BinaryOp::And => Value::Bool(is_truthy(left) && is_truthy(right)),
63 BinaryOp::Or => Value::Bool(is_truthy(left) || is_truthy(right)),
64 }
65}