rule page in the validation client

This commit is contained in:
Priec
2026-05-10 09:23:33 +02:00
parent 17a13569d8
commit def75c00b4
9 changed files with 130 additions and 43 deletions

View File

@@ -1,5 +1,6 @@
use crate::{ValidationConfig, ValidationMergeError, ValidationSettings};
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationRule {
@@ -18,19 +19,52 @@ impl ValidationRule {
pub struct ValidationSet {
pub name: String,
pub description: Option<String>,
pub rules: Vec<ValidationRule>,
pub items: Vec<ValidationSetItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ValidationSetItem {
GlobalRuleRef(String),
InlineRule {
name: Option<String>,
validation: ValidationSettings,
},
}
impl ValidationSet {
pub fn resolve_settings(&self) -> Result<ValidationSettings, ValidationMergeError> {
ValidationSettings::merge_rules(self.rules.iter().map(|rule| &rule.settings))
pub fn resolve_settings_with_rules<'a>(
&'a self,
rules: impl Fn(&str) -> Option<&'a ValidationRule>,
) -> Result<ValidationSettings, ValidationSetResolveError> {
let settings = self.items.iter().map(|item| match item {
ValidationSetItem::GlobalRuleRef(name) => {
rules(name).map(|rule| &rule.settings).ok_or_else(|| {
ValidationSetResolveError::MissingGlobalRule { name: name.clone() }
})
}
ValidationSetItem::InlineRule { validation, .. } => Ok(validation),
});
let settings = settings.collect::<Result<Vec<_>, _>>()?;
Ok(ValidationSettings::merge_rules(settings)?)
}
pub fn resolve(&self) -> Result<ValidationConfig, ValidationMergeError> {
Ok(self.resolve_settings()?.resolve())
pub fn resolve_with_rules<'a>(
&'a self,
rules: impl Fn(&str) -> Option<&'a ValidationRule>,
) -> Result<ValidationConfig, ValidationSetResolveError> {
Ok(self.resolve_settings_with_rules(rules)?.resolve())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum ValidationSetResolveError {
#[error("validation set references missing global rule '{name}'")]
MissingGlobalRule { name: String },
#[error(transparent)]
Merge(#[from] ValidationMergeError),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppliedValidation {
pub set_name: Option<String>,
@@ -56,19 +90,17 @@ mod tests {
let set = ValidationSet {
name: "phone".to_string(),
description: None,
rules: vec![
ValidationRule {
name: "phone-length".to_string(),
description: None,
settings: ValidationSettings {
items: vec![
ValidationSetItem::InlineRule {
name: Some("phone-length".to_string()),
validation: ValidationSettings {
character_limits: Some(CharacterLimits::new_range(10, 15)),
..ValidationSettings::default()
},
},
ValidationRule {
name: "digits-only".to_string(),
description: None,
settings: ValidationSettings {
ValidationSetItem::InlineRule {
name: Some("digits-only".to_string()),
validation: ValidationSettings {
pattern: Some(PatternSettings {
filters: vec![PositionFilterSettings {
positions: PositionRange::From(0),
@@ -82,7 +114,9 @@ mod tests {
],
};
let settings = set.resolve_settings().expect("set should resolve");
let settings = set
.resolve_settings_with_rules(|_| None)
.expect("set should resolve");
assert!(settings.character_limits.is_some());
assert_eq!(settings.pattern.expect("pattern").filters.len(), 1);
@@ -93,19 +127,17 @@ mod tests {
let set = ValidationSet {
name: "conflict".to_string(),
description: None,
rules: vec![
ValidationRule {
name: "short".to_string(),
description: None,
settings: ValidationSettings {
items: vec![
ValidationSetItem::InlineRule {
name: Some("short".to_string()),
validation: ValidationSettings {
character_limits: Some(CharacterLimits::new(10)),
..ValidationSettings::default()
},
},
ValidationRule {
name: "long".to_string(),
description: None,
settings: ValidationSettings {
ValidationSetItem::InlineRule {
name: Some("long".to_string()),
validation: ValidationSettings {
character_limits: Some(CharacterLimits::new(20)),
..ValidationSettings::default()
},
@@ -113,6 +145,6 @@ mod tests {
],
};
assert!(set.resolve_settings().is_err());
assert!(set.resolve_settings_with_rules(|_| None).is_err());
}
}