///|
fn compare_numbers(
operator : Operator,
left : Json,
right : Json,
) -> Result[Bool, EvalError] {
guard left is Number(a, ..) && right is Number(b, ..) else {
return Err(TypeMismatch("numeric comparison requires two numbers"))
}
Ok(
match operator {
GreaterThan => a > b
GreaterOrEqual => a >= b
LessThan => a < b
LessOrEqual => a <= b
_ => false
},
)
}
///|
fn evaluate_comparison(
operator : Operator,
left : Json,
right : Json,
) -> Result[Bool, EvalError] {
match operator {
Equal => Ok(json_deep_equal(left, right))
NotEqual => Ok(!json_deep_equal(left, right))
GreaterThan | GreaterOrEqual | LessThan | LessOrEqual =>
compare_numbers(operator, left, right)
_ =>
Err(
TypeMismatch("operator \{operator_name(operator)} is not a comparison"),
)
}
}
///|
fn evaluate_in(needle : Json, haystack : Json) -> Result[Bool, EvalError] {
guard haystack is Array(values) else {
return Err(TypeMismatch("in requires an array as its second argument"))
}
Ok(values.any(value => json_deep_equal(needle, value)))
}
///|
fn evaluate_text(
operator : Operator,
left : Json,
right : Json,
) -> Result[Bool, EvalError] {
guard left is String(text) && right is String(part) else {
return Err(TypeMismatch("string operator requires two strings"))
}
Ok(
match operator {
Contains => text.contains(part)
StartsWith => text.has_prefix(part)
EndsWith => text.has_suffix(part)
_ => false
},
)
}
///|
fn evaluate_binary_operator(
operator : Operator,
left : Json,
right : Json,
) -> Result[Bool, EvalError] {
match operator {
In => evaluate_in(left, right)
Contains | StartsWith | EndsWith => evaluate_text(operator, left, right)
Equal | NotEqual | GreaterThan | GreaterOrEqual | LessThan | LessOrEqual =>
evaluate_comparison(operator, left, right)
_ =>
Err(
TypeMismatch(
"operator \{operator_name(operator)} is not a binary value operator",
),
)
}
}