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        &mut self,
165        nd: NextData<'input, 'facet>,
166        expectation: Expectation,
167    ) -> NextResult<'input, 'facet, Spanned<Outcome<'input>>, Spanned<DeserErrorKind>>;
168
169    /// Skip the next value; used to ignore an input.
170    fn skip<'input, 'facet>(
171        &mut self,
172        nd: NextData<'input, 'facet>,
173    ) -> NextResult<'input, 'facet, Span, Spanned<DeserErrorKind>>;
174}
175
176/// Instructions guiding the parsing flow, indicating the next expected action or token.
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178pub enum Instruction {
179    /// Expect a value, specifying the context or reason.
180    Value(ValueReason),
181    /// Skip the next value; used to ignore an input.
182    SkipValue,
183    /// Indicate completion of a structure or value; triggers popping from stack.
184    Pop(PopReason),
185    /// Expect an object key or the end of an object.
186    ObjectKeyOrObjectClose,
187    /// Expect a list item or the end of a list.
188    ListItemOrListClose,
189}
190
191/// Reasons for expecting a value, reflecting the current parse context.
192#[derive(Debug, Clone, Copy, PartialEq, Eq)]
193pub enum ValueReason {
194    /// Parsing at the root level.
195    TopLevel,
196    /// Parsing a value inside an object.
197    ObjectVal,
198}
199
200/// Reasons for popping a state from the stack, indicating why a scope is ended.
201#[derive(Debug, Clone, Copy, PartialEq, Eq)]
202pub enum PopReason {
203    /// Ending the top-level parsing scope.
204    TopLevel,
205    /// Ending a value within an object.
206    ObjectVal,
207    /// Ending value within a list
208    ListVal,
209    /// Ending a `Some()` in an option
210    Some,
211}
212
213/// Deserialize a value of type `T` from raw input bytes using format `F`.
214///
215/// This function sets up the initial working state and drives the deserialization process,
216/// ensuring that the resulting value is fully materialized and valid.
217pub fn deserialize<'input, 'facet, T, F>(
218    input: &'input [u8],
219    format: F,
220) -> Result<T, DeserError<'input>>
221where
222    T: Facet<'facet>,
223    F: Format,
224    'input: 'facet,
225{
226    let wip = Wip::alloc_shape(T::SHAPE).map_err(|e| DeserError {
227        input: input.into(),
228        span: Span { start: 0, len: 0 },
229        kind: DeserErrorKind::ReflectError(e),
230    })?;
231    deserialize_wip(wip, input, format)?
232        .materialize()
233        .map_err(|e| DeserError::new_reflect(e, input, Span { start: 0, len: 0 }))
234}
235
236/// Deserializes a working-in-progress value into a fully materialized heap value.
237/// This function drives the parsing loop until the entire input is consumed and the value is complete.
238pub fn deserialize_wip<'input, 'facet, F>(
239    mut wip: Wip<'facet>,
240    input: &'input [u8],
241    mut format: F,
242) -> Result<HeapValue<'facet>, DeserError<'input>>
243where
244    F: Format,
245    'input: 'facet,
246{
247    // This struct is just a bundle of the state that we need to pass around all the time.
248    let mut runner = StackRunner {
249        original_input: input,
250        input,
251        stack: vec![
252            Instruction::Pop(PopReason::TopLevel),
253            Instruction::Value(ValueReason::TopLevel),
254        ],
255        last_span: Span::new(0, 0),
256    };
257
258    macro_rules! next {
259        ($runner:ident, $wip:ident, $expectation:expr, $method:ident) => {{
260            let nd = NextData {
261                start: $runner.last_span.end(), // or supply the appropriate start value if available
262                runner: $runner,
263                wip: $wip,
264            };
265            let (nd, res) = format.next(nd, $expectation);
266            $runner = nd.runner;
267            $wip = nd.wip;
268            let outcome = res.map_err(|span_kind| {
269                $runner.last_span = span_kind.span;
270                $runner.err(span_kind.node)
271            })?;
272            $runner.last_span = outcome.span;
273            trace!("Got outcome {}", outcome.blue());
274            $wip = $runner.$method($wip, outcome)?;
275        }};
276    }
277
278    loop {
279        let frame_count = wip.frames_count();
280        debug_assert!(
281            frame_count
282                >= runner
283                    .stack
284                    .iter()
285                    .filter(|f| matches!(f, Instruction::Pop(_)))
286                    .count()
287        );
288
289        let insn = match runner.stack.pop() {
290            Some(insn) => insn,
291            None => unreachable!("Instruction stack is empty"),
292        };
293
294        trace!("[{frame_count}] Instruction {:?}", insn.yellow());
295
296        match insn {
297            Instruction::Pop(reason) => {
298                wip = runner.pop(wip, reason)?;
299
300                if reason == PopReason::TopLevel {
301                    return wip.build().map_err(|e| runner.reflect_err(e));
302                } else {
303                    wip = wip.pop().map_err(|e| runner.reflect_err(e))?;
304                }
305            }
306            Instruction::Value(_why) => {
307                let expectation = match _why {
308                    ValueReason::TopLevel => Expectation::Value,
309                    ValueReason::ObjectVal => Expectation::ObjectVal,
310                };
311                next!(runner, wip, expectation, value);
312            }
313            Instruction::ObjectKeyOrObjectClose => {
314                next!(
315                    runner,
316                    wip,
317                    Expectation::ObjectKeyOrObjectClose,
318                    object_key_or_object_close
319                );
320            }
321            Instruction::ListItemOrListClose => {
322                next!(
323                    runner,
324                    wip,
325                    Expectation::ListItemOrListClose,
326                    list_item_or_list_close
327                );
328            }
329            Instruction::SkipValue => {
330                // Call F::skip to skip over the next value in the input
331                let nd = NextData {
332                    start: runner.last_span.end(),
333                    runner,
334                    wip,
335                };
336                let (nd, res) = format.skip(nd);
337                runner = nd.runner;
338                wip = nd.wip;
339                // Only propagate error, don't modify wip, since skip just advances input
340                let span = res.map_err(|span_kind| {
341                    runner.last_span = span_kind.span;
342                    runner.err(span_kind.node)
343                })?;
344                // do the actual skip
345                runner.last_span = span;
346            }
347        }
348    }
349}
350
351#[doc(hidden)]
352/// Maintains the parsing state and context necessary to drive deserialization.
353///
354/// This struct tracks what the parser expects next, manages input position,
355/// and remembers the span of the last processed token to provide accurate error reporting.
356pub struct StackRunner<'input> {
357    /// A version of the input that doesn't advance as we parse.
358    original_input: &'input [u8],
359    /// The raw input data being deserialized.
360    pub input: &'input [u8],
361
362    /// Stack of parsing instructions guiding the control flow.
363    pub stack: Vec<Instruction>,
364    /// Span of the last processed token, for accurate error reporting.
365    pub last_span: Span,
366}
367
368impl<'input> StackRunner<'input> {
369    /// Convenience function to create a DeserError using the original input and last_span.
370    fn err(&self, kind: DeserErrorKind) -> DeserError<'input> {
371        DeserError::new(kind, self.original_input, self.last_span)
372    }
373
374    /// Convenience function to create a DeserError from a ReflectError,
375    /// using the original input and last_span for context.
376    fn reflect_err(&self, err: ReflectError) -> DeserError<'input> {
377        DeserError::new_reflect(err, self.original_input, self.last_span)
378    }
379
380    fn pop<'facet>(
381        &mut self,
382        mut wip: Wip<'facet>,
383        reason: PopReason,
384    ) -> Result<Wip<'facet>, DeserError<'input>> {
385        trace!("Popping because {:?}", reason.yellow());
386
387        let container_shape = wip.shape();
388        match container_shape.def {
389            Def::Struct(sd) => {
390                let mut has_unset = false;
391
392                trace!("Let's check all fields are initialized");
393                for (index, field) in sd.fields.iter().enumerate() {
394                    let is_set = wip.is_field_set(index).map_err(|err| {
395                        trace!("Error checking field set status: {:?}", err);
396                        self.reflect_err(err)
397                    })?;
398                    if !is_set {
399                        if field.flags.contains(FieldFlags::DEFAULT) {
400                            wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
401                            if let Some(default_in_place_fn) = field.vtable.default_fn {
402                                wip = wip
403                                    .put_from_fn(default_in_place_fn)
404                                    .map_err(|e| self.reflect_err(e))?;
405                                trace!(
406                                    "Field #{} {:?} was set to default value (via custom fn)",
407                                    index.yellow(),
408                                    field.blue()
409                                );
410                            } else {
411                                if !field.shape().is(Characteristic::Default) {
412                                    return Err(self.reflect_err(
413                                        ReflectError::DefaultAttrButNoDefaultImpl {
414                                            shape: field.shape(),
415                                        },
416                                    ));
417                                }
418                                wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
419                                trace!(
420                                    "Field #{} {:?} was set to default value (via default impl)",
421                                    index.yellow(),
422                                    field.blue()
423                                );
424                            }
425                            wip = wip.pop().map_err(|e| self.reflect_err(e))?;
426                        } else {
427                            trace!(
428                                "Field #{} {:?} is not initialized",
429                                index.yellow(),
430                                field.blue()
431                            );
432                            has_unset = true;
433                        }
434                    }
435                }
436
437                if has_unset && container_shape.has_default_attr() {
438                    // let's allocate and build a default value
439                    let default_val = Wip::alloc_shape(container_shape)
440                        .map_err(|e| self.reflect_err(e))?
441                        .put_default()
442                        .map_err(|e| self.reflect_err(e))?
443                        .build()
444                        .map_err(|e| self.reflect_err(e))?;
445                    let peek = default_val.peek().into_struct().unwrap();
446
447                    for (index, field) in sd.fields.iter().enumerate() {
448                        let is_set = wip.is_field_set(index).map_err(|err| {
449                            trace!("Error checking field set status: {:?}", err);
450                            self.reflect_err(err)
451                        })?;
452                        if !is_set {
453                            let address_of_field_from_default = peek.field(index).unwrap().data();
454                            wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
455                            wip = wip
456                                .put_shape(address_of_field_from_default, field.shape())
457                                .map_err(|e| self.reflect_err(e))?;
458                            wip = wip.pop().map_err(|e| self.reflect_err(e))?;
459                        }
460                    }
461                }
462            }
463            Def::Enum(_) => {
464                trace!(
465                    "TODO: make sure enums are initialized (support container-level and field-level default, etc.)"
466                );
467            }
468            _ => {
469                trace!(
470                    "Thing being popped is not a container I guess (it's a {})",
471                    wip.shape()
472                );
473            }
474        }
475        Ok(wip)
476    }
477
478    /// Internal common handler for GotScalar outcome, to deduplicate code.
479    fn handle_scalar<'facet>(
480        &self,
481        wip: Wip<'facet>,
482        scalar: Scalar<'input>,
483    ) -> Result<Wip<'facet>, DeserError<'input>> {
484        match scalar {
485            Scalar::String(cow) => {
486                match wip.innermost_shape().def {
487                    Def::Enum(_) => {
488                        if wip.selected_variant().is_some() {
489                            // If we already have a variant selected, just put the string
490                            wip.put(cow.to_string()).map_err(|e| self.reflect_err(e))
491                        } else {
492                            // Try to select the variant
493                            match wip.find_variant(&cow) {
494                                Some((variant_index, _)) => {
495                                    wip.variant(variant_index).map_err(|e| self.reflect_err(e))
496                                }
497                                None => Err(self.err(DeserErrorKind::NoSuchVariant {
498                                    name: cow.to_string(),
499                                    enum_shape: wip.innermost_shape(),
500                                })),
501                            }
502                        }
503                    }
504                    _ => wip.put(cow.to_string()).map_err(|e| self.reflect_err(e)),
505                }
506            }
507            Scalar::U64(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
508            Scalar::I64(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
509            Scalar::F64(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
510            Scalar::Bool(value) => wip.put(value).map_err(|e| self.reflect_err(e)),
511            Scalar::Null => wip.put_default().map_err(|e| self.reflect_err(e)),
512        }
513    }
514
515    /// Handle value parsing
516    fn value<'facet>(
517        &mut self,
518        mut wip: Wip<'facet>,
519        outcome: Spanned<Outcome<'input>>,
520    ) -> Result<Wip<'facet>, DeserError<'input>> {
521        trace!(
522            "Handling value at wip shape {} (wip innermost shape {})",
523            wip.shape().blue(),
524            wip.innermost_shape().yellow()
525        );
526
527        match outcome.node {
528            Outcome::Scalar(Scalar::Null) => {
529                return wip.put_default().map_err(|e| self.reflect_err(e));
530            }
531            _ => {
532                if matches!(wip.shape().def, Def::Option(_)) {
533                    trace!("Starting Some(_) option for {}", wip.shape().blue());
534                    wip = wip.push_some().map_err(|e| self.reflect_err(e))?;
535                    self.stack.push(Instruction::Pop(PopReason::Some));
536                }
537            }
538        }
539
540        match outcome.node {
541            Outcome::Scalar(s) => {
542                wip = self.handle_scalar(wip, s)?;
543            }
544            Outcome::ListStarted => {
545                let shape = wip.innermost_shape();
546                match shape.def {
547                    Def::Array(_) => {
548                        trace!("Array starting for array ({})!", shape.blue());
549                    }
550                    Def::Slice(_) => {
551                        trace!("Array starting for slice ({})!", shape.blue());
552                    }
553                    Def::List(_) => {
554                        trace!("Array starting for list ({})!", shape.blue());
555                        wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
556                    }
557                    Def::Enum(_) => {
558                        trace!("Array starting for enum ({})!", shape.blue());
559                    }
560                    Def::Struct(_) => {
561                        trace!("Array starting for tuple ({})!", shape.blue());
562                        wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
563                    }
564                    Def::Scalar(sd) => {
565                        if matches!(sd.affinity, ScalarAffinity::Empty(_)) {
566                            trace!("Empty tuple/scalar, nice");
567                            wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
568                        } else {
569                            return Err(self.err(DeserErrorKind::UnsupportedType {
570                                got: shape,
571                                wanted: "array, list, tuple, or slice",
572                            }));
573                        }
574                    }
575                    _ => {
576                        return Err(self.err(DeserErrorKind::UnsupportedType {
577                            got: shape,
578                            wanted: "array, list, tuple, or slice",
579                        }));
580                    }
581                }
582
583                trace!("Beginning pushback");
584                self.stack.push(Instruction::ListItemOrListClose);
585                wip = wip.begin_pushback().map_err(|e| self.reflect_err(e))?;
586            }
587            Outcome::ListEnded => {
588                trace!("List closing");
589                wip = wip.pop().map_err(|e| self.reflect_err(e))?;
590            }
591            Outcome::ObjectStarted => {
592                let shape = wip.innermost_shape();
593                match shape.def {
594                    Def::Map(_md) => {
595                        trace!("Object starting for map value ({})!", shape.blue());
596                        wip = wip.put_default().map_err(|e| self.reflect_err(e))?;
597                    }
598                    Def::Enum(_ed) => {
599                        trace!("Object starting for enum value ({})!", shape.blue());
600                        // nothing to do here
601                    }
602                    Def::Struct(_) => {
603                        trace!("Object starting for struct value ({})!", shape.blue());
604                        // nothing to do here
605                    }
606                    _ => {
607                        return Err(self.err(DeserErrorKind::UnsupportedType {
608                            got: shape,
609                            wanted: "map, enum, or struct",
610                        }));
611                    }
612                }
613
614                self.stack.push(Instruction::ObjectKeyOrObjectClose);
615            }
616            Outcome::ObjectEnded => todo!(),
617        }
618        Ok(wip)
619    }
620
621    fn object_key_or_object_close<'facet>(
622        &mut self,
623        mut wip: Wip<'facet>,
624        outcome: Spanned<Outcome<'input>>,
625    ) -> Result<Wip<'facet>, DeserError<'input>>
626    where
627        'input: 'facet,
628    {
629        match outcome.node {
630            Outcome::Scalar(Scalar::String(key)) => {
631                trace!("Parsed object key: {}", key);
632
633                let mut ignore = false;
634                let mut needs_pop = true;
635                let mut handled_by_flatten = false;
636
637                match wip.innermost_shape().def {
638                    Def::Struct(sd) => {
639                        // First try to find a direct field match
640                        if let Some(index) = wip.field_index(&key) {
641                            trace!("It's a struct field");
642                            wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
643                        } else {
644                            // Check for flattened fields
645                            let mut found_in_flatten = false;
646                            for (index, field) in sd.fields.iter().enumerate() {
647                                if field.flags.contains(FieldFlags::FLATTEN) {
648                                    trace!("Found flattened field #{}", index);
649                                    // Enter the flattened field
650                                    wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
651
652                                    // Check if this flattened field has the requested key
653                                    if let Some(subfield_index) = wip.field_index(&key) {
654                                        trace!("Found key {} in flattened field", key);
655                                        wip = wip
656                                            .field(subfield_index)
657                                            .map_err(|e| self.reflect_err(e))?;
658                                        found_in_flatten = true;
659                                        handled_by_flatten = true;
660                                        break;
661                                    } else if let Some((_variant_index, _variant)) =
662                                        wip.find_variant(&key)
663                                    {
664                                        trace!("Found key {} in flattened field", key);
665                                        wip = wip
666                                            .variant_named(&key)
667                                            .map_err(|e| self.reflect_err(e))?;
668                                        found_in_flatten = true;
669                                        break;
670                                    } else {
671                                        // Key not in this flattened field, go back up
672                                        wip = wip.pop().map_err(|e| self.reflect_err(e))?;
673                                    }
674                                }
675                            }
676
677                            if !found_in_flatten {
678                                if wip.shape().has_deny_unknown_fields_attr() {
679                                    trace!(
680                                        "It's not a struct field AND we're denying unknown fields"
681                                    );
682                                    return Err(self.err(DeserErrorKind::UnknownField {
683                                        field_name: key.to_string(),
684                                        shape: wip.shape(),
685                                    }));
686                                } else {
687                                    trace!(
688                                        "It's not a struct field and we're ignoring unknown fields"
689                                    );
690                                    ignore = true;
691                                }
692                            }
693                        }
694                    }
695                    Def::Enum(_ed) => match wip.find_variant(&key) {
696                        Some((index, variant)) => {
697                            trace!("Variant {} selected", variant.name.blue());
698                            wip = wip.variant(index).map_err(|e| self.reflect_err(e))?;
699                            needs_pop = false;
700                        }
701                        None => {
702                            if let Some(_variant_index) = wip.selected_variant() {
703                                trace!(
704                                    "Already have a variant selected, treating key as struct field of variant"
705                                );
706                                // Try to find the field index of the key within the selected variant
707                                if let Some(index) = wip.field_index(&key) {
708                                    trace!("Found field {} in selected variant", key.blue());
709                                    wip = wip.field(index).map_err(|e| self.reflect_err(e))?;
710                                } else if wip.shape().has_deny_unknown_fields_attr() {
711                                    trace!("Unknown field in variant and denying unknown fields");
712                                    return Err(self.err(DeserErrorKind::UnknownField {
713                                        field_name: key.to_string(),
714                                        shape: wip.shape(),
715                                    }));
716                                } else {
717                                    trace!("Ignoring unknown field in variant");
718                                    ignore = true;
719                                }
720                            } else {
721                                return Err(self.err(DeserErrorKind::NoSuchVariant {
722                                    name: key.to_string(),
723                                    enum_shape: wip.shape(),
724                                }));
725                            }
726                        }
727                    },
728                    Def::Map(_) => {
729                        wip = wip.push_map_key().map_err(|e| self.reflect_err(e))?;
730                        wip = wip.put(key.to_string()).map_err(|e| self.reflect_err(e))?;
731                        wip = wip.push_map_value().map_err(|e| self.reflect_err(e))?;
732                    }
733                    _ => {
734                        return Err(self.err(DeserErrorKind::Unimplemented(
735                            "object key for non-struct/map",
736                        )));
737                    }
738                }
739
740                self.stack.push(Instruction::ObjectKeyOrObjectClose);
741                if ignore {
742                    self.stack.push(Instruction::SkipValue);
743                } else {
744                    if needs_pop && !handled_by_flatten {
745                        trace!("Pushing Pop insn to stack (ObjectVal)");
746                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
747                    } else if handled_by_flatten {
748                        // We need two pops for flattened fields - one for the field itself,
749                        // one for the containing struct
750                        trace!("Pushing Pop insn to stack (ObjectVal) for flattened field");
751                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
752                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
753                    }
754                    self.stack.push(Instruction::Value(ValueReason::ObjectVal));
755                }
756                Ok(wip)
757            }
758            Outcome::ObjectEnded => {
759                trace!("Object closing");
760                Ok(wip)
761            }
762            _ => Err(self.err(DeserErrorKind::UnexpectedOutcome {
763                got: outcome.node.into_owned(),
764                wanted: "scalar or object close",
765            })),
766        }
767    }
768
769    fn list_item_or_list_close<'facet>(
770        &mut self,
771        mut wip: Wip<'facet>,
772        outcome: Spanned<Outcome<'input>>,
773    ) -> Result<Wip<'facet>, DeserError<'input>>
774    where
775        'input: 'facet,
776    {
777        match outcome.node {
778            Outcome::ListEnded => {
779                trace!("List close");
780                Ok(wip)
781            }
782            _ => {
783                self.stack.push(Instruction::ListItemOrListClose);
784                self.stack.push(Instruction::Pop(PopReason::ListVal));
785
786                trace!(
787                    "Expecting list item, doing a little push before doing value with outcome {}",
788                    outcome.magenta()
789                );
790                trace!("Before push, wip.shape is {}", wip.shape().blue());
791                wip = wip.push().map_err(|e| self.reflect_err(e))?;
792                trace!(" After push, wip.shape is {}", wip.shape().cyan());
793                wip = self.value(wip, outcome)?;
794                Ok(wip)
795            }
796        }
797    }
798}