1use std::collections::HashMap;
2
3use crate::config::RuleSpec;
4use crate::error::{Error, Result};
5use crate::rule::Rule;
6
7pub type RuleBuilder = fn(&RuleSpec) -> Result<Box<dyn Rule>>;
8
9#[derive(Default)]
12pub struct RuleRegistry {
13 builders: HashMap<String, RuleBuilder>,
14}
15
16impl std::fmt::Debug for RuleRegistry {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("RuleRegistry")
19 .field("kinds", &self.builders.keys().collect::<Vec<_>>())
20 .finish()
21 }
22}
23
24impl RuleRegistry {
25 pub fn new() -> Self {
26 Self::default()
27 }
28
29 pub fn register(&mut self, kind: &str, builder: RuleBuilder) {
30 self.builders.insert(kind.to_string(), builder);
31 }
32
33 pub fn build(&self, spec: &RuleSpec) -> Result<Box<dyn Rule>> {
34 let builder = self
35 .builders
36 .get(&spec.kind)
37 .ok_or_else(|| Error::UnknownRuleKind(spec.kind.clone()))?;
38 builder(spec)
39 }
40
41 pub fn known_kinds(&self) -> impl Iterator<Item = &str> {
42 self.builders.keys().map(String::as_str)
43 }
44}