allwright_plugin_sdk/
accessibility_yaml.rs1use serde_json::Value;
4use std::fmt::Write;
5
6pub fn to_string(value: &Value) -> Result<String, String> {
7 let mut output = String::new();
8 write_value(value, 0, &mut output)?;
9 Ok(output)
10}
11
12fn scalar(value: &Value) -> Result<String, String> {
13 serde_json::to_string(value)
14 .map(|text| {
16 text.replace('\u{0085}', "\\u0085")
17 .replace('\u{2028}', "\\u2028")
18 .replace('\u{2029}', "\\u2029")
19 })
20 .map_err(|error| error.to_string())
21}
22
23fn is_collection(value: &Value) -> bool {
24 match value {
25 Value::Array(items) => !items.is_empty(),
26 Value::Object(items) => !items.is_empty(),
27 _ => false,
28 }
29}
30
31fn write_entry(value: &Value, indent: usize, output: &mut String) -> Result<(), String> {
32 if is_collection(value) {
33 output.push('\n');
34 write_value(value, indent + 2, output)
35 } else {
36 writeln!(output, " {}", scalar(value)?).unwrap();
37 Ok(())
38 }
39}
40
41fn write_value(value: &Value, indent: usize, output: &mut String) -> Result<(), String> {
42 let padding = " ".repeat(indent);
43 match value {
44 Value::Object(items) if !items.is_empty() => {
45 for (key, child) in items {
46 write!(output, "{padding}{}:", scalar(&Value::String(key.clone()))?).unwrap();
47 write_entry(child, indent, output)?;
48 }
49 }
50 Value::Array(items) if !items.is_empty() => {
51 for child in items {
52 write!(output, "{padding}-").unwrap();
53 write_entry(child, indent, output)?;
54 }
55 }
56 _ => writeln!(output, "{padding}{}", scalar(value)?).unwrap(),
57 }
58 Ok(())
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use serde_json::json;
65
66 #[test]
67 fn scalar_types_survive_standard_yaml_parsing() {
68 let value = json!({"yes": ["yes", "NO", "on", "OFF", "2026-09-05", "12:34",
69 "true", "null", "001", "a\nb\r\tc", "\u{0085}\u{2028}\u{2029}", "😀",
70 "\\\"# - [] {} :", true, false, null, 2, 1.5, [], {}]});
71 let output = to_string(&value).unwrap();
72 assert!(output.contains("\"2026-09-05\""));
73 assert!(output.contains("\"yes\""));
74 assert_eq!(serde_yaml::from_str::<Value>(&output).unwrap(), value);
75 }
76}