Skip to main content

kmp_plugin_api/domain/
currency_code.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5use super::interpretation_error::InterpretationError;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
8pub struct CurrencyCode(String);
9
10impl CurrencyCode {
11    pub fn new(value: impl AsRef<str>) -> Result<Self, InterpretationError> {
12        let normalized = value.as_ref().trim().to_ascii_uppercase();
13        if normalized.len() != 3 || !normalized.chars().all(|char| char.is_ascii_uppercase()) {
14            return Err(InterpretationError::new(format!(
15                "invalid currency code `{}`",
16                value.as_ref()
17            )));
18        }
19        Ok(Self(normalized))
20    }
21
22    pub fn as_str(&self) -> &str {
23        &self.0
24    }
25}
26
27impl fmt::Display for CurrencyCode {
28    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
29        formatter.write_str(self.as_str())
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36
37    #[test]
38    fn normalizes_to_uppercase_iso_like_code() {
39        assert_eq!(CurrencyCode::new(" usd ").expect("code").as_str(), "USD");
40    }
41
42    #[test]
43    fn rejects_non_iso_like_values() {
44        assert_eq!(
45            CurrencyCode::new("US").expect_err("invalid").to_string(),
46            "invalid currency code `US`"
47        );
48    }
49}