celes 3.0.0

Rust crate for handling ISO 3166-1 and optionally ISO 3166-2. Each country has a three digit code, two letter code, three letter code, full state name, short English aliases, and optional subdivision data.
Documentation
//! Subdivision tests.
#![cfg(feature = "subdivisions")]

use celes::{Country, SUBDIVISION_DATA_VERSION, Subdivision, SubdivisionParseError};
use std::{
    collections::hash_map::DefaultHasher,
    error::Error,
    fmt::{self, Write},
    hash::{Hash, Hasher},
    mem::size_of,
    str::FromStr,
};

#[test]
fn complete_data_supports_global_and_country_lookups() {
    let subdivisions = Subdivision::subdivisions();

    assert_eq!(SUBDIVISION_DATA_VERSION, "48.2");
    assert_eq!(subdivisions.len(), 5_027);
    assert_eq!(subdivisions.first().map(|value| value.code), Some("AD-02"));
    assert_eq!(subdivisions.last().map(|value| value.code), Some("ZW-MW"));

    let mut country_total = 0;
    for country in Country::countries() {
        let country_subdivisions = country.subdivisions();
        country_total += country_subdivisions.len();

        assert!(country_subdivisions.iter().all(|subdivision| {
            subdivision.country() == *country
                && subdivision
                    .code
                    .strip_prefix(country.alpha2)
                    .is_some_and(|suffix| suffix.starts_with('-'))
        }));
    }
    assert_eq!(country_total, subdivisions.len());

    let united_states = Country::the_united_states_of_america().subdivisions();
    assert!(united_states.iter().any(|value| value.code == "US-CA"));
    assert!(Country::antarctica().subdivisions().is_empty());
}

#[test]
fn subdivisions_resolve_their_country() -> Result<(), Box<dyn Error>> {
    let california = Subdivision::from_str("US-CA")?;

    assert_eq!(
        california.country(),
        Country::the_united_states_of_america()
    );

    Ok(())
}

#[test]
fn codes_parse_case_insensitively() -> Result<(), Box<dyn Error>> {
    let california = Subdivision::from_code("US-CA")?;

    assert_eq!(Subdivision::from_code("US-CA"), Ok(california));
    assert_eq!(Subdivision::from_code("us-ca"), Ok(california));
    assert_eq!(Subdivision::from_code("uS-cA"), Ok(california));
    assert_eq!(Subdivision::from_str("US-CA"), Ok(california));
    assert_eq!(
        Subdivision::from_code("US-ZZ"),
        Err(SubdivisionParseError::InvalidCode)
    );
    assert_eq!(
        Subdivision::from_code("TOO-LONG"),
        Err(SubdivisionParseError::InvalidCode)
    );
    assert_eq!(
        Subdivision::from_code("é"),
        Err(SubdivisionParseError::InvalidCode)
    );

    for subdivision in Subdivision::subdivisions() {
        assert_eq!(
            Subdivision::from_code(subdivision.code),
            Ok(*subdivision),
            "{}",
            subdivision.code
        );
    }

    Ok(())
}

#[test]
fn traits_use_the_canonical_code() {
    struct FailingWriter;

    impl Write for FailingWriter {
        fn write_str(&mut self, _: &str) -> fmt::Result {
            Err(fmt::Error)
        }
    }

    let andorra = Subdivision::from_code("AD-02");
    let california = Subdivision::from_code("US-CA");
    let lowercase_andorra = Subdivision::from_code("ad-02");

    assert!(andorra.is_ok());
    assert!(california.is_ok());
    assert!(lowercase_andorra.is_ok());

    if let (Ok(andorra), Ok(california), Ok(lowercase_andorra)) =
        (andorra, california, lowercase_andorra)
    {
        assert!(andorra < california);
        assert_eq!(andorra, lowercase_andorra);
        assert_eq!(andorra.to_string(), "AD-02");
        assert_eq!(
            format!("{andorra:?}"),
            "Subdivision { code: \"AD-02\", name: \"Canillo\", .. }"
        );
        assert_eq!(size_of::<Subdivision>(), 5 * size_of::<usize>());

        let mut hasher = DefaultHasher::new();
        andorra.hash(&mut hasher);
        assert_ne!(hasher.finish(), 0);

        assert!(write!(FailingWriter, "{andorra}").is_err());
    }
}