1extern crate alloc;
2
3use alloc::sync::Arc;
4use core::fmt;
5
6use facet_solver::{KeyResult, Resolution, ResolutionHandle, Schema, Solver};
7
8use crate::{FieldEvidence, FormatParser, ProbeStream};
9
10pub struct SolveOutcome {
12 pub schema: Arc<Schema>,
14 pub resolution_index: usize,
16}
17
18#[derive(Debug)]
20pub enum SolveVariantError<E> {
21 NoMatch,
23 Parser(E),
25 SchemaError(facet_solver::SchemaError),
27}
28
29impl<E> SolveVariantError<E> {
30 pub fn from_parser(e: E) -> Self {
32 Self::Parser(e)
33 }
34}
35
36impl<E: fmt::Display> fmt::Display for SolveVariantError<E> {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 Self::NoMatch => write!(f, "No variant matched"),
40 Self::Parser(e) => write!(f, "Parser error: {}", e),
41 Self::SchemaError(e) => write!(f, "Schema error: {}", e),
42 }
43 }
44}
45
46impl<E: fmt::Debug + fmt::Display> core::error::Error for SolveVariantError<E> {}
47
48pub fn solve_variant<'de, P>(
53 shape: &'static facet_core::Shape,
54 parser: &mut P,
55) -> Result<Option<SolveOutcome>, SolveVariantError<P::Error>>
56where
57 P: FormatParser<'de>,
58{
59 let schema = Arc::new(Schema::build_auto(shape)?);
60 let mut solver = Solver::new(&schema);
61 let mut probe = parser
62 .begin_probe()
63 .map_err(SolveVariantError::from_parser)?;
64
65 while let Some(field) = probe.next().map_err(SolveVariantError::from_parser)? {
66 if let Some(handle) = handle_key(&mut solver, field) {
67 let idx = handle.index();
68 return Ok(Some(SolveOutcome {
69 schema,
70 resolution_index: idx,
71 }));
72 }
73 }
74
75 Ok(None)
76}
77
78fn handle_key<'a>(
79 solver: &mut Solver<'a>,
80 field: FieldEvidence<'a>,
81) -> Option<ResolutionHandle<'a>> {
82 let owned_name = field.name.into_owned();
83 match solver.see_key(owned_name) {
84 KeyResult::Solved(handle) => Some(handle),
85 KeyResult::Unknown | KeyResult::Unambiguous { .. } | KeyResult::Ambiguous { .. } => None,
86 }
87}
88
89impl<E> From<facet_solver::SchemaError> for SolveVariantError<E> {
90 fn from(e: facet_solver::SchemaError) -> Self {
91 Self::SchemaError(e)
92 }
93}
94impl SolveOutcome {
95 pub fn resolution(&self) -> &Resolution {
97 &self.schema.resolutions()[self.resolution_index]
98 }
99}