Fix validator selection for apply, address and policy command
Before this commit, we would require those target a specific handler, whereas they are in fact global to the entire validator. So now, we recover the behaviour from before where we default to the only available validator when there's no ambiguity. Note that this also solves the need for repeatedly applying parameters to each handler of a parameterized validator. The command now rightfully apply parameters to each corresponding handler.
This commit is contained in:
@@ -52,7 +52,7 @@ pub struct Compiler {
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum LookupResult<'a, T> {
|
||||
One(&'a T),
|
||||
One(String, &'a T),
|
||||
Many,
|
||||
}
|
||||
|
||||
@@ -91,17 +91,48 @@ impl Blueprint {
|
||||
}
|
||||
|
||||
impl Blueprint {
|
||||
pub fn lookup(&self, title: Option<&String>) -> Option<LookupResult<Validator>> {
|
||||
pub fn lookup(
|
||||
&self,
|
||||
want_module_name: Option<&str>,
|
||||
want_validator_name: Option<&str>,
|
||||
) -> Option<LookupResult<Validator>> {
|
||||
let mut validator = None;
|
||||
|
||||
for v in self.validators.iter() {
|
||||
let match_title = Some(&v.title) == title.or(Some(&v.title));
|
||||
if match_title {
|
||||
validator = Some(if validator.is_none() {
|
||||
LookupResult::One(v)
|
||||
} else {
|
||||
LookupResult::Many
|
||||
})
|
||||
let mut split = v.title.split('.');
|
||||
|
||||
let known_module_name = split
|
||||
.next()
|
||||
.expect("validator's name must have two dot-separated components.");
|
||||
|
||||
let known_validator_name = split
|
||||
.next()
|
||||
.expect("validator's name must have two dot-separated components.");
|
||||
|
||||
let is_target = match (want_module_name, want_validator_name) {
|
||||
(None, None) => true,
|
||||
(Some(want_module_name), None) => want_module_name == known_module_name,
|
||||
(None, Some(want_validator_name)) => want_validator_name == known_validator_name,
|
||||
(Some(want_module_name), Some(want_validator_name)) => {
|
||||
want_module_name == known_module_name
|
||||
&& want_validator_name == known_validator_name
|
||||
}
|
||||
};
|
||||
|
||||
let title = format!("{known_module_name}.{known_validator_name}");
|
||||
|
||||
if is_target {
|
||||
match validator {
|
||||
Some(LookupResult::Many) => (),
|
||||
None => {
|
||||
validator = Some(LookupResult::One(title, v));
|
||||
}
|
||||
Some(LookupResult::One(ref known_title, _)) => {
|
||||
if title.as_str() != known_title {
|
||||
validator = Some(LookupResult::Many)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,16 +141,17 @@ impl Blueprint {
|
||||
|
||||
pub fn with_validator<F, A, E>(
|
||||
&self,
|
||||
title: Option<&String>,
|
||||
module_name: Option<&str>,
|
||||
validator_name: Option<&str>,
|
||||
when_too_many: fn(Vec<String>) -> E,
|
||||
when_missing: fn(Vec<String>) -> E,
|
||||
action: F,
|
||||
) -> Result<A, E>
|
||||
where
|
||||
F: Fn(Validator) -> Result<A, E>,
|
||||
F: Fn(&Validator) -> Result<A, E>,
|
||||
{
|
||||
match self.lookup(title) {
|
||||
Some(LookupResult::One(validator)) => action(validator.to_owned()),
|
||||
match self.lookup(module_name, validator_name) {
|
||||
Some(LookupResult::One(_, validator)) => action(validator),
|
||||
Some(LookupResult::Many) => Err(when_too_many(
|
||||
self.validators.iter().map(|v| v.title.clone()).collect(),
|
||||
)),
|
||||
|
||||
Reference in New Issue
Block a user