use super::*;
pub(crate) fn non_empty_trimmed(sample: &[String]) -> Vec<&str> {
sample
.iter()
.map(|v| v.trim())
.filter(|v| !v.is_empty())
.collect()
}
pub(crate) fn non_empty_lower(sample: &[String]) -> Vec<String> {
sample
.iter()
.map(|v| v.trim().to_lowercase())
.filter(|v| !v.is_empty())
.collect()
}
pub(crate) fn demote_when_substance_fails(
result: &mut ColumnResult,
sample: &[String],
label: &str,
rule: &str,
predicate: impl Fn(&str) -> bool,
) {
if rhh::is_disabled(rule) {
return;
}
if result.label != label {
return;
}
let non_empty = non_empty_trimmed(sample);
if non_empty.len() < 3 {
return;
}
let valid = non_empty.iter().filter(|v| predicate(v)).count();
if valid * 2 >= non_empty.len() {
return;
}
result.label = "unknown".to_string();
result.confidence = result.confidence.min(0.6);
result.disambiguation_applied = true;
result.disambiguation_rule = Some(rule.to_string());
result.detected_locale = None;
}
pub(crate) fn demote_by_shape_when_substance_fails(
result: &mut ColumnResult,
sample: &[String],
taxonomy: &Taxonomy,
rule: &str,
predicate: impl Fn(&str) -> bool,
) {
let non_empty = non_empty_trimmed(sample);
if non_empty.len() < 3 {
return;
}
let valid = non_empty.iter().filter(|v| predicate(v)).count();
if valid * 2 >= non_empty.len() {
return;
}
let (is_bare, any_decimal) = values_look_like_bare_numbers(sample);
let demoted_from = result.label.clone();
result.label = if is_bare {
if any_decimal {
"representation.numeric.decimal_number".to_string()
} else {
"representation.numeric.integer_number".to_string()
}
} else {
"representation.identifier.alphanumeric_id".to_string()
};
result.confidence = result.confidence.min(0.6);
result.disambiguation_applied = true;
result.disambiguation_rule = Some(format!("{rule}:{demoted_from}"));
result.detected_locale = detect_locale_from_validation(sample, &result.label, taxonomy);
}
pub(crate) fn demote_bare_to_numeric(
result: &mut ColumnResult,
sample: &[String],
taxonomy: Option<&Taxonomy>,
any_decimal: bool,
rule: &str,
header: &str,
) {
result.label = if any_decimal {
"representation.numeric.decimal_number".to_string()
} else {
"representation.numeric.integer_number".to_string()
};
result.confidence = result.confidence.min(0.6);
result.disambiguation_applied = true;
result.disambiguation_rule = Some(format!("{rule}:{}", header.to_lowercase()));
if let Some(taxonomy) = taxonomy {
result.detected_locale = detect_locale_from_validation(sample, &result.label, taxonomy);
}
}