kmp_plugin_api/domain/
currency_code.rs1use 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}