1#![cfg_attr(not(feature = "std"), no_std)]
2
3pub extern crate alloc;
4
5#[macro_export]
7macro_rules! country_code {
8 (
9 length = $length:tt;
10 $( #[$meta:meta] )*
11 $pub:vis enum $name:ident {
12 $(
13 $( #[$variant_meta:meta] )*
14 $variant:ident,
15 )+
16 }
17 ) => {
18 $(#[$meta])*
19 $pub enum $name {
20 $(
21 $( #[$variant_meta] )*
22 $variant,
23 )+
24 Other($crate::alloc::boxed::Box<str>),
25 }
26
27 impl $name {
29 pub const VARS: &'static [$name] = &[
30 $(
31 $name::$variant,
32 )+
33 ];
34 }
35
36 impl ::core::str::FromStr for $name {
38 type Err = $crate::error::ParseError;
39
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 match s {
42 $(
43 ::core::stringify!($variant) => Ok(Self::$variant),
44 )+
45 s if s.len() == $length => Ok(Self::Other(s.into())),
46 s => Err($crate::error::ParseError::Invalid(s.into()))
47 }
48 }
49 }
50
51 impl ::core::fmt::Display for $name {
53 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
54 match self {
55 $(
56 Self::$variant => ::core::write!(f, "{}", ::core::stringify!($variant)),
57 )+
58 Self::Other(s) => ::core::write!(f, "{}", s)
59 }
60 }
61 }
62
63 impl ::core::default::Default for $name {
65 fn default() -> Self {
66 Self::Other(Default::default())
67 }
68 }
69
70 impl ::core::cmp::PartialEq for $name {
72 fn eq(&self, other: &Self) -> bool {
73 $crate::alloc::format!("{}", self) == $crate::alloc::format!("{}", other)
74 }
75 }
76
77 impl ::core::cmp::Eq for $name {
78 }
79
80 $crate::impl_partial_eq_str_for_display! { str, $name }
82 $crate::impl_partial_eq_str_for_display! { &'a str, $name }
83 $crate::impl_partial_eq_str_for_display! { $crate::alloc::borrow::Cow<'a, str>, $name }
84 $crate::impl_partial_eq_str_for_display! { $crate::alloc::string::String, $name }
85
86 #[cfg(feature = "std")]
88 impl ::std::hash::Hash for $name {
89 fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
90 $crate::alloc::format!("{}", self).hash(state);
91 }
92 }
93
94 #[cfg(feature = "serde")]
96 impl<'de> ::serde::Deserialize<'de> for $name {
97 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
98 where
99 D: ::serde::Deserializer<'de>,
100 {
101 use ::core::str::FromStr as _;
102
103 let s = $crate::alloc::boxed::Box::<str>::deserialize(deserializer)?;
104 Self::from_str(&s).map_err(::serde::de::Error::custom)
105 }
106 }
107
108 #[cfg(feature = "serde")]
110 impl ::serde::Serialize for $name {
111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 where
113 S: ::serde::Serializer,
114 {
115 use $crate::alloc::string::ToString as _;
116
117 self.to_string().serialize(serializer)
118 }
119 }
120 };
121}
122
123pub mod error;
125
126pub mod iso3166_1;
128pub mod iso3166_2;
129
130pub use iso3166_1::alpha_2::CountryCode;
131pub use iso3166_2::SubdivisionCode;
132
133#[macro_export]
135macro_rules! impl_partial_eq_str_for_display {
136 ($str:ty, $display:ty) => {
137 #[allow(unused_lifetimes)]
138 impl<'a> ::core::cmp::PartialEq<$str> for $display {
139 fn eq(&self, other: &$str) -> bool {
140 ::core::cmp::PartialEq::eq(&$crate::alloc::format!("{}", self)[..], &other[..])
141 }
142 }
143 };
144}