use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct City<'a> {
pub name: &'a str, pub gmt: Vec<&'a str>, pub latitude: &'a str, pub longitude: &'a str, pub altitude: &'a str, }
#[derive(Debug)]
pub struct Details<'a> {
pub flag: &'a str, pub calling_code: &'a str, pub name: &'a str, pub currency: &'a str, pub capital: &'a str, pub cities: Vec<City<'a>>, }
pub struct Country<'a> {
data: HashMap<&'a str, Details<'a>>, }
impl<'a> Country<'a> {
pub fn new() -> Self {
let mut data = HashMap::new();
let entries = [
(
"BH",
"🇧ðŸ‡",
"973",
"Bahrain",
"BHD",
"Manama",
vec![
City {
name: "Manama",
gmt: vec!["GMT+3"],
latitude: "26.22787",
longitude: "50.58565",
altitude: "10",
},
City {
name: "Riffa",
gmt: vec!["GMT+3"],
latitude: "26.129999",
longitude: "50.555000",
altitude: "15",
},
],
),
(
"CA",
"🇨🇦",
"1",
"Canada",
"CAD",
"Ottawa",
vec![
City {
name: "Ottawa",
gmt: vec!["GMT-5", "GMT-4"],
latitude: "45.4215",
longitude: "-75.6972",
altitude: "70",
},
City {
name: "Toronto",
gmt: vec!["GMT-5", "GMT-4"],
latitude: "43.65107",
longitude: "-79.347015",
altitude: "76.5",
},
],
),
(
"DZ",
"🇩🇿",
"213",
"Algeria",
"DZD",
"Algiers",
vec![
City {
name: "Algiers",
gmt: vec!["GMT+1"],
latitude: "36.737232",
longitude: "3.086472",
altitude: "424",
},
City {
name: "Oran",
gmt: vec!["GMT+1"],
latitude: "35.69694440",
longitude: "0.63305560",
altitude: "0.9",
},
],
),
(
"SA",
"🇸🇦",
"966",
"Saudi Arabia",
"SAR",
"Riyadh",
vec![
City {
name: "Riyadh",
gmt: vec!["GMT+3"],
latitude: "24.7136",
longitude: "46.6753",
altitude: "612",
},
City {
name: "Jeddah",
gmt: vec!["GMT+3"],
latitude: "21.2854",
longitude: "39.2376",
altitude: "12",
},
],
),
(
"SD",
"🇸🇩",
"249",
"Sudan",
"SDG",
"Khartoum",
vec![
City {
name: "Khartoum",
gmt: vec!["GMT+2"],
latitude: "15.5007",
longitude: "32.5599",
altitude: "385",
},
City {
name: "Omdurman",
gmt: vec!["GMT+2"],
latitude: "15.6866",
longitude: "32.4752",
altitude: "375",
},
City {
name: "Khartoum Bahri",
gmt: vec!["GMT+2"],
latitude: "15.6151",
longitude: "32.552",
altitude: "360",
},
],
),
(
"GB",
"🇬🇧",
"44",
"United Kingdom",
"GBP",
"London",
vec![
City {
name: "London",
gmt: vec!["GMT+0", "GMT+1"],
latitude: "51.509865",
longitude: "-0.118092",
altitude: "24",
},
City {
name: "Manchester",
gmt: vec!["GMT+0", "GMT+1"],
latitude: "53.4808",
longitude: "-2.2426",
altitude: "38",
},
],
),
(
"UK",
"🇬🇧",
"44",
"United Kingdom",
"GBP",
"London",
vec![
City {
name: "London",
gmt: vec!["GMT+0", "GMT+1"],
latitude: "51.509865",
longitude: "-0.118092",
altitude: "24",
},
City {
name: "Birmingham",
gmt: vec!["GMT+0", "GMT+1"],
latitude: "52.4862",
longitude: "-1.8904",
altitude: "150",
},
],
),
(
"US",
"🇺🇸",
"1",
"United States",
"USD",
"Washington, D.C.",
vec![
City {
name: "Washington, D.C.",
gmt: vec!["GMT-5", "GMT-4"],
latitude: "38.89511",
longitude: "-77.03637",
altitude: "125",
},
City {
name: "New York",
gmt: vec!["GMT-5", "GMT-4"],
latitude: "40.730610",
longitude: "-73.935242",
altitude: "10",
},
],
),
];
for &(short_name, flag, calling_code, country_name, currency, capital, ref cities) in
&entries
{
data.insert(
short_name,
Details {
flag,
calling_code,
name: country_name,
currency,
capital,
cities: cities.clone(),
},
);
}
Country { data }
}
pub fn insert_one(
&mut self,
short_name: &'a str,
details: Vec<&'a str>,
cities: Vec<City<'a>>,
) {
let details_struct = Details {
flag: details[0],
calling_code: details[1],
name: details[2],
currency: details[3],
capital: details[4],
cities,
};
self.data.insert(short_name, details_struct);
}
pub fn insert_many(&mut self, entries: Vec<(&'a str, Vec<&'a str>, Vec<City<'a>>)>) {
for (short_name, details, cities) in entries {
self.insert_one(short_name, details, cities);
}
}
pub fn insert_one_city(&mut self, country_code: &'a str, new_city: City<'a>) {
if let Some(details) = self.data.get_mut(country_code) {
let mut replaced = false; for city in &mut details.cities {
if city.name == new_city.name {
*city = new_city.clone(); replaced = true;
break;
}
}
if !replaced {
details.cities.push(new_city);
}
}
}
pub fn insert_many_cities(&mut self, country_code: &'a str, new_cities: Vec<City<'a>>) {
if let Some(details) = self.data.get_mut(country_code) {
for new_city in new_cities {
let mut replaced = false; for city in &mut details.cities {
if city.name == new_city.name {
*city = new_city.clone(); replaced = true;
break;
}
}
if !replaced {
details.cities.push(new_city);
}
}
}
}
pub fn retrieve(&self) -> &HashMap<&'a str, Details<'a>> {
&self.data
}
pub fn sort_asc(&self) -> Vec<&Details<'a>> {
let mut sorted: Vec<&Details<'a>> = self.data.values().collect();
sorted.sort_by(|a, b| a.name.cmp(b.name));
sorted
}
pub fn sort_desc(&self) -> Vec<&Details<'a>> {
let mut sorted: Vec<&Details<'a>> = self.data.values().collect();
sorted.sort_by(|a, b| b.name.cmp(a.name)); sorted
}
pub fn country_detail(&self, country_code: &'a str, key: &'a str) -> String {
if let Some(detail) = self.retrieve().get(country_code) {
match key {
"flag" => detail.flag.to_string(),
"calling_code" => detail.calling_code.to_string(),
"name" => detail.name.to_string(),
"currency" => detail.currency.to_string(),
"capital" => detail.capital.to_string(),
"cities" => {
let cities_json: Vec<String> = detail.cities.iter()
.map(|city| {
format!(
"{{ \"name\": \"{}\", \"gmt\": {:?}, \"latitude\": \"{}\", \"longitude\": \"{}\", \"altitude\": \"{}\" }}",
city.name, city.gmt, city.latitude, city.longitude, city.altitude
)
})
.collect();
format!("[{}]", cities_json.join(", ")) }
_ => String::new(), }
} else {
String::new() }
}
pub fn country_details(&self, country_code: &'a str) -> String {
if let Some(detail) = self.retrieve().get(country_code) {
let cities_json: Vec<String> = detail.cities.iter()
.map(|city| {
format!(
"{{ \"name\": \"{}\", \"gmt\": {:?}, \"latitude\": \"{}\", \"longitude\": \"{}\", \"altitude\": \"{}\" }}",
city.name, city.gmt, city.latitude, city.longitude, city.altitude
)
})
.collect();
format!(
"{{ \"flag\": \"{}\", \"calling_code\": \"{}\", \"name\": \"{}\", \"capital\": \"{}\", \"currency\": \"{}\", \"cities\": [{}] }}",
detail.flag, detail.calling_code, detail.name, detail.capital, detail.currency, cities_json.join(", ")
)
} else {
String::from("{ \"flag\": \"\", \"calling_code\": \"\", \"name\": \"\", \"capital\": \"\", \"currency\": \"\", \"cities\": [] }")
}
}
pub fn city_detail(&self, country_code: &'a str, city_name: &'a str, key: &'a str) -> String {
if let Some(detail) = self.retrieve().get(country_code) {
if let Some(city) = detail.cities.iter().find(|&c| c.name == city_name) {
match key {
"gmt" => city.gmt.join(", "),
"latitude" => city.latitude.to_string(),
"longitude" => city.longitude.to_string(),
"altitude" => city.altitude.to_string(),
"name" => city.name.to_string(),
_ => String::new(),
}
} else {
String::new() }
} else {
String::new() }
}
pub fn city_details(&self, country_code: &'a str, city_name: &'a str) -> String {
if let Some(detail) = self.retrieve().get(country_code) {
if let Some(city) = detail.cities.iter().find(|&c| c.name == city_name) {
return format!(
"{{ \"name\": \"{}\", \"gmt\": {:?}, \"latitude\": \"{}\", \"longitude\": \"{}\", \"altitude\": \"{}\" }}",
city.name, city.gmt, city.latitude, city.longitude, city.altitude
);
}
}
String::from("{ \"name\": \"\", \"gmt\": [], \"latitude\": \"\", \"longitude\": \"\", \"altitude\": \"\" }")
}
pub fn delete_one_city(&mut self, country_code: &'a str, city_name: &'a str) {
if let Some(details) = self.data.get_mut(country_code) {
details.cities.retain(|city| city.name != city_name); }
}
pub fn delete_many_cities(&mut self, country_code: &'a str, city_names: &[&'a str]) {
if let Some(details) = self.data.get_mut(country_code) {
details
.cities
.retain(|city| !city_names.contains(&city.name)); }
}
pub fn delete_all_cities(&mut self, country_code: &'a str) {
if let Some(details) = self.data.get_mut(country_code) {
details.cities.clear(); }
}
pub fn delete_one(&mut self, short_name: &str) {
self.data.remove(short_name);
}
pub fn delete_many(&mut self, short_names: &[&str]) {
for &short_name in short_names {
self.data.remove(short_name);
}
}
pub fn delete_all(&mut self) {
self.data.clear();
}
}