Skip to main content

shell_sanitize/
rule.rs

1use crate::error::RuleViolation;
2
3/// Result of a rule check: either pass or one or more violations.
4pub type RuleResult = Result<(), Vec<RuleViolation>>;
5
6/// A sanitization rule that inspects an input string and reports violations.
7///
8/// Implement this trait to create custom rules. Rules are composable via
9/// [`Sanitizer`](crate::Sanitizer).
10///
11/// # Example
12///
13/// ```
14/// use shell_sanitize::{Rule, RuleResult, RuleViolation};
15///
16/// struct NoSpacesRule;
17///
18/// impl Rule for NoSpacesRule {
19///     fn name(&self) -> &'static str { "no_spaces" }
20///
21///     fn check(&self, input: &str) -> RuleResult {
22///         let violations: Vec<_> = input
23///             .char_indices()
24///             .filter(|(_, c)| *c == ' ')
25///             .map(|(i, _)| RuleViolation::new(self.name(), "space character found")
26///                 .at(i)
27///                 .with_fragment(" "))
28///             .collect();
29///         if violations.is_empty() { Ok(()) } else { Err(violations) }
30///     }
31/// }
32/// ```
33pub trait Rule: Send + Sync {
34    /// A unique, human-readable identifier for this rule.
35    fn name(&self) -> &'static str;
36
37    /// Check the input and return violations, if any.
38    fn check(&self, input: &str) -> RuleResult;
39}
40
41impl Rule for Box<dyn Rule> {
42    fn name(&self) -> &'static str {
43        (**self).name()
44    }
45
46    fn check(&self, input: &str) -> RuleResult {
47        (**self).check(input)
48    }
49}