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