use serde_json::{json, Value};
pub fn eq(value: impl Into<Value>) -> Value {
json!({"$eq": value.into()})
}
pub fn ne(value: impl Into<Value>) -> Value {
json!({"$ne": value.into()})
}
pub fn gt(value: impl Into<Value>) -> Value {
json!({"$gt": value.into()})
}
pub fn gte(value: impl Into<Value>) -> Value {
json!({"$gte": value.into()})
}
pub fn lt(value: impl Into<Value>) -> Value {
json!({"$lt": value.into()})
}
pub fn lte(value: impl Into<Value>) -> Value {
json!({"$lte": value.into()})
}
pub fn in_<I, V>(values: I) -> Value
where
I: IntoIterator<Item = V>,
V: Into<Value>,
{
let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
json!({"$in": arr})
}
pub fn nin<I, V>(values: I) -> Value
where
I: IntoIterator<Item = V>,
V: Into<Value>,
{
let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
json!({"$nin": arr})
}
pub fn exists(present: bool) -> Value {
json!({"$exists": present})
}
pub fn contains(substr: &str) -> Value {
json!({"$contains": substr})
}
pub fn icontains(substr: &str) -> Value {
json!({"$icontains": substr})
}
pub fn starts_with(prefix: &str) -> Value {
json!({"$startsWith": prefix})
}
pub fn ends_with(suffix: &str) -> Value {
json!({"$endsWith": suffix})
}
pub fn glob(pattern: &str) -> Value {
json!({"$glob": pattern})
}
pub fn regex(pattern: &str) -> Value {
json!({"$regex": pattern})
}
pub fn array_contains(value: impl Into<Value>) -> Value {
json!({"$arrayContains": value.into()})
}
pub fn array_contains_all<I, V>(values: I) -> Value
where
I: IntoIterator<Item = V>,
V: Into<Value>,
{
let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
json!({"$arrayContainsAll": arr})
}
pub fn array_contains_any<I, V>(values: I) -> Value
where
I: IntoIterator<Item = V>,
V: Into<Value>,
{
let arr: Vec<Value> = values.into_iter().map(Into::into).collect();
json!({"$arrayContainsAny": arr})
}
pub fn and<I>(conditions: I) -> Value
where
I: IntoIterator<Item = Value>,
{
let arr: Vec<Value> = conditions.into_iter().collect();
json!({"$and": arr})
}
pub fn or<I>(conditions: I) -> Value
where
I: IntoIterator<Item = Value>,
{
let arr: Vec<Value> = conditions.into_iter().collect();
json!({"$or": arr})
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_comparison_ops() {
assert_eq!(eq("hello"), json!({"$eq": "hello"}));
assert_eq!(gte(0.8_f64), json!({"$gte": 0.8}));
assert_eq!(lt(100_i64), json!({"$lt": 100}));
}
#[test]
fn test_string_ops() {
assert_eq!(contains("alice"), json!({"$contains": "alice"}));
assert_eq!(icontains("Alice"), json!({"$icontains": "Alice"}));
assert_eq!(starts_with("entity:"), json!({"$startsWith": "entity:"}));
assert_eq!(ends_with(":alice"), json!({"$endsWith": ":alice"}));
assert_eq!(glob("entity:*:alice"), json!({"$glob": "entity:*:alice"}));
assert_eq!(
regex("^entity:PERSON:"),
json!({"$regex": "^entity:PERSON:"})
);
}
#[test]
fn test_array_ops() {
assert_eq!(
array_contains("entity:PERSON:alice"),
json!({"$arrayContains": "entity:PERSON:alice"})
);
assert_eq!(
array_contains_all(["entity:PERSON:alice", "entity:PERSON:bob"]),
json!({"$arrayContainsAll": ["entity:PERSON:alice", "entity:PERSON:bob"]})
);
assert_eq!(
array_contains_any(["entity:PERSON:alice", "entity:PERSON:carol"]),
json!({"$arrayContainsAny": ["entity:PERSON:alice", "entity:PERSON:carol"]})
);
}
#[test]
fn test_logical_ops() {
let f = and([
json!({"importance": gte(0.8_f64)}),
json!({"tags": array_contains("entity:PERSON:alice")}),
]);
assert_eq!(
f,
json!({"$and": [
{"importance": {"$gte": 0.8}},
{"tags": {"$arrayContains": "entity:PERSON:alice"}}
]})
);
}
#[test]
fn test_in_nin() {
assert_eq!(in_(["a", "b", "c"]), json!({"$in": ["a", "b", "c"]}));
assert_eq!(nin([1_i64, 2_i64, 3_i64]), json!({"$nin": [1, 2, 3]}));
}
#[test]
fn test_exists() {
assert_eq!(exists(true), json!({"$exists": true}));
assert_eq!(exists(false), json!({"$exists": false}));
}
}