Skip to main content

ip2location_iso3166_2/
csv_format.rs

1use core::ops::Deref;
2use std::io::Read;
3
4use csv::{Error as CsvError, Reader, StringRecord};
5
6use crate::record::Record;
7
8//
9#[cfg(feature = "once_cell")]
10pub static RECORDS: once_cell::sync::Lazy<Records> = once_cell::sync::Lazy::new(|| {
11    let csv = include_str!("../data/IP2LOCATION-ISO3166-2.CSV");
12    Records::from_csv(csv.as_bytes()).unwrap()
13});
14
15#[cfg(feature = "once_cell")]
16pub static RECORDS_CODE_MAP: once_cell::sync::Lazy<
17    std::collections::HashMap<country_code::iso3166_2::SubdivisionCode, Record>,
18> = once_cell::sync::Lazy::new(|| {
19    RECORDS
20        .iter()
21        .cloned()
22        .map(|x| (x.code.to_owned(), x))
23        .collect()
24});
25
26//
27#[derive(Debug, Clone)]
28pub struct Records(pub Vec<Record>);
29
30impl Deref for Records {
31    type Target = Vec<Record>;
32
33    fn deref(&self) -> &Self::Target {
34        &self.0
35    }
36}
37
38//
39impl Records {
40    pub fn from_csv<R: Read>(rdr: R) -> Result<Self, RecordsFromCsvError> {
41        let mut rdr = Reader::from_reader(rdr);
42
43        let mut inner = vec![];
44
45        for record in rdr.records() {
46            let record = record.map_err(RecordsFromCsvError::CsvParseFailed)?;
47
48            /*
49            LINE: "AI","Anguilla","-"
50            */
51            let record = if record.get(2) == Some("-") {
52                StringRecord::from(vec![
53                    &record[0],
54                    &record[1],
55                    format!("{}-", &record[0]).as_str(),
56                ])
57            } else {
58                record
59            };
60
61            let row: Record = record
62                .deserialize(None)
63                .map_err(RecordsFromCsvError::RecordDeFailed)?;
64            inner.push(row);
65        }
66
67        Ok(Self(inner))
68    }
69}
70
71//
72#[derive(Debug)]
73pub enum RecordsFromCsvError {
74    CsvParseFailed(CsvError),
75    RecordDeFailed(CsvError),
76}
77
78impl core::fmt::Display for RecordsFromCsvError {
79    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80        write!(f, "{self:?}")
81    }
82}
83
84impl std::error::Error for RecordsFromCsvError {}