countrycode 0.3.0

https://countrycode.org/ ALL COUNTRY CODES
Documentation
use core::ops::Deref;
use std::{io::Read, sync::LazyLock};

use csv::{Error as CsvError, Reader, StringRecord};

use crate::record::Record;

//
pub const CSV_HEADER: &[&str] = &[
    "country_name",
    "iso2",
    "iso3",
    "top_level_domain",
    "fips",
    "iso_mumeric",
    "geo_name_id",
    "e164",
    "phone_code",
    "continent",
    "capital",
    "time_zone_in_capital",
    "currency",
    "language_codes",
    "languages",
    "area",
    "internet_hosts",
    "internet_users",
    "phones_mobile",
    "phones_landline",
    "gdp",
];

//
pub static RECORDS: LazyLock<Records> = LazyLock::new(|| {
    let csv = include_str!("../data/countrycode.csv");
    Records::from_csv(csv.as_bytes()).unwrap()
});

pub static RECORDS_ISO2_MAP: LazyLock<
    std::collections::HashMap<country_code::CountryCode, Record>,
> = LazyLock::new(|| {
    RECORDS
        .iter()
        .cloned()
        .map(|x| (x.iso2.to_owned(), x))
        .collect()
});

//
#[derive(Debug, Clone)]
pub struct Records(pub Vec<Record>);

impl Deref for Records {
    type Target = Vec<Record>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

//
impl Records {
    pub fn from_csv<R: Read>(rdr: R) -> Result<Self, RecordsFromCsvError> {
        let mut rdr = Reader::from_reader(rdr);

        let header = StringRecord::from(CSV_HEADER);

        let mut inner = vec![];

        for record in rdr.records() {
            let record = record.map_err(RecordsFromCsvError::CsvParseFailed)?;
            let row: Record = record
                .deserialize(Some(&header))
                .map_err(RecordsFromCsvError::RecordDeFailed)?;
            inner.push(row);
        }

        Ok(Self(inner))
    }
}

//
#[derive(Debug)]
pub enum RecordsFromCsvError {
    CsvParseFailed(CsvError),
    RecordDeFailed(CsvError),
}

impl core::fmt::Display for RecordsFromCsvError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{self:?}")
    }
}

impl core::error::Error for RecordsFromCsvError {}