rskit_testutil/golden/
normalize.rs1use regex::{NoExpand, Regex};
2use rskit_errors::{AppError, AppResult};
3
4#[derive(Debug, Clone)]
6enum RuleMatcher {
7 Literal(String),
8 Pattern(Regex),
9}
10
11#[derive(Debug, Clone)]
18pub struct Rule {
19 matcher: RuleMatcher,
20 placeholder: String,
21}
22
23impl Rule {
24 #[must_use]
26 pub fn literal(text: impl Into<String>, placeholder: impl Into<String>) -> Self {
27 Self {
28 matcher: RuleMatcher::Literal(text.into()),
29 placeholder: placeholder.into(),
30 }
31 }
32
33 pub fn pattern(pattern: &str, placeholder: impl Into<String>) -> AppResult<Self> {
39 let regex = Regex::new(pattern).map_err(|err| {
40 AppError::invalid_input("pattern", "failed to compile normalization pattern")
41 .with_cause(err)
42 })?;
43 Ok(Self {
44 matcher: RuleMatcher::Pattern(regex),
45 placeholder: placeholder.into(),
46 })
47 }
48
49 fn apply(&self, input: &str) -> String {
50 match &self.matcher {
51 RuleMatcher::Literal(text) => input.replace(text, &self.placeholder),
52 RuleMatcher::Pattern(regex) => regex
53 .replace_all(input, NoExpand(&self.placeholder))
54 .into_owned(),
55 }
56 }
57}
58
59#[derive(Debug, Clone, Default)]
65pub struct Normalizer {
66 rules: Vec<Rule>,
67}
68
69impl Normalizer {
70 #[must_use]
72 pub fn new(rules: Vec<Rule>) -> Self {
73 Self { rules }
74 }
75
76 #[must_use]
78 pub fn apply(&self, input: &str) -> String {
79 self.rules
80 .iter()
81 .fold(input.to_owned(), |text, rule| rule.apply(&text))
82 }
83}