facet_json/
deserialize.rs

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
14/// Deserializes a JSON string into a value of type `T` that implements `Facet`.
15///
16/// This function takes a JSON string representation and converts it into a Rust
17/// value of the specified type `T`. The type must implement the `Facet` trait
18/// to provide the necessary type information for deserialization.
19pub 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
27/// Deserialize JSON from a slice
28///
29/// # Arguments
30///
31/// * `json` - A slice of bytes representing the JSON input.
32///
33/// # Returns
34///
35/// A result containing the deserialized value of type `T` or a `JsonParseErrorWithContext`.
36pub 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/// Represents the next expected token or structure while parsing.
48#[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
67/// Deserialize a JSON string into a Wip object.
68///
69/// # Arguments
70///
71/// * `wip` - A mutable Wip object to deserialize into.
72/// * `input` - A byte slice representing the JSON input.
73///
74/// # Returns
75///
76/// A result containing the updated `Wip` or a `JsonParseErrorWithContext`.
77pub fn from_slice_wip<'input: 'facet, 'facet>(
78    mut wip: Wip<'facet>,
79    input: &'input [u8],
80) -> Result<HeapValue<'facet>, JsonError<'input>> {
81    // This struct is just a bundle of the state that we need to pass around all the time.
82    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
136/// It runs along the stack!
137struct StackRunner<'a> {
138    /// Look! A stack!
139    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's allocate and build a default value
210                    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                // Skip a compound value by tracking nesting depth
257                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                            // primitives, commas, colons, strings, numbers, etc.
269                        }
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                // Primitive value; nothing more to skip
282                Ok(())
283            }
284            other => {
285                // Unexpected token when skipping a value
286                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                                // nothing to do here
326                            }
327                            Def::Struct(_) => {
328                                trace!(
329                                    "Object starting for struct value ({})!",
330                                    wip.shape().blue()
331                                );
332                                // nothing to do here
333                            }
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                                // Check if the array is empty by peeking at the next token
387                                let next_token = self.read_token(&wip)?;
388                                if next_token.node == Token::RBracket {
389                                    // Empty array means unit type () - we're good
390                                    wip = wip.put_default().map_err(|e| {
391                                        JsonError::new_reflect(e, self.input, self.last_span)
392                                    })?;
393                                    return Ok(wip); // Return immediately - no need to push anything
394                                } else {
395                                    // Non-empty array is not valid for unit type
396                                    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                                // just put, then — if it's a tuple field it'll work
442                                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                        // First try to find a direct field match
519                        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                            // Check for flattened fields
526                            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                                    // Enter the flattened field
531                                    wip = wip.field(index).map_err(|e| {
532                                        JsonError::new_reflect(e, self.input, self.last_span)
533                                    })?;
534
535                                    // Check if this flattened field has the requested key
536                                    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                                        // Key not in this flattened field, go back up
555                                        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                                // Try to find the field index of the key within the selected variant
598                                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                        // We need two pops for flattened fields - one for the field itself,
670                        // one for the containing struct
671                        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}