use serde_json::Value;
use vantage_expressions::Expression;
use vantage_expressions::traits::expressive::ExpressiveEnum;
pub fn eq_condition(field: &str, value: Value) -> Expression<Value> {
Expression::new(
"{} = {}",
vec![
ExpressiveEnum::Nested(Expression::new(field.to_string(), vec![])),
ExpressiveEnum::Nested(Expression::new("{}", vec![ExpressiveEnum::Scalar(value)])),
],
)
}
pub(crate) fn condition_to_query_param(cond: &Expression<Value>) -> Option<(String, String)> {
if cond.template != "{} = {}" || cond.parameters.len() != 2 {
return None;
}
let field = match &cond.parameters[0] {
ExpressiveEnum::Nested(e) if e.parameters.is_empty() => e.template.clone(),
_ => return None,
};
let value = match &cond.parameters[1] {
ExpressiveEnum::Nested(e) if e.template == "{}" && e.parameters.len() == 1 => {
match &e.parameters[0] {
ExpressiveEnum::Scalar(v) => json_to_query_string(v)?,
_ => return None,
}
}
ExpressiveEnum::Scalar(v) => json_to_query_string(v)?,
_ => return None,
};
Some((field, value))
}
fn json_to_query_string(v: &Value) -> Option<String> {
match v {
Value::Bool(b) => Some(b.to_string()),
Value::Number(n) => Some(n.to_string()),
Value::String(s) => Some(s.clone()),
Value::Null | Value::Array(_) | Value::Object(_) => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn eq_condition_round_trips_int() {
let cond = eq_condition("userId", json!(1));
let pair = condition_to_query_param(&cond).expect("eq parses");
assert_eq!(pair, ("userId".into(), "1".into()));
}
#[test]
fn eq_condition_round_trips_string() {
let cond = eq_condition("name", json!("Alice"));
let pair = condition_to_query_param(&cond).expect("eq parses");
assert_eq!(pair, ("name".into(), "Alice".into()));
}
#[test]
fn eq_condition_round_trips_bool() {
let cond = eq_condition("completed", json!(true));
let pair = condition_to_query_param(&cond).expect("eq parses");
assert_eq!(pair, ("completed".into(), "true".into()));
}
#[test]
fn raw_expression_with_unknown_template_returns_none() {
let cond = Expression::<Value>::new("CUSTOM SQL", vec![]);
assert!(condition_to_query_param(&cond).is_none());
}
#[test]
fn array_value_returns_none() {
let cond = eq_condition("tags", json!(["a", "b"]));
assert!(condition_to_query_param(&cond).is_none());
}
}