use core::{
convert::TryFrom,
fmt,
str::{self, FromStr},
};
use iso_macro::country_identifiers_from_table;
#[cfg(feature = "std")]
use std::error;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[non_exhaustive]
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub enum Error {
InvalidCountryCode(String),
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
Self::InvalidCountryCode(c) => {
formatter.write_str("`")?;
formatter.write_str(c)?;
formatter.write_str("` is an invalid country code")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for Error {}
pub trait Country {
fn name(&self) -> &'static str;
fn numeric(&self) -> u16;
fn code(&self) -> &'static str;
}
macro country_impl($country:ident, $country_as_string:literal) {
impl Country for $country {
fn name(&self) -> &'static str {
country_identifiers_from_table!(match &self: $country => "name")
}
fn numeric(&self) -> u16 {
country_identifiers_from_table!(match &self: $country => "Iso3166_1_numeric")
}
fn code(&self) -> &'static str {
country_identifiers_from_table!(match &self: $country => $country_as_string)
}
}
impl fmt::Display for $country {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.name())
}
}
impl TryFrom<u16> for $country {
type Error = Error;
fn try_from(c: u16) -> Result<Self, <Self as TryFrom<u16>>::Error> {
country_identifiers_from_table!(match c: "Iso3166_1_numeric" => $country).ok_or(Error::InvalidCountryCode(c.to_string()))
}
}
impl FromStr for $country {
type Err = Error;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
country_identifiers_from_table!(match s: $country_as_string => $country).ok_or(Error::InvalidCountryCode(s.to_string()))
}
}
}
macro country_impl_from($from:ident, $to:ident) {
impl From<$from> for $to {
fn from(c: $from) -> Self {
country_identifiers_from_table!(match c: $from => $to)
}
}
}
country_identifiers_from_table!(enum Iso3166_1_alpha_2: iso3166_1_alpha_2);
country_impl!(Iso3166_1_alpha_2, "Iso3166_1_alpha_2");
country_impl_from!(Iso3166_1_alpha_3, Iso3166_1_alpha_2);
country_identifiers_from_table!(enum Iso3166_1_alpha_3: iso3166_1_alpha_3);
country_impl!(Iso3166_1_alpha_3, "Iso3166_1_alpha_3");
country_impl_from!(Iso3166_1_alpha_2, Iso3166_1_alpha_3);