1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Render one line of an array (item can be scalar, object, or nested array).
use crate::error::Result;
use crate::value::Value;
use super::helpers::{item_needs_raw_marker, push_indent};
use super::object::render_object_body;
pub(super) fn render_array_item(value: &Value, indent: usize, out: &mut String) -> Result<()> {
push_indent(out, indent);
match value {
Value::Null => {
out.push_str("null\n");
}
Value::Bool(b) => {
out.push_str(if *b { "true" } else { "false" });
out.push('\n');
}
Value::Integer(s) => {
out.push_str(s);
out.push('\n');
}
Value::Float(s) => {
out.push_str(s);
out.push('\n');
}
Value::String(s) => {
if s.contains('\r') {
return Err(crate::render::helpers::cr_error());
}
if crate::render::helpers::string_needs_multiline(s) {
// Match pair.rs: prefer indented stripped form for
// readability, fall back to verbatim when stripped can't
// round-trip the content; the shared chooser errors when
// neither form can hold the body (§ 5.6.1).
let form = crate::render::helpers::choose_multiline_form(s, true)?;
if matches!(form, crate::render::helpers::MultilineForm::Stripped) {
// Stripped form (default).
out.push_str("(\n");
let content_indent = indent + 1;
for line in s.split('\n') {
if !line.is_empty() {
push_indent(out, content_indent);
out.push_str(line);
}
out.push('\n');
}
push_indent(out, indent);
out.push_str(")\n");
} else {
// Verbatim fallback.
out.push_str("((\n");
out.push_str(s);
out.push('\n');
push_indent(out, indent);
out.push_str("))\n");
}
} else if s.is_empty() {
// An empty-string item would otherwise render as a bare
// indented blank line, which the parser treats as
// decorative and drops. Force `::` so it stays a
// recognisable literal-string entry.
out.push_str("::\n");
} else {
if item_needs_raw_marker(s) {
out.push_str(":: ");
}
out.push_str(s);
out.push('\n');
}
}
Value::Array(items) => {
if items.is_empty() {
out.push_str("[]\n");
} else {
out.push_str("[\n");
for item in items {
render_array_item(item, indent + 1, out)?;
}
push_indent(out, indent);
out.push_str("]\n");
}
}
Value::Object(obj) => {
if obj.is_empty() {
out.push_str("{}\n");
} else {
out.push_str("{\n");
render_object_body(obj, indent + 1, out)?;
push_indent(out, indent);
out.push_str("}\n");
}
}
}
Ok(())
}