1use alloc::string::{String, ToString};
2use alloc::{vec, vec::Vec};
3use facet_core::{Characteristic, Def, Facet, FieldFlags, ScalarAffinity, StructKind};
4use facet_reflect::{HeapValue, ReflectError, Wip};
5use log::trace;
6use owo_colors::OwoColorize;
7
8mod tokenizer;
9pub use tokenizer::*;
10
11mod error;
12pub use error::*;
13
14pub fn from_str<'input, 'facet, T>(json: &'input str) -> Result<T, JsonError<'input>>
20where
21 T: Facet<'facet>,
22 'input: 'facet,
23{
24 from_slice(json.as_bytes())
25}
26
27pub fn from_slice<'input, 'facet, T>(json: &'input [u8]) -> Result<T, JsonError<'input>>
37where
38 T: Facet<'facet>,
39 'input: 'facet,
40{
41 let wip =
42 Wip::alloc::<T>().map_err(|e| JsonError::new_reflect(e, json, Span::new(0, json.len())))?;
43 let heap_value = from_slice_wip(wip, json)?;
44 Ok(heap_value.materialize::<T>().unwrap())
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49enum Instruction {
50 Value,
51 SkipValue,
52 Pop(PopReason),
53 ObjectKeyOrObjectClose,
54 CommaThenObjectKeyOrObjectClose,
55 ArrayItemOrArrayClose,
56 CommaThenArrayItemOrArrayClose,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60enum PopReason {
61 TopLevel,
62 ObjectVal,
63 ArrayItem,
64 Some,
65}
66
67pub fn from_slice_wip<'input: 'facet, 'facet>(
78 mut wip: Wip<'facet>,
79 input: &'input [u8],
80) -> Result<HeapValue<'facet>, JsonError<'input>> {
81 let mut runner = StackRunner {
83 stack: vec![Instruction::Pop(PopReason::TopLevel), Instruction::Value],
84 tokenizer: Tokenizer::new(input),
85 last_span: Span::new(0, 0),
86 unread_token: None,
87 input,
88 };
89
90 loop {
91 let frame_count = wip.frames_count();
92 debug_assert!(
93 frame_count
94 >= runner
95 .stack
96 .iter()
97 .filter(|f| matches!(f, Instruction::Pop(_)))
98 .count()
99 );
100
101 let insn = match runner.stack.pop() {
102 Some(insn) => insn,
103 None => unreachable!("Instruction stack is empty"),
104 };
105
106 trace!("[{frame_count}] Instruction {:?}", insn.yellow());
107
108 match insn {
109 Instruction::Pop(reason) => {
110 wip = runner.pop(wip, reason)?;
111
112 if reason == PopReason::TopLevel {
113 return wip
114 .build()
115 .map_err(|e| JsonError::new_reflect(e, input, runner.last_span));
116 } else {
117 wip = wip
118 .pop()
119 .map_err(|e| JsonError::new_reflect(e, input, runner.last_span))?;
120 }
121 }
122 Instruction::SkipValue => runner.skip_value(&wip)?,
123 Instruction::Value => wip = runner.value(wip)?,
124 Instruction::ObjectKeyOrObjectClose => wip = runner.object_key_or_object_close(wip)?,
125 Instruction::CommaThenObjectKeyOrObjectClose => {
126 runner.comma_then_object_key_or_object_close(&wip)?
127 }
128 Instruction::ArrayItemOrArrayClose => wip = runner.array_item_or_array_close(wip)?,
129 Instruction::CommaThenArrayItemOrArrayClose => {
130 wip = runner.comma_then_array_item_or_array_close(wip)?
131 }
132 }
133 }
134}
135
136struct StackRunner<'a> {
138 stack: Vec<Instruction>,
140 tokenizer: Tokenizer<'a>,
141 last_span: Span,
142 unread_token: Option<Spanned<Token>>,
143 input: &'a [u8],
144}
145
146impl<'a> StackRunner<'a> {
147 fn pop<'f>(&mut self, mut wip: Wip<'f>, reason: PopReason) -> Result<Wip<'f>, JsonError<'a>> {
148 trace!("Popping because {:?}", reason.yellow());
149
150 let container_shape = wip.shape();
151 match container_shape.def {
152 Def::Struct(sd) => {
153 let mut has_unset = false;
154
155 trace!("Let's check all fields are initialized");
156 for (index, field) in sd.fields.iter().enumerate() {
157 let is_set = wip.is_field_set(index).map_err(|err| {
158 trace!("Error checking field set status: {:?}", err);
159 JsonError::new_reflect(err, self.input, self.last_span)
160 })?;
161 if !is_set {
162 if field.flags.contains(FieldFlags::DEFAULT) {
163 wip = wip.field(index).map_err(|e| {
164 JsonError::new_reflect(e, self.input, self.last_span)
165 })?;
166 if let Some(default_in_place_fn) = field.vtable.default_fn {
167 wip = wip.put_from_fn(default_in_place_fn).map_err(|e| {
168 JsonError::new_reflect(e, self.input, self.last_span)
169 })?;
170 trace!(
171 "Field #{} {:?} was set to default value (via custom fn)",
172 index.yellow(),
173 field.blue()
174 );
175 } else {
176 if !field.shape().is(Characteristic::Default) {
177 return Err(JsonError::new_reflect(
178 ReflectError::DefaultAttrButNoDefaultImpl {
179 shape: field.shape(),
180 },
181 self.input,
182 self.last_span,
183 ));
184 }
185 wip = wip.put_default().map_err(|e| {
186 JsonError::new_reflect(e, self.input, self.last_span)
187 })?;
188 trace!(
189 "Field #{} {:?} was set to default value (via default impl)",
190 index.yellow(),
191 field.blue()
192 );
193 }
194 wip = wip.pop().map_err(|e| {
195 JsonError::new_reflect(e, self.input, self.last_span)
196 })?;
197 } else {
198 trace!(
199 "Field #{} {:?} is not initialized",
200 index.yellow(),
201 field.blue()
202 );
203 has_unset = true;
204 }
205 }
206 }
207
208 if has_unset && container_shape.has_default_attr() {
209 let default_val = Wip::alloc_shape(container_shape)
211 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?
212 .put_default()
213 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?
214 .build()
215 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
216 let peek = default_val.peek().into_struct().unwrap();
217
218 for (index, field) in sd.fields.iter().enumerate() {
219 let is_set = wip.is_field_set(index).map_err(|err| {
220 trace!("Error checking field set status: {:?}", err);
221 JsonError::new_reflect(err, self.input, self.last_span)
222 })?;
223 if !is_set {
224 let address_of_field_from_default = peek.field(index).unwrap().data();
225 wip = wip.field(index).map_err(|e| {
226 JsonError::new_reflect(e, self.input, self.last_span)
227 })?;
228 wip = wip
229 .put_shape(address_of_field_from_default, field.shape())
230 .map_err(|e| {
231 JsonError::new_reflect(e, self.input, self.last_span)
232 })?;
233 wip = wip.pop().map_err(|e| {
234 JsonError::new_reflect(e, self.input, self.last_span)
235 })?;
236 }
237 }
238 }
239 }
240 Def::Enum(_) => {
241 trace!(
242 "TODO: make sure enums are initialized (support container-level and field-level default, etc.)"
243 );
244 }
245 _ => {
246 trace!("Thing being popped is not a container I guess");
247 }
248 }
249 Ok(wip)
250 }
251
252 fn skip_value(&mut self, wip: &Wip<'_>) -> Result<(), JsonError<'a>> {
253 let token = self.read_token(wip)?;
254 match token.node {
255 Token::LBrace | Token::LBracket => {
256 let mut depth = 1;
258 while depth > 0 {
259 let token = self.read_token(wip)?;
260 match token.node {
261 Token::LBrace | Token::LBracket => {
262 depth += 1;
263 }
264 Token::RBrace | Token::RBracket => {
265 depth -= 1;
266 }
267 _ => {
268 }
270 }
271 }
272 Ok(())
273 }
274 Token::String(_)
275 | Token::F64(_)
276 | Token::I64(_)
277 | Token::U64(_)
278 | Token::True
279 | Token::False
280 | Token::Null => {
281 Ok(())
283 }
284 other => {
285 Err(JsonError::new(
287 JsonErrorKind::UnexpectedToken {
288 got: other,
289 wanted: "value",
290 },
291 self.input,
292 self.last_span,
293 ))
294 }
295 }
296 }
297
298 fn value<'facet>(&mut self, mut wip: Wip<'facet>) -> Result<Wip<'facet>, JsonError<'a>> {
299 let token = self.read_token(&wip)?;
300 match token.node {
301 Token::Null => wip
302 .put_default()
303 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span)),
304 _ => {
305 if matches!(wip.shape().def, Def::Option(_)) {
306 trace!("Starting Some(_) option for {}", wip.shape().blue());
307 wip = wip
308 .push_some()
309 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
310 self.stack.push(Instruction::Pop(PopReason::Some))
311 }
312
313 match token.node {
314 Token::Null => unreachable!(),
315 Token::LBrace => {
316 match wip.innermost_shape().def {
317 Def::Map(_md) => {
318 trace!("Object starting for map value ({})!", wip.shape().blue());
319 wip = wip.put_default().map_err(|e| {
320 JsonError::new_reflect(e, self.input, self.last_span)
321 })?;
322 }
323 Def::Enum(_ed) => {
324 trace!("Object starting for enum value ({})!", wip.shape().blue());
325 }
327 Def::Struct(_) => {
328 trace!(
329 "Object starting for struct value ({})!",
330 wip.shape().blue()
331 );
332 }
334 _ => {
335 return Err(JsonError::new(
336 JsonErrorKind::UnsupportedType {
337 got: wip.innermost_shape(),
338 wanted: "map, enum, or struct",
339 },
340 self.input,
341 self.last_span,
342 ));
343 }
344 }
345
346 self.stack.push(Instruction::ObjectKeyOrObjectClose);
347 Ok(wip)
348 }
349 Token::LBracket => {
350 match wip.innermost_shape().def {
351 Def::Array(_) => {
352 trace!("Array starting for array ({})!", wip.shape().blue());
353 }
354 Def::Slice(_) => {
355 trace!("Array starting for slice ({})!", wip.shape().blue());
356 }
357 Def::List(_) => {
358 trace!("Array starting for list ({})!", wip.shape().blue());
359 wip = wip.put_default().map_err(|e| {
360 JsonError::new_reflect(e, self.input, self.last_span)
361 })?;
362 }
363 Def::Enum(_) => {
364 trace!("Array starting for enum ({})!", wip.shape().blue());
365 }
366 Def::Struct(s) => {
367 if s.kind == StructKind::Tuple {
368 trace!("Array starting for tuple ({})!", wip.shape().blue());
369 wip = wip.put_default().map_err(|e| {
370 JsonError::new_reflect(e, self.input, self.last_span)
371 })?;
372 } else {
373 return Err(JsonError::new(
374 JsonErrorKind::UnsupportedType {
375 got: wip.shape(),
376 wanted: "array, list, tuple, or slice",
377 },
378 self.input,
379 self.last_span,
380 ));
381 }
382 }
383 Def::Scalar(s) if matches!(s.affinity, ScalarAffinity::Empty(_)) => {
384 trace!("Array starting for unit type ({})!", wip.shape().blue());
385
386 let next_token = self.read_token(&wip)?;
388 if next_token.node == Token::RBracket {
389 wip = wip.put_default().map_err(|e| {
391 JsonError::new_reflect(e, self.input, self.last_span)
392 })?;
393 return Ok(wip); } else {
395 return Err(JsonError::new(
397 JsonErrorKind::UnsupportedType {
398 got: wip.innermost_shape(),
399 wanted: "empty array",
400 },
401 self.input,
402 self.last_span,
403 ));
404 }
405 }
406 _ => {
407 return Err(JsonError::new(
408 JsonErrorKind::UnsupportedType {
409 got: wip.innermost_shape(),
410 wanted: "array, list, tuple, or slice",
411 },
412 self.input,
413 self.last_span,
414 ));
415 }
416 }
417
418 trace!("Beginning pushback");
419 self.stack.push(Instruction::ArrayItemOrArrayClose);
420 wip.begin_pushback()
421 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))
422 }
423 Token::RBrace | Token::RBracket | Token::Colon | Token::Comma => {
424 Err(JsonError::new(
425 JsonErrorKind::UnexpectedToken {
426 got: token.node,
427 wanted: "value",
428 },
429 self.input,
430 self.last_span,
431 ))
432 }
433 Token::String(s) => match wip.innermost_shape().def {
434 Def::Scalar(_sd) => wip
435 .put::<String>(s)
436 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span)),
437 Def::Enum(_ed) => {
438 if wip.selected_variant().is_some() {
439 trace!("Have variant selected arleady, just putting");
440
441 wip.put::<String>(s).map_err(|e| {
443 JsonError::new_reflect(e, self.input, self.last_span)
444 })
445 } else {
446 match wip.find_variant(&s) {
447 Some((variant_index, _)) => {
448 wip.variant(variant_index).map_err(|e| {
449 JsonError::new_reflect(e, self.input, self.last_span)
450 })
451 }
452 None => Err(JsonError::new(
453 JsonErrorKind::NoSuchVariant {
454 name: s.to_string(),
455 enum_shape: wip.shape(),
456 },
457 self.input,
458 self.last_span,
459 )),
460 }
461 }
462 }
463 _ => Err(JsonError::new(
464 JsonErrorKind::UnsupportedType {
465 got: wip.innermost_shape(),
466 wanted: "enum or string",
467 },
468 self.input,
469 self.last_span,
470 )),
471 },
472 Token::F64(n) => {
473 if wip.innermost_shape() == <f32 as Facet>::SHAPE {
474 wip.put(n as f32)
475 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))
476 } else {
477 wip.put(n)
478 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))
479 }
480 }
481 Token::U64(n) => wip
482 .put(n)
483 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span)),
484 Token::I64(n) => wip
485 .put(n)
486 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span)),
487 Token::True => wip
488 .put::<bool>(true)
489 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span)),
490 Token::False => wip
491 .put::<bool>(false)
492 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span)),
493 Token::EOF => Err(JsonError::new(
494 JsonErrorKind::UnexpectedEof("in value"),
495 self.input,
496 self.last_span,
497 )),
498 }
499 }
500 }
501 }
502
503 fn object_key_or_object_close<'f>(
504 &mut self,
505 mut wip: Wip<'f>,
506 ) -> Result<Wip<'f>, JsonError<'a>> {
507 let token = self.read_token(&wip)?;
508 match token.node {
509 Token::String(key) => {
510 trace!("Parsed object key: {}", key);
511
512 let mut ignore = false;
513 let mut needs_pop = true;
514 let mut handled_by_flatten = false;
515
516 match wip.shape().def {
517 Def::Struct(sd) => {
518 if let Some(index) = wip.field_index(&key) {
520 trace!("It's a struct field");
521 wip = wip.field(index).map_err(|e| {
522 JsonError::new_reflect(e, self.input, self.last_span)
523 })?;
524 } else {
525 let mut found_in_flatten = false;
527 for (index, field) in sd.fields.iter().enumerate() {
528 if field.flags.contains(FieldFlags::FLATTEN) {
529 trace!("Found flattened field #{}", index);
530 wip = wip.field(index).map_err(|e| {
532 JsonError::new_reflect(e, self.input, self.last_span)
533 })?;
534
535 if let Some(subfield_index) = wip.field_index(&key) {
537 trace!("Found key {} in flattened field", key);
538 wip = wip.field(subfield_index).map_err(|e| {
539 JsonError::new_reflect(e, self.input, self.last_span)
540 })?;
541 found_in_flatten = true;
542 handled_by_flatten = true;
543 break;
544 } else if let Some((_variant_index, _variant)) =
545 wip.find_variant(&key)
546 {
547 trace!("Found key {} in flattened field", key);
548 wip = wip.variant_named(&key).map_err(|e| {
549 JsonError::new_reflect(e, self.input, self.last_span)
550 })?;
551 found_in_flatten = true;
552 break;
553 } else {
554 wip = wip.pop().map_err(|e| {
556 JsonError::new_reflect(e, self.input, self.last_span)
557 })?;
558 }
559 }
560 }
561
562 if !found_in_flatten {
563 if wip.shape().has_deny_unknown_fields_attr() {
564 trace!(
565 "It's not a struct field AND we're denying unknown fields"
566 );
567 return Err(JsonError::new(
568 JsonErrorKind::UnknownField {
569 field_name: key.to_string(),
570 shape: wip.shape(),
571 },
572 self.input,
573 self.last_span,
574 ));
575 } else {
576 trace!(
577 "It's not a struct field and we're ignoring unknown fields"
578 );
579 ignore = true;
580 }
581 }
582 }
583 }
584 Def::Enum(_ed) => match wip.find_variant(&key) {
585 Some((index, variant)) => {
586 trace!("Variant {} selected", variant.name.blue());
587 wip = wip.variant(index).map_err(|e| {
588 JsonError::new_reflect(e, self.input, self.last_span)
589 })?;
590 needs_pop = false;
591 }
592 None => {
593 if let Some(_variant_index) = wip.selected_variant() {
594 trace!(
595 "Already have a variant selected, treating key as struct field of variant"
596 );
597 if let Some(index) = wip.field_index(&key) {
599 trace!("Found field {} in selected variant", key.blue());
600 wip = wip.field(index).map_err(|e| {
601 JsonError::new_reflect(e, self.input, self.last_span)
602 })?;
603 } else if wip.shape().has_deny_unknown_fields_attr() {
604 trace!("Unknown field in variant and denying unknown fields");
605 return Err(JsonError::new(
606 JsonErrorKind::UnknownField {
607 field_name: key.to_string(),
608 shape: wip.shape(),
609 },
610 self.input,
611 self.last_span,
612 ));
613 } else {
614 trace!("Ignoring unknown field in variant");
615 ignore = true;
616 }
617 } else {
618 return Err(JsonError::new(
619 JsonErrorKind::NoSuchVariant {
620 name: key.to_string(),
621 enum_shape: wip.shape(),
622 },
623 self.input,
624 self.last_span,
625 ));
626 }
627 }
628 },
629 Def::Map(_) => {
630 wip = wip
631 .push_map_key()
632 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
633 wip = wip
634 .put(key)
635 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
636 wip = wip
637 .push_map_value()
638 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
639 }
640 _ => {
641 return Err(JsonError::new(
642 JsonErrorKind::Unimplemented("object key for non-struct/map"),
643 self.input,
644 self.last_span,
645 ));
646 }
647 }
648
649 let colon = self.read_token(&wip)?;
650 if colon.node != Token::Colon {
651 return Err(JsonError::new(
652 JsonErrorKind::UnexpectedToken {
653 got: colon.node,
654 wanted: "colon",
655 },
656 self.input,
657 self.last_span,
658 ));
659 }
660 self.stack
661 .push(Instruction::CommaThenObjectKeyOrObjectClose);
662 if ignore {
663 self.stack.push(Instruction::SkipValue);
664 } else {
665 if needs_pop && !handled_by_flatten {
666 trace!("Pushing Pop insn to stack (ObjectVal)");
667 self.stack.push(Instruction::Pop(PopReason::ObjectVal));
668 } else if handled_by_flatten {
669 trace!("Pushing Pop insn to stack (ObjectVal) for flattened field");
672 self.stack.push(Instruction::Pop(PopReason::ObjectVal));
673 self.stack.push(Instruction::Pop(PopReason::ObjectVal));
674 }
675 self.stack.push(Instruction::Value);
676 }
677 Ok(wip)
678 }
679 Token::RBrace => {
680 trace!("Object closing");
681 Ok(wip)
682 }
683 _ => Err(JsonError::new(
684 JsonErrorKind::UnexpectedToken {
685 got: token.node,
686 wanted: "object key or closing brace",
687 },
688 self.input,
689 self.last_span,
690 )),
691 }
692 }
693
694 fn comma_then_object_key_or_object_close(
695 &mut self,
696 wip: &Wip<'_>,
697 ) -> Result<(), JsonError<'a>> {
698 let token = self.read_token(wip)?;
699 match token.node {
700 Token::Comma => {
701 trace!("Object comma");
702 self.stack.push(Instruction::ObjectKeyOrObjectClose);
703 Ok(())
704 }
705 Token::RBrace => {
706 trace!("Object close");
707 Ok(())
708 }
709 _ => Err(JsonError::new(
710 JsonErrorKind::UnexpectedToken {
711 got: token.node,
712 wanted: "comma",
713 },
714 self.input,
715 self.last_span,
716 )),
717 }
718 }
719
720 fn array_item_or_array_close<'facet>(
721 &mut self,
722 mut wip: Wip<'facet>,
723 ) -> Result<Wip<'facet>, JsonError<'a>> {
724 let token = self.read_token(&wip)?;
725 match token.node {
726 Token::RBracket => {
727 trace!("Array close");
728 Ok(wip)
729 }
730 _ => {
731 trace!("Array item");
732 assert!(
733 self.unread_token.is_none(),
734 "Cannot put back more than one token at a time"
735 );
736 self.unread_token = Some(token);
737 wip = wip
738 .begin_pushback()
739 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
740 wip = wip
741 .push()
742 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
743
744 self.stack.push(Instruction::CommaThenArrayItemOrArrayClose);
745 trace!("Pushing Pop insn to stack (arrayitem)");
746 self.stack.push(Instruction::Pop(PopReason::ArrayItem));
747 self.stack.push(Instruction::Value);
748 Ok(wip)
749 }
750 }
751 }
752
753 fn comma_then_array_item_or_array_close<'facet>(
754 &mut self,
755 mut wip: Wip<'facet>,
756 ) -> Result<Wip<'facet>, JsonError<'a>> {
757 let token = self.read_token(&wip)?;
758 match token.node {
759 Token::RBracket => {
760 trace!("Array close");
761 Ok(wip)
762 }
763 Token::Comma => {
764 trace!("Array comma");
765 wip = wip
766 .push()
767 .map_err(|e| JsonError::new_reflect(e, self.input, self.last_span))?;
768 self.stack.push(Instruction::CommaThenArrayItemOrArrayClose);
769 trace!("Pushing Pop insn to stack (arrayitem)");
770 self.stack.push(Instruction::Pop(PopReason::ArrayItem));
771 self.stack.push(Instruction::Value);
772 Ok(wip)
773 }
774 _ => Err(JsonError::new(
775 JsonErrorKind::UnexpectedToken {
776 got: token.node,
777 wanted: "comma or closing bracket",
778 },
779 self.input,
780 self.last_span,
781 )),
782 }
783 }
784
785 fn read_token(&mut self, _wip: &Wip<'_>) -> Result<Spanned<Token>, JsonError<'a>> {
786 if let Some(token) = self.unread_token.take() {
787 self.last_span = token.span;
788 Ok(token)
789 } else {
790 match self.tokenizer.next_token() {
791 Ok(token) => {
792 self.last_span = token.span;
793 Ok(token)
794 }
795 Err(e) => {
796 self.last_span = e.span;
797 Err(JsonError::new_syntax(e.kind, self.input, self.last_span))
798 }
799 }
800 }
801 }
802}