Skip to main content

facet_format/
deserializer.rs

1extern crate alloc;
2
3use alloc::borrow::Cow;
4use alloc::format;
5
6use facet_core::{Def, Facet, NumericType, PrimitiveType, Shape, StructKind, Type, UserType};
7pub use facet_path::{Path, PathStep};
8use facet_reflect::{HeapValue, Partial, is_spanned_shape};
9
10use crate::{ContainerKind, FormatParser, ParseEvent, ScalarTypeHint, ScalarValue};
11
12mod error;
13pub use error::*;
14
15mod dynamic;
16mod eenum;
17mod pointer;
18mod scalar_matches;
19mod setters;
20mod struct_simple;
21mod struct_with_flatten;
22mod validate;
23
24/// Generic deserializer that drives a format-specific parser directly into `Partial`.
25///
26/// The const generic `BORROW` controls whether string data can be borrowed:
27/// - `BORROW=true`: strings without escapes are borrowed from input
28/// - `BORROW=false`: all strings are owned
29pub struct FormatDeserializer<'input, const BORROW: bool, P> {
30    parser: P,
31    /// The span of the most recently consumed event (for error reporting).
32    last_span: Option<facet_reflect::Span>,
33    /// Current path through the type structure (for error reporting).
34    current_path: Path,
35    _marker: core::marker::PhantomData<&'input ()>,
36}
37
38impl<'input, P> FormatDeserializer<'input, true, P> {
39    /// Create a new deserializer that can borrow strings from input.
40    pub const fn new(parser: P) -> Self {
41        Self {
42            parser,
43            last_span: None,
44            current_path: Path::new(),
45            _marker: core::marker::PhantomData,
46        }
47    }
48}
49
50impl<'input, P> FormatDeserializer<'input, false, P> {
51    /// Create a new deserializer that produces owned strings.
52    pub const fn new_owned(parser: P) -> Self {
53        Self {
54            parser,
55            last_span: None,
56            current_path: Path::new(),
57            _marker: core::marker::PhantomData,
58        }
59    }
60}
61
62impl<'input, const BORROW: bool, P> FormatDeserializer<'input, BORROW, P> {
63    /// Consume the facade and return the underlying parser.
64    pub fn into_inner(self) -> P {
65        self.parser
66    }
67
68    /// Borrow the inner parser mutably.
69    pub const fn parser_mut(&mut self) -> &mut P {
70        &mut self.parser
71    }
72}
73
74impl<'input, P> FormatDeserializer<'input, true, P>
75where
76    P: FormatParser<'input>,
77{
78    /// Deserialize the next value in the stream into `T`, allowing borrowed strings.
79    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
80    where
81        T: Facet<'input>,
82    {
83        let wip: Partial<'input, true> =
84            Partial::alloc::<T>().map_err(DeserializeError::reflect)?;
85        let partial = self.deserialize_into(wip)?;
86        let heap_value: HeapValue<'input, true> =
87            partial.build().map_err(DeserializeError::reflect)?;
88        heap_value
89            .materialize::<T>()
90            .map_err(DeserializeError::reflect)
91    }
92
93    /// Deserialize the next value in the stream into `T` (for backward compatibility).
94    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
95    where
96        T: Facet<'input>,
97    {
98        self.deserialize()
99    }
100
101    /// Deserialize using deferred mode, allowing interleaved field initialization.
102    ///
103    /// This is required for formats like TOML that allow table reopening, where
104    /// fields of a nested struct may be set, then fields of a sibling, then more
105    /// fields of the original struct.
106    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
107    where
108        T: Facet<'input>,
109    {
110        let wip: Partial<'input, true> =
111            Partial::alloc::<T>().map_err(DeserializeError::reflect)?;
112        let wip = wip.begin_deferred().map_err(DeserializeError::reflect)?;
113        let partial = self.deserialize_into(wip)?;
114        let partial = partial
115            .finish_deferred()
116            .map_err(DeserializeError::reflect)?;
117        let heap_value: HeapValue<'input, true> =
118            partial.build().map_err(DeserializeError::reflect)?;
119        heap_value
120            .materialize::<T>()
121            .map_err(DeserializeError::reflect)
122    }
123}
124
125impl<'input, P> FormatDeserializer<'input, false, P>
126where
127    P: FormatParser<'input>,
128{
129    /// Deserialize the next value in the stream into `T`, using owned strings.
130    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
131    where
132        T: Facet<'static>,
133    {
134        // SAFETY: alloc_owned produces Partial<'static, false>, but our deserializer
135        // expects 'input. Since BORROW=false means we never borrow from input anyway,
136        // this is safe. We also transmute the HeapValue back to 'static before materializing.
137        #[allow(unsafe_code)]
138        let wip: Partial<'input, false> = unsafe {
139            core::mem::transmute::<Partial<'static, false>, Partial<'input, false>>(
140                Partial::alloc_owned::<T>().map_err(DeserializeError::reflect)?,
141            )
142        };
143        let partial = self.deserialize_into(wip)?;
144        let heap_value: HeapValue<'input, false> =
145            partial.build().map_err(DeserializeError::reflect)?;
146
147        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
148        // The transmute only changes the phantom lifetime marker.
149        #[allow(unsafe_code)]
150        let heap_value: HeapValue<'static, false> = unsafe {
151            core::mem::transmute::<HeapValue<'input, false>, HeapValue<'static, false>>(heap_value)
152        };
153
154        heap_value
155            .materialize::<T>()
156            .map_err(DeserializeError::reflect)
157    }
158
159    /// Deserialize the next value in the stream into `T` (for backward compatibility).
160    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
161    where
162        T: Facet<'static>,
163    {
164        self.deserialize()
165    }
166
167    /// Deserialize using deferred mode, allowing interleaved field initialization.
168    ///
169    /// This is required for formats like TOML that allow table reopening, where
170    /// fields of a nested struct may be set, then fields of a sibling, then more
171    /// fields of the original struct.
172    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError<P::Error>>
173    where
174        T: Facet<'static>,
175    {
176        // SAFETY: alloc_owned produces Partial<'static, false>, but our deserializer
177        // expects 'input. Since BORROW=false means we never borrow from input anyway,
178        // this is safe. We also transmute the HeapValue back to 'static before materializing.
179        #[allow(unsafe_code)]
180        let wip: Partial<'input, false> = unsafe {
181            core::mem::transmute::<Partial<'static, false>, Partial<'input, false>>(
182                Partial::alloc_owned::<T>().map_err(DeserializeError::reflect)?,
183            )
184        };
185        let wip = wip.begin_deferred().map_err(DeserializeError::reflect)?;
186        let partial = self.deserialize_into(wip)?;
187        let partial = partial
188            .finish_deferred()
189            .map_err(DeserializeError::reflect)?;
190        let heap_value: HeapValue<'input, false> =
191            partial.build().map_err(DeserializeError::reflect)?;
192
193        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
194        // The transmute only changes the phantom lifetime marker.
195        #[allow(unsafe_code)]
196        let heap_value: HeapValue<'static, false> = unsafe {
197            core::mem::transmute::<HeapValue<'input, false>, HeapValue<'static, false>>(heap_value)
198        };
199
200        heap_value
201            .materialize::<T>()
202            .map_err(DeserializeError::reflect)
203    }
204
205    /// Deserialize using an explicit source shape for parser hints.
206    ///
207    /// This is useful for non-self-describing formats like postcard where you need
208    /// to decode data that was serialized using a specific type, but you only have
209    /// the shape information at runtime (not the concrete type).
210    ///
211    /// The target type `T` should typically be a `DynamicValue` like `facet_value::Value`.
212    pub fn deserialize_with_shape<T>(
213        &mut self,
214        source_shape: &'static Shape,
215    ) -> Result<T, DeserializeError<P::Error>>
216    where
217        T: Facet<'static>,
218    {
219        #[allow(unsafe_code)]
220        let wip: Partial<'input, false> = unsafe {
221            core::mem::transmute::<Partial<'static, false>, Partial<'input, false>>(
222                Partial::alloc_owned::<T>().map_err(DeserializeError::reflect)?,
223            )
224        };
225        let partial = self.deserialize_into_with_shape(wip, source_shape)?;
226        let heap_value: HeapValue<'input, false> =
227            partial.build().map_err(DeserializeError::reflect)?;
228
229        #[allow(unsafe_code)]
230        let heap_value: HeapValue<'static, false> = unsafe {
231            core::mem::transmute::<HeapValue<'input, false>, HeapValue<'static, false>>(heap_value)
232        };
233
234        heap_value
235            .materialize::<T>()
236            .map_err(DeserializeError::reflect)
237    }
238}
239
240impl<'input, const BORROW: bool, P> FormatDeserializer<'input, BORROW, P>
241where
242    P: FormatParser<'input>,
243{
244    /// Read the next event, returning an error if EOF is reached.
245    #[inline]
246    fn expect_event(
247        &mut self,
248        expected: &'static str,
249    ) -> Result<ParseEvent<'input>, DeserializeError<P::Error>> {
250        let event = self
251            .parser
252            .next_event()
253            .map_err(DeserializeError::Parser)?
254            .ok_or(DeserializeError::UnexpectedEof { expected })?;
255        trace!(?event, expected, "expect_event: got event");
256        // Capture the span of the consumed event for error reporting
257        self.last_span = self.parser.current_span();
258        Ok(event)
259    }
260
261    /// Peek at the next event, returning an error if EOF is reached.
262    #[inline]
263    fn expect_peek(
264        &mut self,
265        expected: &'static str,
266    ) -> Result<ParseEvent<'input>, DeserializeError<P::Error>> {
267        let event = self
268            .parser
269            .peek_event()
270            .map_err(DeserializeError::Parser)?
271            .ok_or(DeserializeError::UnexpectedEof { expected })?;
272        trace!(?event, expected, "expect_peek: peeked event");
273        Ok(event)
274    }
275
276    /// Push a step onto the current path (for error reporting).
277    #[inline]
278    fn push_path(&mut self, step: PathStep) {
279        self.current_path.push(step);
280    }
281
282    /// Pop the last step from the current path.
283    #[inline]
284    fn pop_path(&mut self) {
285        self.current_path.pop();
286    }
287
288    /// Get a clone of the current path (for attaching to errors).
289    #[inline]
290    fn path_clone(&self) -> Path {
291        self.current_path.clone()
292    }
293
294    /// Main deserialization entry point - deserialize into a Partial.
295    pub fn deserialize_into(
296        &mut self,
297        mut wip: Partial<'input, BORROW>,
298    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
299        let shape = wip.shape();
300        trace!(
301            shape_name = shape.type_identifier,
302            "deserialize_into: starting"
303        );
304
305        // Check for raw capture type (e.g., RawJson)
306        // Raw capture types are tuple structs with a single Cow<str> field
307        // If capture_raw returns None (e.g., streaming mode), fall through
308        // and try normal deserialization (which will likely fail with a helpful error)
309        if self.parser.raw_capture_shape() == Some(shape)
310            && let Some(raw) = self
311                .parser
312                .capture_raw()
313                .map_err(DeserializeError::Parser)?
314        {
315            // The raw type is a tuple struct like RawJson(Cow<str>)
316            // Access field 0 (the Cow<str>) and set it
317            wip = wip.begin_nth_field(0).map_err(DeserializeError::reflect)?;
318            wip = self.set_string_value(wip, Cow::Borrowed(raw))?;
319            wip = wip.end().map_err(DeserializeError::reflect)?;
320            return Ok(wip);
321        }
322
323        // Check for container-level proxy (format-specific proxies take precedence)
324        let format_ns = self.parser.format_namespace();
325        let (wip_returned, has_proxy) = wip
326            .begin_custom_deserialization_from_shape_with_format(format_ns)
327            .map_err(DeserializeError::reflect)?;
328        wip = wip_returned;
329        if has_proxy {
330            wip = self.deserialize_into(wip)?;
331            return wip.end().map_err(DeserializeError::reflect);
332        }
333
334        // Check for field-level proxy (opaque types with proxy attribute)
335        // Format-specific proxies take precedence over format-agnostic proxies
336        if wip
337            .parent_field()
338            .and_then(|field| field.effective_proxy(format_ns))
339            .is_some()
340        {
341            wip = wip
342                .begin_custom_deserialization_with_format(format_ns)
343                .map_err(DeserializeError::reflect)?;
344            wip = self.deserialize_into(wip)?;
345            wip = wip.end().map_err(DeserializeError::reflect)?;
346            return Ok(wip);
347        }
348
349        // Check Def first for Option
350        if matches!(&shape.def, Def::Option(_)) {
351            return self.deserialize_option(wip);
352        }
353
354        // Check Def for Result - treat it as a 2-variant enum
355        if matches!(&shape.def, Def::Result(_)) {
356            return self.deserialize_result_as_enum(wip);
357        }
358
359        // Priority 1: Check for builder_shape (immutable collections like Bytes -> BytesMut)
360        if shape.builder_shape.is_some() {
361            wip = wip.begin_inner().map_err(DeserializeError::reflect)?;
362            wip = self.deserialize_into(wip)?;
363            wip = wip.end().map_err(DeserializeError::reflect)?;
364            return Ok(wip);
365        }
366
367        // Priority 2: Check for smart pointers (Box, Arc, Rc)
368        if matches!(&shape.def, Def::Pointer(_)) {
369            return self.deserialize_pointer(wip);
370        }
371
372        // Priority 3: Check for .inner (transparent wrappers like NonZero)
373        // Collections (List/Map/Set/Array) have .inner for variance but shouldn't use this path
374        // Opaque scalars (like ULID) may have .inner for documentation but should NOT be
375        // deserialized as transparent wrappers - they use hint_opaque_scalar instead
376        let is_opaque_scalar =
377            matches!(shape.def, Def::Scalar) && matches!(shape.ty, Type::User(UserType::Opaque));
378        if shape.inner.is_some()
379            && !is_opaque_scalar
380            && !matches!(
381                &shape.def,
382                Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
383            )
384        {
385            wip = wip.begin_inner().map_err(DeserializeError::reflect)?;
386            wip = self.deserialize_into(wip)?;
387            wip = wip.end().map_err(DeserializeError::reflect)?;
388            return Ok(wip);
389        }
390
391        // Priority 4: Check for metadata-annotated types (like Spanned<T>)
392        if is_spanned_shape(shape) {
393            return self.deserialize_spanned(wip);
394        }
395
396        // Priority 4.5: Check for metadata containers (like Documented<T>)
397        // These deserialize transparently - metadata fields stay at defaults, value field gets the data
398        if shape.is_metadata_container() {
399            trace!("deserialize_into: metadata container detected, deserializing transparently");
400            if let Type::User(UserType::Struct(st)) = &shape.ty {
401                for field in st.fields {
402                    if field.metadata_kind().is_none() {
403                        // This is the value field - recurse into it with the current event stream
404                        wip = wip
405                            .begin_field(field.effective_name())
406                            .map_err(DeserializeError::reflect)?;
407                        wip = self.deserialize_into(wip)?;
408                        wip = wip.end().map_err(DeserializeError::reflect)?;
409                    }
410                    // Metadata fields stay at their defaults (None for doc)
411                }
412            }
413            return Ok(wip);
414        }
415
416        // Priority 5: Check the Type for structs and enums
417        match &shape.ty {
418            Type::User(UserType::Struct(struct_def)) => {
419                if matches!(struct_def.kind, StructKind::Tuple | StructKind::TupleStruct) {
420                    trace!("deserialize_into: dispatching to deserialize_tuple");
421                    return self.deserialize_tuple(wip);
422                }
423                trace!("deserialize_into: dispatching to deserialize_struct");
424                return self.deserialize_struct(wip);
425            }
426            Type::User(UserType::Enum(_)) => {
427                trace!("deserialize_into: dispatching to deserialize_enum");
428                return self.deserialize_enum(wip);
429            }
430            _ => {}
431        }
432
433        // Priority 6: Check Def for containers and scalars
434        match &shape.def {
435            Def::Scalar => {
436                trace!("deserialize_into: dispatching to deserialize_scalar");
437                self.deserialize_scalar(wip)
438            }
439            Def::List(_) => {
440                trace!("deserialize_into: dispatching to deserialize_list");
441                self.deserialize_list(wip)
442            }
443            Def::Map(_) => {
444                trace!("deserialize_into: dispatching to deserialize_map");
445                self.deserialize_map(wip)
446            }
447            Def::Array(_) => {
448                trace!("deserialize_into: dispatching to deserialize_array");
449                self.deserialize_array(wip)
450            }
451            Def::Set(_) => {
452                trace!("deserialize_into: dispatching to deserialize_set");
453                self.deserialize_set(wip)
454            }
455            Def::DynamicValue(_) => {
456                trace!("deserialize_into: dispatching to deserialize_dynamic_value");
457                self.deserialize_dynamic_value(wip)
458            }
459            _ => Err(DeserializeError::Unsupported(format!(
460                "unsupported shape def: {:?}",
461                shape.def
462            ))),
463        }
464    }
465
466    /// Deserialize using an explicit source shape for parser hints.
467    ///
468    /// This walks `hint_shape` for control flow and parser hints, but builds
469    /// into the `wip` Partial (which should be a DynamicValue like `Value`).
470    pub fn deserialize_into_with_shape(
471        &mut self,
472        wip: Partial<'input, BORROW>,
473        hint_shape: &'static Shape,
474    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
475        self.deserialize_value_recursive(wip, hint_shape)
476    }
477
478    /// Internal recursive deserialization using hint_shape for dispatch.
479    fn deserialize_value_recursive(
480        &mut self,
481        mut wip: Partial<'input, BORROW>,
482        hint_shape: &'static Shape,
483    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
484        // Handle Option
485        if let Def::Option(opt_def) = &hint_shape.def {
486            self.parser.hint_option();
487            let event = self.expect_peek("value for option")?;
488            // Treat both Null and Unit as None
489            // Unit is used by Styx for tags without payload (e.g., @string vs @string{...})
490            if matches!(
491                event,
492                ParseEvent::Scalar(ScalarValue::Null | ScalarValue::Unit)
493            ) {
494                let _ = self.expect_event("null or unit")?;
495                wip = wip.set_default().map_err(DeserializeError::reflect)?;
496            } else {
497                wip = self.deserialize_value_recursive(wip, opt_def.t)?;
498            }
499            return Ok(wip);
500        }
501
502        // Handle smart pointers - unwrap to inner type
503        if let Def::Pointer(ptr_def) = &hint_shape.def
504            && let Some(pointee) = ptr_def.pointee()
505        {
506            return self.deserialize_value_recursive(wip, pointee);
507        }
508
509        // Handle transparent wrappers (but not collections)
510        if let Some(inner) = hint_shape.inner
511            && !matches!(
512                &hint_shape.def,
513                Def::List(_) | Def::Map(_) | Def::Set(_) | Def::Array(_)
514            )
515        {
516            return self.deserialize_value_recursive(wip, inner);
517        }
518
519        // Dispatch based on hint shape type
520        match &hint_shape.ty {
521            Type::User(UserType::Struct(struct_def)) => {
522                if matches!(struct_def.kind, StructKind::Tuple | StructKind::TupleStruct) {
523                    self.deserialize_tuple_dynamic(wip, struct_def.fields)
524                } else {
525                    self.deserialize_struct_dynamic(wip, struct_def.fields)
526                }
527            }
528            Type::User(UserType::Enum(enum_def)) => self.deserialize_enum_dynamic(wip, enum_def),
529            _ => match &hint_shape.def {
530                Def::Scalar => self.deserialize_scalar_dynamic(wip, hint_shape),
531                Def::List(list_def) => self.deserialize_list_dynamic(wip, list_def.t),
532                Def::Array(array_def) => {
533                    self.deserialize_array_dynamic(wip, array_def.t, array_def.n)
534                }
535                Def::Map(map_def) => self.deserialize_map_dynamic(wip, map_def.k, map_def.v),
536                Def::Set(set_def) => self.deserialize_list_dynamic(wip, set_def.t),
537                _ => Err(DeserializeError::Unsupported(format!(
538                    "unsupported hint shape for dynamic deserialization: {:?}",
539                    hint_shape.def
540                ))),
541            },
542        }
543    }
544
545    fn deserialize_option(
546        &mut self,
547        mut wip: Partial<'input, BORROW>,
548    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
549        // Hint to non-self-describing parsers that an Option is expected
550        self.parser.hint_option();
551
552        let event = self.expect_peek("value for option")?;
553
554        // Treat both Null and Unit as None
555        // Unit is used by Styx for tags without payload (e.g., @string vs @string{...})
556        if matches!(
557            event,
558            ParseEvent::Scalar(ScalarValue::Null | ScalarValue::Unit)
559        ) {
560            // Consume the null/unit
561            let _ = self.expect_event("null or unit")?;
562            // Set to None (default)
563            wip = wip.set_default().map_err(DeserializeError::reflect)?;
564        } else {
565            // Some(value)
566            wip = wip.begin_some().map_err(DeserializeError::reflect)?;
567            wip = self.deserialize_into(wip)?;
568            wip = wip.end().map_err(DeserializeError::reflect)?;
569        }
570        Ok(wip)
571    }
572
573    /// Check if a field matches a given name by effective name or alias.
574    fn field_matches(field: &facet_core::Field, name: &str) -> bool {
575        field.effective_name() == name || field.alias.iter().any(|alias| *alias == name)
576    }
577
578    /// Get the display name for a variant (respecting rename attribute).
579    fn get_variant_display_name(variant: &facet_core::Variant) -> &'static str {
580        variant.effective_name()
581    }
582
583    /// Find a variant by its display name (checking rename attributes).
584    /// Returns the effective name to use with `select_variant_named`.
585    fn find_variant_by_display_name<'a>(
586        enum_def: &'a facet_core::EnumType,
587        display_name: &str,
588    ) -> Option<&'a str> {
589        enum_def.variants.iter().find_map(|v| {
590            if v.effective_name() == display_name {
591                Some(v.effective_name())
592            } else {
593                None
594            }
595        })
596    }
597
598    fn deserialize_struct(
599        &mut self,
600        wip: Partial<'input, BORROW>,
601    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
602        // Get struct fields for lookup
603        let struct_def = match &wip.shape().ty {
604            Type::User(UserType::Struct(def)) => def,
605            _ => {
606                return Err(DeserializeError::Unsupported(format!(
607                    "expected struct type but got {:?}",
608                    wip.shape().ty
609                )));
610            }
611        };
612
613        // Check if we have any flattened fields
614        let has_flatten = struct_def.fields.iter().any(|f| f.is_flattened());
615
616        if has_flatten {
617            self.deserialize_struct_with_flatten(wip)
618        } else {
619            self.deserialize_struct_simple(wip)
620        }
621    }
622
623    /// Deserialize into a type with span metadata (like `Spanned<T>`).
624    ///
625    /// This handles structs that have:
626    /// - One or more non-metadata fields (the actual values to deserialize)
627    /// - A field with `#[facet(metadata = span)]` to store source location
628    ///
629    /// The metadata field is populated with a default span since most format parsers
630    /// don't track source locations.
631    fn deserialize_spanned(
632        &mut self,
633        mut wip: Partial<'input, BORROW>,
634    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
635        let shape = wip.shape();
636
637        // Find the span metadata field and non-metadata fields
638        let Type::User(UserType::Struct(struct_def)) = &shape.ty else {
639            return Err(DeserializeError::Unsupported(format!(
640                "expected struct with span metadata, found {}",
641                shape.type_identifier
642            )));
643        };
644
645        let span_field = struct_def
646            .fields
647            .iter()
648            .find(|f| f.metadata_kind() == Some("span"))
649            .ok_or_else(|| {
650                DeserializeError::Unsupported(format!(
651                    "expected struct with span metadata field, found {}",
652                    shape.type_identifier
653                ))
654            })?;
655
656        let value_fields: alloc::vec::Vec<_> = struct_def
657            .fields
658            .iter()
659            .filter(|f| !f.is_metadata())
660            .collect();
661
662        // Deserialize all non-metadata fields transparently
663        // For the common case (Spanned<T> with a single "value" field), this is just one field
664        for field in value_fields {
665            wip = wip
666                .begin_field(field.name)
667                .map_err(DeserializeError::reflect)?;
668            wip = self.deserialize_into(wip)?;
669            wip = wip.end().map_err(DeserializeError::reflect)?;
670        }
671
672        // Set the span metadata field to default
673        // Most format parsers don't track source spans, so we use a default (unknown) span
674        wip = wip
675            .begin_field(span_field.name)
676            .map_err(DeserializeError::reflect)?;
677        wip = wip.set_default().map_err(DeserializeError::reflect)?;
678        wip = wip.end().map_err(DeserializeError::reflect)?;
679
680        Ok(wip)
681    }
682
683    fn deserialize_tuple(
684        &mut self,
685        mut wip: Partial<'input, BORROW>,
686    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
687        // Get field count for tuple hints
688        let field_count = match &wip.shape().ty {
689            Type::User(UserType::Struct(def)) => def.fields.len(),
690            _ => 0, // Unit type or unknown - will be handled below
691        };
692
693        // Hint to non-self-describing parsers how many fields to expect
694        // Tuples are like positional structs, so we use hint_struct_fields
695        self.parser.hint_struct_fields(field_count);
696
697        // Special case: transparent newtypes (marked with #[facet(transparent)] or
698        // #[repr(transparent)]) can accept values directly without a sequence wrapper.
699        // This enables patterns like:
700        //   #[facet(transparent)]
701        //   struct Wrapper(i32);
702        //   toml: "value = 42"  ->  Wrapper(42)
703        // Plain tuple structs without the transparent attribute use array syntax.
704        if field_count == 1 && wip.shape().is_transparent() {
705            // Unwrap into field "0" and deserialize directly
706            wip = wip.begin_field("0").map_err(DeserializeError::reflect)?;
707            wip = self.deserialize_into(wip)?;
708            wip = wip.end().map_err(DeserializeError::reflect)?;
709            return Ok(wip);
710        }
711
712        // Special case: unit type () can accept Scalar(Unit) directly
713        // This enables patterns like styx bare identifiers: { id, name } -> IndexMap<String, ()>
714        if field_count == 0 && matches!(self.expect_peek("value")?, ParseEvent::Scalar(ScalarValue::Unit)) {
715            self.expect_event("value")?; // consume the unit scalar
716            return Ok(wip);
717        }
718
719        let event = self.expect_event("value")?;
720
721        // Accept either SequenceStart (JSON arrays) or StructStart (for
722        // non-self-describing formats like postcard where tuples are positional structs)
723        let struct_mode = match event {
724            ParseEvent::SequenceStart(_) => false,
725            // For non-self-describing formats, StructStart(Object) is valid for tuples
726            // because hint_struct_fields was called and tuples are positional structs
727            ParseEvent::StructStart(_) if !self.parser.is_self_describing() => true,
728            // For self-describing formats like TOML/JSON, objects with numeric keys
729            // (e.g., { "0" = true, "1" = 1 }) are valid tuple representations
730            ParseEvent::StructStart(ContainerKind::Object) => true,
731            ParseEvent::StructStart(kind) => {
732                return Err(DeserializeError::TypeMismatch {
733                    expected: "array",
734                    got: kind.name().into(),
735                    span: self.last_span,
736                    path: None,
737                });
738            }
739            _ => {
740                return Err(DeserializeError::TypeMismatch {
741                    expected: "sequence start for tuple",
742                    got: format!("{event:?}"),
743                    span: self.last_span,
744                    path: None,
745                });
746            }
747        };
748
749        let mut index = 0usize;
750        loop {
751            let event = self.expect_peek("value")?;
752
753            // Check for end of container
754            if matches!(event, ParseEvent::SequenceEnd | ParseEvent::StructEnd) {
755                self.expect_event("value")?;
756                break;
757            }
758
759            // In struct mode, skip FieldKey events
760            if struct_mode && matches!(event, ParseEvent::FieldKey(_)) {
761                self.expect_event("value")?;
762                continue;
763            }
764
765            // Select field by index
766            let field_name = alloc::string::ToString::to_string(&index);
767            wip = wip
768                .begin_field(&field_name)
769                .map_err(DeserializeError::reflect)?;
770            wip = self.deserialize_into(wip)?;
771            wip = wip.end().map_err(DeserializeError::reflect)?;
772            index += 1;
773        }
774
775        Ok(wip)
776    }
777
778    /// Helper to find a tag value from field evidence.
779    fn find_tag_value<'a>(
780        evidence: &'a [crate::FieldEvidence<'input>],
781        tag_key: &str,
782    ) -> Option<&'a str> {
783        evidence
784            .iter()
785            .find(|e| e.name == tag_key)
786            .and_then(|e| match &e.scalar_value {
787                Some(ScalarValue::Str(s)) => Some(s.as_ref()),
788                _ => None,
789            })
790    }
791
792    /// Helper to collect all evidence from a probe stream.
793    fn collect_evidence<S: crate::ProbeStream<'input, Error = P::Error>>(
794        mut probe: S,
795    ) -> Result<alloc::vec::Vec<crate::FieldEvidence<'input>>, P::Error> {
796        let mut evidence = alloc::vec::Vec::new();
797        while let Some(ev) = probe.next()? {
798            evidence.push(ev);
799        }
800        Ok(evidence)
801    }
802
803    fn deserialize_list(
804        &mut self,
805        mut wip: Partial<'input, BORROW>,
806    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
807        trace!("deserialize_list: starting");
808
809        // Check if this is a Vec<u8> - if so, try the optimized byte sequence path
810        // We specifically check for Vec (not Bytes, BytesMut, or other list-like types)
811        // because those types may have different builder patterns
812        let is_byte_vec = wip.shape().type_identifier == "Vec"
813            && matches!(
814                &wip.shape().def,
815                Def::List(list_def) if list_def.t.type_identifier == "u8"
816            );
817
818        if is_byte_vec && self.parser.hint_byte_sequence() {
819            // Parser supports bulk byte reading - expect Scalar(Bytes(...))
820            let event = self.expect_event("bytes")?;
821            trace!(?event, "deserialize_list: got bytes event");
822
823            return match event {
824                ParseEvent::Scalar(ScalarValue::Bytes(bytes)) => self.set_bytes_value(wip, bytes),
825                _ => Err(DeserializeError::TypeMismatch {
826                    expected: "bytes",
827                    got: format!("{event:?}"),
828                    span: self.last_span,
829                    path: None,
830                }),
831            };
832        }
833
834        // Fallback: element-by-element deserialization
835        // Hint to non-self-describing parsers that a sequence is expected
836        self.parser.hint_sequence();
837
838        let event = self.expect_event("value")?;
839        trace!(?event, "deserialize_list: got container start event");
840
841        // Expect SequenceStart for lists
842        match event {
843            ParseEvent::SequenceStart(_) => {
844                trace!("deserialize_list: got sequence start");
845            }
846            ParseEvent::StructStart(kind) => {
847                return Err(DeserializeError::TypeMismatch {
848                    expected: "array",
849                    got: kind.name().into(),
850                    span: self.last_span,
851                    path: None,
852                });
853            }
854            _ => {
855                return Err(DeserializeError::TypeMismatch {
856                    expected: "sequence start",
857                    got: format!("{event:?}"),
858                    span: self.last_span,
859                    path: None,
860                });
861            }
862        };
863
864        // Initialize the list
865        wip = wip.init_list().map_err(DeserializeError::reflect)?;
866        trace!("deserialize_list: initialized list, starting loop");
867
868        loop {
869            let event = self.expect_peek("value")?;
870            trace!(?event, "deserialize_list: loop iteration");
871
872            // Check for end of sequence
873            if matches!(event, ParseEvent::SequenceEnd) {
874                self.expect_event("value")?;
875                trace!("deserialize_list: reached end of sequence");
876                break;
877            }
878
879            trace!("deserialize_list: deserializing list item");
880            wip = wip.begin_list_item().map_err(DeserializeError::reflect)?;
881            wip = self.deserialize_into(wip)?;
882            wip = wip.end().map_err(DeserializeError::reflect)?;
883        }
884
885        trace!("deserialize_list: completed");
886        Ok(wip)
887    }
888
889    fn deserialize_array(
890        &mut self,
891        mut wip: Partial<'input, BORROW>,
892    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
893        // Get the fixed array length from the type definition
894        let array_len = match &wip.shape().def {
895            Def::Array(array_def) => array_def.n,
896            _ => {
897                return Err(DeserializeError::Unsupported(
898                    "deserialize_array called on non-array type".into(),
899                ));
900            }
901        };
902
903        // Hint to non-self-describing parsers that a fixed-size array is expected
904        // (unlike hint_sequence, this doesn't read a length prefix)
905        self.parser.hint_array(array_len);
906
907        let event = self.expect_event("value")?;
908
909        // Expect SequenceStart for arrays
910        match event {
911            ParseEvent::SequenceStart(_) => {}
912            ParseEvent::StructStart(kind) => {
913                return Err(DeserializeError::TypeMismatch {
914                    expected: "array",
915                    got: kind.name().into(),
916                    span: self.last_span,
917                    path: None,
918                });
919            }
920            _ => {
921                return Err(DeserializeError::TypeMismatch {
922                    expected: "sequence start for array",
923                    got: format!("{event:?}"),
924                    span: self.last_span,
925                    path: None,
926                });
927            }
928        };
929
930        // Transition to Array tracker state. This is important for empty arrays
931        // like [u8; 0] which have no elements to initialize but still need
932        // their tracker state set correctly for require_full_initialization to pass.
933        wip = wip.init_array().map_err(DeserializeError::reflect)?;
934
935        let mut index = 0usize;
936        loop {
937            let event = self.expect_peek("value")?;
938
939            // Check for end of sequence
940            if matches!(event, ParseEvent::SequenceEnd) {
941                self.expect_event("value")?;
942                break;
943            }
944
945            wip = wip
946                .begin_nth_field(index)
947                .map_err(DeserializeError::reflect)?;
948            wip = self.deserialize_into(wip)?;
949            wip = wip.end().map_err(DeserializeError::reflect)?;
950            index += 1;
951        }
952
953        Ok(wip)
954    }
955
956    fn deserialize_set(
957        &mut self,
958        mut wip: Partial<'input, BORROW>,
959    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
960        // Hint to non-self-describing parsers that a sequence is expected
961        self.parser.hint_sequence();
962
963        let event = self.expect_event("value")?;
964
965        // Expect SequenceStart for sets
966        match event {
967            ParseEvent::SequenceStart(_) => {}
968            ParseEvent::StructStart(kind) => {
969                return Err(DeserializeError::TypeMismatch {
970                    expected: "set",
971                    got: kind.name().into(),
972                    span: self.last_span,
973                    path: None,
974                });
975            }
976            _ => {
977                return Err(DeserializeError::TypeMismatch {
978                    expected: "sequence start for set",
979                    got: format!("{event:?}"),
980                    span: self.last_span,
981                    path: None,
982                });
983            }
984        };
985
986        // Initialize the set
987        wip = wip.init_set().map_err(DeserializeError::reflect)?;
988
989        loop {
990            let event = self.expect_peek("value")?;
991
992            // Check for end of sequence
993            if matches!(event, ParseEvent::SequenceEnd) {
994                self.expect_event("value")?;
995                break;
996            }
997
998            wip = wip.begin_set_item().map_err(DeserializeError::reflect)?;
999            wip = self.deserialize_into(wip)?;
1000            wip = wip.end().map_err(DeserializeError::reflect)?;
1001        }
1002
1003        Ok(wip)
1004    }
1005
1006    fn deserialize_map(
1007        &mut self,
1008        mut wip: Partial<'input, BORROW>,
1009    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
1010        // For non-self-describing formats, hint that a map is expected
1011        self.parser.hint_map();
1012
1013        let event = self.expect_event("value")?;
1014
1015        // Initialize the map
1016        wip = wip.init_map().map_err(DeserializeError::reflect)?;
1017
1018        // Handle both self-describing (StructStart) and non-self-describing (SequenceStart) formats
1019        match event {
1020            ParseEvent::StructStart(_) => {
1021                // Self-describing format (e.g., JSON): maps are represented as objects
1022                loop {
1023                    let event = self.expect_event("value")?;
1024                    match event {
1025                        ParseEvent::StructEnd => break,
1026                        ParseEvent::FieldKey(key) => {
1027                            // Begin key
1028                            wip = wip.begin_key().map_err(DeserializeError::reflect)?;
1029                            wip = self.deserialize_map_key(wip, key.name, key.doc, key.tag)?;
1030                            wip = wip.end().map_err(DeserializeError::reflect)?;
1031
1032                            // Begin value
1033                            wip = wip.begin_value().map_err(DeserializeError::reflect)?;
1034                            wip = self.deserialize_into(wip)?;
1035                            wip = wip.end().map_err(DeserializeError::reflect)?;
1036                        }
1037                        other => {
1038                            return Err(DeserializeError::TypeMismatch {
1039                                expected: "field key or struct end for map",
1040                                got: format!("{other:?}"),
1041                                span: self.last_span,
1042                                path: None,
1043                            });
1044                        }
1045                    }
1046                }
1047            }
1048            ParseEvent::SequenceStart(_) => {
1049                // Non-self-describing format (e.g., postcard): maps are sequences of key-value pairs
1050                loop {
1051                    let event = self.expect_peek("value")?;
1052                    match event {
1053                        ParseEvent::SequenceEnd => {
1054                            self.expect_event("value")?;
1055                            break;
1056                        }
1057                        ParseEvent::OrderedField => {
1058                            self.expect_event("value")?;
1059
1060                            // Deserialize key
1061                            wip = wip.begin_key().map_err(DeserializeError::reflect)?;
1062                            wip = self.deserialize_into(wip)?;
1063                            wip = wip.end().map_err(DeserializeError::reflect)?;
1064
1065                            // Deserialize value
1066                            wip = wip.begin_value().map_err(DeserializeError::reflect)?;
1067                            wip = self.deserialize_into(wip)?;
1068                            wip = wip.end().map_err(DeserializeError::reflect)?;
1069                        }
1070                        other => {
1071                            return Err(DeserializeError::TypeMismatch {
1072                                expected: "ordered field or sequence end for map",
1073                                got: format!("{other:?}"),
1074                                span: self.last_span,
1075                                path: None,
1076                            });
1077                        }
1078                    }
1079                }
1080            }
1081            other => {
1082                return Err(DeserializeError::TypeMismatch {
1083                    expected: "struct start or sequence start for map",
1084                    got: format!("{other:?}"),
1085                    span: self.last_span,
1086                    path: None,
1087                });
1088            }
1089        }
1090
1091        Ok(wip)
1092    }
1093
1094    fn deserialize_scalar(
1095        &mut self,
1096        mut wip: Partial<'input, BORROW>,
1097    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
1098        // Hint to non-self-describing parsers what scalar type is expected
1099        let shape = wip.shape();
1100
1101        // First, try hint_opaque_scalar for types that may have format-specific
1102        // binary representations (e.g., UUID as 16 raw bytes in postcard)
1103        let opaque_handled = match shape.type_identifier {
1104            // Standard primitives are never opaque
1105            "bool" | "u8" | "u16" | "u32" | "u64" | "u128" | "usize" | "i8" | "i16" | "i32"
1106            | "i64" | "i128" | "isize" | "f32" | "f64" | "String" | "&str" | "char" => false,
1107            // For all other scalar types, ask the parser if it handles them specially
1108            _ => self.parser.hint_opaque_scalar(shape.type_identifier, shape),
1109        };
1110
1111        // If the parser didn't handle the opaque type, fall back to standard hints
1112        if !opaque_handled {
1113            let hint = match shape.type_identifier {
1114                "bool" => Some(ScalarTypeHint::Bool),
1115                "u8" => Some(ScalarTypeHint::U8),
1116                "u16" => Some(ScalarTypeHint::U16),
1117                "u32" => Some(ScalarTypeHint::U32),
1118                "u64" => Some(ScalarTypeHint::U64),
1119                "u128" => Some(ScalarTypeHint::U128),
1120                "usize" => Some(ScalarTypeHint::Usize),
1121                "i8" => Some(ScalarTypeHint::I8),
1122                "i16" => Some(ScalarTypeHint::I16),
1123                "i32" => Some(ScalarTypeHint::I32),
1124                "i64" => Some(ScalarTypeHint::I64),
1125                "i128" => Some(ScalarTypeHint::I128),
1126                "isize" => Some(ScalarTypeHint::Isize),
1127                "f32" => Some(ScalarTypeHint::F32),
1128                "f64" => Some(ScalarTypeHint::F64),
1129                "String" | "&str" => Some(ScalarTypeHint::String),
1130                "char" => Some(ScalarTypeHint::Char),
1131                // For unknown scalar types, check if they implement FromStr
1132                // (e.g., camino::Utf8PathBuf, types not handled by hint_opaque_scalar)
1133                _ if shape.is_from_str() => Some(ScalarTypeHint::String),
1134                _ => None,
1135            };
1136            if let Some(hint) = hint {
1137                self.parser.hint_scalar_type(hint);
1138            }
1139        }
1140
1141        let event = self.expect_event("value")?;
1142
1143        match event {
1144            ParseEvent::Scalar(scalar) => {
1145                wip = self.set_scalar(wip, scalar)?;
1146                Ok(wip)
1147            }
1148            ParseEvent::StructStart(_container_kind) => {
1149                // When deserializing into a scalar, extract the _arg value.
1150                let mut found_scalar: Option<ScalarValue<'input>> = None;
1151
1152                loop {
1153                    let inner_event = self.expect_event("field or struct end")?;
1154                    match inner_event {
1155                        ParseEvent::StructEnd => break,
1156                        ParseEvent::FieldKey(key) => {
1157                            // Look for _arg field (single argument)
1158                            if key.name.as_deref() == Some("_arg") {
1159                                let value_event = self.expect_event("argument value")?;
1160                                if let ParseEvent::Scalar(scalar) = value_event {
1161                                    found_scalar = Some(scalar);
1162                                } else {
1163                                    // Skip non-scalar argument
1164                                    self.parser.skip_value().map_err(DeserializeError::Parser)?;
1165                                }
1166                            } else {
1167                                // Skip other fields (_node_name, _arguments, properties, etc.)
1168                                self.parser.skip_value().map_err(DeserializeError::Parser)?;
1169                            }
1170                        }
1171                        _ => {
1172                            // Skip unexpected events
1173                        }
1174                    }
1175                }
1176
1177                if let Some(scalar) = found_scalar {
1178                    wip = self.set_scalar(wip, scalar)?;
1179                    Ok(wip)
1180                } else {
1181                    Err(DeserializeError::TypeMismatch {
1182                        expected: "scalar value or node with argument",
1183                        got: "node without argument".to_string(),
1184                        span: self.last_span,
1185                        path: None,
1186                    })
1187                }
1188            }
1189            other => Err(DeserializeError::TypeMismatch {
1190                expected: "scalar value",
1191                got: format!("{other:?}"),
1192                span: self.last_span,
1193                path: None,
1194            }),
1195        }
1196    }
1197
1198    /// Deserialize a map key from a string or tag.
1199    ///
1200    /// Format parsers typically emit string keys, but the target map might have non-string key types
1201    /// (e.g., integers, enums). This function parses the string key into the appropriate type:
1202    /// - String types: set directly
1203    /// - Enum unit variants: use select_variant_named
1204    /// - Integer types: parse the string as a number
1205    /// - Transparent newtypes: descend into the inner type
1206    /// - Option types: None key becomes None, Some(key) recurses into inner type
1207    /// - Metadata containers (like `Documented<T>`): populate doc/tag metadata and recurse into value
1208    ///
1209    /// The `tag` parameter is for formats like Styx where keys can be type patterns (e.g., `@string`).
1210    /// When present, it indicates the key was a tag rather than a bare identifier.
1211    fn deserialize_map_key(
1212        &mut self,
1213        mut wip: Partial<'input, BORROW>,
1214        key: Option<Cow<'input, str>>,
1215        doc: Option<Vec<Cow<'input, str>>>,
1216        tag: Option<Cow<'input, str>>,
1217    ) -> Result<Partial<'input, BORROW>, DeserializeError<P::Error>> {
1218        let shape = wip.shape();
1219
1220        trace!(shape_name = %shape, shape_def = ?shape.def, ?key, ?doc, ?tag, "deserialize_map_key");
1221
1222        // Handle metadata containers (like Documented<T> or ObjectKey): populate metadata and recurse into value
1223        if shape.is_metadata_container() {
1224            trace!("deserialize_map_key: metadata container detected");
1225
1226            // Find field info from the shape's struct type
1227            if let Type::User(UserType::Struct(st)) = &shape.ty {
1228                for field in st.fields {
1229                    if field.metadata_kind() == Some("doc") {
1230                        // This is the doc field - set it from the doc parameter
1231                        wip = wip
1232                            .begin_field(field.effective_name())
1233                            .map_err(DeserializeError::reflect)?;
1234                        if let Some(ref doc_lines) = doc {
1235                            // Set as Some(Vec<String>)
1236                            wip = wip.begin_some().map_err(DeserializeError::reflect)?;
1237                            wip = wip.init_list().map_err(DeserializeError::reflect)?;
1238                            for line in doc_lines {
1239                                wip = wip.begin_list_item().map_err(DeserializeError::reflect)?;
1240                                wip = self.set_string_value(wip, line.clone())?;
1241                                wip = wip.end().map_err(DeserializeError::reflect)?;
1242                            }
1243                            wip = wip.end().map_err(DeserializeError::reflect)?;
1244                        } else {
1245                            // Set as None
1246                            wip = wip.set_default().map_err(DeserializeError::reflect)?;
1247                        }
1248                        wip = wip.end().map_err(DeserializeError::reflect)?;
1249                    } else if field.metadata_kind() == Some("tag") {
1250                        // This is the tag field - set it from the tag parameter
1251                        wip = wip
1252                            .begin_field(field.effective_name())
1253                            .map_err(DeserializeError::reflect)?;
1254                        if let Some(ref tag_name) = tag {
1255                            // Set as Some(String)
1256                            wip = wip.begin_some().map_err(DeserializeError::reflect)?;
1257                            wip = self.set_string_value(wip, tag_name.clone())?;
1258                            wip = wip.end().map_err(DeserializeError::reflect)?;
1259                        } else {
1260                            // Set as None (not a tagged key)
1261                            wip = wip.set_default().map_err(DeserializeError::reflect)?;
1262                        }
1263                        wip = wip.end().map_err(DeserializeError::reflect)?;
1264                    } else if field.metadata_kind().is_none() {
1265                        // This is the value field - recurse with the key and tag.
1266                        // Doc is already consumed by this container, but tag may be needed
1267                        // by a nested metadata container (e.g., Documented<ObjectKey>).
1268                        wip = wip
1269                            .begin_field(field.effective_name())
1270                            .map_err(DeserializeError::reflect)?;
1271                        wip = self.deserialize_map_key(wip, key.clone(), None, tag.clone())?;
1272                        wip = wip.end().map_err(DeserializeError::reflect)?;
1273                    }
1274                }
1275            }
1276
1277            return Ok(wip);
1278        }
1279
1280        // Handle Option<T> key types: None key -> None variant, Some(key) -> Some(inner)
1281        if let Def::Option(_) = &shape.def {
1282            match key {
1283                None => {
1284                    // Unit key -> None variant (use set_default to mark as initialized)
1285                    wip = wip.set_default().map_err(DeserializeError::reflect)?;
1286                    return Ok(wip);
1287                }
1288                Some(inner_key) => {
1289                    // Named key -> Some(inner)
1290                    wip = wip.begin_some().map_err(DeserializeError::reflect)?;
1291                    wip = self.deserialize_map_key(wip, Some(inner_key), None, None)?;
1292                    wip = wip.end().map_err(DeserializeError::reflect)?;
1293                    return Ok(wip);
1294                }
1295            }
1296        }
1297
1298        // From here on, we need an actual key name
1299        let key = key.ok_or_else(|| DeserializeError::TypeMismatch {
1300            expected: "named key",
1301            got: "unit key".to_string(),
1302            span: self.last_span,
1303            path: None,
1304        })?;
1305
1306        // For transparent types (like UserId(String)), we need to use begin_inner
1307        // to set the inner value. But NOT for pointer types like &str or Cow<str>
1308        // which are handled directly.
1309        let is_pointer = matches!(shape.def, Def::Pointer(_));
1310        if shape.inner.is_some() && !is_pointer {
1311            wip = wip.begin_inner().map_err(DeserializeError::reflect)?;
1312            wip = self.deserialize_map_key(wip, Some(key), None, None)?;
1313            wip = wip.end().map_err(DeserializeError::reflect)?;
1314            return Ok(wip);
1315        }
1316
1317        // Check if target is an enum - use select_variant_named for unit variants
1318        if let Type::User(UserType::Enum(_)) = &shape.ty {
1319            wip = wip
1320                .select_variant_named(&key)
1321                .map_err(DeserializeError::reflect)?;
1322            return Ok(wip);
1323        }
1324
1325        // Check if target is a numeric type - parse the string key as a number
1326        if let Type::Primitive(PrimitiveType::Numeric(num_ty)) = &shape.ty {
1327            match num_ty {
1328                NumericType::Integer { signed } => {
1329                    if *signed {
1330                        let n: i64 = key.parse().map_err(|_| DeserializeError::TypeMismatch {
1331                            expected: "valid integer for map key",
1332                            got: format!("string '{}'", key),
1333                            span: self.last_span,
1334                            path: None,
1335                        })?;
1336                        // Use set for each size - the Partial handles type conversion
1337                        wip = wip.set(n).map_err(DeserializeError::reflect)?;
1338                    } else {
1339                        let n: u64 = key.parse().map_err(|_| DeserializeError::TypeMismatch {
1340                            expected: "valid unsigned integer for map key",
1341                            got: format!("string '{}'", key),
1342                            span: self.last_span,
1343                            path: None,
1344                        })?;
1345                        wip = wip.set(n).map_err(DeserializeError::reflect)?;
1346                    }
1347                    return Ok(wip);
1348                }
1349                NumericType::Float => {
1350                    let n: f64 = key.parse().map_err(|_| DeserializeError::TypeMismatch {
1351                        expected: "valid float for map key",
1352                        got: format!("string '{}'", key),
1353                        span: self.last_span,
1354                        path: None,
1355                    })?;
1356                    wip = wip.set(n).map_err(DeserializeError::reflect)?;
1357                    return Ok(wip);
1358                }
1359            }
1360        }
1361
1362        // Default: treat as string
1363        wip = self.set_string_value(wip, key)?;
1364        Ok(wip)
1365    }
1366}