1use std::fmt;
2
3use base64::prelude::*;
4
5use crate::token::*;
6use crate::Error;
7use crate::IntoTokens;
8use crate::TokenError;
9use crate::TokenSink;
10
11#[derive(Debug, Eq, PartialEq)]
13pub enum WriteError {
14 Fmt(fmt::Error),
16
17 Token(TokenError),
19}
20
21impl fmt::Display for WriteError {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 match self {
24 Self::Fmt(err) => err.fmt(f),
25 Self::Token(err) => err.fmt(f),
26 }
27 }
28}
29
30impl std::error::Error for WriteError {}
31impl Error for WriteError {
32 fn invalid_token(token: Token<'_>, expected: Option<TokenTypes>) -> Self {
33 WriteError::Token(TokenError::invalid_token(token, expected))
34 }
35
36 fn invalid_field(field: &str) -> Self {
37 WriteError::Token(TokenError::invalid_field(field))
38 }
39
40 fn missing_fields(fields: &[&str]) -> Self {
41 WriteError::Token(TokenError::missing_fields(fields))
42 }
43
44 fn invalid_variant(variant: EnumVariant<'_>) -> Self {
45 WriteError::Token(TokenError::invalid_variant(variant))
46 }
47
48 fn unexpected_end(expected: Option<TokenTypes>) -> Self {
49 WriteError::Token(TokenError::unexpected_end(expected))
50 }
51}
52
53pub fn json_from_tokens<I: IntoTokens, W: fmt::Write>(
57 writer: W,
58 into: I,
59) -> Result<(), WriteError> {
60 let mut sink = JsonTokenSink {
61 writer,
62 state: JsonState::Plain,
63 states: Vec::new(),
64 };
65 into.into_tokens(&mut sink)?;
66
67 match sink.state {
68 JsonState::Done => Ok(()),
69 _ => Err(WriteError::unexpected_end(sink.expect_tokens())),
70 }
71}
72
73struct JsonTokenSink<W: fmt::Write> {
74 writer: W,
75 state: JsonState,
76 states: Vec<JsonState>,
77}
78
79impl<W: fmt::Write> JsonTokenSink<W> {
80 fn write_sep(&mut self, token: &Token<'_>) -> Result<(), WriteError> {
83 match self.state {
84 JsonState::Plain => self.state = JsonState::Done,
85 JsonState::FirstArrayElement => self.state = JsonState::ArrayElement,
86 JsonState::ArrayElement => self
87 .writer
88 .write_str(",")
89 .map_err(|err| WriteError::Fmt(err))?,
90 JsonState::FirstObjectKey => {
91 match token {
92 Token::Field(_) => {}
93 _ => {
94 return Err(WriteError::invalid_token(
95 token.clone(),
96 Some(TokenTypes::new(TokenType::Field)),
97 ))
98 }
99 }
100
101 self.state = JsonState::ObjectValue;
102 }
103 JsonState::ObjectKey => {
104 match token {
105 Token::Field(_) => {}
106 _ => {
107 return Err(WriteError::invalid_token(
108 token.clone(),
109 Some(TokenTypes::new(TokenType::Field)),
110 ))
111 }
112 }
113
114 self.writer
115 .write_str(",")
116 .map_err(|err| WriteError::Fmt(err))?;
117 self.state = JsonState::ObjectValue;
118 }
119 JsonState::ObjectValue => {
120 self.writer
121 .write_str(":")
122 .map_err(|err| WriteError::Fmt(err))?;
123 self.state = JsonState::ObjectKey;
124 }
125 JsonState::EnumVariant(kind) => self.state = JsonState::EnumStart(kind),
126 JsonState::EnumStart(_) => {
127 self.writer
128 .write_str(":")
129 .map_err(|err| WriteError::Fmt(err))?;
130 self.state = JsonState::EnumEnd;
131 }
132 JsonState::EnumEnd => {}
133 JsonState::Done => unreachable!(),
134 }
135
136 Ok(())
137 }
138
139 fn write_bytes(&mut self, v: &[u8]) -> Result<(), fmt::Error> {
140 let w = &mut self.writer;
141
142 w.write_char('"')?;
143 w.write_str(BASE64_STANDARD.encode(v).as_str())?;
144 w.write_char('"')?;
145
146 Ok(())
147 }
148
149 fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
150 let mut start = 0;
151 let mut end = 0;
152 let w = &mut self.writer;
153
154 w.write_char('"')?;
155
156 for c in s.chars() {
157 if c == '\\' || c == '"' || c < ' ' {
158 w.write_str(&s[start..end])?;
159
160 w.write_char('\\')?;
161
162 match c {
163 '\x07' => w.write_char('b')?,
164 '\x0C' => w.write_char('f')?,
165 '\n' => w.write_char('n')?,
166 '\r' => w.write_char('r')?,
167 '\t' => w.write_char('t')?,
168 c if c < ' ' => write!(w, "u{:04X}", c as u32)?,
169 c => w.write_char(c)?,
170 }
171
172 end += c.len_utf8();
173 start = end;
174 } else {
175 end += c.len_utf8();
176 }
177 }
178
179 if start < end {
180 w.write_str(&s[start..end])?;
181 }
182
183 w.write_char('"')?;
184
185 Ok(())
186 }
187}
188
189impl<W: fmt::Write> TokenSink for JsonTokenSink<W> {
190 type Error = WriteError;
191
192 fn yield_token(&mut self, token: Token<'_>) -> Result<bool, Self::Error> {
193 if token.is_end() {
194 match self.state {
195 JsonState::FirstArrayElement | JsonState::ArrayElement => match token {
196 Token::EndSeq | Token::EndTuple => {}
197 _ => {
198 return Err(WriteError::invalid_token(
199 token.into(),
200 Some(TokenTypes::new(TokenType::EndTuple).with(TokenType::EndSeq)),
201 ))
202 }
203 },
204 JsonState::FirstObjectKey | JsonState::ObjectKey => match token {
205 Token::EndStruct => {}
206 _ => {
207 return Err(WriteError::invalid_token(
208 token.into(),
209 Some(TokenTypes::new(TokenType::EndStruct)),
210 ))
211 }
212 },
213 JsonState::EnumEnd => match token {
214 Token::EndEnum => {}
215 _ => {
216 return Err(WriteError::invalid_token(
217 token.into(),
218 Some(TokenTypes::new(TokenType::EndEnum)),
219 ))
220 }
221 },
222
223 JsonState::ObjectValue => {
224 return Err(WriteError::Token(TokenError::InvalidToken(
225 token.into(),
226 None,
227 )))
228 }
229 JsonState::EnumVariant(_) => {
230 return Err(WriteError::Token(TokenError::InvalidToken(
231 token.into(),
232 Some(TokenTypes::new(TokenType::Variant)),
233 )))
234 }
235 JsonState::EnumStart(EnumKind::Tuple) => self
237 .writer
238 .write_str(":[]")
239 .map_err(|err| WriteError::Fmt(err))?,
240 JsonState::EnumStart(EnumKind::Struct) => self
241 .writer
242 .write_str(":{}")
243 .map_err(|err| WriteError::Fmt(err))?,
244 _ => {}
245 }
246
247 self.state = JsonState::Done;
248 } else {
249 self.write_sep(&token)?;
250 }
251
252 let w = &mut self.writer;
253
254 match token {
255 Token::Unit => w.write_str("null"),
256 Token::Bool(v) => write!(w, "{}", v),
257 Token::U8(v) => write!(w, "{}", v),
258 Token::U16(v) => write!(w, "{}", v),
259 Token::U32(v) => write!(w, "{}", v),
260 Token::U64(v) => write!(w, "{}", v),
261 Token::U128(v) => write!(w, "{}", v),
262 Token::Usize(v) => write!(w, "{}", v),
263 Token::I8(v) => write!(w, "{}", v),
264 Token::I16(v) => write!(w, "{}", v),
265 Token::I32(v) => write!(w, "{}", v),
266 Token::I64(v) => write!(w, "{}", v),
267 Token::I128(v) => write!(w, "{}", v),
268 Token::Isize(v) => write!(w, "{}", v),
269 Token::F32(v) => write!(w, "{}", v),
270 Token::F64(v) => write!(w, "{}", v),
271 Token::Char(v) => self.write_str(v.to_string().as_str()),
272 Token::Bytes(v) => self.write_bytes(v),
273 Token::Str(s) => self.write_str(s),
274 Token::Field(s) => self.write_str(s),
275 Token::Variant(EnumVariant::Str(s)) => self.write_str(s),
276 Token::Variant(EnumVariant::Usize(i)) => write!(w, "\"{}\"", i),
277
278 Token::Seq(_) => {
279 self.states.push(std::mem::replace(
280 &mut self.state,
281 JsonState::FirstArrayElement,
282 ));
283 w.write_str("[")
284 }
285 Token::Tuple(_) => {
286 self.states.push(std::mem::replace(
287 &mut self.state,
288 JsonState::FirstArrayElement,
289 ));
290 w.write_str("[")
291 }
292 Token::Struct(_) => {
293 self.states.push(std::mem::replace(
294 &mut self.state,
295 JsonState::FirstObjectKey,
296 ));
297 w.write_str("{")
298 }
299 Token::Enum(meta) => {
300 self.states.push(std::mem::replace(
301 &mut self.state,
302 JsonState::EnumVariant(meta.kind.unwrap_or(EnumKind::Tuple)),
303 ));
304 w.write_str("{")
305 }
306
307 Token::EndSeq => {
308 self.state = self
309 .states
310 .pop()
311 .ok_or(WriteError::invalid_token(token, Some(TokenTypes::EMPTY)))?;
312 w.write_str("]")
313 }
314 Token::EndTuple => {
315 self.state = self
316 .states
317 .pop()
318 .ok_or(WriteError::invalid_token(token, Some(TokenTypes::EMPTY)))?;
319 w.write_str("]")
320 }
321 Token::EndStruct => {
322 self.state = self
323 .states
324 .pop()
325 .ok_or(WriteError::invalid_token(token, Some(TokenTypes::EMPTY)))?;
326 w.write_str("}")
327 }
328 Token::EndEnum => {
329 self.state = self
330 .states
331 .pop()
332 .ok_or(WriteError::invalid_token(token, Some(TokenTypes::EMPTY)))?;
333 w.write_str("}")
334 }
335 }
336 .map_err(|err| WriteError::Fmt(err))?;
337
338 Ok(true)
339 }
340
341 fn expect_tokens(&mut self) -> Option<TokenTypes> {
342 match self.state {
343 JsonState::Plain => None,
344 JsonState::FirstArrayElement => None,
345 JsonState::ArrayElement => None,
346 JsonState::FirstObjectKey => Some(TokenTypes::new(TokenType::Field)),
347 JsonState::ObjectKey => Some(TokenTypes::new(TokenType::Field)),
348 JsonState::ObjectValue => None,
349 JsonState::EnumVariant(_) => Some(TokenTypes::new(TokenType::Variant)),
350 JsonState::EnumStart(EnumKind::Tuple) => Some(TokenTypes::new(TokenType::Tuple)),
351 JsonState::EnumStart(EnumKind::Struct) => Some(TokenTypes::new(TokenType::Struct)),
352 JsonState::EnumEnd => Some(TokenTypes::new(TokenType::EndEnum)),
353 JsonState::Done => Some(TokenTypes::EMPTY),
354 }
355 }
356}
357
358#[derive(Debug)]
359enum JsonState {
360 Plain,
361 FirstArrayElement,
362 ArrayElement,
363 FirstObjectKey,
364 ObjectKey,
365 ObjectValue,
366 EnumVariant(EnumKind),
367 EnumStart(EnumKind),
368 EnumEnd,
369 Done,
370}
371
372#[cfg(test)]
373mod tests {
374 use super::*;
375 use crate::TokenVec;
376
377 #[test]
378 fn test_from_tokens_plain() {
379 let cases = vec![
380 (Token::Unit, "null"),
381 (Token::Bool(true), "true"),
382 (Token::U8(42), "42"),
383 (Token::U16(42), "42"),
384 (Token::U32(42), "42"),
385 (Token::U64(42), "42"),
386 (Token::U128(42), "42"),
387 (Token::Usize(42), "42"),
388 (Token::I8(42), "42"),
389 (Token::I16(42), "42"),
390 (Token::I32(42), "42"),
391 (Token::I64(42), "42"),
392 (Token::I128(42), "42"),
393 (Token::Isize(42), "42"),
394 (Token::Char('a'), "\"a\""),
395 (Token::Bytes(b""), "\"\""),
396 (Token::Bytes(b"\x00"), "\"AA==\""),
397 (Token::Str("hello"), "\"hello\""),
398 (Token::Str("\n"), "\"\\n\""),
399 (Token::Str("❤️"), "\"❤️\""),
400 (Token::Str("\x1F"), "\"\\u001F\""),
401 (Token::Str("hello"), "\"hello\""),
402 ];
403
404 for (token, want) in cases {
405 let mut got = String::new();
406 json_from_tokens(&mut got, TokenVec::from_iter(vec![token].into_iter())).unwrap();
407 assert_eq!(got, want);
408 }
409 }
410
411 #[test]
412 fn test_from_tokens_seq() {
413 let cases = vec![
414 (
415 vec![Token::Seq(SeqMeta { size_hint: None }), Token::EndSeq],
416 "[]",
417 ),
418 (
419 vec![
420 Token::Seq(SeqMeta { size_hint: None }),
421 Token::Bool(true),
422 Token::EndSeq,
423 ],
424 "[true]",
425 ),
426 (
427 vec![
428 Token::Seq(SeqMeta { size_hint: None }),
429 Token::Bool(true),
430 Token::Bool(false),
431 Token::EndSeq,
432 ],
433 "[true,false]",
434 ),
435 (
436 vec![
437 Token::Seq(SeqMeta { size_hint: None }),
438 Token::Seq(SeqMeta { size_hint: None }),
439 Token::Bool(true),
440 Token::EndSeq,
441 Token::EndSeq,
442 ],
443 "[[true]]",
444 ),
445 ];
446
447 for (tokens, want) in cases {
448 let mut got = String::new();
449 json_from_tokens(&mut got, TokenVec::from_iter(tokens.into_iter())).unwrap();
450 assert_eq!(got, want);
451 }
452 }
453
454 #[test]
455 fn test_from_tokens_tuple() {
456 let cases = vec![
457 (
458 vec![Token::Tuple(TupleMeta { size_hint: None }), Token::EndTuple],
459 "[]",
460 ),
461 (
462 vec![
463 Token::Tuple(TupleMeta { size_hint: None }),
464 Token::Bool(true),
465 Token::EndTuple,
466 ],
467 "[true]",
468 ),
469 (
470 vec![
471 Token::Tuple(TupleMeta { size_hint: None }),
472 Token::Bool(true),
473 Token::Bool(false),
474 Token::EndTuple,
475 ],
476 "[true,false]",
477 ),
478 (
479 vec![
480 Token::Tuple(TupleMeta { size_hint: None }),
481 Token::Tuple(TupleMeta { size_hint: None }),
482 Token::Bool(true),
483 Token::EndTuple,
484 Token::EndTuple,
485 ],
486 "[[true]]",
487 ),
488 ];
489
490 for (tokens, want) in cases {
491 let mut got = String::new();
492 json_from_tokens(&mut got, TokenVec::from_iter(tokens.into_iter())).unwrap();
493 assert_eq!(got, want);
494 }
495 }
496
497 #[test]
498 fn test_from_tokens_struct() {
499 let cases = vec![
500 (
501 vec![Token::Struct(StructMeta { fields: None }), Token::EndStruct],
502 "{}",
503 ),
504 (
505 vec![
506 Token::Struct(StructMeta { fields: None }),
507 Token::Field("akey"),
508 Token::Bool(true),
509 Token::EndStruct,
510 ],
511 "{\"akey\":true}",
512 ),
513 (
514 vec![
515 Token::Struct(StructMeta { fields: None }),
516 Token::Field("akey"),
517 Token::Bool(true),
518 Token::Field("bkey"),
519 Token::Bool(false),
520 Token::EndStruct,
521 ],
522 "{\"akey\":true,\"bkey\":false}",
523 ),
524 (
525 vec![
526 Token::Struct(StructMeta { fields: None }),
527 Token::Field("akey"),
528 Token::Struct(StructMeta { fields: None }),
529 Token::Field("bkey"),
530 Token::Bool(false),
531 Token::EndStruct,
532 Token::EndStruct,
533 ],
534 "{\"akey\":{\"bkey\":false}}",
535 ),
536 ];
537
538 for (tokens, want) in cases {
539 let mut got = String::new();
540 json_from_tokens(&mut got, TokenVec::from_iter(tokens.into_iter())).unwrap();
541 assert_eq!(got, want);
542 }
543 }
544
545 #[test]
546 fn test_from_tokens_enum_tuple() {
547 let cases = vec![
548 (
549 vec![
550 Token::Enum(EnumMeta {
551 variants: None,
552 kind: None,
553 }),
554 Token::Variant(EnumVariant::Str("a")),
555 Token::EndEnum,
556 ],
557 "{\"a\":[]}",
558 ),
559 (
560 vec![
561 Token::Enum(EnumMeta {
562 variants: None,
563 kind: None,
564 }),
565 Token::Variant(EnumVariant::Usize(42)),
566 Token::EndEnum,
567 ],
568 "{\"42\":[]}",
569 ),
570 (
571 vec![
572 Token::Enum(EnumMeta {
573 variants: None,
574 kind: None,
575 }),
576 Token::Variant(EnumVariant::Str("a")),
577 Token::Tuple(TupleMeta { size_hint: Some(1) }),
578 Token::Bool(true),
579 Token::EndTuple,
580 Token::EndEnum,
581 ],
582 "{\"a\":[true]}",
583 ),
584 (
585 vec![
586 Token::Enum(EnumMeta {
587 variants: None,
588 kind: None,
589 }),
590 Token::Variant(EnumVariant::Str("a")),
591 Token::Tuple(TupleMeta { size_hint: Some(2) }),
592 Token::Bool(true),
593 Token::Bool(false),
594 Token::EndTuple,
595 Token::EndEnum,
596 ],
597 "{\"a\":[true,false]}",
598 ),
599 (
600 vec![
601 Token::Enum(EnumMeta {
602 variants: None,
603 kind: None,
604 }),
605 Token::Variant(EnumVariant::Str("a")),
606 Token::Tuple(TupleMeta { size_hint: Some(1) }),
607 Token::Enum(EnumMeta {
608 variants: None,
609 kind: None,
610 }),
611 Token::Variant(EnumVariant::Str("b")),
612 Token::Tuple(TupleMeta { size_hint: Some(1) }),
613 Token::Bool(true),
614 Token::EndTuple,
615 Token::EndEnum,
616 Token::EndTuple,
617 Token::EndEnum,
618 ],
619 "{\"a\":[{\"b\":[true]}]}",
620 ),
621 ];
622
623 for (tokens, want) in cases {
624 let mut got = String::new();
625 json_from_tokens(&mut got, TokenVec::from_iter(tokens.into_iter())).unwrap();
626 assert_eq!(got, want);
627 }
628 }
629
630 #[test]
631 fn test_from_tokens_enum_struct() {
632 let cases = vec![
633 (
634 vec![
635 Token::Enum(EnumMeta {
636 variants: None,
637 kind: None,
638 }),
639 Token::Variant(EnumVariant::Str("a")),
640 Token::Struct(StructMeta {
641 fields: Some(&["b"]),
642 }),
643 Token::Field("b"),
644 Token::Bool(true),
645 Token::EndStruct,
646 Token::EndEnum,
647 ],
648 r#"{"a":{"b":true}}"#,
649 ),
650 (
651 vec![
652 Token::Enum(EnumMeta {
653 variants: None,
654 kind: None,
655 }),
656 Token::Variant(EnumVariant::Str("a")),
657 Token::Struct(StructMeta {
658 fields: Some(&["b", "c"]),
659 }),
660 Token::Field("b"),
661 Token::Bool(true),
662 Token::Field("c"),
663 Token::Bool(false),
664 Token::EndStruct,
665 Token::EndEnum,
666 ],
667 r#"{"a":{"b":true,"c":false}}"#,
668 ),
669 (
670 vec![
671 Token::Enum(EnumMeta {
672 variants: None,
673 kind: None,
674 }),
675 Token::Variant(EnumVariant::Str("a")),
676 Token::Struct(StructMeta {
677 fields: Some(&["b"]),
678 }),
679 Token::Field("b"),
680 Token::Enum(EnumMeta {
681 variants: None,
682 kind: None,
683 }),
684 Token::Variant(EnumVariant::Str("c")),
685 Token::Struct(StructMeta {
686 fields: Some(&["d"]),
687 }),
688 Token::Field("d"),
689 Token::Bool(true),
690 Token::EndStruct,
691 Token::EndEnum,
692 Token::EndStruct,
693 Token::EndEnum,
694 ],
695 r#"{"a":{"b":{"c":{"d":true}}}}"#,
696 ),
697 ];
698
699 for (tokens, want) in cases {
700 let mut got = String::new();
701 json_from_tokens(&mut got, TokenVec::from_iter(tokens.into_iter())).unwrap();
702 assert_eq!(got, want);
703 }
704 }
705}