1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#![doc = include_str!("../README.md")]

#![forbid(unsafe_code)]
#![no_std]

#[cfg(feature = "short-names")]
use core::fmt;

mod countries;
#[cfg(feature = "short-names")]
mod countries_short_names;

pub use countries::{CountryAlpha2, CountryAlpha3};

/// A country in the list of countries defined by ISO 3166-1.
/// 
/// # Examples
/// 
/// ```
/// use countries_tools::{Country, CountryAlpha2};
/// 
/// let united_states = Country::from(CountryAlpha2::US);
/// println!("{} is in North America.", united_states);
/// // Prints "United States of America is in North America."
/// 
/// assert_eq!(united_states.short_name(), "United States of America");
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Country {
    alpha2: CountryAlpha2,
    alpha3: CountryAlpha3,
    numeric: u16,
}

impl Country {
    // No need to make this public, since countries are created by this crate only.
    #[inline]
    const fn new(
        alpha2: CountryAlpha2,
        alpha3: CountryAlpha3,
        numeric: u16,
        // NOTE: short name is not part of the struct as &'static str size is 16 bytes
        //         and that would make the struct 24 bytes, making the cache of the CPU
        //         less efficient. Instead alpha2 code enum is used as offset to get the
        //         short name from the array of short names. That make the struct 4 bytes
        //         and the cache of the CPU more efficient.
        //
        //       This has been measured with criterion before and the results show an speed
        //         improvement of 47.21%-61.14% when searching for a country by numeric code,
        //         and 0.15%-87.35% when searching for a country by alpha2 or alpha3 code.
    ) -> Self {
        Self {
            alpha2,
            alpha3,
            numeric,
        }
    }

    #[inline]
    pub const fn alpha2(&self) -> CountryAlpha2 {
        self.alpha2
    }

    #[inline]
    pub const fn alpha3(&self) -> CountryAlpha3 {
        self.alpha3
    }

    #[inline]
    pub const fn numeric(&self) -> u16 {
        self.numeric
    }

    #[cfg(feature = "short-names")]
    #[inline]
    pub const fn short_name(&self) -> &'static str {
        countries_short_names::short_name_from_alpha2(self.alpha2)
    }
}

#[cfg(feature = "short-names")]
impl fmt::Display for Country {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.short_name().fmt(f)
    }
}