formualizer_eval/
locale.rs1#[derive(Copy, Clone, Debug, Eq, PartialEq)]
13pub struct Locale;
14
15impl Locale {
16 pub const fn invariant() -> Self {
17 Locale
18 }
19
20 pub fn parse_number_invariant(&self, s: &str) -> Option<f64> {
25 let trimmed = s.trim();
26 if let Some(without_pct) = trimmed.strip_suffix('%') {
27 let n = without_pct.trim().parse::<f64>().ok()?;
28 Some(n / 100.0)
29 } else {
30 trimmed.parse::<f64>().ok()
31 }
32 }
33
34 pub fn fold_case_invariant(&self, s: &str) -> String {
36 s.to_ascii_lowercase()
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::Locale;
43
44 #[test]
45 fn parse_number_invariant_supports_percent_suffix() {
46 let loc = Locale::invariant();
47 assert_eq!(loc.parse_number_invariant("90%"), Some(0.9));
48 assert_eq!(loc.parse_number_invariant(" 90.5% "), Some(0.905));
49 assert_eq!(loc.parse_number_invariant("90 %"), Some(0.9));
50 }
51
52 #[test]
53 fn parse_number_invariant_rejects_invalid_percent_text() {
54 let loc = Locale::invariant();
55 assert_eq!(loc.parse_number_invariant("abc%"), None);
56 assert_eq!(loc.parse_number_invariant("%"), None);
57 assert_eq!(loc.parse_number_invariant("90% trailing"), None);
58 }
59}