1extern crate alloc;
2
3use alloc::{collections::BTreeSet, vec::Vec};
4
5use facet_reflect::FieldInfo;
6use facet_solver::Resolution;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[non_exhaustive]
11pub enum FieldMatch<'a> {
12 KnownFirst(&'a FieldInfo),
14 Duplicate(&'a FieldInfo),
16 Unknown,
18}
19
20pub struct StructFieldTracker<'a> {
27 resolution: &'a Resolution,
28 seen: BTreeSet<&'static str>,
29}
30
31impl<'a> StructFieldTracker<'a> {
32 pub const fn new(resolution: &'a Resolution) -> Self {
34 Self {
35 resolution,
36 seen: BTreeSet::new(),
37 }
38 }
39
40 pub fn record(&mut self, name: &str) -> FieldMatch<'a> {
42 match self.resolution.field_by_name(name) {
43 Some(info) => {
44 if self.seen.insert(info.serialized_name) {
45 FieldMatch::KnownFirst(info)
46 } else {
47 FieldMatch::Duplicate(info)
48 }
49 }
50 None => FieldMatch::Unknown,
51 }
52 }
53
54 pub fn missing_required(&self) -> Vec<&'static str> {
56 self.resolution
57 .required_field_names()
58 .iter()
59 .copied()
60 .filter(|name| !self.seen.contains(name))
61 .collect()
62 }
63
64 pub fn missing_optional(&self) -> impl Iterator<Item = &'a FieldInfo> {
66 self.resolution
67 .fields()
68 .values()
69 .filter(move |info| !info.required && !self.seen.contains(&info.serialized_name))
70 }
71}