Skip to main content

nodedb_query/expr/
binary.rs

1//! Binary-operator evaluation on `Value` operands.
2
3use 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}