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