1use super::Handler;
26use crate::{
27 error,
28 path::{Element, Path},
29 streamer::{ParsedKind, Token},
30};
31use std::{any::Any, str::FromStr};
32
33#[derive(Debug)]
35pub struct Indenter {
36 spaces: Option<usize>,
38 stack: Option<Vec<(usize, ParsedKind)>>,
40}
41
42impl Indenter {
43 pub fn new(spaces: Option<usize>) -> Self {
48 Self {
49 spaces,
50 stack: None,
51 }
52 }
53
54 fn write_indent_level(&self, buff: &mut Vec<u8>) {
55 if let Some(stack) = self.stack.as_ref() {
56 for _ in 0..(stack.len() - 1) * self.spaces.unwrap_or(0) {
57 buff.push(b' ');
58 }
59 }
60 }
61}
62
63impl FromStr for Indenter {
64 type Err = error::Handler;
65 fn from_str(intend_str: &str) -> Result<Self, Self::Err> {
66 if intend_str.is_empty() {
67 Ok(Self::new(None))
68 } else {
69 Ok(Self::new(Some(
70 intend_str.parse::<usize>().map_err(error::Handler::new)?,
71 )))
72 }
73 }
74}
75
76impl Handler for Indenter {
77 fn start(
78 &mut self,
79 path: &Path,
80 _matcher_idx: usize,
81 token: Token,
82 ) -> Result<Option<Vec<u8>>, error::Handler> {
83 let kind = if let Token::Start(_, kind) = token {
84 kind
85 } else {
86 unreachable![];
87 };
88
89 let mut res = vec![];
90 self.stack = if let Some(mut stack) = self.stack.take() {
91 stack.push((0, kind));
92 if stack.len() > 1 {
94 if stack[stack.len() - 2].0 != 0 {
95 res.push(b',');
96 }
97 if self.spaces.is_some() {
98 res.push(b'\n');
99 }
100 }
101 Some(stack)
102 } else {
103 Some(vec![(0, kind)])
105 };
106
107 self.write_indent_level(&mut res);
108 let stack = self.stack.as_ref().unwrap();
110 if stack.len() > 1 {
111 if matches!(stack[stack.len() - 2].1, ParsedKind::Obj) {
113 if let Element::Key(key) = &path.get_path()[path.depth() - 1] {
114 res.push(b'"');
115 res.extend(key.as_bytes());
116 res.extend(br#"":"#);
117 if self.spaces.is_some() {
118 res.push(b' ');
119 }
120 } else {
121 unreachable!();
122 }
123 }
124 }
125
126 match kind {
127 ParsedKind::Arr => {
128 res.push(b'[');
129 }
130 ParsedKind::Obj => {
131 res.push(b'{');
132 }
133 _ => {}
134 }
135
136 if res.is_empty() {
137 Ok(None)
138 } else {
139 Ok(Some(res))
140 }
141 }
142
143 fn feed(
144 &mut self,
145 data: &[u8],
146 _matcher_idx: usize,
147 ) -> Result<Option<Vec<u8>>, error::Handler> {
148 let mut result = vec![];
149 if let Some(stack) = self.stack.as_ref() {
150 if let Some((_, kind)) = stack.last() {
151 match kind {
152 ParsedKind::Obj | ParsedKind::Arr => {}
153 _ => {
154 result.extend(data.to_vec());
155 }
156 }
157 }
158 }
159 Ok(Some(result))
160 }
161
162 fn end(
163 &mut self,
164 _path: &Path,
165 _matcher_idx: usize,
166 token: Token,
167 ) -> Result<Option<Vec<u8>>, error::Handler> {
168 let kind = if let Token::End(_, kind) = token {
169 kind
170 } else {
171 unreachable![];
172 };
173
174 let mut res = vec![];
175 if let Some(stack) = self.stack.as_ref() {
176 match kind {
177 ParsedKind::Arr => {
178 if stack.last().unwrap().0 != 0 && self.spaces.is_some() {
179 res.push(b'\n');
180 self.write_indent_level(&mut res);
181 }
182 res.push(b']');
183 }
184 ParsedKind::Obj => {
185 if stack.last().unwrap().0 != 0 && self.spaces.is_some() {
186 res.push(b'\n');
187 self.write_indent_level(&mut res);
188 }
189 res.push(b'}');
190 }
191 _ => {}
192 };
193 }
194
195 if let Some(stack) = self.stack.as_mut() {
196 stack.pop();
198 if let Some((idx, _)) = stack.last_mut() {
200 *idx += 1;
201 }
202
203 if stack.is_empty() && self.spaces.is_some() {
205 res.push(b'\n');
206 self.stack = None;
207 }
208 }
209
210 if res.is_empty() {
211 Ok(None)
212 } else {
213 Ok(Some(res))
214 }
215 }
216
217 fn is_converter(&self) -> bool {
218 true
219 }
220
221 fn as_any(&self) -> &dyn Any {
222 self
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::Indenter;
229 use crate::strategy::{All, OutputConverter, Strategy};
230 use rstest::*;
231 use std::sync::{Arc, Mutex};
232
233 fn make_all_with_spaces(level: Option<usize>) -> All {
234 let mut all = All::new();
235 all.set_convert(true);
236 all.add_handler(Arc::new(Mutex::new(Indenter::new(level))));
237 all
238 }
239
240 #[rstest(
241 spaces,
242 input,
243 output,
244 case::null_none(None, b"null", b"null"),
245 case::null_0(Some(0), b"null", b"null\n"),
246 case::null_2(Some(2), b"null", b"null\n"),
247 case::obj_none(None, b"{}", b"{}"),
248 case::obj_0(Some(0), b"{}", b"{}\n"),
249 case::obj_2(Some(2), b"{}", b"{}\n"),
250 case::arr_none(None, b"[]", b"[]"),
251 case::arr_0(Some(0), b"[]", b"[]\n"),
252 case::arr_2(Some(2), b"[]", b"[]\n"),
253 case::str_none(None, br#""str""#, br#""str""#),
254 case::str_0(Some(0), br#""str""#, b"\"str\"\n"),
255 case::str_2(Some(2), br#""str""#, b"\"str\"\n"),
256 before => [b"\n\n", b"\n", b" ", b""],
257 after => [b"\n\n", b"\n", b" "]
258 )]
259 fn leafs(spaces: Option<usize>, input: &[u8], output: &[u8], before: &[u8], after: &[u8]) {
260 let mut all = make_all_with_spaces(spaces);
261 let mut final_input = vec![];
262 final_input.extend(before);
263 final_input.extend(input);
264 final_input.extend(after);
265 let result = OutputConverter::new().convert(&all.process(&final_input).unwrap());
266
267 assert_eq!(result.len(), 1);
268 assert_eq!((None, output.to_vec()), result[0]);
269 }
270
271 #[test]
272 fn flat_array() {
273 let input = b" [ \n 3 \n , null,true,\n false, \"10\"\n]".to_vec();
274
275 let mut all = make_all_with_spaces(None);
277 assert_eq!(
278 br#"[3,null,true,false,"10"]"#.to_vec(),
279 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
280 );
281
282 let mut all = make_all_with_spaces(Some(0));
284 assert_eq!(
285 b"[\n3,\nnull,\ntrue,\nfalse,\n\"10\"\n]\n".to_vec(),
286 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
287 );
288
289 let mut all = make_all_with_spaces(Some(2));
291 assert_eq!(
292 b"[\n 3,\n null,\n true,\n false,\n \"10\"\n]\n".to_vec(),
293 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
294 );
295 }
296
297 #[test]
298 fn nested_array() {
299 let input = b" [ \n [3] \n , [],null,[[]], \"10\"\n,[[[]]]]".to_vec();
300
301 let mut all = make_all_with_spaces(None);
303 assert_eq!(
304 br#"[[3],[],null,[[]],"10",[[[]]]]"#.to_vec(),
305 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
306 );
307
308 let mut all = make_all_with_spaces(Some(0));
310 assert_eq!(
311 b"[\n[\n3\n],\n[],\nnull,\n[\n[]\n],\n\"10\",\n[\n[\n[]\n]\n]\n]\n".to_vec(),
312 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
313 );
314
315 let mut all = make_all_with_spaces(Some(2));
317 assert_eq!(
318 b"[\n [\n 3\n ],\n [],\n null,\n [\n []\n ],\n \"10\",\n [\n [\n []\n ]\n ]\n]\n".to_vec(),
319 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
320 );
321 }
322
323 #[test]
324 fn flat_object() {
325 let input =
326 b" { \n \"1\" \n: 1 , \"2\":\"2\", \"3\": null\n, \"4\":\n\nfalse\n\n\n}".to_vec();
327
328 let mut all = make_all_with_spaces(None);
330 assert_eq!(
331 br#"{"1":1,"2":"2","3":null,"4":false}"#.to_vec(),
332 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
333 );
334
335 let mut all = make_all_with_spaces(Some(0));
337 assert_eq!(
338 b"{\n\"1\": 1,\n\"2\": \"2\",\n\"3\": null,\n\"4\": false\n}\n".to_vec(),
339 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
340 );
341
342 let mut all = make_all_with_spaces(Some(2));
344 assert_eq!(
345 b"{\n \"1\": 1,\n \"2\": \"2\",\n \"3\": null,\n \"4\": false\n}\n".to_vec(),
346 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
347 );
348 }
349
350 #[test]
351 fn nested_object() {
352 let input =
353 b" { \n \"1\" \n: {} , \"2\":{\"2a\": {}}, \"3\": null\n, \"4\":\n\n{\"4a\": {\"4aa\": {}}}\n\n\n}".to_vec();
354
355 let mut all = make_all_with_spaces(None);
357 assert_eq!(
358 br#"{"1":{},"2":{"2a":{}},"3":null,"4":{"4a":{"4aa":{}}}}"#.to_vec(),
359 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
360 );
361
362 let mut all = make_all_with_spaces(Some(0));
364 assert_eq!(
365 b"{\n\"1\": {},\n\"2\": {\n\"2a\": {}\n},\n\"3\": null,\n\"4\": {\n\"4a\": {\n\"4aa\": {}\n}\n}\n}\n".to_vec(),
366 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
367 );
368
369 let mut all = make_all_with_spaces(Some(2));
371 assert_eq!(
372 b"{\n \"1\": {},\n \"2\": {\n \"2a\": {}\n },\n \"3\": null,\n \"4\": {\n \"4a\": {\n \"4aa\": {}\n }\n }\n}\n".to_vec(),
373 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
374 );
375 }
376
377 #[test]
378 fn complex() {
379 let input =
380 b" { \n \"1\" \n: [] , \"2\":{\"2a\": []}, \"3\": null\n, \"4\":\n\n[ {\"4aa\": {}}]\n\n\n}".to_vec();
381
382 let mut all = make_all_with_spaces(None);
384 assert_eq!(
385 br#"{"1":[],"2":{"2a":[]},"3":null,"4":[{"4aa":{}}]}"#.to_vec(),
386 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
387 );
388
389 let mut all = make_all_with_spaces(Some(0));
391 assert_eq!(
392 b"{\n\"1\": [],\n\"2\": {\n\"2a\": []\n},\n\"3\": null,\n\"4\": [\n{\n\"4aa\": {}\n}\n]\n}\n".to_vec(),
393 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
394 );
395
396 let mut all = make_all_with_spaces(Some(2));
398 assert_eq!(
399 b"{\n \"1\": [],\n \"2\": {\n \"2a\": []\n },\n \"3\": null,\n \"4\": [\n {\n \"4aa\": {}\n }\n ]\n}\n".to_vec(),
400 OutputConverter::new().convert(&all.process(&input).unwrap())[0].1
401 );
402 }
403}