locale_codes/
region.rs

1/*!
2Codes for the representation of names of countries and their subdivisions.
3
4The purpose of ISO 3166 is to define internationally recognised codes
5of letters and/or numbers that we can use when we refer to countries
6and subdivisions. However, it does not define the names of countries
7– this information comes from United Nations sources (Terminology
8Bulletin Country Names and the Country and Region Codes for Statistical
9Use maintained by the United Nations Statistics Divisions).
10
11## Source - ISO 3166
12
13The data used here is taken from the page
14[Github](https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes).
15*/
16
17use std::collections::HashMap;
18
19use serde::{Deserialize, Serialize};
20
21// ------------------------------------------------------------------------------------------------
22// Public Types
23// ------------------------------------------------------------------------------------------------
24
25/// A representation of registered region data maintained by ISO.
26#[derive(Deserialize, Serialize, Debug)]
27pub struct RegionInfo {
28    /// The unique numeric identifier for this region.
29    pub code: u16,
30    /// The name of this region.
31    pub name: String,
32}
33
34// ------------------------------------------------------------------------------------------------
35// Public Functions
36// ------------------------------------------------------------------------------------------------
37
38lazy_static! {
39    static ref REGIONS: HashMap<u16, RegionInfo> = load_regions_from_json();
40}
41
42pub fn lookup(code: u16) -> Option<&'static RegionInfo> {
43    info!("lookup_region: {}", code);
44    match REGIONS.get(&code) {
45        Some(v) => Some(v),
46        None => None,
47    }
48}
49
50pub fn all_codes() -> Vec<u16> {
51    REGIONS.keys().cloned().collect()
52}
53
54// ------------------------------------------------------------------------------------------------
55// Generated Data
56// ------------------------------------------------------------------------------------------------
57
58fn load_regions_from_json() -> HashMap<u16, RegionInfo> {
59    info!("load_regions_from_json - loading JSON");
60    let raw_data = include_bytes!("data/regions.json");
61    let raw_map: HashMap<String, String> = serde_json::from_slice(raw_data).unwrap();
62    raw_map
63        .iter()
64        .map(|(code, name)| {
65            (
66                code.parse::<u16>().unwrap(),
67                RegionInfo {
68                    code: code.parse::<u16>().unwrap(),
69                    name: name.to_string(),
70                },
71            )
72        })
73        .collect()
74}
75
76// ------------------------------------------------------------------------------------------------
77// Unit Tests
78// ------------------------------------------------------------------------------------------------
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    // --------------------------------------------------------------------------------------------
85    #[test]
86    fn test_region_codes() {
87        let codes = all_codes();
88        assert!(codes.len() > 0);
89    }
90
91    #[test]
92    fn test_good_region_code() {
93        match lookup(21) {
94            None => panic!("was expecting a region"),
95            Some(region) => assert_eq!(region.name, "Northern America"),
96        }
97    }
98
99    #[test]
100    fn test_bad_region_code() {
101        match lookup(0) {
102            None => (),
103            Some(_) => panic!("was expecting a None in response"),
104        }
105    }
106}