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    /// Gates the schema-driven hints (`hint_struct_fields`, `hint_enum`,
201    /// `hint_scalar_type`, ...) that only those formats consume.
202    /// Computed once at construction time.
203    is_non_self_describing: bool,
204
205    /// Whether to bypass event buffering. True for non-self-describing
206    /// formats and for parsers that need container hints (Lua): hints clear
207    /// or reclassify the parser's peeked event and must take effect
208    /// immediately, which buffered events would defeat.
209    bypass_event_buffer: bool,
210
211    _marker: PhantomData<&'input ()>,
212}
213
214impl<'parser, 'input> FormatDeserializer<'parser, 'input, true> {
215    /// Create a new deserializer that can borrow strings from input.
216    pub fn new(parser: &'parser mut dyn FormatParser<'input>) -> Self {
217        Self::with_buffer_capacity(parser, DEFAULT_EVENT_BUFFER_SIZE)
218    }
219
220    /// Create a new deserializer with a custom buffer capacity.
221    pub fn with_buffer_capacity(
222        parser: &'parser mut dyn FormatParser<'input>,
223        buffer_capacity: usize,
224    ) -> Self {
225        let is_non_self_describing = !parser.is_self_describing();
226        let bypass_event_buffer = is_non_self_describing || parser.needs_container_hints();
227        Self {
228            parser,
229            last_span: Span { offset: 0, len: 0 },
230            event_buffer: VecDeque::with_capacity(buffer_capacity),
231            buffer_capacity,
232            is_non_self_describing,
233            bypass_event_buffer,
234            _marker: PhantomData,
235        }
236    }
237}
238
239impl<'parser, 'input> FormatDeserializer<'parser, 'input, false> {
240    /// Create a new deserializer that produces owned strings.
241    pub fn new_owned(parser: &'parser mut dyn FormatParser<'input>) -> Self {
242        Self::with_buffer_capacity_owned(parser, DEFAULT_EVENT_BUFFER_SIZE)
243    }
244
245    /// Create a new deserializer with a custom buffer capacity.
246    pub fn with_buffer_capacity_owned(
247        parser: &'parser mut dyn FormatParser<'input>,
248        buffer_capacity: usize,
249    ) -> Self {
250        let is_non_self_describing = !parser.is_self_describing();
251        let bypass_event_buffer = is_non_self_describing || parser.needs_container_hints();
252        Self {
253            parser,
254            last_span: Span { offset: 0, len: 0 },
255            event_buffer: VecDeque::with_capacity(buffer_capacity),
256            buffer_capacity,
257            is_non_self_describing,
258            bypass_event_buffer,
259            _marker: PhantomData,
260        }
261    }
262}
263
264impl<'parser, 'input, const BORROW: bool> FormatDeserializer<'parser, 'input, BORROW> {
265    /// Borrow the inner parser mutably.
266    pub fn parser_mut(&mut self) -> &mut dyn FormatParser<'input> {
267        self.parser
268    }
269
270    /// Save deserializer state (both parser position AND event buffer).
271    ///
272    /// This must be used instead of calling `parser.save()` directly, because
273    /// the deserializer buffers events from the parser. If we only save/restore
274    /// the parser position, events already in the buffer would be lost.
275    fn save(&mut self) -> DeserializerSavePoint<'input> {
276        DeserializerSavePoint {
277            parser_save_point: self.parser.save(),
278            event_buffer: self.event_buffer.clone(),
279        }
280    }
281
282    /// Restore deserializer state (both parser position AND event buffer).
283    fn restore(&mut self, save_point: DeserializerSavePoint<'input>) {
284        self.parser.restore(save_point.parser_save_point);
285        self.event_buffer = save_point.event_buffer;
286    }
287}
288
289impl<'parser, 'input> FormatDeserializer<'parser, 'input, true> {
290    /// Deserialize the next value in the stream into `T`, allowing borrowed strings.
291    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError>
292    where
293        T: Facet<'input>,
294    {
295        let wip = Partial::alloc_with_plan(cached_type_plan_arc::<T>()?)?;
296        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
297        // SpanGuard must cover build() and materialize() which can fail with ReflectError.
298        // Created AFTER deserialize_into so last_span points to the final token.
299        let _guard = SpanGuard::new(self.last_span);
300        let heap_value = partial.build()?;
301        Ok(heap_value.materialize::<T>()?)
302    }
303
304    /// Deserialize the next value in the stream into `T` (for backward compatibility).
305    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError>
306    where
307        T: Facet<'input>,
308    {
309        self.deserialize()
310    }
311
312    /// Deserialize using deferred mode, allowing interleaved field initialization.
313    ///
314    /// This is required for formats like TOML that allow table reopening, where
315    /// fields of a nested struct may be set, then fields of a sibling, then more
316    /// fields of the original struct.
317    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError>
318    where
319        T: Facet<'input>,
320    {
321        let wip = Partial::alloc_with_plan(cached_type_plan_arc::<T>()?)?;
322        let wip = wip.begin_deferred()?;
323        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
324
325        // SpanGuard must cover finish_deferred(), build() and materialize() which can fail with ReflectError.
326        // Created AFTER deserialize_into so last_span points to the final token.
327        let _guard = SpanGuard::new(self.last_span);
328        let partial = partial.finish_deferred()?;
329        let heap_value = partial.build()?;
330        Ok(heap_value.materialize::<T>()?)
331    }
332}
333
334impl<'parser, 'input> FormatDeserializer<'parser, 'input, false> {
335    /// Deserialize the next value in the stream into `T`, using owned strings.
336    pub fn deserialize<T>(&mut self) -> Result<T, DeserializeError>
337    where
338        T: Facet<'static>,
339    {
340        let wip = Partial::alloc_owned_with_plan(cached_type_plan_arc::<T>()?)?;
341        // SAFETY: alloc_owned_with_plan produces Partial<'static, false>, but deserialize_into
342        // expects 'input. Since BORROW=false means we never borrow from input anyway,
343        // this is safe.
344        #[allow(unsafe_code)]
345        let wip: Partial<'input, false> = unsafe { core::mem::transmute(wip) };
346
347        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
348
349        // SpanGuard must cover build() and materialize() which can fail with ReflectError.
350        // Created AFTER deserialize_into so last_span points to the final token.
351        let _guard = SpanGuard::new(self.last_span);
352        let heap_value = partial.build()?;
353
354        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
355        // The transmute only changes the phantom lifetime marker.
356        #[allow(unsafe_code)]
357        let heap_value: HeapValue<'static, false> = unsafe { core::mem::transmute(heap_value) };
358
359        Ok(heap_value.materialize::<T>()?)
360    }
361
362    /// Deserialize the next value in the stream into `T` (for backward compatibility).
363    pub fn deserialize_root<T>(&mut self) -> Result<T, DeserializeError>
364    where
365        T: Facet<'static>,
366    {
367        self.deserialize()
368    }
369
370    /// Deserialize using deferred mode, allowing interleaved field initialization.
371    ///
372    /// This is required for formats like TOML that allow table reopening, where
373    /// fields of a nested struct may be set, then fields of a sibling, then more
374    /// fields of the original struct.
375    pub fn deserialize_deferred<T>(&mut self) -> Result<T, DeserializeError>
376    where
377        T: Facet<'static>,
378    {
379        let wip = Partial::alloc_owned_with_plan(cached_type_plan_arc::<T>()?)?;
380        // SAFETY: alloc_owned_with_plan produces Partial<'static, false>, but deserialize_into
381        // expects 'input. Since BORROW=false means we never borrow from input anyway,
382        // this is safe.
383        #[allow(unsafe_code)]
384        let wip: Partial<'input, false> = unsafe { core::mem::transmute(wip) };
385        let wip = wip.begin_deferred()?;
386        let partial = self.deserialize_into(wip, MetaSource::FromEvents)?;
387
388        // SpanGuard must cover finish_deferred(), build() and materialize() which can fail with ReflectError.
389        // Created AFTER deserialize_into so last_span points to the final token.
390        let _guard = SpanGuard::new(self.last_span);
391        let partial = partial.finish_deferred()?;
392        let heap_value = partial.build()?;
393
394        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
395        // The transmute only changes the phantom lifetime marker.
396        #[allow(unsafe_code)]
397        let heap_value: HeapValue<'static, false> = unsafe { core::mem::transmute(heap_value) };
398
399        Ok(heap_value.materialize::<T>()?)
400    }
401
402    /// Deserialize using an explicit source shape for parser hints.
403    ///
404    /// This is useful for non-self-describing formats like postcard where you need
405    /// to decode data that was serialized using a specific type, but you only have
406    /// the shape information at runtime (not the concrete type).
407    ///
408    /// The target type `T` should typically be a `DynamicValue` like `facet_value::Value`.
409    pub fn deserialize_with_shape<T>(
410        &mut self,
411        source_shape: &'static Shape,
412    ) -> Result<T, DeserializeError>
413    where
414        T: Facet<'static>,
415    {
416        let wip = Partial::alloc_owned_with_plan(cached_type_plan_arc::<T>()?)?;
417        // SAFETY: alloc_owned_with_plan produces Partial<'static, false>, but deserialize_into
418        // expects 'input. Since BORROW=false means we never borrow from input anyway,
419        // this is safe.
420        #[allow(unsafe_code)]
421        let wip: Partial<'input, false> = unsafe { core::mem::transmute(wip) };
422
423        let partial = self.deserialize_into_with_shape(wip, source_shape)?;
424
425        // SpanGuard must cover build() and materialize() which can fail with ReflectError.
426        // Created AFTER deserialize_into so last_span points to the final token.
427        let _guard = SpanGuard::new(self.last_span);
428        let heap_value = partial.build()?;
429
430        // SAFETY: HeapValue<'input, false> contains no borrowed data because BORROW=false.
431        // The transmute only changes the phantom lifetime marker.
432        #[allow(unsafe_code)]
433        let heap_value: HeapValue<'static, false> = unsafe { core::mem::transmute(heap_value) };
434
435        Ok(heap_value.materialize::<T>()?)
436    }
437}
438
439impl<'parser, 'input, const BORROW: bool> FormatDeserializer<'parser, 'input, BORROW> {
440    /// Refill the event buffer from the parser.
441    #[inline]
442    fn refill_buffer(&mut self) -> Result<(), ParseError> {
443        let _old_len = self.event_buffer.len();
444        self.parser
445            .next_events(&mut self.event_buffer, self.buffer_capacity)?;
446        let _new_len = self.event_buffer.len();
447        trace!("buffer refill {_old_len} => {_new_len} events");
448        Ok(())
449    }
450
451    /// Check if parser is non-self-describing.
452    #[inline(always)]
453    fn is_non_self_describing(&self) -> bool {
454        self.is_non_self_describing
455    }
456
457    /// Read the next event, returning an error if EOF is reached.
458    #[inline]
459    fn expect_event(
460        &mut self,
461        expected: &'static str,
462    ) -> Result<ParseEvent<'input>, DeserializeError> {
463        // Bypass buffering for non-self-describing and hint-dependent
464        // formats: hints clear or reclassify the parser's peeked event and
465        // must take effect immediately
466        if self.bypass_event_buffer {
467            let event = self.parser.next_event()?.ok_or_else(|| {
468                DeserializeErrorKind::UnexpectedEof { expected }.with_span(self.last_span)
469            })?;
470            trace!(?event, expected, "expect_event (direct): got event");
471            self.last_span = event.span;
472            return Ok(event);
473        }
474
475        // Refill if empty
476        if self.event_buffer.is_empty() {
477            self.refill_buffer()?;
478        }
479
480        let event = self.event_buffer.pop_front().ok_or_else(|| {
481            DeserializeErrorKind::UnexpectedEof { expected }.with_span(self.last_span)
482        })?;
483
484        trace!(?event, expected, "expect_event: got event");
485        self.last_span = event.span;
486        Ok(event)
487    }
488
489    /// Peek at the next event, returning an error if EOF is reached.
490    #[inline]
491    fn expect_peek(
492        &mut self,
493        expected: &'static str,
494    ) -> Result<ParseEvent<'input>, DeserializeError> {
495        self.peek_event_opt()?.ok_or_else(|| {
496            DeserializeErrorKind::UnexpectedEof { expected }.with_span(self.last_span)
497        })
498    }
499
500    /// Peek at the next event, returning None if EOF is reached.
501    #[inline]
502    fn peek_event_opt(&mut self) -> Result<Option<ParseEvent<'input>>, DeserializeError> {
503        // Bypass buffering for non-self-describing and hint-dependent formats
504        if self.bypass_event_buffer {
505            let event = self.parser.peek_event()?;
506            if let Some(ref _e) = event {
507                trace!(?_e, "peek_event_opt (direct): peeked event");
508            }
509            return Ok(event);
510        }
511
512        // Refill if empty
513        if self.event_buffer.is_empty() {
514            self.refill_buffer()?;
515        }
516
517        // FIXME: cloning bad for perf, obvs. can we borrow? can we stop cloningj?
518        let event = self.event_buffer.front().cloned();
519        if let Some(ref _e) = event {
520            trace!(?_e, "peeked event");
521        }
522        Ok(event)
523    }
524
525    /// Count buffered sequence items without consuming events.
526    ///
527    /// Scans the event buffer to count how many items exist at depth 0.
528    /// Returns the count found so far - this is a lower bound useful for
529    /// pre-reserving Vec capacity.
530    ///
531    /// If the full sequence is buffered (ends with `SequenceEnd`), this
532    /// returns the exact count. Otherwise it returns a partial count.
533    ///
534    /// In bypass mode (`bypass_event_buffer`) the buffer is always empty and
535    /// this returns 0 — capacity pre-reservation is simply unavailable there.
536    #[inline]
537    pub(crate) fn count_buffered_sequence_items(&self) -> usize {
538        use crate::ParseEventKind;
539
540        let mut count = 0usize;
541        let mut depth = 0i32;
542
543        for event in &self.event_buffer {
544            match &event.kind {
545                ParseEventKind::StructStart(_) | ParseEventKind::SequenceStart(_) => {
546                    if depth == 0 {
547                        // Starting a new item at depth 0
548                        count += 1;
549                    }
550                    depth += 1;
551                }
552                ParseEventKind::StructEnd | ParseEventKind::SequenceEnd => {
553                    depth -= 1;
554                    if depth < 0 {
555                        // Found the closing SequenceEnd for our list
556                        return count;
557                    }
558                }
559                ParseEventKind::Scalar(_) if depth == 0 => {
560                    // Scalar at depth 0 is a list item
561                    count += 1;
562                }
563                _ => {}
564            }
565        }
566
567        // Return partial count - still useful for reserve
568        count
569    }
570
571    /// Skip the current value using the buffer, returning start and end offsets.
572    #[inline]
573    fn skip_value_with_span(&mut self) -> Result<(usize, usize), DeserializeError> {
574        use crate::ParseEventKind;
575
576        // Peek to get the start offset
577        let first_event = self.expect_peek("value to skip")?;
578        let start_offset = first_event.span.offset as usize;
579        #[allow(unused_assignments)]
580        let mut end_offset = 0usize;
581
582        let mut depth = 0i32;
583        loop {
584            let event = self.expect_event("value to skip")?;
585            // Track the end of each event
586            end_offset = event.span.end();
587
588            match &event.kind {
589                ParseEventKind::StructStart(_) | ParseEventKind::SequenceStart(_) => {
590                    depth += 1;
591                }
592                ParseEventKind::StructEnd | ParseEventKind::SequenceEnd => {
593                    depth -= 1;
594                    if depth <= 0 {
595                        return Ok((start_offset, end_offset));
596                    }
597                }
598                ParseEventKind::Scalar(_) if depth == 0 => {
599                    return Ok((start_offset, end_offset));
600                }
601                _ => {}
602            }
603        }
604    }
605
606    /// Skip the current value using the buffer.
607    #[inline]
608    fn skip_value(&mut self) -> Result<(), DeserializeError> {
609        self.skip_value_with_span()?;
610        Ok(())
611    }
612
613    /// Capture the raw bytes of the current value without parsing it.
614    #[inline]
615    fn capture_raw(&mut self) -> Result<Option<&'input str>, DeserializeError> {
616        let Some(input) = self.parser.input() else {
617            // Parser doesn't provide raw input access
618            self.skip_value()?;
619            return Ok(None);
620        };
621
622        let (start, end) = self.skip_value_with_span()?;
623
624        // Slice the input
625        if end <= input.len() {
626            // SAFETY: We trust the parser's spans to be valid UTF-8 boundaries
627            let raw = core::str::from_utf8(&input[start..end]).map_err(|_| {
628                DeserializeErrorKind::InvalidValue {
629                    message: "raw capture contains invalid UTF-8".into(),
630                }
631                .with_span(self.last_span)
632            })?;
633            Ok(Some(raw))
634        } else {
635            Ok(None)
636        }
637    }
638
639    /// Read the next event, returning None if EOF is reached.
640    #[inline]
641    fn next_event_opt(&mut self) -> Result<Option<ParseEvent<'input>>, DeserializeError> {
642        // Bypass buffering for non-self-describing and hint-dependent formats
643        if self.bypass_event_buffer {
644            let event = self.parser.next_event()?;
645            if let Some(ref event) = event {
646                self.last_span = event.span;
647            }
648            return Ok(event);
649        }
650
651        // Refill if empty
652        if self.event_buffer.is_empty() {
653            self.refill_buffer()?;
654        }
655
656        let Some(event) = self.event_buffer.pop_front() else {
657            return Ok(None);
658        };
659
660        self.last_span = event.span;
661        Ok(Some(event))
662    }
663
664    /// Attempt to solve which enum variant matches the input.
665    ///
666    /// This uses save/restore to read ahead and determine the variant without
667    /// consuming the events permanently. After this returns, the position
668    /// is restored so the actual deserialization can proceed.
669    pub(crate) fn solve_variant(
670        &mut self,
671        shape: &'static facet_core::Shape,
672    ) -> Result<Option<crate::SolveOutcome>, crate::SolveVariantError> {
673        let schema = Arc::new(Schema::build_auto(shape)?);
674        let mut solver = Solver::new(&schema);
675
676        // Save deserializer state (parser position AND event buffer)
677        let save_point = self.save();
678
679        let mut depth = 0i32;
680        let mut in_struct = false;
681        let mut expecting_value = false;
682        let mut pending_ambiguous: Option<(String, Vec<(&FieldInfo, u64)>)> = None;
683
684        let result = loop {
685            let event = self.next_event_opt().map_err(|e| {
686                crate::SolveVariantError::Parser(ParseError::new(
687                    e.span.unwrap_or(self.last_span),
688                    e.kind,
689                ))
690            })?;
691
692            let Some(event) = event else {
693                // EOF reached
694                self.restore(save_point);
695                return Ok(None);
696            };
697
698            if expecting_value && depth == 1 && in_struct {
699                expecting_value = false;
700                if let Some((key, fields)) = pending_ambiguous.take()
701                    && let crate::ParseEventKind::Scalar(scalar) = &event.kind
702                {
703                    let satisfied_shapes = select_best_ambiguous_scalar_shapes(scalar, &fields);
704                    match solver.satisfy_at_path(&[key.as_str()], &satisfied_shapes) {
705                        SatisfyResult::Solved(handle) => break Some(handle),
706                        SatisfyResult::NoMatch => break None,
707                        SatisfyResult::Continue => {}
708                        // A solver result added since this match was written: keep
709                        // scanning (the loop still terminates on struct end / EOF).
710                        _ => {}
711                    }
712                }
713            }
714
715            match event.kind {
716                crate::ParseEventKind::StructStart(_) => {
717                    depth += 1;
718                    if depth == 1 {
719                        in_struct = true;
720                    }
721                }
722                crate::ParseEventKind::StructEnd => {
723                    depth -= 1;
724                    if depth == 0 {
725                        // Done with top-level struct
726                        break None;
727                    }
728                }
729                crate::ParseEventKind::SequenceStart(_) => {
730                    depth += 1;
731                }
732                crate::ParseEventKind::SequenceEnd => {
733                    depth -= 1;
734                }
735                crate::ParseEventKind::FieldKey(ref key) => {
736                    if depth == 1 && in_struct {
737                        // Top-level field - feed to solver
738                        if let Some(name) = key.name() {
739                            match solver.see_key(name.clone()) {
740                                KeyResult::Solved(handle) => {
741                                    break Some(handle);
742                                }
743                                KeyResult::Ambiguous { fields } => {
744                                    pending_ambiguous = Some((name.to_string(), fields));
745                                }
746                                KeyResult::Unknown | KeyResult::Unambiguous { .. } => {
747                                    pending_ambiguous = None;
748                                }
749                                // A key result added since this match was written.
750                                _ => {
751                                    pending_ambiguous = None;
752                                }
753                            }
754                        }
755                        expecting_value = true;
756                    }
757                }
758                crate::ParseEventKind::Scalar(_)
759                | crate::ParseEventKind::OrderedField
760                | crate::ParseEventKind::VariantTag(_) => {
761                    if expecting_value {
762                        expecting_value = false;
763                    }
764                }
765            }
766        };
767
768        // Restore deserializer state regardless of outcome
769        self.restore(save_point);
770
771        match result {
772            Some(handle) => {
773                let idx = handle.index();
774                Ok(Some(crate::SolveOutcome {
775                    schema,
776                    resolution_index: idx,
777                }))
778            }
779            None => Ok(None),
780        }
781    }
782
783    /// Make an error using the last span, the current path of the given wip.
784    fn mk_err(
785        &self,
786        wip: &Partial<'input, BORROW>,
787        kind: DeserializeErrorKind,
788    ) -> DeserializeError {
789        DeserializeError {
790            span: Some(self.last_span),
791            path: Some(wip.path()),
792            kind,
793        }
794    }
795}
796
797fn select_best_ambiguous_scalar_shapes(
798    scalar: &crate::ScalarValue<'_>,
799    fields: &[(&FieldInfo, u64)],
800) -> Vec<&'static Shape> {
801    let mut matches: Vec<(&'static Shape, u8, u64)> = Vec::new();
802    let mut best_quality: Option<u8> = None;
803
804    for (field, score) in fields {
805        let Some(quality) =
806            crate::deserializer::scalar_matches::scalar_match_quality(scalar, field.value_shape)
807        else {
808            continue;
809        };
810
811        match best_quality {
812            Some(best) if quality > best => continue,
813            Some(best) if quality < best => {
814                matches.clear();
815                best_quality = Some(quality);
816            }
817            None => {
818                best_quality = Some(quality);
819            }
820            _ => {}
821        }
822
823        if !matches.iter().any(|(shape, _, existing_score)| {
824            core::ptr::eq(*shape, field.value_shape) && *existing_score == *score
825        }) {
826            matches.push((field.value_shape, quality, *score));
827        }
828    }
829
830    let Some(best_quality) = best_quality else {
831        return Vec::new();
832    };
833
834    let best_specificity = matches
835        .iter()
836        .filter(|(_, quality, _)| *quality == best_quality)
837        .map(|(_, _, score)| *score)
838        .min()
839        .unwrap_or(u64::MAX);
840
841    matches
842        .into_iter()
843        .filter(|(_, quality, score)| *quality == best_quality && *score == best_specificity)
844        .map(|(shape, _, _)| shape)
845        .collect()
846}