use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
use crate::errors::BubbleHearthError;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Deserialize)]
pub enum Locale {
#[serde(rename = "en_US")]
EnglishUS,
#[serde(rename = "en_GB")]
EnglishGB,
#[serde(rename = "es_MX")]
SpanishMX,
#[serde(rename = "es_ES")]
SpanishES,
#[serde(rename = "pt_BR")]
Portuguese,
#[serde(rename = "de_DE")]
German,
#[serde(rename = "fr_FR")]
French,
#[serde(rename = "it_IT")]
Italian,
#[serde(rename = "ru_RU")]
Russian,
#[serde(rename = "ko_KR")]
Korean,
#[serde(rename = "zh_TW")]
ChineseTW,
#[serde(rename = "zh_CN")]
ChineseCN,
}
impl Locale {
pub fn get_normalized_locale(&self) -> &str {
match self {
Locale::EnglishUS => "en_US",
Locale::EnglishGB => "en_GB",
Locale::SpanishMX => "es_MX",
Locale::SpanishES => "es_ES",
Locale::Portuguese => "pt_BR",
Locale::German => "de_DE",
Locale::French => "fr_FR",
Locale::Italian => "it_IT",
Locale::Russian => "ru_RU",
Locale::Korean => "ko_KR",
Locale::ChineseTW => "zh_TW",
Locale::ChineseCN => "zh_CN",
}
}
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StructuredLocale {
#[serde(rename = "en_US")]
pub en_us: String,
#[serde(rename = "en_GB")]
pub en_gb: String,
#[serde(rename = "es_MX")]
pub es_mx: String,
#[serde(rename = "es_ES")]
pub es_es: String,
#[serde(rename = "pt_BR")]
pub pt_br: String,
#[serde(rename = "de_DE")]
pub de_de: String,
#[serde(rename = "fr_FR")]
pub fr_fr: String,
#[serde(rename = "it_IT")]
pub it_it: String,
#[serde(rename = "ru_RU")]
pub ru_ru: String,
#[serde(rename = "ko_KR")]
pub ko_kr: String,
#[serde(rename = "zh_TW")]
pub zh_tw: String,
#[serde(rename = "zh_CN")]
pub zh_cn: String,
}
impl FromStr for Locale {
type Err = BubbleHearthError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"en_US" => Ok(Locale::EnglishUS),
"en_GB" => Ok(Locale::EnglishGB),
"es_MX" => Ok(Locale::SpanishMX),
"es_ES" => Ok(Locale::SpanishES),
"pt_BR" => Ok(Locale::Portuguese),
"de_DE" => Ok(Locale::German),
"fr_FR" => Ok(Locale::French),
"it_IT" => Ok(Locale::Italian),
"ru_RU" => Ok(Locale::Russian),
"ko_KR" => Ok(Locale::Korean),
"zh_TW" => Ok(Locale::ChineseTW),
"zh_CN" => Ok(Locale::ChineseCN),
&_ => Err(BubbleHearthError::LocaleUnknown(s.to_string())),
}
}
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub enum StringOrStructLocale {
StringLocale(String),
StructLocale(Box<StructuredLocale>),
}
impl<'de> Deserialize<'de> for StringOrStructLocale {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let json_value: Value = Deserialize::deserialize(deserializer)?;
match json_value {
Value::String(s) => Ok(StringOrStructLocale::StringLocale(s)),
Value::Object(_) => {
let locale_struct: StructuredLocale = Deserialize::deserialize(json_value).unwrap();
Ok(StringOrStructLocale::StructLocale(Box::new(locale_struct)))
}
_ => Err(serde::de::Error::custom("Invalid data type for locale.")),
}
}
}
#[cfg(test)]
mod localization_tests {
use crate::classic::realms::RealmsIndex;
use crate::localization::StringOrStructLocale::StructLocale;
use crate::localization::{StringOrStructLocale, StructuredLocale};
#[test]
fn serializes_correct_locale_string_when_single_locale_returned() {
let response = r#"
{
"_links": {
"self": {
"href": "https://us.api.blizzard.com/data/wow/realm/?namespace=dynamic-classic-us"
}
},
"realms": [
{
"key": {
"href": "https://us.api.blizzard.com/data/wow/realm/4372?namespace=dynamic-classic-us"
},
"name": "Atiesh",
"id": 4372,
"slug": "atiesh"
}
]
}
"#;
let realms: RealmsIndex = serde_json::from_str(response).unwrap();
let realm = &realms.realms[0];
assert_eq!(
realm.name,
StringOrStructLocale::StringLocale("Atiesh".to_string())
);
}
#[test]
fn serializes_correct_locale_struct_when_multiple_locales_returned() {
let response = r#"
{
"_links": {
"self": {
"href": "https://us.api.blizzard.com/data/wow/realm/?namespace=dynamic-classic-us"
}
},
"realms": [
{
"key": {
"href": "https://us.api.blizzard.com/data/wow/realm/4372?namespace=dynamic-classic-us"
},
"name": {
"en_US": "Atiesh",
"es_MX": "Atiesh",
"pt_BR": "Atiesh",
"de_DE": "Atiesh",
"en_GB": "Atiesh",
"es_ES": "Atiesh",
"fr_FR": "Atiesh",
"it_IT": "Atiesh",
"ru_RU": "Atiesh",
"ko_KR": "Atiesh",
"zh_TW": "阿泰絲",
"zh_CN": "埃提耶什"
},
"id": 4372,
"slug": "atiesh"
}
]
}
"#;
let realms: RealmsIndex = serde_json::from_str(response).unwrap();
let realm = &realms.realms[0];
assert_eq!(
realm.name,
StructLocale(Box::new(StructuredLocale {
en_us: "Atiesh".to_string(),
en_gb: "Atiesh".to_string(),
es_mx: "Atiesh".to_string(),
es_es: "Atiesh".to_string(),
pt_br: "Atiesh".to_string(),
de_de: "Atiesh".to_string(),
fr_fr: "Atiesh".to_string(),
it_it: "Atiesh".to_string(),
ru_ru: "Atiesh".to_string(),
ko_kr: "Atiesh".to_string(),
zh_tw: "阿泰絲".to_string(),
zh_cn: "埃提耶什".to_string(),
}))
);
}
}