1#![doc = include_str!("../README.md")]
4#![no_std]
5
6#[cfg(feature = "serde")]
7pub mod serde;
8
9use core::str::FromStr;
10use iso3166_static::{Alpha2, Alpha3, Numeric};
11
12iso4217_macros::generate!(xml = "list-one.xml", zerocopy = true);
13
14impl Error {
15 #[must_use]
17 pub const fn is_invalid_code(&self) -> bool {
18 matches!(self, Self::InvalidCode)
19 }
20
21 #[must_use]
23 pub const fn is_invalid_length(&self) -> bool {
24 matches!(self, Self::InvalidLength)
25 }
26
27 #[must_use]
29 pub const fn is_invalid_charset(&self) -> bool {
30 matches!(self, Self::InvalidCharset)
31 }
32
33 #[must_use]
35 pub const fn is_no_universal_currency(&self) -> bool {
36 matches!(self, Self::NoUniversalCurrency)
37 }
38}
39
40impl AsRef<str> for Currency {
41 fn as_ref(&self) -> &str {
42 self.as_str()
43 }
44}
45
46impl FromStr for Currency {
47 type Err = Error;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 Self::try_from(s)
51 }
52}
53
54impl TryFrom<u16> for Currency {
55 type Error = Error;
56
57 fn try_from(value: u16) -> Result<Self, Self::Error> {
58 Self::from_u16(value)
59 }
60}
61
62impl TryFrom<&str> for Currency {
63 type Error = Error;
64
65 fn try_from(value: &str) -> Result<Self, Self::Error> {
66 Self::from_str_slice(value)
67 }
68}
69
70impl TryFrom<Numeric> for Currency {
71 type Error = Error;
72
73 fn try_from(value: Numeric) -> Result<Self, Self::Error> {
74 Self::from_numeric_country(value).ok_or(Error::NoUniversalCurrency)
75 }
76}
77
78impl TryFrom<Alpha2> for Currency {
79 type Error = Error;
80
81 fn try_from(value: Alpha2) -> Result<Self, Self::Error> {
82 Self::from_alpha2_country(value).ok_or(Error::NoUniversalCurrency)
83 }
84}
85
86impl TryFrom<Alpha3> for Currency {
87 type Error = Error;
88
89 fn try_from(value: Alpha3) -> Result<Self, Self::Error> {
90 Self::from_alpha3_country(value).ok_or(Error::NoUniversalCurrency)
91 }
92}
93
94#[cfg(test)]
95mod test {
96 use super::*;
97 use iso3166_static::{Alpha2, Alpha3, Numeric};
98
99 #[test]
100 fn for_country() {
101 const NO_CURRENCY: &[Numeric] = &[
102 Numeric::Antarctica,
103 Numeric::SouthGeorgiaAndTheSouthSandwichIslands,
104 Numeric::Palestine,
105 ];
106
107 for i in 1..=899 {
108 if let Ok(numeric) = Numeric::from_u16(i)
110 && let Ok(alpha2) = Alpha2::from_numeric(numeric)
111 && let Ok(alpha3) = Alpha3::from_numeric(numeric)
112 {
113 let numeric_currency = Currency::try_from(numeric);
114 let alpha2_currency = Currency::try_from(alpha2);
115 let alpha3_currency = Currency::try_from(alpha3);
116
117 if NO_CURRENCY.contains(&numeric) {
118 assert_eq!(
119 Error::NoUniversalCurrency,
120 numeric_currency.expect_err("no currency")
121 );
122 assert_eq!(
123 Error::NoUniversalCurrency,
124 alpha2_currency.expect_err("no currency")
125 );
126 assert_eq!(
127 Error::NoUniversalCurrency,
128 alpha3_currency.expect_err("no currency")
129 );
130 } else {
131 assert!(numeric_currency.is_ok());
132 assert!(alpha2_currency.is_ok());
133 assert!(alpha3_currency.is_ok());
134 }
135 }
136 }
137 }
138}