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