#![forbid(unsafe_code)]
#![allow(unused_variables)]
#![deny(clippy::all)]
#[macro_use] mod imports; use imports::*;
x!{abbreviation}
x!{from_str}
x!{country}
x!{error}
x!{impl_serde}
x!{impl_from}
x!{world_region}
#[cfg(test)]
mod world_region_tests {
use super::*;
use std::str::FromStr;
#[test]
fn test_conversions() {
let c = Country::Nigeria;
let wr = WorldRegion::try_from(c).expect("should convert");
match wr {
WorldRegion::Africa(r) => assert_eq!(r, AfricaRegion::Nigeria),
_ => panic!("Expected Africa(Nigeria)"),
}
let back: Country = wr.try_into().expect("should convert back");
assert_eq!(back, Country::Nigeria);
}
#[test]
fn test_abbreviation() {
let wr = WorldRegion::Asia(AsiaRegion::China(asia::ChinaRegion::Beijing));
assert_eq!(wr.abbreviation(), "CN-BJ");
}
#[test]
fn test_abbreviations() {
let wr_africa = WorldRegion::Africa(AfricaRegion::Nigeria);
assert_eq!(wr_africa.abbreviation(), "NG");
let wr_asia = WorldRegion::Asia(AsiaRegion::Japan(asia::JapanRegion::Hokkaido));
assert_eq!(wr_asia.abbreviation(), "JP-HKD");
let wr_europe = WorldRegion::Europe(EuropeRegion::France(europe::FranceRegion::IleDeFrance));
assert_eq!(wr_europe.abbreviation(), "FR-J");
let wr_naa = WorldRegion::NorthAmerica(NorthAmericaRegion::Canada(north_america::CanadaRegion::Ontario));
assert_eq!(wr_naa.abbreviation(), "ON");
let wr_saa = WorldRegion::SouthAmerica(SouthAmericaRegion::Brazil(south_america::BrazilRegion::Sudeste));
assert_eq!(wr_saa.abbreviation(), "BR-SE");
let wr_caa = WorldRegion::CentralAmerica(CentralAmericaRegion::CostaRica);
assert_eq!(wr_caa.abbreviation(), "CR");
let wr_aoa = WorldRegion::AustraliaOceaniaAntarctica(australia_oceania_antarctica::AustraliaOceaniaAntarcticaRegion::Fiji);
assert_eq!(wr_aoa.abbreviation(), "FJ");
}
#[test]
fn test_iso_conversions() {
let wr = WorldRegion::Africa(AfricaRegion::Egypt);
let alpha2: Iso3166Alpha2 = wr.clone().try_into().expect("Alpha2 conversion");
let alpha3: Iso3166Alpha3 = wr.clone().try_into().expect("Alpha3 conversion");
let code: CountryCode = wr.try_into().expect("CountryCode conversion");
assert_eq!(alpha2, Iso3166Alpha2::EG);
assert_eq!(alpha3, Iso3166Alpha3::EGY);
match code {
CountryCode::Alpha2(a2) => assert_eq!(a2, Iso3166Alpha2::EG),
_ => panic!("Expected Alpha2 code"),
}
let wr_unsupported = WorldRegion::Asia(AsiaRegion::GccStates);
let res: Result<Iso3166Alpha2, _> = wr_unsupported.try_into();
assert!(res.is_err(), "GCC States should fail ISO conversion");
}
#[test]
fn test_country_conversions() {
let c = Country::Nigeria;
let wr = WorldRegion::try_from(c).expect("should convert from Nigeria to WorldRegion(Africa)");
match wr {
WorldRegion::Africa(r) => assert_eq!(r, AfricaRegion::Nigeria),
_ => panic!("Expected Africa(Nigeria)"),
}
let back: Country = wr.try_into().expect("should convert back to Country");
assert_eq!(back, Country::Nigeria);
let c_not_rep = Country::VaticanCity; let wr_fail = WorldRegion::try_from(c_not_rep.clone());
assert!(wr_fail.is_err(), "VaticanCity not represented should fail");
}
#[test]
fn test_serialize_deserialize() {
let wr_africa = WorldRegion::Africa(AfricaRegion::Kenya);
let serialized = serde_json::to_string(&wr_africa).expect("serialize africa");
let deserialized: WorldRegion = serde_json::from_str(&serialized).expect("deserialize africa");
assert_eq!(wr_africa, deserialized);
let wr_asia = WorldRegion::Asia(AsiaRegion::China(asia::ChinaRegion::Beijing));
let serialized_asia = serde_json::to_string(&wr_asia).expect("serialize asia");
let deserialized_asia: WorldRegion = serde_json::from_str(&serialized_asia).expect("deserialize asia");
assert_eq!(wr_asia, deserialized_asia);
let v: serde_json::Value = serde_json::from_str(&serialized_asia).expect("parse json");
assert_eq!(v.get("continent").and_then(|x| x.as_str()), Some("Asia"));
assert_eq!(v.get("country").and_then(|x| x.as_str()), Some("China"));
assert_eq!(v.get("region").and_then(|x| x.as_str()), Some("Beijing"));
}
#[test]
fn test_error_handling() {
let wr_unsupported = WorldRegion::Africa(AfricaRegion::SaintHelenaAscensionTristanDaCunha);
let country_res: Result<Country, _> = wr_unsupported.try_into();
assert!(country_res.is_err(), "Should fail for combined region");
}
#[test]
fn test_variant_names_consistency() {
let africa_test = Country::Ethiopia;
let wr_africa = WorldRegion::try_from(africa_test.clone()).expect("Ethiopia -> AfricaRegion");
let back_africa: Country = wr_africa.try_into().expect("AfricaRegion -> Ethiopia");
assert_eq!(back_africa, africa_test);
let asia_test = Country::Japan;
let wr_asia = WorldRegion::try_from(asia_test.clone()).expect("Japan -> AsiaRegion");
let back_asia: Country = wr_asia.try_into().expect("AsiaRegion -> Japan");
assert_eq!(back_asia, asia_test);
let europe_test = Country::France;
let wr_europe = WorldRegion::try_from(europe_test.clone()).expect("France -> EuropeRegion");
let back_europe: Country = wr_europe.try_into().expect("EuropeRegion -> France");
assert_eq!(back_europe, europe_test);
let na_test = Country::Canada;
let wr_na = WorldRegion::try_from(na_test.clone()).expect("Canada -> NorthAmericaRegion");
let back_na: Country = wr_na.try_into().expect("NorthAmericaRegion -> Canada");
assert_eq!(back_na, na_test);
let sa_test = Country::Argentina;
let wr_sa = WorldRegion::try_from(sa_test.clone()).expect("Argentina -> SouthAmericaRegion");
let back_sa: Country = wr_sa.try_into().expect("SouthAmericaRegion -> Argentina");
assert_eq!(back_sa, sa_test);
let ca_test = Country::Panama;
let wr_ca = WorldRegion::try_from(ca_test.clone()).expect("Panama -> CentralAmericaRegion");
let back_ca: Country = wr_ca.try_into().expect("CentralAmericaRegion -> Panama");
assert_eq!(back_ca, ca_test);
let aoa_test = Country::Fiji;
let wr_aoa = WorldRegion::try_from(aoa_test.clone()).expect("Fiji -> AustraliaOceaniaAntarcticaRegion");
let back_aoa: Country = wr_aoa.try_into().expect("AustraliaOceaniaAntarcticaRegion -> Fiji");
assert_eq!(back_aoa, aoa_test);
}
#[test]
fn test_from_str_and_variant_matching() {
let asia_region = AsiaRegion::from_str("Beijing").ok();
assert!(asia_region.is_some());
let wr = WorldRegion::Asia(asia_region.unwrap());
let serialized = serde_json::to_string(&wr).expect("serialize");
let deserialized: WorldRegion = serde_json::from_str(&serialized).expect("deserialize");
assert_eq!(wr, deserialized);
}
#[test]
fn test_unified_iso_conversion_failure() {
let wr_canary = WorldRegion::Africa(AfricaRegion::CanaryIslands);
let res: Result<Iso3166Alpha2, _> = wr_canary.try_into();
assert!(res.is_err(), "Canary Islands should fail ISO conversion");
}
}
#[cfg(test)]
mod exhaustive_world_region_tests {
use super::*;
use std::str::FromStr;
#[test]
fn test_all_continents_country_to_world_region() {
let test_cases = vec![
(Country::Nigeria , "Africa") ,
(Country::Egypt , "Africa") ,
(Country::China , "Asia") ,
(Country::Japan , "Asia") ,
(Country::France , "Europe") ,
(Country::Germany , "Europe") ,
(Country::Canada , "North America") ,
(Country::USA , "North America") ,
(Country::Argentina , "South America") ,
(Country::Brazil , "South America") ,
(Country::CostaRica , "Central America") ,
(Country::Panama , "Central America") ,
(Country::Fiji , "Australia/Oceania/Antarctica") ,
(Country::Australia , "Australia/Oceania/Antarctica") ,
];
for (country, expected_continent) in test_cases {
let wr = WorldRegion::try_from(country.clone())
.unwrap_or_else(|_| panic!("Could not map {:?} to WorldRegion", country));
let serialized = serde_json::to_string(&wr).expect("serialize");
let v: serde_json::Value = serde_json::from_str(&serialized).expect("json parse");
let cont = v.get("continent").and_then(|x| x.as_str()).unwrap();
assert_eq!(cont, expected_continent, "Continent mismatch for {:?}", country);
let back_country: Country = wr.try_into().expect("Should convert back to Country");
assert_eq!(back_country, country, "Round-trip country mismatch");
}
}
#[test]
fn test_iso_code_success() {
let wr = WorldRegion::Europe(EuropeRegion::France(FranceRegion::IleDeFrance));
let alpha2: Iso3166Alpha2 = wr.try_into().expect("Alpha2 conversion failed");
let alpha3: Iso3166Alpha3 = wr.try_into().expect("Alpha3 conversion failed");
let code: CountryCode = wr.try_into().expect("CountryCode conversion failed");
assert_eq!(alpha2, Iso3166Alpha2::FR);
assert_eq!(alpha3, Iso3166Alpha3::FRA);
match code {
CountryCode::Alpha2(a2) => assert_eq!(a2, Iso3166Alpha2::FR),
_ => panic!("Expected Alpha2 code"),
}
}
#[test]
fn test_iso_code_failure() {
let wr_unsupported = WorldRegion::Asia(AsiaRegion::GccStates);
let res: Result<Iso3166Alpha2, _> = wr_unsupported.try_into();
assert!(res.is_err(), "GCC States should fail ISO conversion");
}
#[test]
fn test_not_represented_country() {
let c = Country::VaticanCity; let res = WorldRegion::try_from(c.clone());
match res {
Err(WorldRegionConversionError::NotRepresented { country }) => {
assert_eq!(country, c, "Expected NotRepresented error for {:?}", c);
}
_ => panic!("Expected NotRepresented error for {:?}", c),
}
}
#[test]
fn test_unsupported_region_to_country() {
let wr_unsupported = WorldRegion::Africa(AfricaRegion::SaintHelenaAscensionTristanDaCunha);
let res: Result<Country, _> = wr_unsupported.try_into();
match res {
Err(WorldRegionConversionError::Africa(_)) => {
}
_ => panic!("Expected Africa(...) error for unsupported region"),
}
}
#[test]
fn test_serialize_deserialize_non_subdivided() {
let wr = WorldRegion::CentralAmerica(CentralAmericaRegion::CostaRica);
let serialized = serde_json::to_string(&wr).expect("serialize");
let deserialized: WorldRegion = serde_json::from_str(&serialized).expect("deserialize");
assert_eq!(wr, deserialized);
}
#[test]
fn test_serialize_deserialize_subdivided() {
let wr = WorldRegion::NorthAmerica(NorthAmericaRegion::Canada(north_america::CanadaRegion::Ontario));
let serialized = serde_json::to_string(&wr).expect("serialize");
let deserialized: WorldRegion = serde_json::from_str(&serialized).expect("deserialize");
assert_eq!(wr, deserialized);
let v: serde_json::Value = serde_json::from_str(&serialized).expect("parse json");
assert_eq!(v.get("continent").and_then(|x| x.as_str()), Some("North America"));
assert_eq!(v.get("country").and_then(|x| x.as_str()), Some("Canada"));
assert_eq!(v.get("region").and_then(|x| x.as_str()), Some("Ontario"));
}
#[test]
fn test_abbreviation_across_continents() {
let pairs = vec![
(WorldRegion::Africa(AfricaRegion::Nigeria), "NG"),
(WorldRegion::Asia(AsiaRegion::Japan(asia::JapanRegion::Hokkaido)), "JP-HKD"),
(WorldRegion::Europe(EuropeRegion::Germany(GermanyRegion::Berlin)), "DE-BE"),
(WorldRegion::NorthAmerica(NorthAmericaRegion::UnitedStates(usa::USRegion::UnitedState(usa::UnitedState::California))), "CA"),
(WorldRegion::SouthAmerica(SouthAmericaRegion::Brazil(south_america::BrazilRegion::Sudeste)), "BR-SE"),
(WorldRegion::CentralAmerica(CentralAmericaRegion::Panama), "PA"),
(WorldRegion::AustraliaOceaniaAntarctica(australia_oceania_antarctica::AustraliaOceaniaAntarcticaRegion::Fiji), "FJ"),
];
for (wr, expected_abbr) in pairs {
assert_eq!(wr.abbreviation(), expected_abbr, "Abbreviation mismatch for {:?}", wr);
}
}
#[test]
fn test_string_parsing_case_insensitivity() {
let wr_str = r#"Ile-De-France"#;
let wr = WorldRegion::from_str(wr_str).expect("deserialize");
if let WorldRegion::Europe(EuropeRegion::France(fr)) = wr {
assert_eq!(fr, FranceRegion::IleDeFrance);
} else {
panic!("Expected Europe(France(IleDeFrance))");
}
let wr_str_alt = r#"iLe-De-FrAnCe"#;
let wr_alt = WorldRegion::from_str(wr_str_alt).expect("case-insensitive deserialize");
assert_eq!(wr, wr_alt);
}
#[test]
fn test_round_trip_all_example_continents() {
let examples = vec![
WorldRegion::Africa(AfricaRegion::Kenya),
WorldRegion::Asia(AsiaRegion::China(asia::ChinaRegion::Beijing)),
WorldRegion::Europe(EuropeRegion::Italy(europe::ItalyRegion::Centro)),
WorldRegion::NorthAmerica(NorthAmericaRegion::Canada(north_america::CanadaRegion::Ontario)),
WorldRegion::SouthAmerica(SouthAmericaRegion::Brazil(south_america::BrazilRegion::Sul)),
WorldRegion::CentralAmerica(CentralAmericaRegion::Guatemala),
WorldRegion::AustraliaOceaniaAntarctica(australia_oceania_antarctica::AustraliaOceaniaAntarcticaRegion::NewZealand),
];
for wr in examples {
let serialized = serde_json::to_string(&wr).expect("serialize");
let deserialized: WorldRegion = serde_json::from_str(&serialized).expect("deserialize");
assert_eq!(wr, deserialized, "Round-trip mismatch for {:?}", wr);
}
}
#[test]
fn test_fictional_error() {
let fictional_wr = WorldRegion::from_str("Atlantis");
assert!(fictional_wr.is_err());
}
#[test]
fn test_feature_flag_abbreviation() {
#[cfg(feature = "serde_abbreviation")]
{
let wr = WorldRegion::Europe(EuropeRegion::Spain(spain::SpainRegion::Madrid));
let s = serde_json::to_string(&wr).expect("serialize");
assert_eq!(s, "\"ES\"");
}
}
}