Skip to main content

known_languages/
language.rs

1// This is free and unencumbered software released into the public domain.
2
3use core::str::FromStr;
4
5#[cfg(feature = "alloc")]
6use alloc::{
7    borrow::Cow,
8    string::{String, ToString},
9};
10
11/// A language (based on ISO 639-1).
12#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
13#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[non_exhaustive]
16pub enum Language {
17
18    /// Arabic ("ar" in ISO 639-1)
19    Arabic,
20
21    /// Bengali ("bn" in ISO 639-1)
22    Bengali,
23
24    /// English ("en" in ISO 639-1)
25    #[default]
26    English,
27
28    /// Esperanto ("eo" in ISO 639-1)
29    Esperanto,
30
31    /// Spanish ("es" in ISO 639-1)
32    Spanish,
33
34    /// French ("fr" in ISO 639-1)
35    French,
36
37    /// Hindi ("hi" in ISO 639-1)
38    Hindi,
39
40    /// Indonesian ("id" in ISO 639-1)
41    Indonesian,
42
43    /// Portuguese ("pt" in ISO 639-1)
44    Portuguese,
45
46    /// Urdu ("ur" in ISO 639-1)
47    Urdu,
48
49    /// Chinese ("zh" in ISO 639-1)
50    Chinese,
51
52    #[cfg(feature = "alloc")]
53    Other(String),
54}
55
56impl Language {
57    pub const ALL: &'static [Self] = &[Self::English];
58
59    pub fn as_str(&self) -> &str {
60        use Language::*;
61        match self {
62            Arabic => "ar",
63            Bengali => "bn",
64            English => "en",
65            Esperanto => "eo",
66            Spanish => "es",
67            French => "fr",
68            Hindi => "hi",
69            Indonesian => "id",
70            Portuguese => "pt",
71            Urdu => "ur",
72            Chinese => "zh",
73
74            #[cfg(feature = "alloc")]
75            Other(input) => input.as_str(),
76        }
77    }
78
79    #[cfg(feature = "alloc")]
80    pub fn into_string(self) -> String {
81        self.as_str().into()
82    }
83
84    #[cfg(all(feature = "serde", feature = "alloc"))]
85    pub fn to_json(&self) -> Option<serde_json::Value> {
86        Some(self.clone().into_json())
87    }
88
89    #[cfg(all(feature = "serde", feature = "alloc"))]
90    pub fn into_json(self) -> serde_json::Value {
91        serde_json::Value::String(self.into_string())
92    }
93
94    #[cfg(all(feature = "bson", feature = "alloc"))]
95    pub fn to_bson(&self) -> Option<bson::Bson> {
96        Some(self.clone().into_bson())
97    }
98
99    #[cfg(all(feature = "bson", feature = "alloc"))]
100    pub fn into_bson(self) -> bson::Bson {
101        bson::Bson::String(self.into_string())
102    }
103}
104
105impl FromStr for Language {
106    type Err = ();
107
108    fn from_str(input: &str) -> Result<Self, Self::Err> {
109        use Language::*;
110        Ok(match input {
111            "ar" => Arabic,
112            "bn" => Bengali,
113            "en" => English,
114            "eo" => Esperanto,
115            "es" => Spanish,
116            "fr" => French,
117            "hi" => Hindi,
118            "id" => Indonesian,
119            "pt" => Portuguese,
120            "ur" => Urdu,
121            "zh" => Chinese,
122            _ => return Err(()),
123        })
124    }
125}
126
127impl core::fmt::Display for Language {
128    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
129        write!(f, "{}", self.as_str())
130    }
131}
132
133impl AsRef<str> for Language {
134    fn as_ref(&self) -> &str {
135        self.as_str()
136    }
137}
138
139impl<T> From<&T> for Language
140where
141    T: Clone + Into<Self>,
142{
143    fn from(t: &T) -> Self {
144        t.clone().into()
145    }
146}
147
148impl From<&str> for Language {
149    fn from(input: &str) -> Self {
150        match input.parse() {
151            Ok(output) => output,
152
153            #[cfg(feature = "alloc")]
154            Err(_) => Self::Other(input.into()),
155
156            #[cfg(not(feature = "alloc"))]
157            Err(_) => unimplemented!("unknown language: {}", input),
158        }
159    }
160}
161
162#[cfg(feature = "alloc")]
163impl<'a> From<Cow<'a, str>> for Language {
164    fn from(input: Cow<'a, str>) -> Self {
165        input
166            .parse()
167            .unwrap_or_else(|_| Self::Other(input.into_owned()))
168    }
169}
170
171#[cfg(feature = "alloc")]
172impl From<String> for Language {
173    fn from(input: String) -> Self {
174        input.parse().unwrap_or_else(|_| Self::Other(input))
175    }
176}
177
178#[cfg(all(feature = "serde", feature = "alloc"))]
179impl TryFrom<serde_json::Value> for Language {
180    type Error = ();
181
182    fn try_from(input: serde_json::Value) -> Result<Self, Self::Error> {
183        use serde_json::Value;
184        match input {
185            Value::String(input) => Ok(input.parse().unwrap_or_else(|_| Self::Other(input))),
186            _ => Err(()),
187        }
188    }
189}
190
191impl From<&'static Language> for &str {
192    fn from(input: &'static Language) -> Self {
193        input.as_str()
194    }
195}
196
197#[cfg(feature = "alloc")]
198impl From<Language> for String {
199    fn from(input: Language) -> Self {
200        input.to_string()
201    }
202}