1use crate::PaymentError;
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub struct CountryCode(String);
6
7impl CountryCode {
8 pub fn new(code: impl AsRef<str>) -> Result<Self, PaymentError> {
14 let code = code.as_ref().trim();
15 if code.len() != 2 || !code.bytes().all(|byte| byte.is_ascii_alphabetic()) {
16 return Err(PaymentError::InvalidCountryCode(code.to_owned()));
17 }
18
19 Ok(Self(code.to_ascii_uppercase()))
20 }
21
22 #[inline]
24 #[must_use]
25 pub fn as_str(&self) -> &str {
26 &self.0
27 }
28}
29
30impl AsRef<str> for CountryCode {
31 #[inline]
32 fn as_ref(&self) -> &str {
33 self.as_str()
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn new_uppercases_valid_code() {
43 let code = CountryCode::new("zm").expect("country should be valid");
44
45 assert_eq!(code.as_str(), "ZM");
46 }
47
48 #[test]
49 fn new_rejects_invalid_code() {
50 assert!(matches!(
51 CountryCode::new("ZMB"),
52 Err(PaymentError::InvalidCountryCode(_))
53 ));
54 }
55}