jsonist/formatter/
mod.rs

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}