Skip to main content

aurora_db/network/
http_models.rs

1use crate::error::{AqlError, Result};
2use crate::types::{Document, Value};
3use serde::Deserialize;
4use serde_json::{Value as JsonValue, json};
5use std::collections::HashMap;
6use uuid::Uuid;
7
8// API Payload Structs
9// These define the shape of JSON the server expects.
10
11#[derive(Deserialize)]
12#[serde(rename_all = "camelCase")]
13pub enum FilterOperator {
14    Eq,
15    Ne,
16    Lt,
17    Lte,
18    Gt,
19    Gte,
20    Contains,
21}
22
23#[derive(Deserialize)]
24pub struct Filter {
25    pub field: String,
26    pub operator: FilterOperator,
27    pub value: JsonValue,
28}
29
30#[derive(Deserialize)]
31pub struct SortOptions {
32    pub field: String,
33    pub ascending: bool,
34}
35
36#[derive(Deserialize)]
37pub struct QueryPayload {
38    pub filters: Option<Vec<Filter>>,
39    pub sort: Option<SortOptions>,
40    pub limit: Option<usize>,
41    pub offset: Option<usize>,
42    pub select: Option<Vec<String>>,
43}
44
45// Data Conversion Functions
46
47/// Converts an internal `Document` into a clean, client-friendly `serde_json::Value`.
48pub fn document_to_json(doc: &Document) -> JsonValue {
49    let mut map = serde_json::Map::new();
50
51    // Inject _sid at the top level of the JSON response, matching MongoDB's _id behaviour
52    map.insert("_sid".to_string(), json!(doc._sid));
53
54    for (key, value) in &doc.data {
55        map.insert(key.clone(), value_to_json(value));
56    }
57    JsonValue::Object(map)
58}
59
60/// Recursively converts an internal `Value` into a `serde_json::Value`.
61fn value_to_json(value: &Value) -> JsonValue {
62    match value {
63        Value::Null => JsonValue::Null,
64        Value::String(s) => json!(s),
65        Value::Int(i) => json!(i),
66        Value::Float(f) => json!(f),
67        Value::Bool(b) => json!(b),
68        Value::Uuid(u) => json!(u.to_string()),
69        Value::DateTime(dt) => json!(dt.to_rfc3339()),
70        Value::Array(arr) => JsonValue::Array(arr.iter().map(value_to_json).collect()),
71        Value::Object(obj) => {
72            let map = obj
73                .iter()
74                .map(|(k, v)| (k.clone(), value_to_json(v)))
75                .collect();
76            JsonValue::Object(map)
77        }
78    }
79}
80
81/// Converts an incoming `serde_json::Value` (from a request body) into the `HashMap<String, Value>`
82/// that our `insert_map` function expects.
83pub fn json_to_insert_data(json: JsonValue) -> Result<HashMap<String, Value>> {
84    let map = json.as_object().ok_or_else(|| {
85        AqlError::invalid_operation("Request body must be a JSON object".to_string())
86    })?;
87
88    let mut result = HashMap::new();
89    for (key, value) in map {
90        if key.to_lowercase() == "id" {
91            continue; // Ignore client-provided IDs on insert
92        }
93        result.insert(key.clone(), json_to_value(value)?);
94    }
95    Ok(result)
96}
97
98/// Recursively converts a `serde_json::Value` into an internal `Value`.
99pub fn json_to_value(json_value: &JsonValue) -> Result<Value> {
100    match json_value {
101        JsonValue::Null => Ok(Value::Null),
102        JsonValue::Bool(b) => Ok(Value::Bool(*b)),
103        JsonValue::Number(n) => {
104            if let Some(i) = n.as_i64() {
105                Ok(Value::Int(i))
106            } else if let Some(f) = n.as_f64() {
107                Ok(Value::Float(f))
108            } else {
109                Err(AqlError::invalid_operation(
110                    "Invalid number value".to_string(),
111                ))
112            }
113        }
114        JsonValue::String(s) => {
115            if let Ok(uuid) = Uuid::parse_str(s) {
116                Ok(Value::Uuid(uuid))
117            } else if let Ok(dt) = chrono::DateTime::parse_from_rfc3339(s) {
118                Ok(Value::DateTime(dt.with_timezone(&chrono::Utc)))
119            } else {
120                Ok(Value::String(s.clone()))
121            }
122        }
123        JsonValue::Array(arr) => {
124            let mut values = Vec::new();
125            for item in arr {
126                values.push(json_to_value(item)?);
127            }
128            Ok(Value::Array(values))
129        }
130        JsonValue::Object(obj) => {
131            let mut map = HashMap::new();
132            for (k, v) in obj {
133                map.insert(k.clone(), json_to_value(v)?);
134            }
135            Ok(Value::Object(map))
136        }
137    }
138}