use crate::error::{AqlError, Result};
use crate::types::{Document, Value};
use serde::Deserialize;
use serde_json::{Value as JsonValue, json};
use std::collections::HashMap;
use uuid::Uuid;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum FilterOperator {
Eq,
Ne,
Lt,
Lte,
Gt,
Gte,
Contains,
}
#[derive(Deserialize)]
pub struct Filter {
pub field: String,
pub operator: FilterOperator,
pub value: JsonValue,
}
#[derive(Deserialize)]
pub struct SortOptions {
pub field: String,
pub ascending: bool,
}
#[derive(Deserialize)]
pub struct QueryPayload {
pub filters: Option<Vec<Filter>>,
pub sort: Option<SortOptions>,
pub limit: Option<usize>,
pub offset: Option<usize>,
pub select: Option<Vec<String>>,
}
pub fn document_to_json(doc: &Document) -> JsonValue {
let mut map = serde_json::Map::new();
map.insert("_sid".to_string(), json!(doc._sid));
for (key, value) in &doc.data {
map.insert(key.clone(), value_to_json(value));
}
JsonValue::Object(map)
}
fn value_to_json(value: &Value) -> JsonValue {
match value {
Value::Null => JsonValue::Null,
Value::String(s) => json!(s),
Value::Int(i) => json!(i),
Value::Float(f) => json!(f),
Value::Bool(b) => json!(b),
Value::Uuid(u) => json!(u.to_string()),
Value::DateTime(dt) => json!(dt.to_rfc3339()),
Value::Array(arr) => JsonValue::Array(arr.iter().map(value_to_json).collect()),
Value::Object(obj) => {
let map = obj
.iter()
.map(|(k, v)| (k.clone(), value_to_json(v)))
.collect();
JsonValue::Object(map)
}
}
}
pub fn json_to_insert_data(json: JsonValue) -> Result<HashMap<String, Value>> {
let map = json.as_object().ok_or_else(|| {
AqlError::invalid_operation("Request body must be a JSON object".to_string())
})?;
let mut result = HashMap::new();
for (key, value) in map {
if key.to_lowercase() == "id" {
continue; }
result.insert(key.clone(), json_to_value(value)?);
}
Ok(result)
}
pub fn json_to_value(json_value: &JsonValue) -> Result<Value> {
match json_value {
JsonValue::Null => Ok(Value::Null),
JsonValue::Bool(b) => Ok(Value::Bool(*b)),
JsonValue::Number(n) => {
if let Some(i) = n.as_i64() {
Ok(Value::Int(i))
} else if let Some(f) = n.as_f64() {
Ok(Value::Float(f))
} else {
Err(AqlError::invalid_operation("Invalid number value".to_string()))
}
}
JsonValue::String(s) => {
if let Ok(uuid) = Uuid::parse_str(s) {
Ok(Value::Uuid(uuid))
} else if let Ok(dt) = chrono::DateTime::parse_from_rfc3339(s) {
Ok(Value::DateTime(dt.with_timezone(&chrono::Utc)))
} else {
Ok(Value::String(s.clone()))
}
}
JsonValue::Array(arr) => {
let mut values = Vec::new();
for item in arr {
values.push(json_to_value(item)?);
}
Ok(Value::Array(values))
}
JsonValue::Object(obj) => {
let mut map = HashMap::new();
for (k, v) in obj {
map.insert(k.clone(), json_to_value(v)?);
}
Ok(Value::Object(map))
}
}
}