Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 108 additions & 69 deletions crates/stringsimile-config/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,34 @@ use stringsimile_matcher::{
},
};

/// Configuration for rules
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuleConfig {
#[serde(flatten, default)]
pub(crate) common: CommonRuleConfig,
#[serde(flatten)]
pub(crate) rule_type: RuleTypeConfig,
}

/// Common configuration for rules
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommonRuleConfig {
#[serde(default)]
pub(crate) exit_on_match: bool,
}

impl From<&CommonRuleConfig> for stringsimile_matcher::ruleset::CommonRuleConfig {
fn from(value: &CommonRuleConfig) -> Self {
Self {
exit_on_match: value.exit_on_match,
}
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "rule_type", rename_all = "snake_case", content = "values")]
/// Configuration for rules
pub enum RuleConfig {
/// Configuration for specific rule types
pub enum RuleTypeConfig {
/// Configuration for Levenshtein rule
Levenshtein(LevenshteinConfig),
/// Configuration for Hamming rule
Expand Down Expand Up @@ -130,48 +154,63 @@ impl RuleConfig {
&self,
target_str: &str,
ignore_mismatch_metadata: bool,
) -> Result<Box<dyn GenericMatcherRule>, Error> {
Ok(match self {
RuleConfig::Levenshtein(levenshtein_config) => Box::new(
levenshtein_config
.build(ignore_mismatch_metadata)?
.into_generic_matcher(),
),
RuleConfig::Hamming(hamming_config) => {
Box::new(hamming_config.build()?.into_generic_matcher())
}
RuleConfig::Confusables => Box::new(ConfusablesConfig.build()?.into_generic_matcher()),
RuleConfig::Jaro(jaro_config) => Box::new(jaro_config.build()?.into_generic_matcher()),
RuleConfig::JaroWinkler(jaro_winkler_config) => {
Box::new(jaro_winkler_config.build()?.into_generic_matcher())
}
RuleConfig::DamerauLevenshtein(damerau_levenshtein_config) => {
Box::new(damerau_levenshtein_config.build(ignore_mismatch_metadata)?)
}
RuleConfig::Soundex(soundex_config) => {
Box::new(soundex_config.build(target_str)?.into_generic_matcher())
}
RuleConfig::Metaphone(metaphone_config) => {
Box::new(metaphone_config.build(target_str)?.into_generic_matcher())
}
RuleConfig::Nysiis(nysiis_config) => {
Box::new(nysiis_config.build(target_str)?.into_generic_matcher())
}
RuleConfig::MatchRating => {
Box::new(MatchRatingConfig.build(target_str)?.into_generic_matcher())
}
RuleConfig::Bitflip(bitflip_config) => Box::new(
bitflip_config
.clone()
.unwrap_or_default()
.build(target_str)?
.into_generic_matcher(),
),
RuleConfig::Regex(regex_config) => {
Box::new(regex_config.build()?.into_generic_matcher())
}
RuleConfig::Cidr(cidr_config) => Box::new(cidr_config.build()?.into_generic_matcher()),
})
) -> Result<
(
stringsimile_matcher::ruleset::CommonRuleConfig,
Box<dyn GenericMatcherRule>,
),
Error,
> {
Ok((
(&self.common).into(),
match &self.rule_type {
RuleTypeConfig::Levenshtein(levenshtein_config) => Box::new(
levenshtein_config
.build(ignore_mismatch_metadata)?
.into_generic_matcher(),
),
RuleTypeConfig::Hamming(hamming_config) => {
Box::new(hamming_config.build()?.into_generic_matcher())
}
RuleTypeConfig::Confusables => {
Box::new(ConfusablesConfig.build()?.into_generic_matcher())
}
RuleTypeConfig::Jaro(jaro_config) => {
Box::new(jaro_config.build()?.into_generic_matcher())
}
RuleTypeConfig::JaroWinkler(jaro_winkler_config) => {
Box::new(jaro_winkler_config.build()?.into_generic_matcher())
}
RuleTypeConfig::DamerauLevenshtein(damerau_levenshtein_config) => {
Box::new(damerau_levenshtein_config.build(ignore_mismatch_metadata)?)
}
RuleTypeConfig::Soundex(soundex_config) => {
Box::new(soundex_config.build(target_str)?.into_generic_matcher())
}
RuleTypeConfig::Metaphone(metaphone_config) => {
Box::new(metaphone_config.build(target_str)?.into_generic_matcher())
}
RuleTypeConfig::Nysiis(nysiis_config) => {
Box::new(nysiis_config.build(target_str)?.into_generic_matcher())
}
RuleTypeConfig::MatchRating => {
Box::new(MatchRatingConfig.build(target_str)?.into_generic_matcher())
}
RuleTypeConfig::Bitflip(bitflip_config) => Box::new(
bitflip_config
.clone()
.unwrap_or_default()
.build(target_str)?
.into_generic_matcher(),
),
RuleTypeConfig::Regex(regex_config) => {
Box::new(regex_config.build()?.into_generic_matcher())
}
RuleTypeConfig::Cidr(cidr_config) => {
Box::new(cidr_config.build()?.into_generic_matcher())
}
},
))
}
}

Expand Down Expand Up @@ -491,7 +530,7 @@ mod tests {
}
"#;

let RuleConfig::Levenshtein(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Levenshtein(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Levenshtein config");
};
assert_eq!(3, config.maximum_distance);
Expand All @@ -508,7 +547,7 @@ mod tests {
}
"#;

let RuleConfig::Jaro(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Jaro(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Jaro config");
};
assert_eq!(0.4, config.match_percent_threshold);
Expand All @@ -522,7 +561,7 @@ mod tests {
}
"#;

let RuleConfig::Confusables = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Confusables = serde_json::from_str(json).unwrap() else {
panic!("Expected Confusables config");
};
}
Expand All @@ -538,7 +577,7 @@ mod tests {
}
"#;

let RuleConfig::DamerauLevenshtein(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::DamerauLevenshtein(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Damera Levenshtein config");
};
assert_eq!(3, config.maximum_distance);
Expand All @@ -555,7 +594,7 @@ mod tests {
}
"#;

let RuleConfig::JaroWinkler(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::JaroWinkler(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Jaro-Winkler config");
};
assert_eq!(0.4, config.match_percent_threshold);
Expand All @@ -572,7 +611,7 @@ mod tests {
}
"#;

let RuleConfig::Hamming(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Hamming(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Hamming config");
};
assert_eq!(3, config.maximum_distance);
Expand All @@ -590,7 +629,7 @@ mod tests {
}
"#;

let RuleConfig::Soundex(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Soundex(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Soundex config");
};
assert_eq!(3, config.minimum_similarity);
Expand All @@ -608,7 +647,7 @@ mod tests {
}
"#;

let RuleConfig::Soundex(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Soundex(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Soundex config");
};
assert_eq!(3, config.minimum_similarity);
Expand All @@ -627,7 +666,7 @@ mod tests {
}
"#;

let RuleConfig::Soundex(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Soundex(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Soundex config");
};
assert_eq!(3, config.minimum_similarity);
Expand All @@ -646,7 +685,7 @@ mod tests {
}
"#;

let RuleConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Metaphone config");
};
assert_eq!(Some(3), config.max_code_length);
Expand All @@ -662,7 +701,7 @@ mod tests {
}
"#;

let RuleConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Metaphone config");
};
assert_eq!(Some(4), config.max_code_length);
Expand All @@ -680,7 +719,7 @@ mod tests {
}
"#;

let RuleConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Metaphone config");
};
assert_eq!(None, config.max_code_length);
Expand All @@ -698,7 +737,7 @@ mod tests {
}
"#;

let RuleConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Metaphone config");
};
assert_eq!(default_metaphone_max_code_length(), config.max_code_length);
Expand All @@ -717,7 +756,7 @@ mod tests {
}
"#;

let RuleConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Metaphone(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Metaphone config");
};
assert_eq!(Some(3), config.max_code_length);
Expand All @@ -735,7 +774,7 @@ mod tests {
}
"#;

let RuleConfig::Nysiis(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Nysiis(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Nysiis config");
};
assert!(!config.strict);
Expand All @@ -750,7 +789,7 @@ mod tests {
}
"#;

let RuleConfig::Nysiis(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Nysiis(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Nysiis config");
};
assert!(config.strict);
Expand All @@ -764,7 +803,7 @@ mod tests {
}
"#;

let RuleConfig::MatchRating = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::MatchRating = serde_json::from_str(json).unwrap() else {
panic!("Expected Match Rating config");
};
}
Expand All @@ -777,7 +816,7 @@ mod tests {
}
"#;

let RuleConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Biflip config");
};
let config = config.unwrap_or_default();
Expand All @@ -798,7 +837,7 @@ mod tests {
}
"#;

let RuleConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Biflip config");
};
let config = config.unwrap_or_default();
Expand All @@ -820,7 +859,7 @@ mod tests {
}
"#;

let RuleConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Biflip config");
};
let config = config.unwrap_or_default();
Expand All @@ -842,7 +881,7 @@ mod tests {
}
"#;

let RuleConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Bitflip(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Biflip config");
};
let config = config.unwrap_or_default();
Expand All @@ -869,7 +908,7 @@ mod tests {
}
"#;

let RuleConfig::Regex(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Regex(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Regex config");
};
assert_eq!(config.pattern, "test");
Expand All @@ -889,7 +928,7 @@ mod tests {
}
"#;

let RuleConfig::Regex(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Regex(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected Regex config");
};
assert_eq!(config.pattern, "[");
Expand All @@ -909,7 +948,7 @@ mod tests {
}
"#;

let RuleConfig::Cidr(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Cidr(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected CIDR config");
};
assert_eq!(config.address, "192.168.0.0/24");
Expand All @@ -929,7 +968,7 @@ mod tests {
}
"#;

let RuleConfig::Cidr(config) = serde_json::from_str(json).unwrap() else {
let RuleTypeConfig::Cidr(config) = serde_json::from_str(json).unwrap() else {
panic!("Expected CIDR config");
};
assert_eq!(config.address, "test");
Expand Down
Loading
Loading