known-languages 0.0.2

Well-known languages.
Documentation
// This is free and unencumbered software released into the public domain.

use core::str::FromStr;

#[cfg(feature = "alloc")]
use alloc::{
    borrow::Cow,
    string::{String, ToString},
};

/// A language (based on ISO 639-1).
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum Language {

    /// Arabic ("ar" in ISO 639-1)
    Arabic,

    /// Bengali ("bn" in ISO 639-1)
    Bengali,

    /// English ("en" in ISO 639-1)
    #[default]
    English,

    /// Esperanto ("eo" in ISO 639-1)
    Esperanto,

    /// Spanish ("es" in ISO 639-1)
    Spanish,

    /// French ("fr" in ISO 639-1)
    French,

    /// Hindi ("hi" in ISO 639-1)
    Hindi,

    /// Indonesian ("id" in ISO 639-1)
    Indonesian,

    /// Portuguese ("pt" in ISO 639-1)
    Portuguese,

    /// Urdu ("ur" in ISO 639-1)
    Urdu,

    /// Chinese ("zh" in ISO 639-1)
    Chinese,

    #[cfg(feature = "alloc")]
    Other(String),
}

impl Language {
    pub const ALL: &'static [Self] = &[Self::English];

    pub fn as_str(&self) -> &str {
        use Language::*;
        match self {
            Arabic => "ar",
            Bengali => "bn",
            English => "en",
            Esperanto => "eo",
            Spanish => "es",
            French => "fr",
            Hindi => "hi",
            Indonesian => "id",
            Portuguese => "pt",
            Urdu => "ur",
            Chinese => "zh",

            #[cfg(feature = "alloc")]
            Other(input) => input.as_str(),
        }
    }

    #[cfg(feature = "alloc")]
    pub fn into_string(self) -> String {
        self.as_str().into()
    }

    #[cfg(all(feature = "serde", feature = "alloc"))]
    pub fn to_json(&self) -> Option<serde_json::Value> {
        Some(self.clone().into_json())
    }

    #[cfg(all(feature = "serde", feature = "alloc"))]
    pub fn into_json(self) -> serde_json::Value {
        serde_json::Value::String(self.into_string())
    }

    #[cfg(all(feature = "bson", feature = "alloc"))]
    pub fn to_bson(&self) -> Option<bson::Bson> {
        Some(self.clone().into_bson())
    }

    #[cfg(all(feature = "bson", feature = "alloc"))]
    pub fn into_bson(self) -> bson::Bson {
        bson::Bson::String(self.into_string())
    }
}

impl FromStr for Language {
    type Err = ();

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        use Language::*;
        Ok(match input {
            "ar" => Arabic,
            "bn" => Bengali,
            "en" => English,
            "eo" => Esperanto,
            "es" => Spanish,
            "fr" => French,
            "hi" => Hindi,
            "id" => Indonesian,
            "pt" => Portuguese,
            "ur" => Urdu,
            "zh" => Chinese,
            _ => return Err(()),
        })
    }
}

impl core::fmt::Display for Language {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl AsRef<str> for Language {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl<T> From<&T> for Language
where
    T: Clone + Into<Self>,
{
    fn from(t: &T) -> Self {
        t.clone().into()
    }
}

impl From<&str> for Language {
    fn from(input: &str) -> Self {
        match input.parse() {
            Ok(output) => output,

            #[cfg(feature = "alloc")]
            Err(_) => Self::Other(input.into()),

            #[cfg(not(feature = "alloc"))]
            Err(_) => unimplemented!("unknown language: {}", input),
        }
    }
}

#[cfg(feature = "alloc")]
impl<'a> From<Cow<'a, str>> for Language {
    fn from(input: Cow<'a, str>) -> Self {
        input
            .parse()
            .unwrap_or_else(|_| Self::Other(input.into_owned()))
    }
}

#[cfg(feature = "alloc")]
impl From<String> for Language {
    fn from(input: String) -> Self {
        input.parse().unwrap_or_else(|_| Self::Other(input))
    }
}

#[cfg(all(feature = "serde", feature = "alloc"))]
impl TryFrom<serde_json::Value> for Language {
    type Error = ();

    fn try_from(input: serde_json::Value) -> Result<Self, Self::Error> {
        use serde_json::Value;
        match input {
            Value::String(input) => Ok(input.parse().unwrap_or_else(|_| Self::Other(input))),
            _ => Err(()),
        }
    }
}

impl From<&'static Language> for &str {
    fn from(input: &'static Language) -> Self {
        input.as_str()
    }
}

#[cfg(feature = "alloc")]
impl From<Language> for String {
    fn from(input: Language) -> Self {
        input.to_string()
    }
}