use serde_json::Value;
use crate::schema::{FieldDef, Schema};
use crate::types::get_default;
use super::cache::ensure_cache;
use super::registry::FnRegistry;
fn none_if_null(v: Value) -> Option<Value> {
if v.is_null() {
None
} else {
Some(v)
}
}
pub fn field_default(field: &FieldDef) -> Option<Value> {
if let Some(d) = &field.default {
return Some(d.clone());
}
none_if_null(get_default(&field.field_type))
}
pub(super) fn raw_field_default(defn: &Value) -> Option<Value> {
match defn {
Value::String(s) => none_if_null(get_default(s)),
Value::Object(o) => {
if let Some(d) = o.get("default") {
if !d.is_null() {
return Some(d.clone());
}
}
let t = o.get("type").and_then(|v| v.as_str()).unwrap_or("");
none_if_null(get_default(t))
}
_ => None,
}
}
pub(super) fn is_object_field(field: &FieldDef) -> bool {
field.field_type == "object" && field.fields.as_ref().map(|v| !v.is_null()).unwrap_or(false)
}
fn raw_is_object_field(defn: &Value) -> bool {
let Some(o) = defn.as_object() else {
return false;
};
o.get("type").and_then(|v| v.as_str()) == Some("object")
&& o.get("fields").map(|v| !v.is_null()).unwrap_or(false)
}
pub fn fill_nested_defaults(obj: &mut Value, fields_def: &Value) {
let Some(defs) = fields_def.as_object() else {
return;
};
let Some(o) = obj.as_object_mut() else {
return;
};
for (key, defn) in defs {
let absent = o.get(key).map(|v| v.is_null()).unwrap_or(true);
if absent {
if let Some(d) = raw_field_default(defn) {
o.insert(key.clone(), d);
}
}
if raw_is_object_field(defn) {
let nested = defn.get("fields").cloned().unwrap_or(Value::Null);
if let Some(sub) = o.get_mut(key) {
if sub.is_object() {
fill_nested_defaults(sub, &nested);
}
}
}
}
}
pub fn apply_defaults_and_computes(
doc: &Value,
schema: &Schema,
fn_registry: Option<&dyn FnRegistry>,
) -> Result<Value, String> {
let Some(src) = doc.as_object() else {
return Ok(doc.clone());
};
let mut obj = src.clone();
for (key, field) in &schema.fields {
let absent = obj.get(key).map(|v| v.is_null()).unwrap_or(true);
if absent {
if !(key == "_id" && schema.id_is_autoincrement()) {
if let Some(defn) = field_default(field) {
obj.insert(key.clone(), defn);
}
}
}
if is_object_field(field) {
if let Some(fd) = field.fields.clone() {
if let Some(sub) = obj.get_mut(key) {
if sub.is_object() {
fill_nested_defaults(sub, &fd);
}
}
}
}
}
let mut result = Value::Object(obj);
let cache = ensure_cache(schema);
for entry in &cache.fn_list {
let v = match fn_registry {
Some(r) => r.call_sync(&entry.fn_ref, &result)?,
None => return Err(format!("计算列 {} 未注册同步实现", entry.key)),
};
let Some(o) = result.as_object_mut() else {
return Err("apply_defaults_and_computes:结果不是对象".to_string());
};
o.insert(entry.key.clone(), v);
}
Ok(result)
}