extern crate alloc;
use alloc::{collections::BTreeSet, vec::Vec};
use facet_reflect::FieldInfo;
use facet_solver::Resolution;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FieldMatch<'a> {
KnownFirst(&'a FieldInfo),
Duplicate(&'a FieldInfo),
Unknown,
}
pub struct StructFieldTracker<'a> {
resolution: &'a Resolution,
seen: BTreeSet<&'static str>,
}
impl<'a> StructFieldTracker<'a> {
pub const fn new(resolution: &'a Resolution) -> Self {
Self {
resolution,
seen: BTreeSet::new(),
}
}
pub fn record(&mut self, name: &str) -> FieldMatch<'a> {
match self.resolution.field_by_name(name) {
Some(info) => {
if self.seen.insert(info.serialized_name) {
FieldMatch::KnownFirst(info)
} else {
FieldMatch::Duplicate(info)
}
}
None => FieldMatch::Unknown,
}
}
pub fn missing_required(&self) -> Vec<&'static str> {
self.resolution
.required_field_names()
.iter()
.copied()
.filter(|name| !self.seen.contains(name))
.collect()
}
pub fn missing_optional(&self) -> impl Iterator<Item = &'a FieldInfo> {
self.resolution
.fields()
.values()
.filter(move |info| !info.required && !self.seen.contains(&info.serialized_name))
}
}