1
2pub enum IndentStyle {
4 Tabs, Spaces(usize), }
7
8pub fn prettify(raw_json: &str, style: IndentStyle) -> Result<String, String> {
11 let mut output = String::new();
12 let mut indent_level = 0;
13 let mut in_string = false;
14 let mut is_escaped = false; let indent_str = match style {
18 IndentStyle::Tabs => "\t".to_string(),
19 IndentStyle::Spaces(count) => " ".repeat(count),
20 };
21
22 let push_indent = |buf: &mut String, level: usize| {
24 buf.push('\n');
25 for _ in 0..level {
26 buf.push_str(&indent_str);
27 }
28 };
29
30 let chars: Vec<char> = crate::strip_comments(raw_json).chars().collect();
31
32 for (_i, &c) in chars.iter().enumerate() {
34 if c == '"' && !is_escaped {
36 in_string = !in_string;
37 output.push(c);
38 continue;
39 }
40
41 if in_string {
43 if c == '\\' && !is_escaped {
44 is_escaped = true;
45 } else {
46 is_escaped = false;
47 }
48 output.push(c);
49 continue;
50 }
51
52 if c.is_whitespace() {
56 continue;
57 }
58
59 match c {
60 '{' | '[' => {
61 output.push(c);
62 indent_level += 1;
63 push_indent(&mut output, indent_level);
64 }
65 '}' | ']' => {
66 if indent_level == 0 {
67 return Err("Unbalanced braces or brackets".to_string());
68 }
69 indent_level -= 1;
70 push_indent(&mut output, indent_level);
71 output.push(c);
72 }
73 ',' => {
74 output.push(c);
75 push_indent(&mut output, indent_level);
76 }
77 ':' => {
78 output.push(c);
79 output.push(' '); }
81 _ => {
82 output.push(c);
83 }
84 }
85 }
86
87 if in_string {
89 return Err("Unclosed string quote".to_string());
90 }
91 if indent_level != 0 {
92 return Err("Unbalanced braces or brackets".to_string());
93 }
94
95 Ok(output)
96}
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_format_simple_json() {
103 let json = r#"{"key":"value"}"#;
104 let expected = "{\n \"key\": \"value\"\n}";
105 assert_eq!(prettify(json, IndentStyle::Spaces(2)).unwrap(), expected);
106 }
107
108 #[test]
109 fn test_extra_closing_brace() {
110 let json = r#"{"key": "value"}}"#;
111 assert!(prettify(json, IndentStyle::Spaces(2)).is_err());
112 }
113
114
115 #[test]
116 fn test_format_nested_json() {
117 let json = r#"{"key":{"nested":"value"}}"#;
118 let expected = "{\n \"key\": {\n \"nested\": \"value\"\n }\n}";
119 let result = prettify(json, IndentStyle::Spaces(2)).unwrap();
120 assert_eq!(result, expected);
121 }
122
123 #[test]
124 fn test_format_array() {
125 let json = r#"[1,2,3]"#;
126 let expected = "[\n\t1,\n\t2,\n\t3\n]";
127 let result = prettify(json, IndentStyle::Tabs).unwrap();
128 assert_eq!(result, expected);
129 }
130
131 #[test]
132 fn test_prettify_with_special_chars() {
133 let json = r#"{"key": "value: with colon, and braces {}"}"#;
134 let expected = "{\n \"key\": \"value: with colon, and braces {}\"\n}";
135 let result = prettify(json, IndentStyle::Spaces(4)).unwrap();
136 assert_eq!(result, expected);
137 }
138
139 #[test]
140 fn test_unbalanced_braces() {
141 let json = r#"{"key":"value""#;
142 let result = prettify(json, IndentStyle::Spaces(4));
143 assert!(result.is_err());
144 assert_eq!(result.unwrap_err(), "Unbalanced braces or brackets");
145 }
146
147 #[test]
148 fn test_unclosed_string() {
149 let json = r#"{"key":"value}"#; let result = prettify(json, IndentStyle::Spaces(4));
151 assert!(result.is_err());
152 assert_eq!(result.unwrap_err(), "Unclosed string quote");
153 }
154}