ip2location-country-multilingual 0.3.0

IP2Location™ Country Multilingual Database
Documentation
use core::ops::Deref;
use std::io::Read;

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

use crate::record::Record;

//
#[cfg(feature = "once_cell")]
pub static RECORDS: once_cell::sync::Lazy<Records> = once_cell::sync::Lazy::new(|| {
    let csv = include_str!("../data/IP2LOCATION-COUNTRY-MULTILINGUAL.CSV");
    Records::from_csv(csv.as_bytes()).unwrap()
});

//
#[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 mut inner = vec![];

        for record in rdr.records() {
            let record = record.map_err(RecordsFromCsvError::CsvParseFailed)?;
            let row: Record = record
                .deserialize(None)
                .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 std::error::Error for RecordsFromCsvError {}