json_event_parser_witespace/
write.rs

1#![allow(dead_code)]
2
3use crate::event::JsonEvent;
4use anyhow::Result;
5use std::borrow::Borrow;
6use std::io::Write;
7
8pub struct JsonWriter<W: Write> {
9    writer: W,
10}
11
12impl<W: Write> JsonWriter<W> {
13    pub fn from_writer(writer: W) -> Self {
14        Self { writer }
15    }
16
17    pub fn write_event(&mut self, event: JsonEvent) -> Result<()> {
18        match event {
19            JsonEvent::WhiteSpace(whitespace) => {
20                self.writer.write_all(whitespace.as_bytes())?;
21            }
22            JsonEvent::String(string) => {
23                write_escaped_json_string(string.borrow(), &mut self.writer)?;
24            }
25            JsonEvent::Number(number) => {
26                self.writer.write_all(number.as_bytes())?;
27            }
28            JsonEvent::Boolean(boolean) => {
29                self.writer
30                    .write_all(if boolean { b"true" } else { b"false" })?;
31            }
32            JsonEvent::Null => {
33                self.writer.write_all(b"null")?;
34            }
35            JsonEvent::StartObject => {
36                self.writer.write_all(b"{")?;
37            }
38            JsonEvent::NextObjectValue => {
39                self.writer.write_all(b",")?;
40            }
41            JsonEvent::EndObject => {
42                self.writer.write_all(b"}")?;
43            }
44            JsonEvent::ObjectKey(key) => {
45                write_escaped_json_string(key.borrow(), &mut self.writer)?;
46                self.writer.write_all(b":")?;
47            }
48            JsonEvent::StartArray => {
49                self.writer.write_all(b"[")?;
50            }
51            JsonEvent::NextArrayValue => {
52                self.writer.write_all(b",")?;
53            }
54            JsonEvent::EndArray => {
55                self.writer.write_all(b"]")?;
56            }
57            JsonEvent::Eof => {}
58        }
59        Ok(())
60    }
61}
62
63fn write_escaped_json_string(s: &str, sink: &mut impl Write) -> Result<()> {
64    sink.write_all(b"\"")?;
65    let mut buffer = [b'\\', b'u', 0, 0, 0, 0];
66    for c in s.chars() {
67        match c {
68            '\\' => sink.write_all(b"\\\\"),
69            '"' => sink.write_all(b"\\\""),
70            c => {
71                if c < char::from(32) {
72                    match c {
73                        '\u{08}' => sink.write_all(b"\\b"),
74                        '\u{0C}' => sink.write_all(b"\\f"),
75                        '\n' => sink.write_all(b"\\n"),
76                        '\r' => sink.write_all(b"\\r"),
77                        '\t' => sink.write_all(b"\\t"),
78                        c => {
79                            let mut c = c as u8;
80                            for i in (2..6).rev() {
81                                let ch = c % 16;
82                                buffer[i] = ch + if ch < 10 { b'0' } else { b'A' };
83                                c /= 16;
84                            }
85                            sink.write_all(&buffer)
86                        }
87                    }
88                } else {
89                    sink.write_all(c.encode_utf8(&mut buffer[2..]).as_bytes())
90                }
91            }
92        }?;
93    }
94    sink.write_all(b"\"")?;
95    Ok(())
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101    use crate::read::JsonReader;
102    use rstest::rstest;
103    use std::borrow::Cow;
104    use std::fs::File;
105    use std::io::{BufReader, Cursor, Read};
106
107    fn write_events(events: Vec<JsonEvent>) -> String {
108        let mut buffer = Vec::new();
109        {
110            let mut writer = JsonWriter::from_writer(&mut buffer);
111            for event in events {
112                writer.write_event(event).unwrap();
113            }
114        }
115
116        String::from_utf8(buffer).unwrap()
117    }
118
119    #[test]
120    fn simple_write() {
121        let events = vec![
122            JsonEvent::StartObject,
123            JsonEvent::ObjectKey(Cow::Owned("key".to_string())),
124            JsonEvent::String(Cow::Owned("value".to_string())),
125            JsonEvent::EndObject,
126        ];
127
128        let json_str = write_events(events);
129        assert_eq!(json_str, "{\"key\":\"value\"}");
130    }
131
132    #[test]
133    fn with_whitespace() {
134        let events = vec![
135            JsonEvent::WhiteSpace("\n  ".to_string()),
136            JsonEvent::StartObject,
137            JsonEvent::ObjectKey(Cow::Owned("key".to_string())),
138            JsonEvent::String(Cow::Owned("value".to_string())),
139            JsonEvent::EndObject,
140        ];
141
142        let json_str = write_events(events);
143        assert_eq!(json_str, "\n  {\"key\":\"value\"}");
144    }
145
146    #[rstest]
147    fn read_and_write(
148        #[values(
149            "        {\"key\":    \"value\"  \n, \"key2\": 123}   ",
150            "    [ 1 , 2 , 3]   "
151        )]
152        json_str: &str,
153    ) {
154        let mut reader = JsonReader::from_reader(BufReader::new(Cursor::new(json_str.as_bytes())));
155        let mut output_json_buffer = vec![];
156        {
157            let mut writer = JsonWriter::from_writer(&mut output_json_buffer);
158
159            let mut buffer = vec![];
160            loop {
161                let event = reader.read_event(&mut buffer).unwrap();
162                dbg!(&event);
163                if event == JsonEvent::Eof {
164                    break;
165                }
166                writer.write_event(event).unwrap();
167            }
168        }
169        let output_json_str = String::from_utf8(output_json_buffer).unwrap();
170
171        assert_eq!(output_json_str, json_str);
172    }
173
174    #[test]
175    fn read_and_write_realcase() {
176        let mut buf = String::new();
177        File::open("assets/notebook/sample.ipynb")
178            .unwrap()
179            .read_to_string(&mut buf)
180            .unwrap();
181
182        let mut reader = JsonReader::from_reader(BufReader::new(Cursor::new(buf.as_bytes())));
183        let mut output_json_buffer = vec![];
184        {
185            let mut writer = JsonWriter::from_writer(&mut output_json_buffer);
186
187            let mut buffer = vec![];
188            loop {
189                let event = reader.read_event(&mut buffer).unwrap();
190                dbg!(&event);
191                if event == JsonEvent::Eof {
192                    break;
193                }
194                writer.write_event(event).unwrap();
195            }
196        }
197        let output_json_str = String::from_utf8(output_json_buffer).unwrap();
198
199        assert_eq!(output_json_str, buf);
200    }
201}