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}