iso3166_1/lib.rs
1// ISC License (ISC)
2//
3// Copyright (c) 2016, Austin Hellyer <hello@austinhellyer.me>
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
13// RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
14// CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16//
17// What is ISO 3166-1?
18//
19// | ISO 3166-1 is part of the ISO 3166 standard published by the International
20// | Organization for Standardization (ISO), and defines codes for the names of
21// | countries, dependent territories, and special areas of geographical
22// | interest.
23// |
24// | - [Wikipedia](http://en.wikipedia.org/wiki/ISO_3166-1)
25//
26// Originally by taiyaeix on GitHub.
27
28mod codes;
29
30pub use codes::all;
31
32/// Struct that contains the data for each Country Code defined by ISO 3166-1,
33/// including the following pieces of information:
34///
35/// - `alpha2` - Two-character Alpha-2 code.
36/// - `alpha3` - Three-character Alpha-3 code.
37/// - `name` - English short name of country.
38/// - `num` - Numeric code of country.
39///
40/// Derives from Clone and Debug.
41#[derive(Clone, Debug)]
42pub struct CountryCode<'a> {
43 pub alpha2: &'a str,
44 pub alpha3: &'a str,
45 pub name: &'a str,
46 pub num: &'a str,
47}
48
49/// Returns an `Option` of a `CountryCode` with the given alpha2 code.
50///
51/// # Examples
52///
53/// ```rust
54/// let country = iso3166_1::alpha2("AF").unwrap();
55/// ```
56pub fn alpha2<'a>(alpha2: &str) -> Option<CountryCode<'a>> {
57 let mut code_ret: Option<CountryCode> = None;
58
59 for code in all() {
60 if code.alpha2 == alpha2 {
61 code_ret = Some(code.clone());
62
63 break;
64 }
65 }
66
67 code_ret
68}
69
70/// Returns an `Option` of a `CountryCode` with the given alpha3 code.
71///
72/// # Examples
73///
74/// ```rust
75/// let country = iso3166_1::alpha3("ATA").unwrap();
76/// ```
77pub fn alpha3<'a>(alpha3: &str) -> Option<CountryCode<'a>> {
78 let mut code_ret: Option<CountryCode> = None;
79
80 for code in all() {
81 if code.alpha3 == alpha3 {
82 code_ret = Some(code.clone());
83
84 break;
85 }
86 }
87
88 code_ret
89}
90
91/// Returns an `Option` of a `CountryCode` with the given name.
92///
93/// # Examples
94///
95/// ```rust
96/// let country = iso3166_1::name("Angola").unwrap();
97/// ```
98pub fn name<'a>(name: &str) -> Option<CountryCode<'a>> {
99 let mut code_ret: Option<CountryCode> = None;
100
101 for code in all() {
102 if code.name == name {
103 code_ret = Some(code.clone());
104
105 break;
106 }
107 }
108
109 code_ret
110}
111
112/// Returns an `Option` of a `CountryCode` with the given numeric value.
113///
114/// # Examples
115///
116/// ```rust
117/// let country = iso3166_1::num("016").unwrap();
118/// ```
119pub fn num<'a>(num: &str) -> Option<CountryCode<'a>> {
120 let mut code_ret: Option<CountryCode> = None;
121
122 for code in all() {
123 if code.num == num {
124 code_ret = Some(code.clone());
125
126 break;
127 }
128 }
129
130 code_ret
131}
132
133/// Returns a `Vec` of `CountryCode`s that have a numeric value within the range
134/// of the `from` and `to` given. The from and to are optional, and can either
135/// be `None` or `Some(&str)` for variations of the range wanted.
136///
137/// # Examples
138///
139/// Getting all values between `100` and `300`:
140///
141/// ```rust
142/// let countries = iso3166_1::num_range(Some("100"), Some("300"));
143/// ```
144///
145/// Getting all values from `400` and beyond:
146///
147/// ```rust
148/// let countries = iso3166_1::num_range(Some("400"), None);
149/// ```
150///
151/// Getting all values up to `500`:
152///
153/// ```rust
154/// let countries = iso3166_1::num_range(None, Some("500"));
155/// ```
156///
157/// Getting no values, if that's your thing:
158///
159/// ```
160/// let countries = iso3166_1::num_range(None, None);
161/// ```
162pub fn num_range<'a>(from: Option<&str>,
163 to: Option<&str>) -> Vec<CountryCode<'a>> {
164 let mut codes: Vec<CountryCode> = vec![];
165
166 let from_do: bool = from.is_some();
167 let to_do: bool = to.is_some();
168
169 let from_val: i16 = if from_do {
170 from.unwrap().parse::<i16>().unwrap()
171 } else {
172 0
173 };
174 let to_val: i16 = if to_do {
175 to.unwrap().parse::<i16>().unwrap()
176 } else {
177 0
178 };
179
180 for code in all() {
181 let num_as_int: i16 = code.num.parse::<i16>().unwrap();
182
183 let gte: bool = num_as_int >= from_val;
184 let lte: bool = num_as_int <= to_val;
185
186 let matches: bool = if from_do && to_do {
187 gte && lte
188 } else if from_do {
189 gte
190 } else if to_do {
191 lte
192 } else {
193 false
194 };
195
196 if matches {
197 codes.push(code.clone());
198 }
199 }
200
201 codes
202}