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