use serde_json::json;
use super::{FieldSchema, FieldType};
use crate::value::QuillValue;
pub fn zero_value(field: &FieldSchema) -> QuillValue {
if let Some(values) = &field.enum_values {
let first = values.first().cloned().unwrap_or_default();
return QuillValue::from_json(json!(first));
}
let json = match field.r#type {
FieldType::Array => json!([]),
FieldType::Object => match &field.properties {
Some(properties) => serde_json::Value::Object(
properties
.iter()
.map(|(name, schema)| (name.clone(), zero_value(schema).into_json()))
.collect(),
),
None => json!({}),
},
FieldType::Integer | FieldType::Number => json!(0),
FieldType::Boolean => json!(false),
_ => json!(""),
};
QuillValue::from_json(json)
}
#[cfg(test)]
mod tests {
use super::*;
fn field(yaml: &str) -> FieldSchema {
let value = QuillValue::from_yaml_str(yaml).unwrap();
FieldSchema::from_quill_value("field".to_string(), &value).unwrap()
}
#[test]
fn object_with_properties_zero_fills_each_scalar_leaf() {
let schema = field(
r#"
type: object
properties:
street: { type: string }
zip: { type: integer }
active: { type: boolean }
"#,
);
assert_eq!(
zero_value(&schema).into_json(),
json!({ "street": "", "zip": 0, "active": false })
);
}
#[test]
fn nested_object_recurses_to_type_empty_leaves() {
let schema = field(
r#"
type: object
properties:
name: { type: string }
address:
type: object
properties:
city: { type: string }
tags: { type: array, items: { type: string } }
"#,
);
assert_eq!(
zero_value(&schema).into_json(),
json!({
"name": "",
"address": { "city": "", "tags": [] }
})
);
}
#[test]
fn property_less_object_degrades_to_empty_object() {
let schema = field("type: object\n");
assert_eq!(zero_value(&schema).into_json(), json!({}));
}
}