use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FormData {
pub fields: IndexMap<String, FieldValue>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FieldValue {
Number(f64),
Boolean(bool),
Text(String),
Null,
Array(Vec<IndexMap<String, FieldValue>>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FormSchema {
pub fields: IndexMap<String, FieldSchema>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum FieldType {
Text,
Numeric,
Boolean,
Static,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldSchema {
pub som_path: String,
pub field_type: FieldType,
pub required: bool,
pub repeatable: bool,
pub max_occurrences: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub calculate: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub validate: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn field_value_json_roundtrip() {
let val = FieldValue::Number(42.5);
let json = serde_json::to_string(&val).unwrap();
assert_eq!(json, "42.5");
let val = FieldValue::Boolean(true);
let json = serde_json::to_string(&val).unwrap();
assert_eq!(json, "true");
let val = FieldValue::Text("hello".to_string());
let json = serde_json::to_string(&val).unwrap();
assert_eq!(json, "\"hello\"");
let val = FieldValue::Null;
let json = serde_json::to_string(&val).unwrap();
assert_eq!(json, "null");
}
#[test]
fn form_data_json_roundtrip() {
let mut fields = IndexMap::new();
fields.insert("name".to_string(), FieldValue::Text("Acme".to_string()));
fields.insert("amount".to_string(), FieldValue::Number(100.0));
let data = FormData { fields };
let json = serde_json::to_string_pretty(&data).unwrap();
let parsed: FormData = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.fields.len(), 2);
}
#[test]
fn field_schema_omits_none_scripts() {
let schema = FieldSchema {
som_path: "form1.Name".to_string(),
field_type: FieldType::Text,
required: true,
repeatable: false,
max_occurrences: Some(1),
calculate: None,
validate: None,
};
let json = serde_json::to_string(&schema).unwrap();
assert!(!json.contains("calculate"));
assert!(!json.contains("validate"));
}
}