use super::PatternMatch;
use crate::types::redaction::PiiCategory;
use once_cell::sync::Lazy;
use regex::Regex;
const IBAN_COUNTRIES: &[&str] = &[
"AD", "AE", "AL", "AT", "AZ", "BA", "BE", "BG", "BH", "BR", "BY", "CH", "CR", "CY", "CZ", "DE", "DK", "DO", "EE",
"EG", "ES", "FI", "FO", "FR", "GB", "GE", "GI", "GL", "GR", "GT", "HR", "HU", "IE", "IL", "IQ", "IS", "IT", "JO",
"KW", "KZ", "LB", "LC", "LI", "LT", "LU", "LV", "LY", "MC", "MD", "ME", "MK", "MR", "MT", "MU", "NL", "NO", "PK",
"PL", "PS", "PT", "QA", "RO", "RS", "SA", "SC", "SE", "SI", "SK", "SM", "ST", "SV", "TL", "TN", "TR", "UA", "VA",
"VG", "XK",
];
static RE_IBAN: Lazy<Regex> =
Lazy::new(|| Regex::new(r"\b[A-Z]{2}\d{2}(?:[ ]?[A-Z0-9]){11,30}\b").expect("iban regex compiles"));
pub fn find_all(text: &str) -> Vec<PatternMatch> {
let upper = text.to_ascii_uppercase();
RE_IBAN
.find_iter(&upper)
.filter_map(|m| {
let raw = &upper[m.start()..m.end()];
let cc = &raw[..2];
if !IBAN_COUNTRIES.contains(&cc) {
return None;
}
let compact: String = raw.chars().filter(|c| !c.is_whitespace()).collect();
if !(15..=34).contains(&compact.len()) {
return None;
}
Some(PatternMatch {
start: m.start(),
end: m.end(),
category: PiiCategory::Iban,
text: text[m.start()..m.end()].to_string(),
})
})
.collect()
}