1extern crate alloc;
8
9use alloc::borrow::Cow;
10use alloc::collections::BTreeMap;
11use alloc::collections::BTreeSet;
12use alloc::format;
13use alloc::string::String;
14use alloc::string::ToString;
15use alloc::vec::Vec;
16use core::fmt;
17
18use facet_core::{Field, Shape};
19
20pub type KeyPath = Vec<&'static str>;
24
25#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
27pub enum PathSegment {
28 Field(&'static str),
30 Variant(&'static str, &'static str),
32}
33
34#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub struct FieldPath {
37 segments: Vec<PathSegment>,
38}
39
40impl fmt::Debug for FieldPath {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 write!(f, "FieldPath(")?;
43 for (i, seg) in self.segments.iter().enumerate() {
44 if i > 0 {
45 write!(f, ".")?;
46 }
47 match seg {
48 PathSegment::Field(name) => write!(f, "{name}")?,
49 PathSegment::Variant(field, variant) => write!(f, "{field}::{variant}")?,
50 }
51 }
52 write!(f, ")")
53 }
54}
55
56impl fmt::Display for FieldPath {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 let mut first = true;
59 for seg in &self.segments {
60 match seg {
61 PathSegment::Field(name) => {
62 if !first {
63 write!(f, ".")?;
64 }
65 write!(f, "{name}")?;
66 first = false;
67 }
68 PathSegment::Variant(_, _) => {
69 }
71 }
72 }
73 Ok(())
74 }
75}
76
77impl FieldPath {
78 pub fn empty() -> Self {
80 Self {
81 segments: Vec::new(),
82 }
83 }
84
85 pub fn depth(&self) -> usize {
87 self.segments.len()
88 }
89
90 pub fn push_field(&self, name: &'static str) -> Self {
92 let mut new = self.clone();
93 new.segments.push(PathSegment::Field(name));
94 new
95 }
96
97 pub fn push_variant(&self, field_name: &'static str, variant_name: &'static str) -> Self {
99 let mut new = self.clone();
100 new.segments
101 .push(PathSegment::Variant(field_name, variant_name));
102 new
103 }
104
105 pub fn parent(&self) -> Self {
107 let mut new = self.clone();
108 new.segments.pop();
109 new
110 }
111
112 pub fn segments(&self) -> &[PathSegment] {
114 &self.segments
115 }
116
117 pub fn last(&self) -> Option<&PathSegment> {
119 self.segments.last()
120 }
121}
122
123#[derive(Debug, Clone)]
125pub struct VariantSelection {
126 pub path: FieldPath,
128 pub enum_name: &'static str,
130 pub variant_name: &'static str,
132}
133
134#[derive(Debug, Clone)]
136pub struct FieldInfo {
137 pub serialized_name: &'static str,
139
140 pub path: FieldPath,
142
143 pub required: bool,
145
146 pub value_shape: &'static Shape,
148
149 pub field: &'static Field,
151}
152
153impl PartialEq for FieldInfo {
154 fn eq(&self, other: &Self) -> bool {
155 self.serialized_name == other.serialized_name
156 && self.path == other.path
157 && self.required == other.required
158 && core::ptr::eq(self.value_shape, other.value_shape)
159 && core::ptr::eq(self.field, other.field)
160 }
161}
162
163impl Eq for FieldInfo {}
164
165#[derive(Debug)]
167pub enum MatchResult {
168 Exact,
170 WithOptionalMissing(Vec<&'static str>),
172 NoMatch {
174 missing_required: Vec<&'static str>,
176 unknown: Vec<String>,
178 },
179}
180
181#[derive(Debug, Clone)]
187pub struct Resolution {
188 variant_selections: Vec<VariantSelection>,
191
192 fields: BTreeMap<&'static str, FieldInfo>,
194
195 required_field_names: BTreeSet<&'static str>,
197
198 known_paths: BTreeSet<KeyPath>,
202}
203
204#[derive(Debug, Clone)]
206pub struct DuplicateFieldError {
207 pub field_name: &'static str,
209 pub first_path: FieldPath,
211 pub second_path: FieldPath,
213}
214
215impl fmt::Display for DuplicateFieldError {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 write!(
218 f,
219 "duplicate field '{}': found at {} and {}",
220 self.field_name, self.first_path, self.second_path
221 )
222 }
223}
224
225impl Resolution {
226 pub fn new() -> Self {
228 Self {
229 variant_selections: Vec::new(),
230 fields: BTreeMap::new(),
231 required_field_names: BTreeSet::new(),
232 known_paths: BTreeSet::new(),
233 }
234 }
235
236 pub fn add_key_path(&mut self, path: KeyPath) {
238 self.known_paths.insert(path);
239 }
240
241 pub fn add_field(&mut self, info: FieldInfo) -> Result<(), DuplicateFieldError> {
247 if let Some(existing) = self.fields.get(info.serialized_name)
248 && existing.path != info.path
249 {
250 return Err(DuplicateFieldError {
251 field_name: info.serialized_name,
252 first_path: existing.path.clone(),
253 second_path: info.path,
254 });
255 }
256 if info.required {
257 self.required_field_names.insert(info.serialized_name);
258 }
259 self.fields.insert(info.serialized_name, info);
260 Ok(())
261 }
262
263 pub fn add_variant_selection(
265 &mut self,
266 path: FieldPath,
267 enum_name: &'static str,
268 variant_name: &'static str,
269 ) {
270 self.variant_selections.push(VariantSelection {
271 path,
272 enum_name,
273 variant_name,
274 });
275 }
276
277 pub fn merge(&mut self, other: &Resolution) -> Result<(), DuplicateFieldError> {
283 for (name, info) in &other.fields {
284 if let Some(existing) = self.fields.get(*name)
285 && existing.path != info.path
286 {
287 return Err(DuplicateFieldError {
288 field_name: name,
289 first_path: existing.path.clone(),
290 second_path: info.path.clone(),
291 });
292 }
293 self.fields.insert(*name, info.clone());
294 if info.required {
295 self.required_field_names.insert(*name);
296 }
297 }
298 for vs in &other.variant_selections {
299 self.variant_selections.push(vs.clone());
300 }
301 for path in &other.known_paths {
302 self.known_paths.insert(path.clone());
303 }
304 Ok(())
305 }
306
307 pub fn mark_all_optional(&mut self) {
310 self.required_field_names.clear();
311 for info in self.fields.values_mut() {
312 info.required = false;
313 }
314 }
315
316 pub fn matches(&self, input_fields: &BTreeSet<Cow<'_, str>>) -> MatchResult {
318 let mut missing_required = Vec::new();
319 let mut missing_optional = Vec::new();
320
321 for (name, info) in &self.fields {
322 if !input_fields.iter().any(|k| k.as_ref() == *name) {
323 if info.required {
324 missing_required.push(*name);
325 } else {
326 missing_optional.push(*name);
327 }
328 }
329 }
330
331 let unknown: Vec<String> = input_fields
333 .iter()
334 .filter(|f| !self.fields.contains_key(f.as_ref()))
335 .map(|s| s.to_string())
336 .collect();
337
338 if !missing_required.is_empty() || !unknown.is_empty() {
339 MatchResult::NoMatch {
340 missing_required,
341 unknown,
342 }
343 } else if missing_optional.is_empty() {
344 MatchResult::Exact
345 } else {
346 MatchResult::WithOptionalMissing(missing_optional)
347 }
348 }
349
350 pub fn describe(&self) -> String {
355 if self.variant_selections.is_empty() {
356 String::from("(no variants)")
357 } else {
358 let parts: Vec<_> = self
359 .variant_selections
360 .iter()
361 .map(|vs| format!("{}::{}", vs.enum_name, vs.variant_name))
362 .collect();
363 parts.join(" + ")
364 }
365 }
366
367 pub fn deserialization_order(&self) -> Vec<&FieldInfo> {
369 let mut fields: Vec<_> = self.fields.values().collect();
370 fields.sort_by(|a, b| {
371 b.path
373 .depth()
374 .cmp(&a.path.depth())
375 .then_with(|| a.path.cmp(&b.path))
377 });
378 fields
379 }
380
381 pub fn field(&self, name: &str) -> Option<&FieldInfo> {
383 self.fields.get(name)
384 }
385
386 pub fn fields(&self) -> &BTreeMap<&'static str, FieldInfo> {
388 &self.fields
389 }
390
391 pub fn required_field_names(&self) -> &BTreeSet<&'static str> {
393 &self.required_field_names
394 }
395
396 pub fn missing_optional_fields<'a>(
401 &'a self,
402 seen_keys: &'a BTreeSet<Cow<'_, str>>,
403 ) -> impl Iterator<Item = &'a FieldInfo> {
404 self.fields.values().filter(move |info| {
405 !info.required && !seen_keys.iter().any(|k| k.as_ref() == info.serialized_name)
406 })
407 }
408
409 pub fn variant_selections(&self) -> &[VariantSelection] {
411 &self.variant_selections
412 }
413
414 pub fn child_fields(&self) -> impl Iterator<Item = &FieldInfo> {
419 self.fields.values().filter(|f| f.field.is_child())
420 }
421
422 pub fn property_fields(&self) -> impl Iterator<Item = &FieldInfo> {
427 self.fields.values().filter(|f| !f.field.is_child())
428 }
429
430 pub fn known_paths(&self) -> &BTreeSet<KeyPath> {
432 &self.known_paths
433 }
434
435 pub fn has_key_path(&self, path: &[&str]) -> bool {
438 self.known_paths.iter().any(|known| {
439 known.len() == path.len() && known.iter().zip(path.iter()).all(|(a, b)| *a == *b)
440 })
441 }
442}
443
444impl Default for Resolution {
445 fn default() -> Self {
446 Self::new()
447 }
448}