use regex::Regex;
pub struct DecimalFormat {
positive_pattern: String,
negative_pattern: String,
}
impl DecimalFormat {
pub fn new(pattern: &str) -> Result<Self, String> {
let special_chars = ['\'', '(', ')', '0', '.', ',', '#', ';', '¤', '%'];
let mut in_quotes = false;
let mut patterns = vec![String::new()];
for c in pattern.chars() {
if !in_quotes && c == '\'' {
in_quotes = true;
patterns.last_mut().unwrap().push(c);
continue;
}
if in_quotes && c == '\'' {
in_quotes = false;
patterns.last_mut().unwrap().push(c);
continue;
}
if !in_quotes && !special_chars.contains(&c) {
return Err(format!("Invalid character: {}", c));
}
if c == ';' && !in_quotes {
patterns.push(String::new()); } else {
patterns.last_mut().unwrap().push(c); }
}
if patterns.len() > 2 {
return Err("Invalid pattern".to_string());
}
let positive_pattern = patterns.first().ok_or("Missing positive pattern")?.clone();
let negative_pattern = patterns
.get(1)
.map(|p| format!("-{}", p))
.unwrap_or_else(|| format!("-{}", positive_pattern));
Ok(DecimalFormat {
positive_pattern,
negative_pattern,
})
}
pub fn validate_number(&self, input: &str) -> Result<(), &'static str> {
let positive_regex = Self::pattern_to_regex(&self.positive_pattern)?;
let negative_regex = Self::pattern_to_regex(&self.negative_pattern)?;
let positive_re = Regex::new(&positive_regex).map_err(|_| "Invalid regex pattern")?;
let negative_re = Regex::new(&negative_regex).map_err(|_| "Invalid regex pattern")?;
if positive_re.is_match(input) || negative_re.is_match(input) {
Ok(())
} else {
Err("Input does not match pattern")
}
}
fn pattern_to_regex(pattern: &str) -> Result<String, &'static str> {
let mut regex_pattern = String::new();
let mut in_quotes = false;
for c in pattern.chars() {
if !in_quotes && c == '\'' {
in_quotes = true;
continue;
}
if in_quotes && c == '\'' {
in_quotes = false;
continue;
}
if in_quotes {
regex_pattern.push(c);
} else {
match c {
'0' => regex_pattern.push_str("\\d"), '#' => regex_pattern.push_str("\\d?"), ',' => regex_pattern.push_str("\\,?"),
'.' => regex_pattern.push_str("\\."),
';' => regex_pattern.push_str("\\;"),
'¤' => regex_pattern.push_str("\\$"),
_ => regex_pattern.push(c),
}
}
}
regex_pattern.insert(0, '^');
regex_pattern.push('$');
Ok(regex_pattern)
}
}