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#![doc = include_str!("../README.md")]
6
7extern crate alloc;
8
9use alloc::string::ToString;
10use alloc::{vec, vec::Vec};
11use core::fmt::Debug;
12use facet_core::{NumericType, PrimitiveType};
13
14mod error;
15use alloc::borrow::Cow;
16
17pub use error::*;
18
19mod span;
20use facet_core::{Characteristic, Def, Facet, FieldFlags, PointerType, StructKind, Type, UserType};
21use owo_colors::OwoColorize;
22pub use span::*;
23
24use facet_reflect::{HeapValue, Partial, ReflectError};
25use log::trace;
26
27#[derive(PartialEq, Debug, Clone)]
28/// A scalar value used during deserialization.
29/// `u64` and `i64` are separated because `i64` doesn't fit in `u64`,
30/// but having `u64` is a fast path for 64-bit architectures — no need to
31/// go through `u128` / `i128` for everything
32pub enum Scalar<'input> {
33    /// Owned or borrowed string data.
34    String(Cow<'input, str>),
35    /// Unsigned 64-bit integer scalar.
36    U64(u64),
37    /// Signed 64-bit integer scalar.
38    I64(i64),
39    /// 64-bit floating-point scalar.
40    F64(f64),
41    /// 128-bit unsigned integer scalar.
42    U128(u128),
43    /// 128-bit signed integer scalar.
44    I128(i128),
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::U128(val) => write!(f, "u128 {val}"),
109            Scalar::I128(val) => write!(f, "i128 {val}"),
110            Scalar::Bool(val) => write!(f, "bool {val}"),
111            Scalar::Null => write!(f, "null"),
112        }
113    }
114}
115
116impl Outcome<'_> {
117    fn into_owned(self) -> Outcome<'static> {
118        match self {
119            Outcome::Scalar(scalar) => {
120                let owned_scalar = match scalar {
121                    Scalar::String(cow) => Scalar::String(Cow::Owned(cow.into_owned())),
122                    Scalar::U64(val) => Scalar::U64(val),
123                    Scalar::I64(val) => Scalar::I64(val),
124                    Scalar::F64(val) => Scalar::F64(val),
125                    Scalar::U128(val) => Scalar::U128(val),
126                    Scalar::I128(val) => Scalar::I128(val),
127                    Scalar::Bool(val) => Scalar::Bool(val),
128                    Scalar::Null => Scalar::Null,
129                };
130                Outcome::Scalar(owned_scalar)
131            }
132            Outcome::ListStarted => Outcome::ListStarted,
133            Outcome::ListEnded => Outcome::ListEnded,
134            Outcome::ObjectStarted => Outcome::ObjectStarted,
135            Outcome::ObjectEnded => Outcome::ObjectEnded,
136        }
137    }
138}
139
140/// Carries the current parsing state and the in-progress value during deserialization.
141/// This bundles the mutable context that must be threaded through parsing steps.
142pub struct NextData<'input, 'facet>
143where
144    'input: 'facet,
145{
146    /// The offset we're supposed to start parsing from
147    start: usize,
148
149    /// Controls the parsing flow and stack state.
150    runner: StackRunner<'input>,
151
152    /// Holds the intermediate representation of the value being built.
153    pub wip: Partial<'facet>,
154}
155
156impl<'input, 'facet> NextData<'input, 'facet>
157where
158    'input: 'facet,
159{
160    /// Returns the input (from the start! not from the current position)
161    pub fn input(&self) -> &'input [u8] {
162        self.runner.input
163    }
164
165    /// Returns the parsing start offset.
166    pub fn start(&self) -> usize {
167        self.start
168    }
169}
170
171/// The result of advancing the parser: updated state and parse outcome or error.
172pub type NextResult<'input, 'facet, T, E> = (NextData<'input, 'facet>, Result<T, E>);
173
174/// Trait defining a deserialization format.
175/// Provides the next parsing step based on current state and expected input.
176pub trait Format {
177    /// The lowercase source ID of the format, used for error reporting.
178    fn source(&self) -> &'static str;
179
180    /// Advance the parser with current state and expectation, producing the next outcome or error.
181    #[allow(clippy::type_complexity)]
182    fn next<'input, 'facet>(
183        &mut self,
184        nd: NextData<'input, 'facet>,
185        expectation: Expectation,
186    ) -> NextResult<'input, 'facet, Spanned<Outcome<'input>>, Spanned<DeserErrorKind>>;
187
188    /// Skip the next value; used to ignore an input.
189    #[allow(clippy::type_complexity)]
190    fn skip<'input, 'facet>(
191        &mut self,
192        nd: NextData<'input, 'facet>,
193    ) -> NextResult<'input, 'facet, Span, Spanned<DeserErrorKind>>;
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    /// Ending a smart pointer (ie. wrapping a `T` back into a `Box<T>`, or `Arc<T>` etc.)
232    SmartPointer,
233    /// Ending a wrapper value such as a newtype
234    Wrapper,
235}
236
237mod deser_impl {
238    use super::*;
239
240    /// Deserialize a value of type `T` from raw input bytes using format `F`.
241    ///
242    /// This function sets up the initial working state and drives the deserialization process,
243    /// ensuring that the resulting value is fully materialized and valid.
244    pub fn deserialize<'input, 'facet, T, F>(
245        input: &'input [u8],
246        format: &mut F,
247    ) -> Result<T, DeserError<'input>>
248    where
249        T: Facet<'facet>,
250        F: Format,
251        'input: 'facet,
252    {
253        // Run the entire deserialization process and capture any errors
254        let result: Result<T, DeserError<'input>> = {
255            // Step 1: Allocate shape
256            let wip = match Partial::alloc_shape(T::SHAPE) {
257                Ok(wip) => wip,
258                Err(e) => {
259                    let default_span = Span::default();
260                    return Err(DeserError::new_reflect(e, input, default_span));
261                }
262            };
263
264            // Step 2: Run deserialize_wip
265            let heap_value = match deserialize_wip(wip, input, format) {
266                Ok(val) => val,
267                Err(e) => {
268                    return Err(e);
269                }
270            };
271
272            // Step 3: Materialize
273            match heap_value.materialize() {
274                Ok(val) => Ok(val),
275                Err(e) => {
276                    let default_span = Span::default();
277                    return Err(DeserError::new_reflect(e, input, default_span));
278                }
279            }
280        };
281
282        result
283    }
284}
285
286/// Deserialize a value of type `T` from raw input bytes using format `F`.
287///
288/// This function sets up the initial working state and drives the deserialization process,
289/// ensuring that the resulting value is fully materialized and valid.
290pub fn deserialize<'input, 'facet, T, F>(
291    input: &'input [u8],
292    format: F,
293) -> Result<T, DeserError<'input>>
294where
295    T: Facet<'facet>,
296    F: Format,
297    'input: 'facet,
298{
299    let mut format_copy = format;
300    deser_impl::deserialize(input, &mut format_copy)
301}
302
303/// Deserializes a working-in-progress value into a fully materialized heap value.
304/// This function drives the parsing loop until the entire input is consumed and the value is complete.
305pub fn deserialize_wip<'input, 'facet, F>(
306    mut wip: Partial<'facet>,
307    input: &'input [u8],
308    format: &mut F,
309) -> Result<HeapValue<'facet>, DeserError<'input>>
310where
311    F: Format,
312    'input: 'facet,
313{
314    // This struct is just a bundle of the state that we need to pass around all the time.
315    let mut runner = StackRunner {
316        original_input: input,
317        input,
318        stack: vec![
319            Instruction::Pop(PopReason::TopLevel),
320            Instruction::Value(ValueReason::TopLevel),
321        ],
322        last_span: Span::new(0, 0),
323        format_source: format.source(),
324        array_indices: Vec::new(),
325        enum_tuple_field_count: None,
326        enum_tuple_current_field: None,
327    };
328
329    macro_rules! next {
330        ($runner:ident, $wip:ident, $expectation:expr, $method:ident) => {{
331            let nd = NextData {
332                start: $runner.last_span.end(), // or supply the appropriate start value if available
333                runner: $runner,
334                wip: $wip,
335            };
336            let (nd, res) = format.next(nd, $expectation);
337            $runner = nd.runner;
338            $wip = nd.wip;
339            let outcome = res.map_err(|span_kind| {
340                $runner.last_span = span_kind.span;
341                $runner.err(span_kind.node)
342            })?;
343            $runner.last_span = outcome.span;
344            $wip = $runner.$method($wip, outcome)?;
345        }};
346    }
347
348    loop {
349        // Note: frames_count() is no longer available in the new Partial API
350        // This was used for debugging/assertions only
351
352        let insn = match runner.stack.pop() {
353            Some(insn) => insn,
354            None => unreachable!("Instruction stack is empty"),
355        };
356
357        trace!("Instruction {:?}", insn.bright_red());
358
359        match insn {
360            Instruction::Pop(reason) => {
361                wip = runner.pop(wip, reason)?;
362
363                if reason == PopReason::TopLevel {
364                    // Exit all nested frames (e.g., from flattened fields) before building
365                    while wip.frame_count() > 1 {
366                        wip.end().map_err(|e| runner.reflect_err(e))?;
367                    }
368                    return wip.build().map_err(|e| runner.reflect_err(e));
369                } else {
370                    wip.end().map_err(|e| runner.reflect_err(e))?;
371                }
372            }
373            Instruction::Value(_why) => {
374                let expectation = match _why {
375                    ValueReason::TopLevel => Expectation::Value,
376                    ValueReason::ObjectVal => Expectation::ObjectVal,
377                };
378                next!(runner, wip, expectation, value);
379            }
380            Instruction::ObjectKeyOrObjectClose => {
381                next!(
382                    runner,
383                    wip,
384                    Expectation::ObjectKeyOrObjectClose,
385                    object_key_or_object_close
386                );
387            }
388            Instruction::ListItemOrListClose => {
389                next!(
390                    runner,
391                    wip,
392                    Expectation::ListItemOrListClose,
393                    list_item_or_list_close
394                );
395            }
396            Instruction::SkipValue => {
397                // Call F::skip to skip over the next value in the input
398                let nd = NextData {
399                    start: runner.last_span.end(),
400                    runner,
401                    wip,
402                };
403                let (nd, res) = format.skip(nd);
404                runner = nd.runner;
405                wip = nd.wip;
406                // Only propagate error, don't modify wip, since skip just advances input
407                let span = res.map_err(|span_kind| {
408                    runner.last_span = span_kind.span;
409                    runner.err(span_kind.node)
410                })?;
411                // do the actual skip
412                runner.last_span = span;
413            }
414        }
415    }
416}
417
418/// Helper function to check if an f64 has no fractional part
419/// This is needed for no-std compatibility where f64::fract() is not available
420#[inline]
421fn has_no_fractional_part(value: f64) -> bool {
422    value == (value as i64) as f64
423}
424
425/// Trait for numeric type conversions
426trait NumericConvert {
427    fn to_i8(&self) -> Option<i8>;
428    fn to_i16(&self) -> Option<i16>;
429    fn to_i32(&self) -> Option<i32>;
430    fn to_i64(&self) -> Option<i64>;
431    fn to_i128(&self) -> Option<i128>;
432    fn to_isize(&self) -> Option<isize>;
433
434    fn to_u8(&self) -> Option<u8>;
435    fn to_u16(&self) -> Option<u16>;
436    fn to_u32(&self) -> Option<u32>;
437    fn to_u64(&self) -> Option<u64>;
438    fn to_u128(&self) -> Option<u128>;
439    fn to_usize(&self) -> Option<usize>;
440
441    fn to_f32(&self) -> Option<f32>;
442    fn to_f64(&self) -> Option<f64>;
443}
444
445impl NumericConvert for u64 {
446    fn to_i8(&self) -> Option<i8> {
447        (*self).try_into().ok()
448    }
449    fn to_i16(&self) -> Option<i16> {
450        (*self).try_into().ok()
451    }
452    fn to_i32(&self) -> Option<i32> {
453        (*self).try_into().ok()
454    }
455    fn to_i64(&self) -> Option<i64> {
456        (*self).try_into().ok()
457    }
458    fn to_i128(&self) -> Option<i128> {
459        Some(*self as i128)
460    }
461    fn to_isize(&self) -> Option<isize> {
462        (*self).try_into().ok()
463    }
464
465    fn to_u8(&self) -> Option<u8> {
466        (*self).try_into().ok()
467    }
468    fn to_u16(&self) -> Option<u16> {
469        (*self).try_into().ok()
470    }
471    fn to_u32(&self) -> Option<u32> {
472        (*self).try_into().ok()
473    }
474    fn to_u64(&self) -> Option<u64> {
475        Some(*self)
476    }
477    fn to_u128(&self) -> Option<u128> {
478        Some(*self as u128)
479    }
480    fn to_usize(&self) -> Option<usize> {
481        (*self).try_into().ok()
482    }
483
484    fn to_f32(&self) -> Option<f32> {
485        Some(*self as f32)
486    }
487    fn to_f64(&self) -> Option<f64> {
488        Some(*self as f64)
489    }
490}
491
492impl NumericConvert for i64 {
493    fn to_i8(&self) -> Option<i8> {
494        (*self).try_into().ok()
495    }
496    fn to_i16(&self) -> Option<i16> {
497        (*self).try_into().ok()
498    }
499    fn to_i32(&self) -> Option<i32> {
500        (*self).try_into().ok()
501    }
502    fn to_i64(&self) -> Option<i64> {
503        Some(*self)
504    }
505    fn to_i128(&self) -> Option<i128> {
506        Some(*self as i128)
507    }
508    fn to_isize(&self) -> Option<isize> {
509        (*self).try_into().ok()
510    }
511
512    fn to_u8(&self) -> Option<u8> {
513        (*self).try_into().ok()
514    }
515    fn to_u16(&self) -> Option<u16> {
516        (*self).try_into().ok()
517    }
518    fn to_u32(&self) -> Option<u32> {
519        (*self).try_into().ok()
520    }
521    fn to_u64(&self) -> Option<u64> {
522        (*self).try_into().ok()
523    }
524    fn to_u128(&self) -> Option<u128> {
525        (*self).try_into().ok()
526    }
527    fn to_usize(&self) -> Option<usize> {
528        (*self).try_into().ok()
529    }
530
531    fn to_f32(&self) -> Option<f32> {
532        Some(*self as f32)
533    }
534    fn to_f64(&self) -> Option<f64> {
535        Some(*self as f64)
536    }
537}
538
539impl NumericConvert for f64 {
540    fn to_i8(&self) -> Option<i8> {
541        if has_no_fractional_part(*self) && *self >= i8::MIN as f64 && *self <= i8::MAX as f64 {
542            Some(*self as i8)
543        } else {
544            None
545        }
546    }
547    fn to_i16(&self) -> Option<i16> {
548        if has_no_fractional_part(*self) && *self >= i16::MIN as f64 && *self <= i16::MAX as f64 {
549            Some(*self as i16)
550        } else {
551            None
552        }
553    }
554    fn to_i32(&self) -> Option<i32> {
555        if has_no_fractional_part(*self) && *self >= i32::MIN as f64 && *self <= i32::MAX as f64 {
556            Some(*self as i32)
557        } else {
558            None
559        }
560    }
561    fn to_i64(&self) -> Option<i64> {
562        if has_no_fractional_part(*self) && *self >= i64::MIN as f64 && *self <= i64::MAX as f64 {
563            Some(*self as i64)
564        } else {
565            None
566        }
567    }
568    fn to_i128(&self) -> Option<i128> {
569        if has_no_fractional_part(*self) && *self >= i128::MIN as f64 && *self <= i128::MAX as f64 {
570            Some(*self as i128)
571        } else {
572            None
573        }
574    }
575    fn to_isize(&self) -> Option<isize> {
576        if has_no_fractional_part(*self) && *self >= isize::MIN as f64 && *self <= isize::MAX as f64
577        {
578            Some(*self as isize)
579        } else {
580            None
581        }
582    }
583
584    fn to_u8(&self) -> Option<u8> {
585        if has_no_fractional_part(*self) && *self >= 0.0 && *self <= u8::MAX as f64 {
586            Some(*self as u8)
587        } else {
588            None
589        }
590    }
591    fn to_u16(&self) -> Option<u16> {
592        if has_no_fractional_part(*self) && *self >= 0.0 && *self <= u16::MAX as f64 {
593            Some(*self as u16)
594        } else {
595            None
596        }
597    }
598    fn to_u32(&self) -> Option<u32> {
599        if has_no_fractional_part(*self) && *self >= 0.0 && *self <= u32::MAX as f64 {
600            Some(*self as u32)
601        } else {
602            None
603        }
604    }
605    fn to_u64(&self) -> Option<u64> {
606        if has_no_fractional_part(*self) && *self >= 0.0 && *self <= u64::MAX as f64 {
607            Some(*self as u64)
608        } else {
609            None
610        }
611    }
612    fn to_u128(&self) -> Option<u128> {
613        if has_no_fractional_part(*self) && *self >= 0.0 && *self <= u128::MAX as f64 {
614            Some(*self as u128)
615        } else {
616            None
617        }
618    }
619    fn to_usize(&self) -> Option<usize> {
620        if has_no_fractional_part(*self) && *self >= 0.0 && *self <= usize::MAX as f64 {
621            Some(*self as usize)
622        } else {
623            None
624        }
625    }
626
627    fn to_f32(&self) -> Option<f32> {
628        Some(*self as f32)
629    }
630    fn to_f64(&self) -> Option<f64> {
631        Some(*self)
632    }
633}
634
635impl NumericConvert for u128 {
636    fn to_i8(&self) -> Option<i8> {
637        (*self).try_into().ok()
638    }
639    fn to_i16(&self) -> Option<i16> {
640        (*self).try_into().ok()
641    }
642    fn to_i32(&self) -> Option<i32> {
643        (*self).try_into().ok()
644    }
645    fn to_i64(&self) -> Option<i64> {
646        (*self).try_into().ok()
647    }
648    fn to_i128(&self) -> Option<i128> {
649        Some(*self as i128)
650    }
651    fn to_isize(&self) -> Option<isize> {
652        (*self).try_into().ok()
653    }
654
655    fn to_u8(&self) -> Option<u8> {
656        (*self).try_into().ok()
657    }
658    fn to_u16(&self) -> Option<u16> {
659        (*self).try_into().ok()
660    }
661    fn to_u32(&self) -> Option<u32> {
662        (*self).try_into().ok()
663    }
664    fn to_u64(&self) -> Option<u64> {
665        (*self).try_into().ok()
666    }
667    fn to_u128(&self) -> Option<u128> {
668        Some(*self)
669    }
670    fn to_usize(&self) -> Option<usize> {
671        (*self).try_into().ok()
672    }
673
674    fn to_f32(&self) -> Option<f32> {
675        Some(*self as f32)
676    }
677    fn to_f64(&self) -> Option<f64> {
678        Some(*self as f64)
679    }
680}
681
682impl NumericConvert for i128 {
683    fn to_i8(&self) -> Option<i8> {
684        (*self).try_into().ok()
685    }
686    fn to_i16(&self) -> Option<i16> {
687        (*self).try_into().ok()
688    }
689    fn to_i32(&self) -> Option<i32> {
690        (*self).try_into().ok()
691    }
692    fn to_i64(&self) -> Option<i64> {
693        (*self).try_into().ok()
694    }
695    fn to_i128(&self) -> Option<i128> {
696        Some(*self)
697    }
698    fn to_isize(&self) -> Option<isize> {
699        (*self).try_into().ok()
700    }
701
702    fn to_u8(&self) -> Option<u8> {
703        (*self).try_into().ok()
704    }
705    fn to_u16(&self) -> Option<u16> {
706        (*self).try_into().ok()
707    }
708    fn to_u32(&self) -> Option<u32> {
709        (*self).try_into().ok()
710    }
711    fn to_u64(&self) -> Option<u64> {
712        (*self).try_into().ok()
713    }
714    fn to_u128(&self) -> Option<u128> {
715        (*self).try_into().ok()
716    }
717    fn to_usize(&self) -> Option<usize> {
718        (*self).try_into().ok()
719    }
720
721    fn to_f32(&self) -> Option<f32> {
722        Some(*self as f32)
723    }
724    fn to_f64(&self) -> Option<f64> {
725        Some(*self as f64)
726    }
727}
728
729#[doc(hidden)]
730/// Maintains the parsing state and context necessary to drive deserialization.
731///
732/// This struct tracks what the parser expects next, manages input position,
733/// and remembers the span of the last processed token to provide accurate error reporting.
734pub struct StackRunner<'input> {
735    /// A version of the input that doesn't advance as we parse.
736    pub original_input: &'input [u8],
737
738    /// The raw input data being deserialized.
739    pub input: &'input [u8],
740
741    /// Stack of parsing instructions guiding the control flow.
742    pub stack: Vec<Instruction>,
743
744    /// Span of the last processed token, for accurate error reporting.
745    pub last_span: Span,
746
747    /// Format source identifier for error reporting
748    pub format_source: &'static str,
749
750    /// Array index tracking - maps depth to current index for arrays
751    pub array_indices: Vec<usize>,
752
753    /// Tuple variant field tracking - number of fields in current enum tuple variant
754    pub enum_tuple_field_count: Option<usize>,
755
756    /// Tuple variant field tracking - current field index being processed
757    pub enum_tuple_current_field: Option<usize>,
758}
759
760impl<'input> StackRunner<'input> {
761    /// Convenience function to create a DeserError using the original input and last_span.
762    fn err(&self, kind: DeserErrorKind) -> DeserError<'input> {
763        DeserError::new(kind, self.original_input, self.last_span)
764    }
765
766    /// Convenience function to create a DeserError from a ReflectError,
767    /// using the original input and last_span for context.
768    fn reflect_err(&self, err: ReflectError) -> DeserError<'input> {
769        DeserError::new_reflect(err, self.original_input, self.last_span)
770    }
771
772    pub fn pop<'facet>(
773        &mut self,
774        mut wip: Partial<'facet>,
775        reason: PopReason,
776    ) -> Result<Partial<'facet>, DeserError<'input>> {
777        trace!(
778            "--- STACK has {:?} {}",
779            self.stack.green(),
780            "(POP)".bright_yellow()
781        );
782        trace!("Popping because {:?}", reason.yellow());
783
784        let container_shape = wip.shape();
785        match container_shape.ty {
786            Type::User(UserType::Struct(sd)) => {
787                let mut has_unset = false;
788
789                trace!("Let's check all fields are initialized");
790                for (index, field) in sd.fields.iter().enumerate() {
791                    let is_set = wip.is_field_set(index).map_err(|err| {
792                        trace!("Error checking field set status: {err:?}");
793                        self.reflect_err(err)
794                    })?;
795                    if !is_set {
796                        if field.flags.contains(FieldFlags::DEFAULT) {
797                            wip.set_nth_field_to_default(index)
798                                .map_err(|e| self.reflect_err(e))?;
799                        } else {
800                            trace!(
801                                "Field #{} {} @ {} is not initialized",
802                                index.yellow(),
803                                field.name.green(),
804                                field.offset.blue(),
805                            );
806                            has_unset = true;
807                        }
808                    }
809                }
810
811                if has_unset {
812                    if container_shape.has_default_attr() {
813                        // let's allocate and build a default value
814                        let default_val = Partial::alloc_shape(container_shape)
815                            .map_err(|e| self.reflect_err(e))?
816                            .set_default()
817                            .map_err(|e| self.reflect_err(e))?
818                            .build()
819                            .map_err(|e| self.reflect_err(e))?;
820                        let peek = default_val.peek().into_struct().unwrap();
821
822                        for (index, field) in sd.fields.iter().enumerate() {
823                            let is_set = wip.is_field_set(index).map_err(|err| {
824                                trace!("Error checking field set status: {err:?}");
825                                self.reflect_err(err)
826                            })?;
827                            if !is_set {
828                                trace!(
829                                    "Field #{} {} @ {} is being set to default value (from default instance)",
830                                    index.yellow(),
831                                    field.name.green(),
832                                    field.offset.blue(),
833                                );
834                                wip.begin_nth_field(index)
835                                    .map_err(|e| self.reflect_err(e))?;
836                                // Get the field as a Peek from the default value
837                                let def_field = peek.field(index).unwrap();
838
839                                // SAFETY: this is actually wrong, since it's moving out of a field of
840                                // the struct `peek` points to, so if that field has a Drop impl
841                                // it'll be dropped twice.
842                                unsafe {
843                                    wip.set_from_peek(&def_field)
844                                        .map_err(|e| self.reflect_err(e))?;
845                                }
846                                wip.end().map_err(|e| self.reflect_err(e))?;
847                            }
848                        }
849                    } else {
850                        // Find the first uninitialized field to report in the error
851                        for (index, field) in sd.fields.iter().enumerate() {
852                            let is_set = wip.is_field_set(index).map_err(|err| {
853                                trace!("Error checking field set status: {err:?}");
854                                self.reflect_err(err)
855                            })?;
856                            if !is_set {
857                                return Err(self.reflect_err(ReflectError::UninitializedField {
858                                    shape: container_shape,
859                                    field_name: field.name,
860                                }));
861                            }
862                        }
863                    }
864                }
865            }
866            Type::User(UserType::Enum(_ed)) => {
867                trace!("Checking if enum is initialized correctly");
868
869                // Check if a variant has been selected
870                if let Some(variant) = wip.selected_variant() {
871                    trace!("Variant {} is selected", variant.name.blue());
872
873                    // Check if all fields in the variant are initialized
874                    if !variant.data.fields.is_empty() {
875                        let mut has_unset = false;
876
877                        for (index, field) in variant.data.fields.iter().enumerate() {
878                            let is_set = wip.is_field_set(index).map_err(|err| {
879                                trace!("Error checking field set status: {err:?}");
880                                self.reflect_err(err)
881                            })?;
882
883                            if !is_set {
884                                if field.flags.contains(FieldFlags::DEFAULT) {
885                                    wip.begin_nth_field(index)
886                                        .map_err(|e| self.reflect_err(e))?;
887
888                                    // Check for field-level default function first, then type-level default
889                                    if field.vtable.default_fn.is_some() {
890                                        wip.set_default().map_err(|e| self.reflect_err(e))?;
891                                        trace!(
892                                            "Field #{} @ {} in variant {} was set to default value (via field default function)",
893                                            index.yellow(),
894                                            field.offset.blue(),
895                                            variant.name
896                                        );
897                                    } else if field.shape().is(Characteristic::Default) {
898                                        wip.set_default().map_err(|e| self.reflect_err(e))?;
899                                        trace!(
900                                            "Field #{} @ {} in variant {} was set to default value (via type default impl)",
901                                            index.yellow(),
902                                            field.offset.blue(),
903                                            variant.name
904                                        );
905                                    } else {
906                                        return Err(self.reflect_err(
907                                            ReflectError::DefaultAttrButNoDefaultImpl {
908                                                shape: field.shape(),
909                                            },
910                                        ));
911                                    }
912                                    wip.end().map_err(|e| self.reflect_err(e))?;
913                                } else {
914                                    trace!(
915                                        "Field #{} @ {} in variant {} is not initialized",
916                                        index.yellow(),
917                                        field.offset.blue(),
918                                        variant.name
919                                    );
920                                    has_unset = true;
921                                }
922                            }
923                        }
924
925                        if has_unset {
926                            if container_shape.has_default_attr() {
927                                trace!(
928                                    "Enum has DEFAULT attr but variant has uninitialized fields"
929                                );
930                                // Handle similar to struct, allocate and build default value for variant
931                                let default_val = Partial::alloc_shape(container_shape)
932                                    .map_err(|e| self.reflect_err(e))?
933                                    .set_default()
934                                    .map_err(|e| self.reflect_err(e))?
935                                    .build()
936                                    .map_err(|e| self.reflect_err(e))?;
937
938                                let peek = default_val.peek();
939                                let peek_enum =
940                                    peek.into_enum().map_err(|e| self.reflect_err(e))?;
941                                let default_variant = peek_enum
942                                    .active_variant()
943                                    .map_err(|e| self.err(DeserErrorKind::VariantError(e)))?;
944
945                                if default_variant.name == variant.name {
946                                    // It's the same variant, fill in the missing fields
947                                    for (index, _field) in variant.data.fields.iter().enumerate() {
948                                        let is_set = wip.is_field_set(index).map_err(|err| {
949                                            trace!("Error checking field set status: {err:?}");
950                                            self.reflect_err(err)
951                                        })?;
952                                        if !is_set {
953                                            if let Ok(Some(def_field)) = peek_enum.field(index) {
954                                                wip.begin_nth_field(index)
955                                                    .map_err(|e| self.reflect_err(e))?;
956
957                                                // SAFETY: this is actually wrong, since it's moving out of a field of
958                                                // the struct `peek` points to, so if that field has a Drop impl
959                                                // it'll be dropped twice.
960                                                unsafe {
961                                                    wip.set_from_peek(&def_field)
962                                                        .map_err(|e| self.reflect_err(e))?;
963                                                }
964                                                wip.end().map_err(|e| self.reflect_err(e))?;
965                                            }
966                                        }
967                                    }
968                                }
969                            } else {
970                                // Find the first uninitialized field to report in the error
971                                for (index, field) in variant.data.fields.iter().enumerate() {
972                                    let is_set = wip.is_field_set(index).map_err(|err| {
973                                        trace!("Error checking field set status: {err:?}");
974                                        self.reflect_err(err)
975                                    })?;
976                                    if !is_set {
977                                        return Err(self.reflect_err(
978                                            ReflectError::UninitializedEnumField {
979                                                shape: container_shape,
980                                                variant_name: variant.name,
981                                                field_name: field.name,
982                                            },
983                                        ));
984                                    }
985                                }
986                            }
987                        }
988                    }
989                } else if container_shape.has_default_attr() {
990                    // No variant selected, but enum has default attribute - set to default
991                    trace!("No variant selected but enum has DEFAULT attr; setting to default");
992
993                    wip.set_default().map_err(|e| self.reflect_err(e))?;
994                }
995            }
996            _ => {
997                trace!(
998                    "Thing being popped is not a container I guess (it's a {})",
999                    wip.shape(),
1000                );
1001            }
1002        }
1003        Ok(wip)
1004    }
1005
1006    /// Internal common handler for GotScalar outcome, to deduplicate code.
1007    /// Helper to set numeric values with type conversion
1008    fn set_numeric_value<'facet>(
1009        &self,
1010        wip: &mut Partial<'facet>,
1011        value: &dyn NumericConvert,
1012    ) -> Result<(), DeserError<'input>>
1013    where
1014        'input: 'facet,
1015    {
1016        let shape = wip.shape();
1017
1018        let Type::Primitive(PrimitiveType::Numeric(numeric_type)) = shape.ty else {
1019            return Err(self.err(DeserErrorKind::UnsupportedType {
1020                got: shape,
1021                wanted: "numeric type",
1022            }));
1023        };
1024
1025        // Get the size from the layout
1026        let size_bytes = shape
1027            .layout
1028            .sized_layout()
1029            .map_err(|_| {
1030                self.err(DeserErrorKind::UnsupportedType {
1031                    got: shape,
1032                    wanted: "sized numeric type",
1033                })
1034            })?
1035            .size();
1036
1037        if matches!(shape.def, Def::Scalar) {
1038            // Helper closure to convert and set numeric value
1039            macro_rules! convert_and_set {
1040                ($converter:expr, $target_type:expr) => {{
1041                    let converted = $converter.ok_or_else(|| {
1042                        self.err(DeserErrorKind::NumericConversion {
1043                            from: "numeric",
1044                            to: $target_type,
1045                        })
1046                    })?;
1047                    wip.set(converted).map_err(|e| self.reflect_err(e))?;
1048                }};
1049            }
1050
1051            match numeric_type {
1052                NumericType::Integer { signed } => {
1053                    // First check if the shape is specifically usize or isize
1054                    if !signed && shape.is_type::<usize>() {
1055                        convert_and_set!(value.to_usize(), "usize")
1056                    } else if signed && shape.is_type::<isize>() {
1057                        convert_and_set!(value.to_isize(), "isize")
1058                    } else {
1059                        // Then check by size
1060                        match (size_bytes, signed) {
1061                            (1, true) => convert_and_set!(value.to_i8(), "i8"),
1062                            (2, true) => convert_and_set!(value.to_i16(), "i16"),
1063                            (4, true) => convert_and_set!(value.to_i32(), "i32"),
1064                            (8, true) => convert_and_set!(value.to_i64(), "i64"),
1065                            (16, true) => convert_and_set!(value.to_i128(), "i128"),
1066                            (1, false) => convert_and_set!(value.to_u8(), "u8"),
1067                            (2, false) => convert_and_set!(value.to_u16(), "u16"),
1068                            (4, false) => convert_and_set!(value.to_u32(), "u32"),
1069                            (8, false) => convert_and_set!(value.to_u64(), "u64"),
1070                            (16, false) => convert_and_set!(value.to_u128(), "u128"),
1071                            _ => {
1072                                return Err(self.err(DeserErrorKind::NumericConversion {
1073                                    from: "numeric",
1074                                    to: if signed {
1075                                        "unknown signed integer size"
1076                                    } else {
1077                                        "unknown unsigned integer size"
1078                                    },
1079                                }));
1080                            }
1081                        }
1082                    }
1083                }
1084                NumericType::Float => match size_bytes {
1085                    4 => convert_and_set!(value.to_f32(), "f32"),
1086                    8 => convert_and_set!(value.to_f64(), "f64"),
1087                    _ => {
1088                        return Err(self.err(DeserErrorKind::NumericConversion {
1089                            from: "numeric",
1090                            to: "unknown float size",
1091                        }));
1092                    }
1093                },
1094            }
1095        } else {
1096            // Not a scalar def - cannot convert
1097            return Err(self.err(DeserErrorKind::UnsupportedType {
1098                got: shape,
1099                wanted: "scalar type",
1100            }));
1101        }
1102
1103        Ok(())
1104    }
1105
1106    fn handle_scalar<'facet>(
1107        &self,
1108        wip: &mut Partial<'facet>,
1109        scalar: Scalar<'input>,
1110    ) -> Result<(), DeserError<'input>>
1111    where
1112        'input: 'facet, // 'input outlives 'facet
1113    {
1114        match scalar {
1115            Scalar::String(cow) => {
1116                match wip.shape().ty {
1117                    Type::User(UserType::Enum(_)) => {
1118                        if wip.selected_variant().is_some() {
1119                            // If we already have a variant selected, just put the string
1120                            wip.set(cow).map_err(|e| self.reflect_err(e))?;
1121                        } else {
1122                            // Try to select the variant
1123                            match wip.find_variant(&cow) {
1124                                Some((variant_index, _)) => {
1125                                    wip.select_nth_variant(variant_index)
1126                                        .map_err(|e| self.reflect_err(e))?;
1127                                }
1128                                None => {
1129                                    return Err(self.err(DeserErrorKind::NoSuchVariant {
1130                                        name: cow.to_string(),
1131                                        enum_shape: wip.shape(),
1132                                    }));
1133                                }
1134                            }
1135                        }
1136                    }
1137                    Type::Pointer(PointerType::Reference(_)) if wip.shape().is_type::<&str>() => {
1138                        // This is for handling the &str type
1139                        // The Cow may be Borrowed (we may have an owned string but need a &str)
1140                        match cow {
1141                            Cow::Borrowed(s) => wip.set(s).map_err(|e| self.reflect_err(e))?,
1142                            Cow::Owned(s) => wip.set(s).map_err(|e| self.reflect_err(e))?,
1143                        }; // Add semicolon to ignore the return value
1144                    }
1145                    _ => {
1146                        // Check if this is a scalar type that can be parsed from a string
1147                        let shape = wip.shape();
1148                        if matches!(shape.def, Def::Scalar) {
1149                            // Try parse_from_str for scalar types that might parse from strings
1150                            // (like IpAddr, UUID, Path, etc.)
1151                            match wip.parse_from_str(cow.as_ref()) {
1152                                Ok(_) => {
1153                                    // Successfully parsed
1154                                }
1155                                Err(parse_err) => {
1156                                    // Parsing failed - check if it's because parse isn't supported
1157                                    // or if parsing actually failed
1158                                    match parse_err {
1159                                        ReflectError::OperationFailed {
1160                                            shape: _,
1161                                            operation,
1162                                        } if operation.contains("does not support parsing") => {
1163                                            // Type doesn't have a parse function, try direct conversion
1164                                            wip.set(cow.to_string())
1165                                                .map_err(|e| self.reflect_err(e))?;
1166                                        }
1167                                        _ => {
1168                                            // Actual parsing failure
1169                                            return Err(self.err(DeserErrorKind::ReflectError(
1170                                                ReflectError::OperationFailed {
1171                                                    shape,
1172                                                    operation: "Failed to parse string value",
1173                                                },
1174                                            )));
1175                                        }
1176                                    }
1177                                }
1178                            }
1179                        } else {
1180                            // Not a scalar, just set as String
1181                            wip.set(cow.to_string()).map_err(|e| self.reflect_err(e))?;
1182                        }
1183                    }
1184                }
1185            }
1186            Scalar::U64(value) => {
1187                self.set_numeric_value(wip, &value)?;
1188            }
1189            Scalar::I64(value) => {
1190                self.set_numeric_value(wip, &value)?;
1191            }
1192            Scalar::F64(value) => {
1193                self.set_numeric_value(wip, &value)?;
1194            }
1195            Scalar::U128(value) => {
1196                self.set_numeric_value(wip, &value)?;
1197            }
1198            Scalar::I128(value) => {
1199                self.set_numeric_value(wip, &value)?;
1200            }
1201            Scalar::Bool(value) => {
1202                wip.set(value).map_err(|e| self.reflect_err(e))?;
1203            }
1204            Scalar::Null => {
1205                wip.set_default().map_err(|e| self.reflect_err(e))?;
1206            }
1207        }
1208        Ok(())
1209    }
1210
1211    /// Handle value parsing
1212    fn value<'facet>(
1213        &mut self,
1214        mut wip: Partial<'facet>,
1215        outcome: Spanned<Outcome<'input>>,
1216    ) -> Result<Partial<'facet>, DeserError<'input>>
1217    where
1218        'input: 'facet, // 'input must outlive 'facet
1219    {
1220        trace!(
1221            "--- STACK has {:?} {}",
1222            self.stack.green(),
1223            "(VALUE)".bright_yellow()
1224        );
1225
1226        let original_shape = wip.shape();
1227        trace!("Handling value of type {}", original_shape.blue());
1228
1229        // Handle null values
1230        if matches!(outcome.node, Outcome::Scalar(Scalar::Null)) {
1231            wip.set_default().map_err(|e| self.reflect_err(e))?;
1232            return Ok(wip);
1233        }
1234
1235        // Resolve the innermost value to deserialize
1236        let mut smart_pointer_begun = false;
1237        loop {
1238            trace!("  Loop iteration: current shape is {}", wip.shape().blue());
1239            if matches!(wip.shape().def, Def::Option(_)) {
1240                trace!("  Starting Some(_) option for {}", wip.shape().blue());
1241                wip.begin_some().map_err(|e| self.reflect_err(e))?;
1242                self.stack.push(Instruction::Pop(PopReason::Some));
1243            } else if let Def::Pointer(inner) = wip.shape().def {
1244                // Check if we've already begun this smart pointer
1245                // (this can happen with slice pointees where the shape doesn't change)
1246                if smart_pointer_begun {
1247                    break;
1248                }
1249                if let Some(pointee) = inner.pointee() {
1250                    trace!(
1251                        "  Starting smart pointer for {} (pointee is {})",
1252                        wip.shape().blue(),
1253                        pointee.yellow(),
1254                    );
1255                } else {
1256                    trace!(
1257                        "  Starting smart pointer for {} (no pointee)",
1258                        wip.shape().blue()
1259                    );
1260                }
1261                trace!("  About to call begin_smart_ptr()");
1262                wip.begin_smart_ptr().map_err(|e| self.reflect_err(e))?;
1263                trace!(
1264                    "  After begin_smart_ptr(), shape is now {}",
1265                    wip.shape().blue()
1266                );
1267                self.stack.push(Instruction::Pop(PopReason::SmartPointer));
1268                smart_pointer_begun = true;
1269            } else if let Some(inner_fn) = wip.shape().inner {
1270                let inner = inner_fn();
1271                trace!(
1272                    "  Starting wrapped value for {} (inner is {})",
1273                    wip.shape().blue(),
1274                    inner.yellow()
1275                );
1276                wip.begin_inner().map_err(|e| self.reflect_err(e))?;
1277                self.stack.push(Instruction::Pop(PopReason::Wrapper));
1278            } else {
1279                break;
1280            }
1281        }
1282
1283        if wip.shape() != original_shape {
1284            trace!(
1285                "Handling shape {} as innermost {}",
1286                original_shape.blue(),
1287                wip.shape().yellow()
1288            );
1289        }
1290
1291        match outcome.node {
1292            Outcome::Scalar(s) => {
1293                trace!("Parsed scalar value: {}", s.cyan());
1294                self.handle_scalar(&mut wip, s)?;
1295            }
1296            Outcome::ListStarted => {
1297                let shape = wip.shape();
1298
1299                // First check if this is a tuple struct (including empty tuples)
1300                if let Type::User(UserType::Struct(st)) = shape.ty {
1301                    if st.kind == StructKind::Tuple {
1302                        trace!(
1303                            "Array starting for tuple struct ({}) with {} fields!",
1304                            shape.blue(),
1305                            st.fields.len()
1306                        );
1307
1308                        // Non-empty tuples need to process list events
1309                        trace!("Beginning pushback");
1310                        self.stack.push(Instruction::ListItemOrListClose);
1311                        return Ok(wip);
1312                    }
1313                }
1314
1315                match shape.def {
1316                    Def::Array(_) => {
1317                        trace!("Array starting for array ({})!", shape.blue());
1318                        // We'll initialize the array elements one by one through the pushback workflow
1319                        // Don't call put_default, as arrays need different initialization
1320                    }
1321                    Def::Slice(_) => {
1322                        trace!("Array starting for slice ({})!", shape.blue());
1323                    }
1324                    Def::List(_) => {
1325                        trace!("Array starting for list ({})!", shape.blue());
1326                        wip.set_default().map_err(|e| self.reflect_err(e))?;
1327                    }
1328                    _ => {
1329                        // Check if we're building a smart pointer slice
1330                        if matches!(shape.def, Def::Pointer(_)) && smart_pointer_begun {
1331                            trace!("Array starting for smart pointer slice ({})!", shape.blue());
1332                            wip.begin_list().map_err(|e| self.reflect_err(e))?;
1333                        } else if let Type::User(user_ty) = shape.ty {
1334                            // For non-collection types, check the Type enum
1335                            match user_ty {
1336                                UserType::Enum(_) => {
1337                                    trace!("Array starting for enum ({})!", shape.blue());
1338                                    // Check if we have a tuple variant selected
1339                                    if let Some(variant) = wip.selected_variant() {
1340                                        use facet_core::StructKind;
1341                                        if variant.data.kind == StructKind::Tuple {
1342                                            // For tuple variants, we'll handle array elements as tuple fields
1343                                            // Initialize tuple field tracking
1344                                            self.enum_tuple_field_count =
1345                                                Some(variant.data.fields.len());
1346                                            self.enum_tuple_current_field = Some(0);
1347                                        } else {
1348                                            return Err(self.err(DeserErrorKind::UnsupportedType {
1349                                                got: shape,
1350                                                wanted: "tuple variant for array deserialization",
1351                                            }));
1352                                        }
1353                                    } else {
1354                                        return Err(self.err(DeserErrorKind::UnsupportedType {
1355                                            got: shape,
1356                                            wanted: "enum with variant selected",
1357                                        }));
1358                                    }
1359                                }
1360                                UserType::Struct(_) => {
1361                                    // Regular struct shouldn't be parsed from array
1362                                    // (Tuples are already handled above)
1363                                    return Err(self.err(DeserErrorKind::UnsupportedType {
1364                                        got: shape,
1365                                        wanted: "array, list, tuple, or slice",
1366                                    }));
1367                                }
1368                                _ => {
1369                                    return Err(self.err(DeserErrorKind::UnsupportedType {
1370                                        got: shape,
1371                                        wanted: "array, list, tuple, or slice",
1372                                    }));
1373                                }
1374                            }
1375                        } else {
1376                            return Err(self.err(DeserErrorKind::UnsupportedType {
1377                                got: shape,
1378                                wanted: "array, list, tuple, or slice",
1379                            }));
1380                        }
1381                    }
1382                }
1383                trace!("Beginning pushback");
1384                self.stack.push(Instruction::ListItemOrListClose);
1385
1386                // Only call begin_list() for actual lists, not arrays
1387                match shape.def {
1388                    Def::List(_) => {
1389                        wip.begin_list().map_err(|e| self.reflect_err(e))?;
1390                    }
1391                    Def::Array(_) => {
1392                        // Arrays don't need begin_list()
1393                        // Initialize index tracking for this array
1394                        self.array_indices.push(0);
1395                    }
1396                    Def::Slice(_) => {
1397                        // Slices don't need begin_list()
1398                        // They will be populated element by element
1399                    }
1400                    _ => {
1401                        // For other types like tuples, no special initialization needed
1402                    }
1403                }
1404            }
1405            Outcome::ListEnded => {
1406                trace!("List closing");
1407                // Clean up array index tracking if this was an array
1408                let shape = wip.shape();
1409                if matches!(shape.def, Def::Array(_)) {
1410                    self.array_indices.pop();
1411                }
1412                wip.end().map_err(|e| self.reflect_err(e))?;
1413            }
1414            Outcome::ObjectStarted => {
1415                let shape = wip.shape();
1416                match shape.def {
1417                    Def::Map(_md) => {
1418                        trace!("Object starting for map value ({})!", shape.blue());
1419                        wip.begin_map().map_err(|e| self.reflect_err(e))?;
1420                    }
1421                    _ => {
1422                        // For non-collection types, check the Type enum
1423                        if let Type::User(user_ty) = shape.ty {
1424                            match user_ty {
1425                                UserType::Enum(_) => {
1426                                    trace!("Object starting for enum value ({})!", shape.blue());
1427                                    // nothing to do here
1428                                }
1429                                UserType::Struct(_) => {
1430                                    trace!("Object starting for struct value ({})!", shape.blue());
1431                                    // nothing to do here
1432                                }
1433                                _ => {
1434                                    return Err(self.err(DeserErrorKind::UnsupportedType {
1435                                        got: shape,
1436                                        wanted: "map, enum, or struct",
1437                                    }));
1438                                }
1439                            }
1440                        } else if let Type::User(UserType::Struct(struct_type)) = shape.ty {
1441                            if struct_type.kind == StructKind::Tuple {
1442                                // This could be a tuple that was serialized as an object
1443                                // Despite this being unusual, we'll handle it here for robustness
1444                                trace!(
1445                                    "Object starting for tuple ({}) with {} fields - unusual but handling",
1446                                    shape.blue(),
1447                                    struct_type.fields.len()
1448                                );
1449                                // Tuples are treated as structs
1450                            }
1451                        } else {
1452                            return Err(self.err(DeserErrorKind::UnsupportedType {
1453                                got: shape,
1454                                wanted: "map, enum, struct, or tuple",
1455                            }));
1456                        }
1457                    }
1458                }
1459
1460                self.stack.push(Instruction::ObjectKeyOrObjectClose);
1461            }
1462            Outcome::ObjectEnded => todo!(),
1463        }
1464        Ok(wip)
1465    }
1466
1467    fn object_key_or_object_close<'facet>(
1468        &mut self,
1469        mut wip: Partial<'facet>,
1470        outcome: Spanned<Outcome<'input>>,
1471    ) -> Result<Partial<'facet>, DeserError<'input>>
1472    where
1473        'input: 'facet,
1474    {
1475        trace!(
1476            "STACK: {:?} {}",
1477            self.stack.green(),
1478            "(OK/OC)".bright_yellow()
1479        );
1480        match outcome.node {
1481            Outcome::Scalar(Scalar::String(key)) => {
1482                trace!("Parsed object key: {}", key.cyan());
1483
1484                let mut ignore = false;
1485                let mut needs_pop = true;
1486                let mut handled_by_flatten = false;
1487
1488                let shape = wip.shape();
1489                match shape.ty {
1490                    Type::User(UserType::Struct(sd)) => {
1491                        // First try to find a direct field match
1492                        if let Some(index) = wip.field_index(&key) {
1493                            trace!("It's a struct field");
1494                            wip.begin_nth_field(index)
1495                                .map_err(|e| self.reflect_err(e))?;
1496                        } else {
1497                            trace!(
1498                                "Did not find direct field match in innermost shape {}",
1499                                shape.blue()
1500                            );
1501
1502                            // Check for flattened fields
1503                            let mut found_in_flatten = false;
1504                            for (index, field) in sd.fields.iter().enumerate() {
1505                                if field.flags.contains(FieldFlags::FLATTEN) {
1506                                    trace!("Found flattened field #{index}");
1507                                    // Enter the flattened field
1508                                    wip.begin_nth_field(index)
1509                                        .map_err(|e| self.reflect_err(e))?;
1510
1511                                    // Check if this flattened field has the requested key
1512                                    if let Some(subfield_index) = wip.field_index(&key) {
1513                                        trace!("Found key {key} in flattened field");
1514                                        wip.begin_nth_field(subfield_index)
1515                                            .map_err(|e| self.reflect_err(e))?;
1516                                        found_in_flatten = true;
1517                                        handled_by_flatten = true;
1518                                        break;
1519                                    } else if let Some((_variant_index, _variant)) =
1520                                        wip.find_variant(&key)
1521                                    {
1522                                        trace!("Found key {key} in flattened field");
1523                                        wip.select_variant_named(&key)
1524                                            .map_err(|e| self.reflect_err(e))?;
1525                                        found_in_flatten = true;
1526                                        break;
1527                                    } else {
1528                                        // Key not in this flattened field, go back up
1529                                        wip.end().map_err(|e| self.reflect_err(e))?;
1530                                    }
1531                                }
1532                            }
1533
1534                            if !found_in_flatten {
1535                                if wip.shape().has_deny_unknown_fields_attr() {
1536                                    trace!(
1537                                        "It's not a struct field AND we're denying unknown fields"
1538                                    );
1539                                    return Err(self.err(DeserErrorKind::UnknownField {
1540                                        field_name: key.to_string(),
1541                                        shape: wip.shape(),
1542                                    }));
1543                                } else {
1544                                    trace!(
1545                                        "It's not a struct field and we're ignoring unknown fields"
1546                                    );
1547                                    ignore = true;
1548                                }
1549                            }
1550                        }
1551                    }
1552                    Type::User(UserType::Enum(_ed)) => match wip.find_variant(&key) {
1553                        Some((index, variant)) => {
1554                            trace!(
1555                                "Selecting variant {}::{}",
1556                                wip.shape().blue(),
1557                                variant.name.yellow(),
1558                            );
1559                            wip.select_nth_variant(index)
1560                                .map_err(|e| self.reflect_err(e))?;
1561
1562                            // Let's see what's in the variant — if it's tuple-like with only one field, we want to push field 0
1563                            if matches!(variant.data.kind, StructKind::Tuple)
1564                                && variant.data.fields.len() == 1
1565                            {
1566                                trace!(
1567                                    "Tuple variant {}::{} encountered, pushing field 0",
1568                                    wip.shape().blue(),
1569                                    variant.name.yellow()
1570                                );
1571                                wip.begin_nth_field(0).map_err(|e| self.reflect_err(e))?;
1572                                self.stack.push(Instruction::Pop(PopReason::ObjectVal));
1573                            }
1574
1575                            needs_pop = false;
1576                        }
1577                        None => {
1578                            if let Some(_variant_index) = wip.selected_variant() {
1579                                trace!(
1580                                    "Already have a variant selected, treating {} as struct field of {}::{}",
1581                                    key,
1582                                    wip.shape().blue(),
1583                                    wip.selected_variant().unwrap().name.yellow(),
1584                                );
1585                                // Try to find the field index of the key within the selected variant
1586                                if let Some(index) = wip.field_index(&key) {
1587                                    trace!("Found field {} in selected variant", key.blue());
1588                                    wip.begin_nth_field(index)
1589                                        .map_err(|e| self.reflect_err(e))?;
1590                                } else if wip.shape().has_deny_unknown_fields_attr() {
1591                                    trace!("Unknown field in variant and denying unknown fields");
1592                                    return Err(self.err(DeserErrorKind::UnknownField {
1593                                        field_name: key.to_string(),
1594                                        shape: wip.shape(),
1595                                    }));
1596                                } else {
1597                                    trace!(
1598                                        "Ignoring unknown field '{}' in variant '{}::{}'",
1599                                        key,
1600                                        wip.shape(),
1601                                        wip.selected_variant().unwrap().name
1602                                    );
1603                                    ignore = true;
1604                                }
1605                            } else {
1606                                return Err(self.err(DeserErrorKind::NoSuchVariant {
1607                                    name: key.to_string(),
1608                                    enum_shape: wip.shape(),
1609                                }));
1610                            }
1611                        }
1612                    },
1613                    _ => {
1614                        // Check if it's a map
1615                        if let Def::Map(map_def) = shape.def {
1616                            wip.begin_key().map_err(|e| self.reflect_err(e))?;
1617
1618                            // Check if the map key type is transparent (has an inner shape)
1619                            let key_shape = map_def.k();
1620                            if key_shape.inner.is_some() {
1621                                // For transparent types, we need to navigate into the inner type
1622                                // The inner type should be String for JSON object keys
1623                                // Use begin_inner for consistency with begin_* naming convention
1624                                wip.begin_inner().map_err(|e| self.reflect_err(e))?;
1625                                wip.set(key.to_string()).map_err(|e| self.reflect_err(e))?;
1626                                wip.end().map_err(|e| self.reflect_err(e))?; // End inner
1627                            } else {
1628                                // For non-transparent types, set the string directly
1629                                wip.set(key.to_string()).map_err(|e| self.reflect_err(e))?;
1630                            }
1631
1632                            wip.end().map_err(|e| self.reflect_err(e))?; // Complete the key frame
1633                            wip.begin_value().map_err(|e| self.reflect_err(e))?;
1634                        } else {
1635                            return Err(self.err(DeserErrorKind::Unimplemented(
1636                                "object key for non-struct/map",
1637                            )));
1638                        }
1639                    }
1640                }
1641
1642                self.stack.push(Instruction::ObjectKeyOrObjectClose);
1643                if ignore {
1644                    self.stack.push(Instruction::SkipValue);
1645                } else {
1646                    if needs_pop && !handled_by_flatten {
1647                        trace!("Pushing Pop insn to stack (ObjectVal)");
1648                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
1649                    } else if handled_by_flatten {
1650                        // For flattened fields, we only need one pop for the field itself.
1651                        // The flattened struct should remain active until the outer object is finished.
1652                        trace!("Pushing Pop insn to stack (ObjectVal) for flattened field");
1653                        self.stack.push(Instruction::Pop(PopReason::ObjectVal));
1654                    }
1655                    self.stack.push(Instruction::Value(ValueReason::ObjectVal));
1656                }
1657                Ok(wip)
1658            }
1659            Outcome::ObjectEnded => {
1660                trace!("Object closing");
1661                Ok(wip)
1662            }
1663            _ => Err(self.err(DeserErrorKind::UnexpectedOutcome {
1664                got: outcome.node.into_owned(),
1665                wanted: "scalar or object close",
1666            })),
1667        }
1668    }
1669
1670    fn list_item_or_list_close<'facet>(
1671        &mut self,
1672        mut wip: Partial<'facet>,
1673        outcome: Spanned<Outcome<'input>>,
1674    ) -> Result<Partial<'facet>, DeserError<'input>>
1675    where
1676        'input: 'facet,
1677    {
1678        trace!(
1679            "--- STACK has {:?} {}",
1680            self.stack.green(),
1681            "(LI/LC)".bright_yellow()
1682        );
1683        match outcome.node {
1684            Outcome::ListEnded => {
1685                trace!("List close");
1686                // Clean up array index tracking if this was an array
1687                let shape = wip.shape();
1688                if matches!(shape.def, Def::Array(_)) {
1689                    self.array_indices.pop();
1690                }
1691
1692                // Clean up enum tuple variant tracking if this was an enum tuple
1693                if let Type::User(UserType::Enum(_)) = shape.ty {
1694                    if self.enum_tuple_field_count.is_some() {
1695                        trace!("Enum tuple variant list ended");
1696                        self.enum_tuple_field_count = None;
1697                        self.enum_tuple_current_field = None;
1698                    }
1699                }
1700
1701                // Special case: if we're at an empty tuple, we've successfully parsed it
1702                if let Type::User(UserType::Struct(st)) = shape.ty {
1703                    if st.kind == StructKind::Tuple && st.fields.is_empty() {
1704                        trace!("Empty tuple parsed from []");
1705                        // The empty tuple is complete - no fields to initialize
1706                    }
1707                }
1708
1709                // Don't end the list here - let the Pop instruction handle it
1710                Ok(wip)
1711            }
1712            _ => {
1713                self.stack.push(Instruction::ListItemOrListClose);
1714                self.stack.push(Instruction::Pop(PopReason::ListVal));
1715
1716                trace!(
1717                    "Expecting list item, doing a little push before doing value with outcome {}",
1718                    outcome.magenta()
1719                );
1720                trace!("Before push, wip.shape is {}", wip.shape().blue());
1721
1722                // Different handling for arrays vs lists
1723                let shape = wip.shape();
1724                match shape.def {
1725                    Def::Array(ad) => {
1726                        // Arrays use the last index in our tracking vector
1727                        if let Some(current_index) = self.array_indices.last().copied() {
1728                            // Check bounds
1729                            if current_index >= ad.n {
1730                                return Err(self.err(DeserErrorKind::ArrayOverflow {
1731                                    shape,
1732                                    max_len: ad.n,
1733                                }));
1734                            }
1735
1736                            // Set this array element
1737                            wip.begin_nth_field(current_index)
1738                                .map_err(|e| self.reflect_err(e))?;
1739
1740                            // Increment the index for next time
1741                            if let Some(last) = self.array_indices.last_mut() {
1742                                *last += 1;
1743                            }
1744                        } else {
1745                            // This shouldn't happen if we properly initialize in ListStarted
1746                            return Err(self.err(DeserErrorKind::Unimplemented(
1747                                "Array index tracking not initialized",
1748                            )));
1749                        }
1750                    }
1751                    Def::List(_) => {
1752                        wip.begin_list_item().map_err(|e| self.reflect_err(e))?;
1753                    }
1754                    _ => {
1755                        // Check if this is a smart pointer with slice pointee
1756                        if matches!(shape.def, Def::Pointer(_)) {
1757                            trace!("List item for smart pointer slice");
1758                            wip.begin_list_item().map_err(|e| self.reflect_err(e))?;
1759                        }
1760                        // Check if this is an enum tuple variant
1761                        else if let Type::User(UserType::Enum(_)) = shape.ty {
1762                            if let (Some(field_count), Some(current_field)) =
1763                                (self.enum_tuple_field_count, self.enum_tuple_current_field)
1764                            {
1765                                if current_field >= field_count {
1766                                    // Too many elements for this tuple variant
1767                                    return Err(self.err(DeserErrorKind::ArrayOverflow {
1768                                        shape,
1769                                        max_len: field_count,
1770                                    }));
1771                                }
1772
1773                                // Process this tuple field
1774                                wip.begin_nth_field(current_field)
1775                                    .map_err(|e| self.reflect_err(e))?;
1776
1777                                // Advance to next field
1778                                self.enum_tuple_current_field = Some(current_field + 1);
1779                            } else {
1780                                return Err(self.err(DeserErrorKind::UnsupportedType {
1781                                    got: shape,
1782                                    wanted: "enum with tuple variant selected",
1783                                }));
1784                            }
1785                        }
1786                        // Check if this is a tuple
1787                        else if let Type::User(UserType::Struct(struct_type)) = shape.ty {
1788                            if struct_type.kind == StructKind::Tuple {
1789                                // Tuples use field indexing
1790                                // Find the next uninitialized field
1791                                let mut field_index = None;
1792                                for i in 0..struct_type.fields.len() {
1793                                    if !wip.is_field_set(i).map_err(|e| self.reflect_err(e))? {
1794                                        field_index = Some(i);
1795                                        break;
1796                                    }
1797                                }
1798
1799                                if let Some(idx) = field_index {
1800                                    wip.begin_nth_field(idx).map_err(|e| self.reflect_err(e))?;
1801                                } else {
1802                                    // All fields are set, this is too many elements
1803                                    return Err(self.err(DeserErrorKind::ArrayOverflow {
1804                                        shape,
1805                                        max_len: struct_type.fields.len(),
1806                                    }));
1807                                }
1808                            } else {
1809                                // Not a tuple struct
1810                                return Err(self.err(DeserErrorKind::UnsupportedType {
1811                                    got: shape,
1812                                    wanted: "array, list, or tuple",
1813                                }));
1814                            }
1815                        } else {
1816                            // Not a struct type at all
1817                            return Err(self.err(DeserErrorKind::UnsupportedType {
1818                                got: shape,
1819                                wanted: "array, list, or tuple",
1820                            }));
1821                        }
1822                    }
1823                }
1824
1825                trace!(" After push, wip.shape is {}", wip.shape().cyan());
1826
1827                // Special handling: if we're now at an empty tuple and we see a list start,
1828                // we can handle the flexible coercion from []
1829                if matches!(outcome.node, Outcome::ListStarted) {
1830                    if let Type::User(UserType::Struct(st)) = wip.shape().ty {
1831                        if st.kind == StructKind::Tuple && st.fields.is_empty() {
1832                            trace!(
1833                                "Empty tuple field with list start - initializing empty tuple and expecting immediate close"
1834                            );
1835                            // Initialize the empty tuple with default value since it has no fields to fill
1836                            wip.set_default().map_err(|e| self.reflect_err(e))?;
1837                            // Continue processing - we still need to handle the list close
1838                        }
1839                    }
1840                }
1841
1842                wip = self.value(wip, outcome)?;
1843                Ok(wip)
1844            }
1845        }
1846    }
1847}
1848
1849#[cfg(test)]
1850mod tests {
1851    #[test]
1852    fn it_works() {}
1853}