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