Skip to main content

facet_format/deserializer/
mod.rs

1//! # Format Deserializer
2//!
3//! This module provides a generic deserializer that drives format-specific parsers
4//! (JSON, TOML, etc.) directly into facet's `Partial` builder.
5//!
6//! ## Error Handling Philosophy
7//!
8//! Good error messages are critical for developer experience. When deserialization
9//! fails, users need to know **where** the error occurred (both in the input and
10//! in the type structure) and **what** went wrong. This module enforces several
11//! invariants to ensure high-quality error messages.
12//!
13//! ### Always Include a Span
14//!
15//! Every error should include a `Span` pointing to the location in the input where
16//! the error occurred. This allows tools to highlight the exact position:
17//!
18//! ```text
19//! error: expected integer, got string
20//!   --> config.toml:15:12
21//!    |
22//! 15 |     count = "not a number"
23//!    |             ^^^^^^^^^^^^^^
24//! ```
25//!
26//! The deserializer tracks `last_span` which is updated after consuming each event.
27//! When constructing errors manually, always use `self.last_span`. The `SpanGuard`
28//! RAII type sets a thread-local span that the `From<ReflectError>` impl uses
29//! automatically.
30//!
31//! ### Always Include a Path
32//!
33//! Every error should include a `Path` showing the location in the type structure.
34//! This is especially important for nested types where the span alone doesn't tell
35//! you which field failed:
36//!
37//! ```text
38//! error: missing required field `email`
39//!   --> config.toml:10:5
40//!    |
41//! 10 |     [users.alice]
42//!    |     ^^^^^^^^^^^^^
43//!    |
44//!    = path: config.users["alice"].contact
45//! ```
46//!
47//! When constructing errors, use `wip.path()` to get the current path through the
48//! type structure. The `Partial` tracks this automatically as you descend into
49//! fields, list items, map keys, etc.
50//!
51//! ### Error Construction Patterns
52//!
53//! **For errors during deserialization (when `wip` is available):**
54//!
55//! ```ignore
56//! return Err(DeserializeError {
57//!     span: Some(self.last_span),
58//!     path: Some(wip.path()),
59//!     kind: DeserializeErrorKind::UnexpectedToken { ... },
60//! });
61//! ```
62//!
63//! **For errors from `Partial` methods (via `?` operator):**
64//!
65//! The `From<ReflectError>` impl automatically captures the span from the
66//! thread-local `SpanGuard` and the path from the `ReflectError`. Just use `?`:
67//!
68//! ```ignore
69//! let _guard = SpanGuard::new(self.last_span);
70//! wip = wip.begin_field("name")?;  // Error automatically has span + path
71//! ```
72//!
73//! **For errors with `DeserializeErrorKind::with_span()`:**
74//!
75//! When you only have an error kind and span (no `wip` for path):
76//!
77//! ```ignore
78//! return Err(DeserializeErrorKind::UnexpectedEof { expected: "value" }
79//!     .with_span(self.last_span));
80//! ```
81//!
82//! Note: `with_span()` sets `path: None`. Prefer the full struct when you have a path.
83//!
84//! ### ReflectError Conversion
85//!
86//! Errors from `facet-reflect` (the `Partial` API) are converted via `From<ReflectError>`.
87//! This impl:
88//!
89//! 1. Captures the span from the thread-local `CURRENT_SPAN` (set by `SpanGuard`)
90//! 2. Preserves the path from `ReflectError::path`
91//! 3. Wraps the error kind in `DeserializeErrorKind::Reflect`
92//!
93//! This means you must have an active `SpanGuard` when calling `Partial` methods
94//! that might fail. The guard is typically created at the start of each
95//! deserialization method:
96//!
97//! ```ignore
98//! pub fn deserialize_struct(&mut self, wip: Partial) -> Result<...> {
99//!     let _guard = SpanGuard::new(self.last_span);
100//!     // ... Partial methods can now use ? and errors will have spans
101//! }
102//! ```
103//!
104//! ## Method Chaining with `.with()`
105//!
106//! The `Partial` API provides a `.with()` method for cleaner chaining when you
107//! need to call deserializer methods (which take `&mut self`) in the middle of
108//! a chain:
109//!
110//! ```ignore
111//! // Instead of:
112//! wip = wip.begin_field("name")?;
113//! wip = self.deserialize_into(wip, MetaSource::FromEvents)?;
114//! wip = wip.end()?;
115//!
116//! // Use:
117//! wip = wip
118//!     .begin_field("name")?
119//!     .with(|w| self.deserialize_into(w))?
120//!     .end()?;
121//! ```
122//!
123//! This keeps the "begin/deserialize/end" pattern visually grouped and makes
124//! the nesting structure clearer.
125
126use std::collections::VecDeque;
127use std::marker::PhantomData;
128use std::sync::Arc;
129
130use facet_core::{Facet, Shape};
131use facet_reflect::{HeapValue, Partial, Span};
132use facet_solver::{FieldInfo, KeyResult, SatisfyResult, Schema, Solver};
133
134use crate::{FormatParser, ParseEvent, type_plan_cache::cached_type_plan_arc};
135
136mod error;
137pub use entry::MetaSource;
138pub use error::*;
139
140/// Convenience setters for string etc.
141mod setters;
142
143/// Entry point for deserialization
144mod entry;
145
146/// Deserialization of dynamic values
147mod dynamic;
148
149/// Enum handling
150mod eenum;
151
152/// Smart pointers (Box, Arc, etc.)
153mod pointer;
154
155/// Check if a scalar matches a target shape
156mod scalar_matches;
157
158/// Simple struct deserialization (no flatten)
159mod struct_simple;
160
161/// Not-so-simple struct deserialization (flatten)
162mod struct_with_flatten;
163
164/// Path navigation for flattened struct deserialization
165mod path_navigator;
166
167/// Default size of the event buffer for batched parsing.
168pub const DEFAULT_EVENT_BUFFER_SIZE: usize = 512;
169
170/// Save point for the deserializer, capturing both parser state and event buffer.
171///
172/// This ensures that when we restore, we restore BOTH the parser position AND
173/// the buffered events that had already been read from the parser.
174struct DeserializerSavePoint<'input> {
175    parser_save_point: crate::SavePoint,
176    event_buffer: VecDeque<ParseEvent<'input>>,
177}
178
179/// Generic deserializer that drives a format-specific parser directly into `Partial`.
180///
181/// The const generic `BORROW` controls whether string data can be borrowed:
182/// - `BORROW=true`: strings without escapes are borrowed from input
183/// - `BORROW=false`: all strings are owned
184///
185/// The lifetime `'parser` is the lifetime of the parser itself, which may be shorter
186/// than `'input` (e.g., for streaming parsers that produce owned data but contain
187/// references to internal state).
188pub struct FormatDeserializer<'parser, 'input, const BORROW: bool> {
189    parser: &'parser mut dyn FormatParser<'input>,
190
191    /// The span of the most recently consumed event (for error reporting).
192    last_span: Span,
193
194    /// Buffer for batched event reading (push back, pop front).
195    event_buffer: VecDeque<ParseEvent<'input>>,
196    /// Maximum number of events to buffer at once.
197    buffer_capacity: usize,
198
199    /// Whether the parser is non-self-describing (postcard, etc.).
200    /// For these formats, we bypass buffering entirely because hints
201    /// clear the parser's peeked event and must take effect immediately.
202    /// Computed once at construction time.
203    is_non_self_describing: bool,
204
205    _marker: PhantomData<&'input ()>,
206}
207
208impl<'parser, 'input> FormatDeserializer<'parser, 'input, true> {
209    /// Create a new deserializer that can borrow strings from input.
210    pub fn new(parser: &'parser mut dyn FormatParser<'input>) -> Self {
211        Self::with_buffer_capacity(parser, DEFAULT_EVENT_BUFFER_SIZE)
212    }
213
214    /// Create a new deserializer with a custom buffer capacity.
215    pub fn with_buffer_capacity(
216        parser: &'parser mut dyn FormatParser<'input>,
217        buffer_capacity: usize,
218    ) -> Self {
219        let is_non_self_describing = !parser.is_self_describing();
220        Self {
221            parser,
222            last_span: Span { offset: 0, len: 0 },
223            event_buffer: VecDeque::with_capacity(buffer_capacity),
224            buffer_capacity,
225            is_non_self_describing,
226            _marker: PhantomData,
227        }
228    }
229}
230
231impl<'parser, 'input> FormatDeserializer<'parser, 'input, false> {
232    /// Create a new deserializer that produces owned strings.
233    pub fn new_owned(parser: &'parser mut dyn FormatParser<'input>) -> Self {
234        Self::with_buffer_capacity_owned(parser, DEFAULT_EVENT_BUFFER_SIZE)
235    }
236
237    /// Create a new deserializer with a custom buffer capacity.
238    pub fn with_buffer_capacity_owned(
239        parser: &'parser mut dyn FormatParser<'input>,
240        buffer_capacity: usize,
241    ) -> Self {
242        let is_non_self_describing = !parser.is_self_describing();
243        Self {
244            parser,
245            last_span: Span { offset: 0, len: 0 },
246            event_buffer: VecDeque::with_capacity(buffer_capacity),
247            buffer_capacity,
248            is_non_self_describing,
249            _marker: PhantomData,
250        }
251    }
252}
253
254impl<'parser, 'input, const BORROW: bool> FormatDeserializer<'parser, 'input, BORROW> {
255    /// Borrow the inner parser mutably.
256    pub fn parser_mut(&mut self) -> &mut dyn FormatParser<'input> {
257        self.parser
258    }
259
260    /// Save deserializer state (both parser position AND event buffer).
261    ///
262    /// This must be used instead of calling `parser.save()` directly, because
263    /// the deserializer buffers events from the parser. If we only save/restore
264    /// the parser position, events already in the buffer would be lost.
265    fn save(&mut self) -> DeserializerSavePoint<'input> {
266        DeserializerSavePoint {
267            parser_save_point: self.parser.save(),
268            event_buffer: self.event_buffer.clone(),
269        }
270    }
271
272    /// Restore deserializer state (both parser position AND event buffer).
273    fn restore(&mut self, save_point: DeserializerSavePoint<'input>) {
274        self.parser.restore(save_point.parser_save_point);
275        self.event_buffer = save_point.event_buffer;
276    }
277}
278
279impl<'parser, 'input> FormatDeserializer<'parser, 'input, true> {
280    /// Deserialize the next value in the stream into `T`, allowing borrowed strings.
281    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError>
282    where
283        T: Facet<'input>,
284    {
285        let wip = Partial::alloc_with_plan(cached_type_plan_arc::<T>()?)?;
286        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
287        // SpanGuard must cover build() and materialize() which can fail with ReflectError.
288        // Created AFTER deserialize_into so last_span points to the final token.
289        let _guard = SpanGuard::new(self.last_span);
290        let heap_value = partial.build()?;
291        Ok(heap_value.materialize::<T>()?)
292    }
293
294    /// Deserialize the next value in the stream into `T` (for backward compatibility).
295    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError>
296    where
297        T: Facet<'input>,
298    {
299        self.deserialize()
300    }
301
302    /// Deserialize using deferred mode, allowing interleaved field initialization.
303    ///
304    /// This is required for formats like TOML that allow table reopening, where
305    /// fields of a nested struct may be set, then fields of a sibling, then more
306    /// fields of the original struct.
307    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError>
308    where
309        T: Facet<'input>,
310    {
311        let wip = Partial::alloc_with_plan(cached_type_plan_arc::<T>()?)?;
312        let wip = wip.begin_deferred()?;
313        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
314
315        // SpanGuard must cover finish_deferred(), build() and materialize() which can fail with ReflectError.
316        // Created AFTER deserialize_into so last_span points to the final token.
317        let _guard = SpanGuard::new(self.last_span);
318        let partial = partial.finish_deferred()?;
319        let heap_value = partial.build()?;
320        Ok(heap_value.materialize::<T>()?)
321    }
322}
323
324impl<'parser, 'input> FormatDeserializer<'parser, 'input, false> {
325    /// Deserialize the next value in the stream into `T`, using owned strings.
326    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError>
327    where
328        T: Facet<'static>,
329    {
330        let wip = Partial::alloc_owned_with_plan(cached_type_plan_arc::<T>()?)?;
331        // SAFETY: alloc_owned_with_plan produces Partial<'static, false>, but deserialize_into
332        // expects 'input. Since BORROW=false means we never borrow from input anyway,
333        // this is safe.
334        #[allow(unsafe_code)]
335        let wip: Partial<'input, false> = unsafe { core::mem::transmute(wip) };
336
337        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
338
339        // SpanGuard must cover build() and materialize() which can fail with ReflectError.
340        // Created AFTER deserialize_into so last_span points to the final token.
341        let _guard = SpanGuard::new(self.last_span);
342        let heap_value = partial.build()?;
343
344        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
345        // The transmute only changes the phantom lifetime marker.
346        #[allow(unsafe_code)]
347        let heap_value: HeapValue<'static, false> = unsafe { core::mem::transmute(heap_value) };
348
349        Ok(heap_value.materialize::<T>()?)
350    }
351
352    /// Deserialize the next value in the stream into `T` (for backward compatibility).
353    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError>
354    where
355        T: Facet<'static>,
356    {
357        self.deserialize()
358    }
359
360    /// Deserialize using deferred mode, allowing interleaved field initialization.
361    ///
362    /// This is required for formats like TOML that allow table reopening, where
363    /// fields of a nested struct may be set, then fields of a sibling, then more
364    /// fields of the original struct.
365    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError>
366    where
367        T: Facet<'static>,
368    {
369        let wip = Partial::alloc_owned_with_plan(cached_type_plan_arc::<T>()?)?;
370        // SAFETY: alloc_owned_with_plan produces Partial<'static, false>, but deserialize_into
371        // expects 'input. Since BORROW=false means we never borrow from input anyway,
372        // this is safe.
373        #[allow(unsafe_code)]
374        let wip: Partial<'input, false> = unsafe { core::mem::transmute(wip) };
375        let wip = wip.begin_deferred()?;
376        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
377
378        // SpanGuard must cover finish_deferred(), build() and materialize() which can fail with ReflectError.
379        // Created AFTER deserialize_into so last_span points to the final token.
380        let _guard = SpanGuard::new(self.last_span);
381        let partial = partial.finish_deferred()?;
382        let heap_value = partial.build()?;
383
384        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
385        // The transmute only changes the phantom lifetime marker.
386        #[allow(unsafe_code)]
387        let heap_value: HeapValue<'static, false> = unsafe { core::mem::transmute(heap_value) };
388
389        Ok(heap_value.materialize::<T>()?)
390    }
391
392    /// Deserialize using an explicit source shape for parser hints.
393    ///
394    /// This is useful for non-self-describing formats like postcard where you need
395    /// to decode data that was serialized using a specific type, but you only have
396    /// the shape information at runtime (not the concrete type).
397    ///
398    /// The target type `T` should typically be a `DynamicValue` like `facet_value::Value`.
399    pub fn deserialize_with_shape<T>(
400        &mut self,
401        source_shape: &'static Shape,
402    ) -> Result<T, DeserializeError>
403    where
404        T: Facet<'static>,
405    {
406        let wip = Partial::alloc_owned_with_plan(cached_type_plan_arc::<T>()?)?;
407        // SAFETY: alloc_owned_with_plan produces Partial<'static, false>, but deserialize_into
408        // expects 'input. Since BORROW=false means we never borrow from input anyway,
409        // this is safe.
410        #[allow(unsafe_code)]
411        let wip: Partial<'input, false> = unsafe { core::mem::transmute(wip) };
412
413        let partial = self.deserialize_into_with_shape(wip, source_shape)?;
414
415        // SpanGuard must cover build() and materialize() which can fail with ReflectError.
416        // Created AFTER deserialize_into so last_span points to the final token.
417        let _guard = SpanGuard::new(self.last_span);
418        let heap_value = partial.build()?;
419
420        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
421        // The transmute only changes the phantom lifetime marker.
422        #[allow(unsafe_code)]
423        let heap_value: HeapValue<'static, false> = unsafe { core::mem::transmute(heap_value) };
424
425        Ok(heap_value.materialize::<T>()?)
426    }
427}
428
429impl<'parser, 'input, const BORROW: bool> FormatDeserializer<'parser, 'input, BORROW> {
430    /// Refill the event buffer from the parser.
431    #[inline]
432    fn refill_buffer(&mut self) -> Result<(), ParseError> {
433        let _old_len = self.event_buffer.len();
434        self.parser
435            .next_events(&mut self.event_buffer, self.buffer_capacity)?;
436        let _new_len = self.event_buffer.len();
437        trace!("buffer refill {_old_len} => {_new_len} events");
438        Ok(())
439    }
440
441    /// Check if parser is non-self-describing.
442    #[inline(always)]
443    fn is_non_self_describing(&self) -> bool {
444        self.is_non_self_describing
445    }
446
447    /// Read the next event, returning an error if EOF is reached.
448    #[inline]
449    fn expect_event(
450        &mut self,
451        expected: &'static str,
452    ) -> Result<ParseEvent<'input>, DeserializeError> {
453        // For non-self-describing formats, bypass buffering entirely
454        // because hints clear the parser's peeked event and must take effect immediately
455        if self.is_non_self_describing() {
456            let event = self.parser.next_event()?.ok_or_else(|| {
457                DeserializeErrorKind::UnexpectedEof { expected }.with_span(self.last_span)
458            })?;
459            trace!(?event, expected, "expect_event (direct): got event");
460            self.last_span = event.span;
461            return Ok(event);
462        }
463
464        // Refill if empty
465        if self.event_buffer.is_empty() {
466            self.refill_buffer()?;
467        }
468
469        let event = self.event_buffer.pop_front().ok_or_else(|| {
470            DeserializeErrorKind::UnexpectedEof { expected }.with_span(self.last_span)
471        })?;
472
473        trace!(?event, expected, "expect_event: got event");
474        self.last_span = event.span;
475        Ok(event)
476    }
477
478    /// Peek at the next event, returning an error if EOF is reached.
479    #[inline]
480    fn expect_peek(
481        &mut self,
482        expected: &'static str,
483    ) -> Result<ParseEvent<'input>, DeserializeError> {
484        self.peek_event_opt()?.ok_or_else(|| {
485            DeserializeErrorKind::UnexpectedEof { expected }.with_span(self.last_span)
486        })
487    }
488
489    /// Peek at the next event, returning None if EOF is reached.
490    #[inline]
491    fn peek_event_opt(&mut self) -> Result<Option<ParseEvent<'input>>, DeserializeError> {
492        // For non-self-describing formats, bypass buffering entirely
493        if self.is_non_self_describing() {
494            let event = self.parser.peek_event()?;
495            if let Some(ref _e) = event {
496                trace!(?_e, "peek_event_opt (direct): peeked event");
497            }
498            return Ok(event);
499        }
500
501        // Refill if empty
502        if self.event_buffer.is_empty() {
503            self.refill_buffer()?;
504        }
505
506        // FIXME: cloning bad for perf, obvs. can we borrow? can we stop cloningj?
507        let event = self.event_buffer.front().cloned();
508        if let Some(ref _e) = event {
509            trace!(?_e, "peeked event");
510        }
511        Ok(event)
512    }
513
514    /// Count buffered sequence items without consuming events.
515    ///
516    /// Scans the event buffer to count how many items exist at depth 0.
517    /// Returns the count found so far - this is a lower bound useful for
518    /// pre-reserving Vec capacity.
519    ///
520    /// If the full sequence is buffered (ends with `SequenceEnd`), this
521    /// returns the exact count. Otherwise it returns a partial count.
522    #[inline]
523    pub(crate) fn count_buffered_sequence_items(&self) -> usize {
524        use crate::ParseEventKind;
525
526        let mut count = 0usize;
527        let mut depth = 0i32;
528
529        for event in &self.event_buffer {
530            match &event.kind {
531                ParseEventKind::StructStart(_) | ParseEventKind::SequenceStart(_) => {
532                    if depth == 0 {
533                        // Starting a new item at depth 0
534                        count += 1;
535                    }
536                    depth += 1;
537                }
538                ParseEventKind::StructEnd | ParseEventKind::SequenceEnd => {
539                    depth -= 1;
540                    if depth < 0 {
541                        // Found the closing SequenceEnd for our list
542                        return count;
543                    }
544                }
545                ParseEventKind::Scalar(_) if depth == 0 => {
546                    // Scalar at depth 0 is a list item
547                    count += 1;
548                }
549                _ => {}
550            }
551        }
552
553        // Return partial count - still useful for reserve
554        count
555    }
556
557    /// Skip the current value using the buffer, returning start and end offsets.
558    #[inline]
559    fn skip_value_with_span(&mut self) -> Result<(usize, usize), DeserializeError> {
560        use crate::ParseEventKind;
561
562        // Peek to get the start offset
563        let first_event = self.expect_peek("value to skip")?;
564        let start_offset = first_event.span.offset as usize;
565        #[allow(unused_assignments)]
566        let mut end_offset = 0usize;
567
568        let mut depth = 0i32;
569        loop {
570            let event = self.expect_event("value to skip")?;
571            // Track the end of each event
572            end_offset = event.span.end();
573
574            match &event.kind {
575                ParseEventKind::StructStart(_) | ParseEventKind::SequenceStart(_) => {
576                    depth += 1;
577                }
578                ParseEventKind::StructEnd | ParseEventKind::SequenceEnd => {
579                    depth -= 1;
580                    if depth <= 0 {
581                        return Ok((start_offset, end_offset));
582                    }
583                }
584                ParseEventKind::Scalar(_) if depth == 0 => {
585                    return Ok((start_offset, end_offset));
586                }
587                _ => {}
588            }
589        }
590    }
591
592    /// Skip the current value using the buffer.
593    #[inline]
594    fn skip_value(&mut self) -> Result<(), DeserializeError> {
595        self.skip_value_with_span()?;
596        Ok(())
597    }
598
599    /// Capture the raw bytes of the current value without parsing it.
600    #[inline]
601    fn capture_raw(&mut self) -> Result<Option<&'input str>, DeserializeError> {
602        let Some(input) = self.parser.input() else {
603            // Parser doesn't provide raw input access
604            self.skip_value()?;
605            return Ok(None);
606        };
607
608        let (start, end) = self.skip_value_with_span()?;
609
610        // Slice the input
611        if end <= input.len() {
612            // SAFETY: We trust the parser's spans to be valid UTF-8 boundaries
613            let raw = core::str::from_utf8(&input[start..end]).map_err(|_| {
614                DeserializeErrorKind::InvalidValue {
615                    message: "raw capture contains invalid UTF-8".into(),
616                }
617                .with_span(self.last_span)
618            })?;
619            Ok(Some(raw))
620        } else {
621            Ok(None)
622        }
623    }
624
625    /// Read the next event, returning None if EOF is reached.
626    #[inline]
627    fn next_event_opt(&mut self) -> Result<Option<ParseEvent<'input>>, DeserializeError> {
628        // Refill if empty
629        if self.event_buffer.is_empty() {
630            self.refill_buffer()?;
631        }
632
633        let Some(event) = self.event_buffer.pop_front() else {
634            return Ok(None);
635        };
636
637        self.last_span = event.span;
638        Ok(Some(event))
639    }
640
641    /// Attempt to solve which enum variant matches the input.
642    ///
643    /// This uses save/restore to read ahead and determine the variant without
644    /// consuming the events permanently. After this returns, the position
645    /// is restored so the actual deserialization can proceed.
646    pub(crate) fn solve_variant(
647        &mut self,
648        shape: &'static facet_core::Shape,
649    ) -> Result<Option<crate::SolveOutcome>, crate::SolveVariantError> {
650        let schema = Arc::new(Schema::build_auto(shape)?);
651        let mut solver = Solver::new(&schema);
652
653        // Save deserializer state (parser position AND event buffer)
654        let save_point = self.save();
655
656        let mut depth = 0i32;
657        let mut in_struct = false;
658        let mut expecting_value = false;
659        let mut pending_ambiguous: Option<(String, Vec<(&FieldInfo, u64)>)> = None;
660
661        let result = loop {
662            let event = self.next_event_opt().map_err(|e| {
663                crate::SolveVariantError::Parser(ParseError::new(
664                    e.span.unwrap_or(self.last_span),
665                    e.kind,
666                ))
667            })?;
668
669            let Some(event) = event else {
670                // EOF reached
671                self.restore(save_point);
672                return Ok(None);
673            };
674
675            if expecting_value && depth == 1 && in_struct {
676                expecting_value = false;
677                if let Some((key, fields)) = pending_ambiguous.take()
678                    && let crate::ParseEventKind::Scalar(scalar) = &event.kind
679                {
680                    let satisfied_shapes = select_best_ambiguous_scalar_shapes(scalar, &fields);
681                    match solver.satisfy_at_path(&[key.as_str()], &satisfied_shapes) {
682                        SatisfyResult::Solved(handle) => break Some(handle),
683                        SatisfyResult::NoMatch => break None,
684                        SatisfyResult::Continue => {}
685                    }
686                }
687            }
688
689            match event.kind {
690                crate::ParseEventKind::StructStart(_) => {
691                    depth += 1;
692                    if depth == 1 {
693                        in_struct = true;
694                    }
695                }
696                crate::ParseEventKind::StructEnd => {
697                    depth -= 1;
698                    if depth == 0 {
699                        // Done with top-level struct
700                        break None;
701                    }
702                }
703                crate::ParseEventKind::SequenceStart(_) => {
704                    depth += 1;
705                }
706                crate::ParseEventKind::SequenceEnd => {
707                    depth -= 1;
708                }
709                crate::ParseEventKind::FieldKey(ref key) => {
710                    if depth == 1 && in_struct {
711                        // Top-level field - feed to solver
712                        if let Some(name) = key.name() {
713                            match solver.see_key(name.clone()) {
714                                KeyResult::Solved(handle) => {
715                                    break Some(handle);
716                                }
717                                KeyResult::Ambiguous { fields } => {
718                                    pending_ambiguous = Some((name.to_string(), fields));
719                                }
720                                KeyResult::Unknown | KeyResult::Unambiguous { .. } => {
721                                    pending_ambiguous = None;
722                                }
723                            }
724                        }
725                        expecting_value = true;
726                    }
727                }
728                crate::ParseEventKind::Scalar(_)
729                | crate::ParseEventKind::OrderedField
730                | crate::ParseEventKind::VariantTag(_) => {
731                    if expecting_value {
732                        expecting_value = false;
733                    }
734                }
735            }
736        };
737
738        // Restore deserializer state regardless of outcome
739        self.restore(save_point);
740
741        match result {
742            Some(handle) => {
743                let idx = handle.index();
744                Ok(Some(crate::SolveOutcome {
745                    schema,
746                    resolution_index: idx,
747                }))
748            }
749            None => Ok(None),
750        }
751    }
752
753    /// Make an error using the last span, the current path of the given wip.
754    fn mk_err(
755        &self,
756        wip: &Partial<'input, BORROW>,
757        kind: DeserializeErrorKind,
758    ) -> DeserializeError {
759        DeserializeError {
760            span: Some(self.last_span),
761            path: Some(wip.path()),
762            kind,
763        }
764    }
765}
766
767fn select_best_ambiguous_scalar_shapes(
768    scalar: &crate::ScalarValue<'_>,
769    fields: &[(&FieldInfo, u64)],
770) -> Vec<&'static Shape> {
771    let mut matches: Vec<(&'static Shape, u8, u64)> = Vec::new();
772    let mut best_quality: Option<u8> = None;
773
774    for (field, score) in fields {
775        let Some(quality) =
776            crate::deserializer::scalar_matches::scalar_match_quality(scalar, field.value_shape)
777        else {
778            continue;
779        };
780
781        match best_quality {
782            Some(best) if quality > best => continue,
783            Some(best) if quality < best => {
784                matches.clear();
785                best_quality = Some(quality);
786            }
787            None => {
788                best_quality = Some(quality);
789            }
790            _ => {}
791        }
792
793        if !matches.iter().any(|(shape, _, existing_score)| {
794            core::ptr::eq(*shape, field.value_shape) && *existing_score == *score
795        }) {
796            matches.push((field.value_shape, quality, *score));
797        }
798    }
799
800    let Some(best_quality) = best_quality else {
801        return Vec::new();
802    };
803
804    let best_specificity = matches
805        .iter()
806        .filter(|(_, quality, _)| *quality == best_quality)
807        .map(|(_, _, score)| *score)
808        .min()
809        .unwrap_or(u64::MAX);
810
811    matches
812        .into_iter()
813        .filter(|(_, quality, score)| *quality == best_quality && *score == best_specificity)
814        .map(|(shape, _, _)| shape)
815        .collect()
816}