facet_deserialize/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![warn(missing_docs)]
3#![warn(clippy::std_instead_of_core)]
4#![warn(clippy::std_instead_of_alloc)]
5#![deny(unsafe_code)]
6#![doc = include_str!("../README.md")]
7
8extern crate alloc;
9
10use alloc::string::ToString;
11use alloc::{vec, vec::Vec};
12
13mod error;
14use alloc::borrow::Cow;
15
16pub use error::*;
17
18mod span;
19use facet_core::{Characteristic, Def, Facet, FieldFlags, ScalarAffinity};
20use owo_colors::OwoColorize;
21pub use span::*;
22
23use facet_reflect::{HeapValue, ReflectError, Wip};
24use log::trace;
25
26#[derive(PartialEq, Debug, Clone)]
27/// A scalar value used during deserialization.
28/// `u64` and `i64` are separated because `i64` doesn't fit in `u64`,
29/// but having `u64` is a fast path for 64-bit architectures — no need to
30/// go through `u128` / `i128` for everything
31pub enum Scalar<'input> {
32    /// Owned or borrowed string data.
33    String(Cow<'input, str>),
34    /// Unsigned 64-bit integer scalar.
35    U64(u64),
36    /// Signed 64-bit integer scalar.
37    I64(i64),
38    /// 64-bit floating-point scalar.
39    F64(f64),
40    /// Boolean scalar.
41    Bool(bool),
42    /// Null scalar (e.g. for formats supporting explicit null).
43    Null,
44}
45
46#[derive(PartialEq, Debug, Clone)]
47/// Expected next input token or structure during deserialization.
48pub enum Expectation {
49    /// Accept a value.
50    Value,
51    /// Expect an object key or the end of an object.
52    ObjectKeyOrObjectClose,
53    /// Expect a value inside an object.
54    ObjectVal,
55    /// Expect a list item or the end of a list.
56    ListItemOrListClose,
57}
58
59#[derive(PartialEq, Debug, Clone)]
60/// Outcome of parsing the next input element.
61pub enum Outcome<'input> {
62    /// Parsed a scalar value.
63    Scalar(Scalar<'input>),
64    /// Starting a list/array.
65    ListStarted,
66    /// Ending a list/array.
67    ListEnded,
68    /// Starting an object/map.
69    ObjectStarted,
70    /// Ending an object/map.
71    ObjectEnded,
72}
73
74impl<'input> From<Scalar<'input>> for Outcome<'input> {
75    fn from(scalar: Scalar<'input>) -> Self {
76        Outcome::Scalar(scalar)
77    }
78}
79
80use core::fmt;
81
82/// Display implementation for `Outcome`, focusing on user-friendly descriptions.
83impl fmt::Display for Outcome<'_> {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        match self {
86            Outcome::Scalar(scalar) => write!(f, "scalar {}", scalar),
87            Outcome::ListStarted => write!(f, "list start"),
88            Outcome::ListEnded => write!(f, "list end"),
89            Outcome::ObjectStarted => write!(f, "object start"),
90            Outcome::ObjectEnded => write!(f, "object end"),
91        }
92    }
93}
94
95/// Display implementation for `Scalar`, for use in displaying `Outcome`.
96impl fmt::Display for Scalar<'_> {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        match self {
99            Scalar::String(s) => write!(f, "string \"{}\"", s),
100            Scalar::U64(val) => write!(f, "u64 {}", val),
101            Scalar::I64(val) => write!(f, "i64 {}", val),
102            Scalar::F64(val) => write!(f, "f64 {}", val),
103            Scalar::Bool(val) => write!(f, "bool {}", val),
104            Scalar::Null => write!(f, "null"),
105        }
106    }
107}
108
109impl Outcome<'_> {
110    fn into_owned(self) -> Outcome<'static> {
111        match self {
112            Outcome::Scalar(scalar) => {
113                let owned_scalar = match scalar {
114                    Scalar::String(cow) => Scalar::String(Cow::Owned(cow.into_owned())),
115                    Scalar::U64(val) => Scalar::U64(val),
116                    Scalar::I64(val) => Scalar::I64(val),
117                    Scalar::F64(val) => Scalar::F64(val),
118                    Scalar::Bool(val) => Scalar::Bool(val),
119                    Scalar::Null => Scalar::Null,
120                };
121                Outcome::Scalar(owned_scalar)
122            }
123            Outcome::ListStarted => Outcome::ListStarted,
124            Outcome::ListEnded => Outcome::ListEnded,
125            Outcome::ObjectStarted => Outcome::ObjectStarted,
126            Outcome::ObjectEnded => Outcome::ObjectEnded,
127        }
128    }
129}
130
131/// Carries the current parsing state and the in-progress value during deserialization.
132/// This bundles the mutable context that must be threaded through parsing steps.
133pub struct NextData<'input: 'facet, 'facet> {
134    /// The offset we're supposed to start parsing from
135    start: usize,
136
137    /// Controls the parsing flow and stack state.
138    runner: StackRunner<'input>,
139
140    /// Holds the intermediate representation of the value being built.
141    pub wip: Wip<'facet>,
142}
143
144impl<'input: 'facet, 'facet> NextData<'input, 'facet> {
145    /// Returns the input (from the start! not from the current position)
146    pub fn input(&self) -> &'input [u8] {
147        self.runner.input
148    }
149
150    /// Returns the parsing start offset.
151    pub fn start(&self) -> usize {
152        self.start
153    }
154}
155
156/// The result of advancing the parser: updated state and parse outcome or error.
157pub type NextResult<'input, 'facet, T, E> = (NextData<'input, 'facet>, Result<T, E>);
158
159/// Trait defining a deserialization format.
160/// Provides the next parsing step based on current state and expected input.
161pub trait Format {
162    /// Advance the parser with current state and expectation, producing the next outcome or error.
163    fn next<'input, 'facet>(
164        nd: NextData<'input, 'facet>,
165        expectation: Expectation,
166    ) -> NextResult<'input, 'facet, Spanned<Outcome<'input>>, Spanned<DeserErrorKind>>;
167
168    /// Skip the next value; used to ignore an input.
169    fn skip<'input, 'facet>(
170        nd: NextData<'input, 'facet>,
171    ) -> NextResult<'input, 'facet, Span, Spanned<DeserErrorKind>>;
172}
173
174/// Instructions guiding the parsing flow, indicating the next expected action or token.
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176pub enum Instruction {
177    /// Expect a value, specifying the context or reason.
178    Value(ValueReason),
179    /// Skip the next value; used to ignore an input.
180    SkipValue,
181    /// Indicate completion of a structure or value; triggers popping from stack.
182    Pop(PopReason),
183    /// Expect an object key or the end of an object.
184    ObjectKeyOrObjectClose,
185    /// Expect a list item or the end of a list.
186    ListItemOrListClose,
187}
188
189/// Reasons for expecting a value, reflecting the current parse context.
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
191pub enum ValueReason {
192    /// Parsing at the root level.
193    TopLevel,
194    /// Parsing a value inside an object.
195    ObjectVal,
196}
197
198/// Reasons for popping a state from the stack, indicating why a scope is ended.
199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
200pub enum PopReason {
201    /// Ending the top-level parsing scope.
202    TopLevel,
203    /// Ending a value within an object.
204    ObjectVal,
205    /// Ending value within a list
206    ListVal,
207    /// Ending a `Some()` in an option
208    Some,
209}
210
211/// Deserialize a value of type `T` from raw input bytes using format `F`.
212///
213/// This function sets up the initial working state and drives the deserialization process,
214/// ensuring that the resulting value is fully materialized and valid.
215pub fn deserialize<'input, 'facet, T, F>(input: &'input [u8]) -> Result<T, DeserError<'input>>
216where
217    T: Facet<'facet>,
218    F: Format,
219    'input: 'facet,
220{
221    let wip = Wip::alloc_shape(T::SHAPE).map_err(|e| DeserError {
222        input: input.into(),
223        span: Span { start: 0, len: 0 },
224        kind: DeserErrorKind::ReflectError(e),
225    })?;
226    deserialize_wip::<F>(wip, input)?
227        .materialize()
228        .map_err(|e| DeserError::new_reflect(e, input, Span { start: 0, len: 0 }))
229}
230
231/// Deserializes a working-in-progress value into a fully materialized heap value.
232/// This function drives the parsing loop until the entire input is consumed and the value is complete.
233pub fn deserialize_wip<'input, 'facet, F>(
234    mut wip: Wip<'facet>,
235    input: &'input [u8],
236) -> Result<HeapValue<'facet>, DeserError<'input>>
237where
238    F: Format,
239    'input: 'facet,
240{
241    // This struct is just a bundle of the state that we need to pass around all the time.
242    let mut runner = StackRunner {
243        original_input: input,
244        input,
245        stack: vec![
246            Instruction::Pop(PopReason::TopLevel),
247            Instruction::Value(ValueReason::TopLevel),
248        ],
249        last_span: Span::new(0, 0),
250    };
251
252    macro_rules! next {
253        ($runner:ident, $wip:ident, $expectation:expr, $method:ident) => {{
254            let nd = NextData {
255                start: $runner.last_span.end(), // or supply the appropriate start value if available
256                runner: $runner,
257                wip: $wip,
258            };
259            let (nd, res) = F::next(nd, $expectation);
260            $runner = nd.runner;
261            $wip = nd.wip;
262            let outcome = res.map_err(|span_kind| {
263                $runner.last_span = span_kind.span;
264                $runner.err(span_kind.node)
265            })?;
266            $runner.last_span = outcome.span;
267            trace!("Got outcome {}", outcome.blue());
268            $wip = $runner.$method($wip, outcome)?;
269        }};
270    }
271
272    loop {
273        let frame_count = wip.frames_count();
274        debug_assert!(
275            frame_count
276                >= runner
277                    .stack
278                    .iter()
279                    .filter(|f| matches!(f, Instruction::Pop(_)))
280                    .count()
281        );
282
283        let insn = match runner.stack.pop() {
284            Some(insn) => insn,
285            None => unreachable!("Instruction stack is empty"),
286        };
287
288        trace!("[{frame_count}] Instruction {:?}", insn.yellow());
289
290        match insn {
291            Instruction::Pop(reason) => {
292                wip = runner.pop(wip, reason)?;
293
294                if reason == PopReason::TopLevel {
295                    return wip.build().map_err(|e| runner.reflect_err(e));
296                } else {
297                    wip = wip.pop().map_err(|e| runner.reflect_err(e))?;
298                }
299            }
300            Instruction::Value(_why) => {
301                let expectation = match _why {
302                    ValueReason::TopLevel => Expectation::Value,
303                    ValueReason::ObjectVal => Expectation::ObjectVal,
304                };
305                next!(runner, wip, expectation, value);
306            }
307            Instruction::ObjectKeyOrObjectClose => {
308                next!(
309                    runner,
310                    wip,
311                    Expectation::ObjectKeyOrObjectClose,
312                    object_key_or_object_close
313                );
314            }
315            Instruction::ListItemOrListClose => {
316                next!(
317                    runner,
318                    wip,
319                    Expectation::ListItemOrListClose,
320                    list_item_or_list_close
321                );
322            }
323            Instruction::SkipValue => {
324                // Call F::skip to skip over the next value in the input
325                let nd = NextData {
326                    start: runner.last_span.end(),
327                    runner,
328                    wip,
329                };
330                let (nd, res) = F::skip(nd);
331                runner = nd.runner;
332                wip = nd.wip;
333                // Only propagate error, don't modify wip, since skip just advances input
334                let span = res.map_err(|span_kind| {
335                    runner.last_span = span_kind.span;
336                    runner.err(span_kind.node)
337                })?;
338                // do the actual skip
339                runner.last_span = span;
340            }
341        }
342    }
343}
344
345#[doc(hidden)]
346/// Maintains the parsing state and context necessary to drive deserialization.
347///
348/// This struct tracks what the parser expects next, manages input position,
349/// and remembers the span of the last processed token to provide accurate error reporting.
350pub struct StackRunner<'input> {
351    /// A version of the input that doesn't advance as we parse.
352    original_input: &'input [u8],
353    /// The raw input data being deserialized.
354    pub input: &'input [u8],
355
356    /// Stack of parsing instructions guiding the control flow.
357    pub stack: Vec<Instruction>,
358    /// Span of the last processed token, for accurate error reporting.
359    pub last_span: Span,
360}
361
362impl<'input> StackRunner<'input> {
363    /// Convenience function to create a DeserError using the original input and last_span.
364    fn err(&self, kind: DeserErrorKind) -> DeserError<'input> {
365        DeserError::new(kind, self.original_input, self.last_span)
366    }
367
368    /// Convenience function to create a DeserError from a ReflectError,
369    /// using the original input and last_span for context.
370    fn reflect_err(&self, err: ReflectError) -> DeserError<'input> {
371        DeserError::new_reflect(err, self.original_input, self.last_span)
372    }
373
374    fn pop<'facet>(
375        &mut self,
376        mut wip: Wip<'facet>,
377        reason: PopReason,
378    ) -> Result<Wip<'facet>, DeserError<'input>> {
379        trace!("Popping because {:?}", reason.yellow());
380
381        let container_shape = wip.shape();
382        match container_shape.def {
383            Def::Struct(sd) => {
384                let mut has_unset = false;
385
386                trace!("Let's check all fields are initialized");
387                for (index, field) in sd.fields.iter().enumerate() {
388                    let is_set = wip.is_field_set(index).map_err(|err| {
389                        trace!("Error checking field set status: {:?}", err);
390                        self.reflect_err(err)
391                    })?;
392                    if !is_set {
393                        if field.flags.contains(FieldFlags::DEFAULT) {
394                            wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
395                            if let Some(default_in_place_fn) = field.vtable.default_fn {
396                                wip = wip
397                                    .put_from_fn(default_in_place_fn)
398                                    .map_err(|e| self.reflect_err(e))?;
399                                trace!(
400                                    "Field #{} {:?} was set to default value (via custom fn)",
401                                    index.yellow(),
402                                    field.blue()
403                                );
404                            } else {
405                                if !field.shape().is(Characteristic::Default) {
406                                    return Err(self.reflect_err(
407                                        ReflectError::DefaultAttrButNoDefaultImpl {
408                                            shape: field.shape(),
409                                        },
410                                    ));
411                                }
412                                wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
413                                trace!(
414                                    "Field #{} {:?} was set to default value (via default impl)",
415                                    index.yellow(),
416                                    field.blue()
417                                );
418                            }
419                            wip = wip.pop().map_err(|e| self.reflect_err(e))?;
420                        } else {
421                            trace!(
422                                "Field #{} {:?} is not initialized",
423                                index.yellow(),
424                                field.blue()
425                            );
426                            has_unset = true;
427                        }
428                    }
429                }
430
431                if has_unset && container_shape.has_default_attr() {
432                    // let's allocate and build a default value
433                    let default_val = Wip::alloc_shape(container_shape)
434                        .map_err(|e| self.reflect_err(e))?
435                        .put_default()
436                        .map_err(|e| self.reflect_err(e))?
437                        .build()
438                        .map_err(|e| self.reflect_err(e))?;
439                    let peek = default_val.peek().into_struct().unwrap();
440
441                    for (index, field) in sd.fields.iter().enumerate() {
442                        let is_set = wip.is_field_set(index).map_err(|err| {
443                            trace!("Error checking field set status: {:?}", err);
444                            self.reflect_err(err)
445                        })?;
446                        if !is_set {
447                            let address_of_field_from_default = peek.field(index).unwrap().data();
448                            wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
449                            wip = wip
450                                .put_shape(address_of_field_from_default, field.shape())
451                                .map_err(|e| self.reflect_err(e))?;
452                            wip = wip.pop().map_err(|e| self.reflect_err(e))?;
453                        }
454                    }
455                }
456            }
457            Def::Enum(_) => {
458                trace!(
459                    "TODO: make sure enums are initialized (support container-level and field-level default, etc.)"
460                );
461            }
462            _ => {
463                trace!(
464                    "Thing being popped is not a container I guess (it's a {})",
465                    wip.shape()
466                );
467            }
468        }
469        Ok(wip)
470    }
471
472    /// Internal common handler for GotScalar outcome, to deduplicate code.
473    fn handle_scalar<'facet>(
474        &self,
475        wip: Wip<'facet>,
476        scalar: Scalar<'input>,
477    ) -> Result<Wip<'facet>, DeserError<'input>> {
478        match scalar {
479            Scalar::String(cow) => {
480                match wip.innermost_shape().def {
481                    Def::Enum(_) => {
482                        if wip.selected_variant().is_some() {
483                            // If we already have a variant selected, just put the string
484                            wip.put(cow.to_string()).map_err(|e| self.reflect_err(e))
485                        } else {
486                            // Try to select the variant
487                            match wip.find_variant(&cow) {
488                                Some((variant_index, _)) => {
489                                    wip.variant(variant_index).map_err(|e| self.reflect_err(e))
490                                }
491                                None => Err(self.err(DeserErrorKind::NoSuchVariant {
492                                    name: cow.to_string(),
493                                    enum_shape: wip.innermost_shape(),
494                                })),
495                            }
496                        }
497                    }
498                    _ => wip.put(cow.to_string()).map_err(|e| self.reflect_err(e)),
499                }
500            }
501            Scalar::U64(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
502            Scalar::I64(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
503            Scalar::F64(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
504            Scalar::Bool(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
505            Scalar::Null => wip.put_default().map_err(|e| self.reflect_err(e)),
506        }
507    }
508
509    /// Handle value parsing
510    fn value<'facet>(
511        &mut self,
512        mut wip: Wip<'facet>,
513        outcome: Spanned<Outcome<'input>>,
514    ) -> Result<Wip<'facet>, DeserError<'input>> {
515        trace!(
516            "Handling value at wip shape {} (wip innermost shape {})",
517            wip.shape().blue(),
518            wip.innermost_shape().yellow()
519        );
520
521        match outcome.node {
522            Outcome::Scalar(Scalar::Null) => {
523                return wip.put_default().map_err(|e| self.reflect_err(e));
524            }
525            _ => {
526                if matches!(wip.shape().def, Def::Option(_)) {
527                    trace!("Starting Some(_) option for {}", wip.shape().blue());
528                    wip = wip.push_some().map_err(|e| self.reflect_err(e))?;
529                    self.stack.push(Instruction::Pop(PopReason::Some));
530                }
531            }
532        }
533
534        match outcome.node {
535            Outcome::Scalar(s) => {
536                wip = self.handle_scalar(wip, s)?;
537            }
538            Outcome::ListStarted => {
539                let shape = wip.innermost_shape();
540                match shape.def {
541                    Def::Array(_) => {
542                        trace!("Array starting for array ({})!", shape.blue());
543                    }
544                    Def::Slice(_) => {
545                        trace!("Array starting for slice ({})!", shape.blue());
546                    }
547                    Def::List(_) => {
548                        trace!("Array starting for list ({})!", shape.blue());
549                        wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
550                    }
551                    Def::Enum(_) => {
552                        trace!("Array starting for enum ({})!", shape.blue());
553                    }
554                    Def::Struct(_) => {
555                        trace!("Array starting for tuple ({})!", shape.blue());
556                        wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
557                    }
558                    Def::Scalar(sd) => {
559                        if matches!(sd.affinity, ScalarAffinity::Empty(_)) {
560                            trace!("Empty tuple/scalar, nice");
561                            wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
562                        } else {
563                            return Err(self.err(DeserErrorKind::UnsupportedType {
564                                got: shape,
565                                wanted: "array, list, tuple, or slice",
566                            }));
567                        }
568                    }
569                    _ => {
570                        return Err(self.err(DeserErrorKind::UnsupportedType {
571                            got: shape,
572                            wanted: "array, list, tuple, or slice",
573                        }));
574                    }
575                }
576
577                trace!("Beginning pushback");
578                self.stack.push(Instruction::ListItemOrListClose);
579                wip = wip.begin_pushback().map_err(|e| self.reflect_err(e))?;
580            }
581            Outcome::ListEnded => {
582                trace!("List closing");
583                wip = wip.pop().map_err(|e| self.reflect_err(e))?;
584            }
585            Outcome::ObjectStarted => {
586                let shape = wip.innermost_shape();
587                match shape.def {
588                    Def::Map(_md) => {
589                        trace!("Object starting for map value ({})!", shape.blue());
590                        wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
591                    }
592                    Def::Enum(_ed) => {
593                        trace!("Object starting for enum value ({})!", shape.blue());
594                        // nothing to do here
595                    }
596                    Def::Struct(_) => {
597                        trace!("Object starting for struct value ({})!", shape.blue());
598                        // nothing to do here
599                    }
600                    _ => {
601                        return Err(self.err(DeserErrorKind::UnsupportedType {
602                            got: shape,
603                            wanted: "map, enum, or struct",
604                        }));
605                    }
606                }
607
608                self.stack.push(Instruction::ObjectKeyOrObjectClose);
609            }
610            Outcome::ObjectEnded => todo!(),
611        }
612        Ok(wip)
613    }
614
615    fn object_key_or_object_close<'facet>(
616        &mut self,
617        mut wip: Wip<'facet>,
618        outcome: Spanned<Outcome<'input>>,
619    ) -> Result<Wip<'facet>, DeserError<'input>>
620    where
621        'input: 'facet,
622    {
623        match outcome.node {
624            Outcome::Scalar(Scalar::String(key)) => {
625                trace!("Parsed object key: {}", key);
626
627                let mut ignore = false;
628                let mut needs_pop = true;
629                let mut handled_by_flatten = false;
630
631                match wip.innermost_shape().def {
632                    Def::Struct(sd) => {
633                        // First try to find a direct field match
634                        if let Some(index) = wip.field_index(&key) {
635                            trace!("It's a struct field");
636                            wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
637                        } else {
638                            // Check for flattened fields
639                            let mut found_in_flatten = false;
640                            for (index, field) in sd.fields.iter().enumerate() {
641                                if field.flags.contains(FieldFlags::FLATTEN) {
642                                    trace!("Found flattened field #{}", index);
643                                    // Enter the flattened field
644                                    wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
645
646                                    // Check if this flattened field has the requested key
647                                    if let Some(subfield_index) = wip.field_index(&key) {
648                                        trace!("Found key {} in flattened field", key);
649                                        wip = wip
650                                            .field(subfield_index)
651                                            .map_err(|e| self.reflect_err(e))?;
652                                        found_in_flatten = true;
653                                        handled_by_flatten = true;
654                                        break;
655                                    } else if let Some((_variant_index, _variant)) =
656                                        wip.find_variant(&key)
657                                    {
658                                        trace!("Found key {} in flattened field", key);
659                                        wip = wip
660                                            .variant_named(&key)
661                                            .map_err(|e| self.reflect_err(e))?;
662                                        found_in_flatten = true;
663                                        break;
664                                    } else {
665                                        // Key not in this flattened field, go back up
666                                        wip = wip.pop().map_err(|e| self.reflect_err(e))?;
667                                    }
668                                }
669                            }
670
671                            if !found_in_flatten {
672                                if wip.shape().has_deny_unknown_fields_attr() {
673                                    trace!(
674                                        "It's not a struct field AND we're denying unknown fields"
675                                    );
676                                    return Err(self.err(DeserErrorKind::UnknownField {
677                                        field_name: key.to_string(),
678                                        shape: wip.shape(),
679                                    }));
680                                } else {
681                                    trace!(
682                                        "It's not a struct field and we're ignoring unknown fields"
683                                    );
684                                    ignore = true;
685                                }
686                            }
687                        }
688                    }
689                    Def::Enum(_ed) => match wip.find_variant(&key) {
690                        Some((index, variant)) => {
691                            trace!("Variant {} selected", variant.name.blue());
692                            wip = wip.variant(index).map_err(|e| self.reflect_err(e))?;
693                            needs_pop = false;
694                        }
695                        None => {
696                            if let Some(_variant_index) = wip.selected_variant() {
697                                trace!(
698                                    "Already have a variant selected, treating key as struct field of variant"
699                                );
700                                // Try to find the field index of the key within the selected variant
701                                if let Some(index) = wip.field_index(&key) {
702                                    trace!("Found field {} in selected variant", key.blue());
703                                    wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
704                                } else if wip.shape().has_deny_unknown_fields_attr() {
705                                    trace!("Unknown field in variant and denying unknown fields");
706                                    return Err(self.err(DeserErrorKind::UnknownField {
707                                        field_name: key.to_string(),
708                                        shape: wip.shape(),
709                                    }));
710                                } else {
711                                    trace!("Ignoring unknown field in variant");
712                                    ignore = true;
713                                }
714                            } else {
715                                return Err(self.err(DeserErrorKind::NoSuchVariant {
716                                    name: key.to_string(),
717                                    enum_shape: wip.shape(),
718                                }));
719                            }
720                        }
721                    },
722                    Def::Map(_) => {
723                        wip = wip.push_map_key().map_err(|e| self.reflect_err(e))?;
724                        wip = wip.put(key.to_string()).map_err(|e| self.reflect_err(e))?;
725                        wip = wip.push_map_value().map_err(|e| self.reflect_err(e))?;
726                    }
727                    _ => {
728                        return Err(self.err(DeserErrorKind::Unimplemented(
729                            "object key for non-struct/map",
730                        )));
731                    }
732                }
733
734                self.stack.push(Instruction::ObjectKeyOrObjectClose);
735                if ignore {
736                    self.stack.push(Instruction::SkipValue);
737                } else {
738                    if needs_pop && !handled_by_flatten {
739                        trace!("Pushing Pop insn to stack (ObjectVal)");
740                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
741                    } else if handled_by_flatten {
742                        // We need two pops for flattened fields - one for the field itself,
743                        // one for the containing struct
744                        trace!("Pushing Pop insn to stack (ObjectVal) for flattened field");
745                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
746                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
747                    }
748                    self.stack.push(Instruction::Value(ValueReason::ObjectVal));
749                }
750                Ok(wip)
751            }
752            Outcome::ObjectEnded => {
753                trace!("Object closing");
754                Ok(wip)
755            }
756            _ => Err(self.err(DeserErrorKind::UnexpectedOutcome {
757                got: outcome.node.into_owned(),
758                wanted: "scalar or object close",
759            })),
760        }
761    }
762
763    fn list_item_or_list_close<'facet>(
764        &mut self,
765        mut wip: Wip<'facet>,
766        outcome: Spanned<Outcome<'input>>,
767    ) -> Result<Wip<'facet>, DeserError<'input>>
768    where
769        'input: 'facet,
770    {
771        match outcome.node {
772            Outcome::ListEnded => {
773                trace!("List close");
774                Ok(wip)
775            }
776            _ => {
777                self.stack.push(Instruction::ListItemOrListClose);
778                self.stack.push(Instruction::Pop(PopReason::ListVal));
779
780                trace!(
781                    "Expecting list item, doing a little push before doing value with outcome {}",
782                    outcome.magenta()
783                );
784                trace!("Before push, wip.shape is {}", wip.shape().blue());
785                wip = wip.push().map_err(|e| self.reflect_err(e))?;
786                trace!(" After push, wip.shape is {}", wip.shape().cyan());
787                wip = self.value(wip, outcome)?;
788                Ok(wip)
789            }
790        }
791    }
792}