1use super::parser::Node;
2use super::parser::AST;
3
4pub mod errors;
5
6pub enum DelimiterCount {
7 Four,
8 Two,
9}
10pub enum Delimiter {
11 Spaces(DelimiterCount),
12 Tabs,
13}
14pub struct FormatConfig {
15 delimiter: Delimiter,
16}
17
18impl FormatConfig {
19 pub fn new(delimiter: Delimiter) -> FormatConfig {
20 FormatConfig { delimiter }
21 }
22}
23
24pub(crate) fn stringify(ast: AST) -> String {
25 let AST { root } = ast;
26 let config = FormatConfig {
27 delimiter: Delimiter::Spaces(DelimiterCount::Four),
28 };
29 print_node(root, 0, &config)
30}
31
32pub(crate) fn stringify_with_config(ast: AST, config: &FormatConfig) -> String {
33 let AST { root } = ast;
34 print_node(root, 0, config)
35}
36
37fn derive(depth: usize, config: &FormatConfig) -> (String, String) {
38 match &config.delimiter {
39 Delimiter::Spaces(count) => {
40 let number = match count {
41 DelimiterCount::Two => 2,
42 DelimiterCount::Four => 4,
43 };
44 (" ".repeat(number * (depth + 1)), " ".repeat(number * depth))
45 }
46 Delimiter::Tabs => ("\t".repeat(depth + 1), "\t".repeat(depth)),
47 }
48}
49
50fn print_node(node: Node, depth: usize, config: &FormatConfig) -> String {
51 match node {
52 Node::Object { pairs } => {
53 let (indent, dedent) = derive(depth, config);
54 let end = format!("{}{}{}", dedent, "}", if depth == 0 { "\n" } else { "" });
55 let joiner = format!("{}{}", ",\n", indent);
56
57 format!(
58 "{}\n{}{}\n{}",
59 "{",
60 indent,
61 pairs
62 .into_iter()
63 .map(|ref item| print_node((**item).clone(), depth + 1, config))
64 .collect::<Vec::<String>>()
65 .join(&joiner),
66 &end
67 )
68 }
69 Node::Array { items } => {
70 let (indent, dedent) = derive(depth, config);
71 let joiner = format!("{}{}", ",\n", indent);
72 format!(
73 "[\n{}{}\n{}]",
74 indent,
75 items
76 .into_iter()
77 .map(|ref item| print_node((**item).clone(), depth + 1, config))
78 .collect::<Vec::<String>>()
79 .join(&joiner),
80 dedent
81 )
82 }
83 Node::Pair { key, value } => format!(
84 "{}: {}",
85 print_node(*key, depth, config),
86 print_node(*value, depth, config)
87 ),
88 Node::Literal { literal } => format!("\"{}\"", literal),
89 Node::Number { value } => format!("{}", value),
90 Node::True => String::from("true"),
91 Node::False => String::from("false"),
92 Node::Null => String::from("null"),
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn print_node_true() {
102 let node = Node::True;
103 let expected_string = "true";
104 let config = FormatConfig {
105 delimiter: Delimiter::Spaces(DelimiterCount::Four),
106 };
107
108 assert_eq!(print_node(node, 0, &config), expected_string)
109 }
110
111 #[test]
112 fn print_node_false() {
113 let node = Node::False;
114 let expected_string = "false";
115 let config = FormatConfig {
116 delimiter: Delimiter::Spaces(DelimiterCount::Four),
117 };
118
119 assert_eq!(print_node(node, 0, &config), expected_string)
120 }
121
122 #[test]
123 fn print_node_null() {
124 let node = Node::Null;
125 let expected_string = "null";
126 let config = FormatConfig {
127 delimiter: Delimiter::Spaces(DelimiterCount::Four),
128 };
129
130 assert_eq!(print_node(node, 0, &config), expected_string)
131 }
132
133 #[test]
134 fn print_node_number() {
135 let node = Node::Number { value: 3.141592 };
136 let expected_string = "3.141592";
137 let config = FormatConfig {
138 delimiter: Delimiter::Spaces(DelimiterCount::Four),
139 };
140
141 assert_eq!(print_node(node, 0, &config), expected_string)
142 }
143
144 #[test]
145 fn print_node_literal() {
146 let node = Node::Literal {
147 literal: "key".to_owned(),
148 };
149 let expected_string = r#""key""#;
150 let config = FormatConfig {
151 delimiter: Delimiter::Spaces(DelimiterCount::Four),
152 };
153
154 assert_eq!(print_node(node, 0, &config), expected_string)
155 }
156
157 #[test]
158 fn print_node_pair() {
159 let key = Node::Literal {
160 literal: "key".to_owned(),
161 };
162 let r#true = Node::True;
163 let config = FormatConfig {
164 delimiter: Delimiter::Spaces(DelimiterCount::Four),
165 };
166
167 let pair = Node::Pair {
168 key: Box::new(key),
169 value: Box::new(r#true),
170 };
171
172 let expected_string = "\"key\": true";
173
174 assert_eq!(print_node(pair, 0, &config), expected_string)
175 }
176
177 #[test]
178 fn print_node_array() {
179 let r#true = Node::True;
180 let r#true2 = Node::True;
181 let config = FormatConfig {
182 delimiter: Delimiter::Spaces(DelimiterCount::Four),
183 };
184
185 let array = Node::Array {
186 items: vec![Box::new(r#true), Box::new(r#true2)],
187 };
188
189 let expected_string = "[
190 true,
191 true
192]";
193
194 assert_eq!(print_node(array, 0, &config), expected_string)
195 }
196
197 #[test]
198 fn print_node_object() {
199 let key = Node::Literal {
200 literal: "key".to_owned(),
201 };
202 let r#true = Node::True;
203 let config = FormatConfig {
204 delimiter: Delimiter::Spaces(DelimiterCount::Four),
205 };
206
207 let pair = Node::Pair {
208 key: Box::new(key),
209 value: Box::new(r#true),
210 };
211
212 let object = Node::Object {
213 pairs: vec![Box::new(pair)],
214 };
215
216 let expected_string = r#"{
217 "key": true
218}
219"#;
220
221 assert_eq!(print_node(object, 0, &config), expected_string)
222 }
223}