use core::{
convert::TryFrom,
fmt,
str::{self, FromStr},
};
use iso_macro::language_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 {
InvalidLanguageCode(String),
NoCorrespondingLanguageCode(&'static str),
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
Self::InvalidLanguageCode(c) => {
formatter.write_str("`")?;
formatter.write_str(c)?;
formatter.write_str("` is an invalid language code")
}
Self::NoCorrespondingLanguageCode(c) => {
formatter.write_str("`")?;
formatter.write_str(c)?;
formatter.write_str("` has no corresponding language code")
}
}
}
}
#[cfg(feature = "std")]
impl error::Error for Error {}
pub trait Language {
fn name(&self) -> &'static str;
fn code(&self) -> &'static str;
}
macro language_impl($language:ident, $language_as_string:literal) {
impl Language for $language {
fn name(&self) -> &'static str {
language_identifiers_from_table!(match &self: $language => "name")
}
fn code(&self) -> &'static str {
language_identifiers_from_table!(match &self: $language => $language_as_string)
}
}
impl fmt::Display for $language {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.name())
}
}
impl FromStr for $language {
type Err = Error;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
language_identifiers_from_table!(match s: $language_as_string => $language).ok_or(Error::InvalidLanguageCode(s.to_string()))
}
}
}
macro language_impl_try_from($from:ident, $to:ident) {
impl TryFrom<$from> for $to {
type Error = Error;
fn try_from(c: $from) -> Result<Self, <Self as TryFrom<$from>>::Error> {
language_identifiers_from_table!(match c: $from => $to).ok_or(Error::NoCorrespondingLanguageCode(c.code()))
}
}
}
language_identifiers_from_table!(enum Iso639_1: iso639_1);
language_impl!(Iso639_1, "Iso639_1");
language_impl_try_from!(Iso639_2b, Iso639_1);
language_impl_try_from!(Iso639_2t, Iso639_1);
language_impl_try_from!(Iso639_3, Iso639_1);
language_identifiers_from_table!(enum Iso639_2b: iso639_2b);
language_impl!(Iso639_2b, "Iso639_2b");
language_impl_try_from!(Iso639_1, Iso639_2b);
language_impl_try_from!(Iso639_2t, Iso639_2b);
language_impl_try_from!(Iso639_3, Iso639_2b);
language_identifiers_from_table!(enum Iso639_2t: iso639_2t);
language_impl!(Iso639_2t, "Iso639_2t");
language_impl_try_from!(Iso639_1, Iso639_2t);
language_impl_try_from!(Iso639_2b, Iso639_2t);
language_impl_try_from!(Iso639_3, Iso639_2t);
language_identifiers_from_table!(enum Iso639_3: iso639_3);
language_impl!(Iso639_3, "Iso639_3");
language_impl_try_from!(Iso639_1, Iso639_3);
language_impl_try_from!(Iso639_2b, Iso639_3);
language_impl_try_from!(Iso639_2t, Iso639_3);