validator: rusty check v3

This commit is contained in:
Quaternions 2025-04-11 17:30:11 -07:00
parent 67215d82cd
commit 3eebd24c8b
Signed by: Quaternions
GPG Key ID: D0DF5964F79AC131

@ -182,7 +182,7 @@ pub struct DuplicateCheck<ID>(Result<(),DuplicateCheckContext<ID>>);
impl<ID> DuplicateCheckContext<ID>{ impl<ID> DuplicateCheckContext<ID>{
fn check(self)->DuplicateCheck<ID>{ fn check(self)->DuplicateCheck<ID>{
let Self(mut set)=self; let Self(mut set)=self;
// drop correct entries // remove correct entries
set.retain(|_,&mut c|c!=1); set.retain(|_,&mut c|c!=1);
// if any entries remain, they are incorrect // if any entries remain, they are incorrect
if set.is_empty(){ if set.is_empty(){
@ -195,33 +195,33 @@ impl<ID> DuplicateCheckContext<ID>{
// check that there is at least one // check that there is at least one
pub struct AtLeastOneMatchingAndNoExtraCheckContext<ID>{ pub struct AtLeastOneMatchingAndNoExtraCheckContext<ID>{
set:HashMap<ID,u64>, extra:HashMap<ID,u64>,
missing:HashSet<ID>, missing:HashSet<ID>,
} }
pub struct AtLeastOneMatchingAndNoExtraCheck<ID>(Result<(),AtLeastOneMatchingAndNoExtraCheckContext<ID>>); pub struct AtLeastOneMatchingAndNoExtraCheck<ID>(Result<(),AtLeastOneMatchingAndNoExtraCheckContext<ID>>);
impl<ID> AtLeastOneMatchingAndNoExtraCheckContext<ID>{ impl<ID> AtLeastOneMatchingAndNoExtraCheckContext<ID>{
fn new(set:HashMap<ID,u64>)->Self{ fn new(initial_set:HashMap<ID,u64>)->Self{
Self{ Self{
set, extra:initial_set,
missing:HashSet::new(), missing:HashSet::new(),
} }
} }
} }
impl<ID:Copy+Eq+std::hash::Hash> AtLeastOneMatchingAndNoExtraCheckContext<ID>{ impl<ID:Copy+Eq+std::hash::Hash> AtLeastOneMatchingAndNoExtraCheckContext<ID>{
fn check<T>(self,reference_set:&HashMap<ID,T>)->AtLeastOneMatchingAndNoExtraCheck<ID>{ fn check<T>(self,reference_set:&HashMap<ID,T>)->AtLeastOneMatchingAndNoExtraCheck<ID>{
let Self{mut set,mut missing}=self; let Self{mut extra,mut missing}=self;
// drop correct entries // remove correct entries
for (id,_) in reference_set{ for (id,_) in reference_set{
if !set.remove(id).is_some(){ if extra.remove(id).is_none(){
// the set did not contain a required item. This is a fail // the set did not contain a required item. This is a fail
missing.insert(*id); missing.insert(*id);
} }
} }
// if any entries remain, they are incorrect // if any entries remain, they are incorrect
if set.is_empty()&&missing.is_empty(){ if extra.is_empty()&&missing.is_empty(){
AtLeastOneMatchingAndNoExtraCheck(Ok(())) AtLeastOneMatchingAndNoExtraCheck(Ok(()))
}else{ }else{
AtLeastOneMatchingAndNoExtraCheck(Err(Self{set,missing})) AtLeastOneMatchingAndNoExtraCheck(Err(Self{extra,missing}))
} }
} }
} }
@ -264,11 +264,10 @@ impl<'a> ModelInfo<'a>{
if display_name.is_empty(){ if display_name.is_empty(){
StringEmptyCheck(Err(StringEmpty)) StringEmptyCheck(Err(StringEmpty))
}else{ }else{
let display_name=StringCheckContext{ StringEmptyCheck(Ok(StringCheckContext{
observed:display_name, observed:display_name,
expected:Cow::Owned(display_name.to_title_case()), expected:Cow::Owned(display_name.to_title_case()),
}.check(display_name); }.check(display_name)))
StringEmptyCheck(Ok(display_name))
} }
}); });
@ -299,7 +298,8 @@ impl<'a> ModelInfo<'a>{
}; };
// check that at least one end zone exists for each start zone. // check that at least one end zone exists for each start zone.
let mode_finish_counts=AtLeastOneMatchingAndNoExtraCheckContext::new(self.counts.mode_finish_counts).check(&self.counts.mode_start_counts); let mode_finish_counts=AtLeastOneMatchingAndNoExtraCheckContext::new(self.counts.mode_finish_counts)
.check(&self.counts.mode_start_counts);
// there must be exactly one start zone for every mode in the map. // there must be exactly one start zone for every mode in the map.
let mode_start_counts=DuplicateCheckContext(self.counts.mode_start_counts).check(); let mode_start_counts=DuplicateCheckContext(self.counts.mode_start_counts).check();