deepl_rustls/
lang.rs

1use std::{fmt::Display, str::FromStr};
2
3use paste::paste;
4use serde::{Deserialize, Deserializer, Serialize};
5use thiserror::Error;
6
7#[derive(Debug, Error)]
8pub enum LangConvertError {
9    #[error("invalid language code {0}")]
10    InvalidLang(String),
11}
12
13type Result<T, E = LangConvertError> = core::result::Result<T, E>;
14
15macro_rules! generate_langs {
16    (
17        $(
18            ($code:literal, $desc:literal);
19        )+
20    ) => {
21        paste! {
22            /// Languages
23            #[allow(non_camel_case_types)]
24            #[derive(Clone, Debug, PartialEq, Eq, Serialize)]
25            #[serde(rename_all = "SCREAMING-KEBAB-CASE")]
26            pub enum Lang {
27                $(
28                    #[doc = $desc]
29                    [<$code>],
30                )+
31            }
32
33            impl Lang {
34                /// Return full language name for the code
35                pub fn description(&self) -> String {
36                    match self {
37                        $(
38                            Self::[<$code>] => $desc.to_string(),
39                        )+
40                    }
41                }
42            }
43
44            impl TryFrom<&str> for Lang {
45                type Error = LangConvertError;
46
47                /// Convert literal to enum `Lang`
48                ///
49                /// # Error
50                ///
51                /// Return `Error::InvalidLang` when given language code is not in the support list.
52                fn try_from(value: &str) -> Result<Self, Self::Error> {
53                    let lang = match value {
54                        $(
55                            $code => Self::[<$code>],
56                        )+
57                        _ => return Err(LangConvertError::InvalidLang(value.to_string())),
58                    };
59
60                    Ok(lang)
61                }
62            }
63
64            impl TryFrom<&String> for Lang {
65                type Error = LangConvertError;
66
67                /// Convert ref String to enum `Lang`
68                ///
69                /// # Error
70                ///
71                /// Return `Error::InvalidLang` when given language code is not in the support list.
72                fn try_from(value: &String) -> Result<Self, Self::Error> {
73                    let lang = match value.as_ref() {
74                        $(
75                            $code => Self::[<$code>],
76                        )+
77                        _ => return Err(LangConvertError::InvalidLang(value.to_string())),
78                    };
79
80                    Ok(lang)
81                }
82            }
83
84            impl AsRef<str> for Lang {
85                fn as_ref(&self) -> &'static str {
86                    match self {
87                        $(
88                            Self::[<$code>] => $code,
89                        )+
90                    }
91                }
92            }
93        }
94    };
95}
96
97generate_langs! {
98    ("AR",    "Arabic");
99    ("BG",    "Bulgarian");
100    ("CS",    "Czech");
101    ("DA",    "Danish");
102    ("DE",    "German");
103    ("EL",    "Greek");
104    ("EN",    "English (Unspecified variant)");
105    ("EN-GB", "English (American)");
106    ("EN-US", "English (British)");
107    ("ES",    "Spanish");
108    ("ET",    "Estonian");
109    ("FI",    "Finnish");
110    ("FR",    "French");
111    ("HU",    "Hungarian");
112    ("ID",    "Indonesian");
113    ("IT",    "Italian");
114    ("JA",    "Japanese");
115    ("KO",    "Korean");
116    ("LT",    "Lithuanian");
117    ("LV",    "Latvian");
118    ("NB",    "Norwegian");
119    ("NL",    "Dutch");
120    ("PL",    "Polish");
121    ("PT",    "Portuguese (all Portuguese varieties mixed)");
122    ("PT-BR", "Portuguese (Brazilian)");
123    ("PT-PT", "Portuguese (All Portuguese varieties excluding Brazilian)");
124    ("RO",    "Romanian");
125    ("RU",    "Russian");
126    ("SK",    "Slovak");
127    ("SL",    "Slovenian");
128    ("SV",    "Swedish");
129    ("TR",    "Turkish");
130    ("UK",    "Ukrainian");
131    ("ZH",    "Chinese");
132}
133
134impl<'de> Deserialize<'de> for Lang {
135    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
136    where
137        D: Deserializer<'de>,
138    {
139        let lang = String::deserialize(deserializer)?.to_uppercase();
140
141        let lang = Lang::try_from(&lang).map_err(|_| {
142            serde::de::Error::custom(
143                format!("invalid language code {lang}. This is an internal issue with the lib, please open issue")
144            )
145        })?;
146
147        Ok(lang)
148    }
149}
150
151impl FromStr for Lang {
152    type Err = LangConvertError;
153
154    fn from_str(s: &str) -> Result<Self, Self::Err> {
155        Lang::try_from(s)
156    }
157}
158
159impl Display for Lang {
160    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161        write!(f, "{}", self.as_ref())
162    }
163}