1use indexmap::IndexMap;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct FormData {
9 pub fields: IndexMap<String, FieldValue>,
11}
12
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
15#[serde(untagged)]
16pub enum FieldValue {
17 Number(f64),
19 Boolean(bool),
21 Text(String),
23 Null,
25 Array(Vec<IndexMap<String, FieldValue>>),
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct FormSchema {
32 pub fields: IndexMap<String, FieldSchema>,
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
38#[serde(rename_all = "lowercase")]
39pub enum FieldType {
40 Text,
42 Numeric,
44 Boolean,
46 Static,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct FieldSchema {
53 pub som_path: String,
55 pub field_type: FieldType,
57 pub required: bool,
59 pub repeatable: bool,
61 pub max_occurrences: Option<u32>,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub calculate: Option<String>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub validate: Option<String>,
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn field_value_json_roundtrip() {
77 let val = FieldValue::Number(42.5);
78 let json = serde_json::to_string(&val).unwrap();
79 assert_eq!(json, "42.5");
80
81 let val = FieldValue::Boolean(true);
82 let json = serde_json::to_string(&val).unwrap();
83 assert_eq!(json, "true");
84
85 let val = FieldValue::Text("hello".to_string());
86 let json = serde_json::to_string(&val).unwrap();
87 assert_eq!(json, "\"hello\"");
88
89 let val = FieldValue::Null;
90 let json = serde_json::to_string(&val).unwrap();
91 assert_eq!(json, "null");
92 }
93
94 #[test]
95 fn form_data_json_roundtrip() {
96 let mut fields = IndexMap::new();
97 fields.insert("name".to_string(), FieldValue::Text("Acme".to_string()));
98 fields.insert("amount".to_string(), FieldValue::Number(100.0));
99 let data = FormData { fields };
100
101 let json = serde_json::to_string_pretty(&data).unwrap();
102 let parsed: FormData = serde_json::from_str(&json).unwrap();
103 assert_eq!(parsed.fields.len(), 2);
104 }
105
106 #[test]
107 fn field_schema_omits_none_scripts() {
108 let schema = FieldSchema {
109 som_path: "form1.Name".to_string(),
110 field_type: FieldType::Text,
111 required: true,
112 repeatable: false,
113 max_occurrences: Some(1),
114 calculate: None,
115 validate: None,
116 };
117 let json = serde_json::to_string(&schema).unwrap();
118 assert!(!json.contains("calculate"));
119 assert!(!json.contains("validate"));
120 }
121}