crate::ix!();
impl FromStr for AsiaRegion {
type Err = RegionParseError;
fn from_str(s: &str) -> Result<AsiaRegion, Self::Err> {
let s = s.trim();
let lower = s.to_lowercase();
match lower.as_str() {
"afghanistan" => return Ok(AsiaRegion::Afghanistan),
"armenia" => return Ok(AsiaRegion::Armenia),
"azerbaijan" => return Ok(AsiaRegion::Azerbaijan),
"bangladesh" => return Ok(AsiaRegion::Bangladesh),
"bhutan" => return Ok(AsiaRegion::Bhutan),
"cambodia" => return Ok(AsiaRegion::Cambodia),
"east timor" => return Ok(AsiaRegion::EastTimor),
"gcc states" => return Ok(AsiaRegion::GccStates),
"iran" => return Ok(AsiaRegion::Iran),
"iraq" => return Ok(AsiaRegion::Iraq),
"israel and palestine" => return Ok(AsiaRegion::IsraelAndPalestine),
"jordan" => return Ok(AsiaRegion::Jordan),
"kazakhstan" => return Ok(AsiaRegion::Kazakhstan),
"kyrgyzstan" => return Ok(AsiaRegion::Kyrgyzstan),
"laos" => return Ok(AsiaRegion::Laos),
"lebanon" => return Ok(AsiaRegion::Lebanon),
"malaysia, singapore, and brunei" => return Ok(AsiaRegion::MalaysiaSingaporeBrunei),
"maldives" => return Ok(AsiaRegion::Maldives),
"mongolia" => return Ok(AsiaRegion::Mongolia),
"myanmar" => return Ok(AsiaRegion::Myanmar),
"nepal" => return Ok(AsiaRegion::Nepal),
"north korea" => return Ok(AsiaRegion::NorthKorea),
"pakistan" => return Ok(AsiaRegion::Pakistan),
"philippines" => return Ok(AsiaRegion::Philippines),
"south korea" => return Ok(AsiaRegion::SouthKorea),
"sri lanka" => return Ok(AsiaRegion::SriLanka),
"syria" => return Ok(AsiaRegion::Syria),
"taiwan" => return Ok(AsiaRegion::Taiwan),
"tajikistan" => return Ok(AsiaRegion::Tajikistan),
"thailand" => return Ok(AsiaRegion::Thailand),
"turkmenistan" => return Ok(AsiaRegion::Turkmenistan),
"uzbekistan" => return Ok(AsiaRegion::Uzbekistan),
"vietnam" => return Ok(AsiaRegion::Vietnam),
"yemen" => return Ok(AsiaRegion::Yemen),
_ => {}
}
if let Some(idx) = s.find('(') {
let end_idx = s.find(')').ok_or(RegionParseError::MissingParenthesis)?;
let country_str = s[..idx].trim();
let region_str = s[idx+1..end_idx].trim();
let country_lower = country_str.to_lowercase();
match country_lower.as_str() {
"china" => {
let cr: ChinaRegion = region_str.parse()?;
return Ok(AsiaRegion::China(cr));
}
"india" => {
let ir: IndiaRegion = region_str.parse()?;
return Ok(AsiaRegion::India(ir));
}
"japan" => {
let jr: JapanRegion = region_str.parse()?;
return Ok(AsiaRegion::Japan(jr));
}
"indonesia" => {
let iir: IndonesiaRegion = region_str.parse()?;
return Ok(AsiaRegion::Indonesia(iir));
}
"russian federation" => {
let rr: RussianFederationRegion = region_str.parse()?;
return Ok(AsiaRegion::RussianFederation(rr));
}
_ => return Err(RegionParseError::UnknownSubdividedCountry(country_str.to_string())),
}
}
if let Ok(cr) = s.parse::<ChinaRegion>() {
return Ok(AsiaRegion::China(cr));
}
if let Ok(ir) = s.parse::<IndiaRegion>() {
return Ok(AsiaRegion::India(ir));
}
if let Ok(jr) = s.parse::<JapanRegion>() {
return Ok(AsiaRegion::Japan(jr));
}
if let Ok(iir) = s.parse::<IndonesiaRegion>() {
return Ok(AsiaRegion::Indonesia(iir));
}
if let Ok(rr) = s.parse::<RussianFederationRegion>() {
return Ok(AsiaRegion::RussianFederation(rr));
}
Err(RegionParseError::UnknownVariant(s.to_string()))
}
}
#[cfg(test)]
mod test_from_str {
use super::*;
#[test]
fn test_from_str_top_level_variants() {
let top_levels = vec![
"Afghanistan", "Armenia", "Azerbaijan", "Bangladesh",
"Bhutan", "Cambodia", "East Timor", "GCC States",
"Iran", "Iraq", "Israel and Palestine", "Jordan",
"Kazakhstan", "Kyrgyzstan", "Laos", "Lebanon",
"Malaysia, Singapore, and Brunei", "Maldives", "Mongolia",
"Myanmar", "Nepal", "North Korea", "Pakistan",
"Philippines", "South Korea", "Sri Lanka", "Syria",
"Taiwan", "Tajikistan", "Thailand", "Turkmenistan",
"Uzbekistan", "Vietnam", "Yemen"
];
for name in top_levels {
let parsed = AsiaRegion::from_str(name).expect(&format!("Should parse {}", name));
assert_eq!(parsed.to_string(), name, "Parsed variant should match original name");
}
}
#[test]
fn test_from_str_subdivided_variants() {
let beijing = "China(Beijing)";
let parsed = AsiaRegion::from_str(beijing).expect("Should parse China(Beijing)");
if let AsiaRegion::China(r) = parsed {
assert_eq!(r, ChinaRegion::Beijing);
} else {
panic!("Parsed variant is not China(Beijing)");
}
let eastern_zone = "India(Eastern Zone)";
let parsed = AsiaRegion::from_str(eastern_zone).expect("Should parse India(Eastern Zone)");
if let AsiaRegion::India(r) = parsed {
assert_eq!(r, IndiaRegion::EasternZone);
} else {
panic!("Parsed variant is not India(Eastern Zone)");
}
let hokkaido = "Japan(Hokkaido)";
let parsed = AsiaRegion::from_str(hokkaido).expect("Should parse Japan(Hokkaido)");
if let AsiaRegion::Japan(r) = parsed {
assert_eq!(r, JapanRegion::Hokkaido);
} else {
panic!("Parsed variant is not Japan(Hokkaido)");
}
let java = "Indonesia(Java)";
let parsed = AsiaRegion::from_str(java).expect("Should parse Indonesia(Java)");
if let AsiaRegion::Indonesia(r) = parsed {
assert_eq!(r, IndonesiaRegion::Java);
} else {
panic!("Parsed variant is not Indonesia(Java)");
}
let siberian = "Russian Federation(Siberian Federal District)";
let parsed = AsiaRegion::from_str(siberian).expect("Should parse Russian Federation(Siberian Federal District)");
if let AsiaRegion::RussianFederation(r) = parsed {
assert_eq!(r, RussianFederationRegion::SiberianFederalDistrict);
} else {
panic!("Parsed variant is not Russian Federation(Siberian Federal District)");
}
}
#[test]
fn test_from_str_subregion_without_parentheses() {
let beijing = "Beijing";
let parsed = AsiaRegion::from_str(beijing).expect("Should parse Beijing as China(Beijing)");
if let AsiaRegion::China(r) = parsed {
assert_eq!(r, ChinaRegion::Beijing);
} else {
panic!("Parsed variant is not China(Beijing)");
}
}
#[test]
fn test_from_str_missing_parenthesis() {
let invalid = "China(Beijing";
match AsiaRegion::from_str(invalid) {
Err(RegionParseError::MissingParenthesis) => {},
_ => panic!("Expected MissingParenthesis error"),
}
}
#[test]
fn test_from_str_unknown_subdivided_country() {
let invalid = "Atlantis(Central)";
match AsiaRegion::from_str(invalid) {
Err(RegionParseError::UnknownSubdividedCountry(c)) if c == "Atlantis" => {},
_ => panic!("Expected UnknownSubdividedCountry error"),
}
}
#[test]
fn test_from_str_unknown_variant() {
let invalid = "Atlantis";
match AsiaRegion::from_str(invalid) {
Err(RegionParseError::UnknownVariant(v)) if v == "Atlantis" => {},
_ => panic!("Expected UnknownVariant error"),
}
}
#[test]
fn test_from_str_unknown_subregion() {
let invalid = "China(Atlantis)";
let res = AsiaRegion::from_str(invalid);
match res {
Err(RegionParseError::UnknownSubregion{ country, subregion }) => {
assert_eq!(country, Country::China);
assert_eq!(subregion, "Atlantis");
},
Err(RegionParseError::StrumParseError(_)) => {},
_ => panic!("Expected UnknownSubregion error"),
}
}
#[test]
fn test_from_str_case_insensitivity() {
let lower = "armenia".parse::<AsiaRegion>().expect("Should parse 'armenia'");
assert_eq!(lower, AsiaRegion::Armenia);
let mixed = "cHiNa(BeIjInG)".parse::<AsiaRegion>().expect("Should parse 'cHiNa(BeIjInG)'");
if let AsiaRegion::China(r) = mixed {
assert_eq!(r, ChinaRegion::Beijing);
} else {
panic!("Parsed variant is not China(Beijing)");
}
}
#[test]
fn test_from_str_extra_spaces() {
let spaced = " China ( Beijing ) ".parse::<AsiaRegion>().expect("Should parse with extra spaces");
if let AsiaRegion::China(r) = spaced {
assert_eq!(r, ChinaRegion::Beijing);
} else {
panic!("Parsed variant is not China(Beijing)");
}
}
}