json_event_parser/
write.rs1use crate::JsonEvent;
2use std::io::{Error, ErrorKind, Result, Write};
3#[cfg(feature = "async-tokio")]
4use tokio::io::{AsyncWrite, AsyncWriteExt};
5
6pub struct WriterJsonSerializer<W: Write> {
21 write: W,
22 writer: LowLevelJsonSerializer,
23}
24
25impl<W: Write> WriterJsonSerializer<W> {
26 pub const fn new(write: W) -> Self {
27 Self {
28 write,
29 writer: LowLevelJsonSerializer::new(),
30 }
31 }
32
33 pub fn serialize_event(&mut self, event: JsonEvent<'_>) -> Result<()> {
34 self.writer.serialize_event(event, &mut self.write)
35 }
36
37 #[deprecated(note = "Use serialize_event() instead")]
38 pub fn write_event(&mut self, event: JsonEvent<'_>) -> Result<()> {
39 self.serialize_event(event)
40 }
41
42 pub fn finish(self) -> Result<W> {
43 self.writer.validate_eof()?;
44 Ok(self.write)
45 }
46}
47
48#[cfg(feature = "async-tokio")]
69pub struct TokioAsyncWriterJsonSerializer<W: AsyncWrite + Unpin> {
70 write: W,
71 writer: LowLevelJsonSerializer,
72 buffer: Vec<u8>,
73}
74
75#[cfg(feature = "async-tokio")]
76impl<W: AsyncWrite + Unpin> TokioAsyncWriterJsonSerializer<W> {
77 pub const fn new(write: W) -> Self {
78 Self {
79 write,
80 writer: LowLevelJsonSerializer::new(),
81 buffer: Vec::new(),
82 }
83 }
84
85 pub async fn serialize_event(&mut self, event: JsonEvent<'_>) -> Result<()> {
86 self.writer.serialize_event(event, &mut self.buffer)?;
87 self.write.write_all(&self.buffer).await?;
88 self.buffer.clear();
89 Ok(())
90 }
91
92 #[deprecated(note = "Use serialize_event() instead")]
93 pub async fn write_event(&mut self, event: JsonEvent<'_>) -> Result<()> {
94 self.serialize_event(event).await
95 }
96
97 pub fn finish(self) -> Result<W> {
98 self.writer.validate_eof()?;
99 Ok(self.write)
100 }
101}
102
103#[derive(Default)]
122pub struct LowLevelJsonSerializer {
123 state_stack: Vec<JsonState>,
124 element_written: bool,
125}
126
127impl LowLevelJsonSerializer {
128 pub const fn new() -> Self {
129 Self {
130 state_stack: Vec::new(),
131 element_written: false,
132 }
133 }
134
135 pub fn serialize_event(&mut self, event: JsonEvent<'_>, mut write: impl Write) -> Result<()> {
136 match event {
137 JsonEvent::String(s) => {
138 self.before_value(&mut write)?;
139 write_escaped_json_string(&s, write)
140 }
141 JsonEvent::Number(number) => {
142 self.before_value(&mut write)?;
143 write.write_all(number.as_bytes())
144 }
145 JsonEvent::Boolean(b) => {
146 self.before_value(&mut write)?;
147 write.write_all(if b { b"true" } else { b"false" })
148 }
149 JsonEvent::Null => {
150 self.before_value(&mut write)?;
151 write.write_all(b"null")
152 }
153 JsonEvent::StartArray => {
154 self.before_value(&mut write)?;
155 self.state_stack.push(JsonState::OpenArray);
156 write.write_all(b"[")
157 }
158 JsonEvent::EndArray => match self.state_stack.pop() {
159 Some(JsonState::OpenArray) | Some(JsonState::ContinuationArray) => {
160 write.write_all(b"]")
161 }
162 Some(s) => {
163 self.state_stack.push(s);
164 Err(Error::new(
165 ErrorKind::InvalidInput,
166 "Closing a not opened array",
167 ))
168 }
169 None => Err(Error::new(
170 ErrorKind::InvalidInput,
171 "Closing a not opened array",
172 )),
173 },
174 JsonEvent::StartObject => {
175 self.before_value(&mut write)?;
176 self.state_stack.push(JsonState::OpenObject);
177 write.write_all(b"{")
178 }
179 JsonEvent::EndObject => match self.state_stack.pop() {
180 Some(JsonState::OpenObject) | Some(JsonState::ContinuationObject) => {
181 write.write_all(b"}")
182 }
183 Some(s) => {
184 self.state_stack.push(s);
185 Err(Error::new(
186 ErrorKind::InvalidInput,
187 "Closing a not opened object",
188 ))
189 }
190 None => Err(Error::new(
191 ErrorKind::InvalidInput,
192 "Closing a not opened object",
193 )),
194 },
195 JsonEvent::ObjectKey(key) => {
196 match self.state_stack.pop() {
197 Some(JsonState::OpenObject) => (),
198 Some(JsonState::ContinuationObject) => write.write_all(b",")?,
199 _ => {
200 return Err(Error::new(
201 ErrorKind::InvalidInput,
202 "Trying to write an object key in an not object",
203 ))
204 }
205 }
206 self.state_stack.push(JsonState::ContinuationObject);
207 self.state_stack.push(JsonState::ObjectValue);
208 write_escaped_json_string(&key, &mut write)?;
209 write.write_all(b":")
210 }
211 JsonEvent::Eof => Err(Error::new(
212 ErrorKind::InvalidInput,
213 "EOF is not allowed in JSON writer",
214 )),
215 }
216 }
217
218 #[deprecated(note = "Use serialize_event() instead")]
219 pub fn write_event(&mut self, event: JsonEvent<'_>, write: impl Write) -> Result<()> {
220 self.serialize_event(event, write)
221 }
222
223 fn before_value(&mut self, mut write: impl Write) -> Result<()> {
224 match self.state_stack.pop() {
225 Some(JsonState::OpenArray) => {
226 self.state_stack.push(JsonState::ContinuationArray);
227 Ok(())
228 }
229 Some(JsonState::ContinuationArray) => {
230 self.state_stack.push(JsonState::ContinuationArray);
231 write.write_all(b",")?;
232 Ok(())
233 }
234 Some(last_state @ JsonState::OpenObject)
235 | Some(last_state @ JsonState::ContinuationObject) => {
236 self.state_stack.push(last_state);
237 Err(Error::new(
238 ErrorKind::InvalidInput,
239 "Object key expected, string found",
240 ))
241 }
242 Some(JsonState::ObjectValue) => Ok(()),
243 None => {
244 if self.element_written {
245 Err(Error::new(
246 ErrorKind::InvalidInput,
247 "A root JSON value has already been written",
248 ))
249 } else {
250 self.element_written = true;
251 Ok(())
252 }
253 }
254 }
255 }
256
257 fn validate_eof(&self) -> Result<()> {
258 if !self.state_stack.is_empty() {
259 return Err(Error::new(
260 ErrorKind::InvalidInput,
261 "The written JSON is not balanced: an object or an array has not been closed",
262 ));
263 }
264 if !self.element_written {
265 return Err(Error::new(
266 ErrorKind::InvalidInput,
267 "A JSON file can't be empty",
268 ));
269 }
270 Ok(())
271 }
272}
273
274enum JsonState {
275 OpenArray,
276 ContinuationArray,
277 OpenObject,
278 ContinuationObject,
279 ObjectValue,
280}
281
282fn write_escaped_json_string(s: &str, mut write: impl Write) -> Result<()> {
283 write.write_all(b"\"")?;
284 let mut buffer = [b'\\', b'u', 0, 0, 0, 0];
285 for c in s.chars() {
286 match c {
287 '\\' => write.write_all(b"\\\\"),
288 '"' => write.write_all(b"\\\""),
289 c => {
290 if c < char::from(32) {
291 match c {
292 '\u{08}' => write.write_all(b"\\b"),
293 '\u{0C}' => write.write_all(b"\\f"),
294 '\n' => write.write_all(b"\\n"),
295 '\r' => write.write_all(b"\\r"),
296 '\t' => write.write_all(b"\\t"),
297 c => {
298 let mut c = c as u8;
299 for i in (2..6).rev() {
300 let ch = c % 16;
301 buffer[i] = if ch < 10 { b'0' + ch } else { b'A' + ch - 10 };
302 c /= 16;
303 }
304 write.write_all(&buffer)
305 }
306 }
307 } else {
308 write.write_all(c.encode_utf8(&mut buffer[2..]).as_bytes())
309 }
310 }
311 }?;
312 }
313 write.write_all(b"\"")?;
314 Ok(())
315}