1extern crate serde;
18extern crate serde_derive;
19extern crate serde_json;
20extern crate unidecode;
21
22use serde::Deserialize;
23use serde::Serialize;
24use std::fs::File;
25use std::io::Read;
26use unidecode::unidecode;
27
28use std::sync::mpsc::channel;
30use std::thread;
31
32const PATH: &str = "assets/citys.json";
33
34#[derive(Serialize, Deserialize, Debug, Clone)]
36pub struct City {
37 pub country: String,
38 pub name: String,
39 pub lat: String,
40 pub lng: String,
41}
42
43#[derive(Debug, Clone)]
45pub struct Citys {
46 pub citys: Vec<City>,
47}
48
49pub trait Fd {
51 fn filter(&self, name: &str) -> Vec<City>;
53 fn filter_multithread(&self, name: &str) -> Vec<City>;
55}
56
57impl Citys {
59 pub fn new(path: &str) -> Citys {
60 let mut s = String::new();
61 let mut file_path: std::path::PathBuf = std::path::PathBuf::new();
62 file_path.push(std::env::current_dir().unwrap().as_path());
63 file_path.push(path);
64 File::open(file_path.as_path())
66 .unwrap()
67 .read_to_string(&mut s)
68 .unwrap();
69 Citys {
70 citys: serde_json::from_str(&s).unwrap(),
71 }
72 }
73}
74
75impl Fd for Citys {
77 fn filter(&self, name: &str) -> Vec<City> {
79 let filter_upper_decode = unidecode(name).to_ascii_uppercase();
80 let mut city: Vec<City> = Vec::new();
81 for x in self.citys.clone() {
82 if name.len() > 0 {
83 let compare_string =
84 unidecode(x.name.as_str()).to_ascii_uppercase();
85 if compare_string.contains(filter_upper_decode.as_str()) {
86 city.push(City {
87 country: x.country.clone(),
88 name: x.name.clone(),
89 lat: x.lat.clone(),
90 lng: x.lng.clone(),
91 });
92 }
93 }
94 }
95 city
96 }
97
98 fn filter_multithread(&self, name: &str) -> Vec<City> {
100 let mut citys: Vec<City> = vec![];
101 if name.len() > 1 {
102 let num_threads = 4;
103 let (tx, rx) = channel();
104 for i in 0..num_threads {
105 let tx = tx.clone();
106 let citys_static: Vec<City> = self.citys.clone();
107 let filter_upper_decode = unidecode(&name).to_ascii_uppercase();
108 let max_jj: usize = citys_static.len() / num_threads;
109 let jj: usize = i * &max_jj;
110 thread::spawn(move || {
111 let mut j: usize = jj;
112 loop {
113 let x = citys_static[j].clone();
114 let compare_string =
115 unidecode(x.name.as_str()).to_ascii_uppercase();
116 if compare_string.contains(filter_upper_decode.as_str())
117 {
118 tx.send(City {
123 country: x.country.clone(),
124 name: x.name.clone(),
125 lat: x.lat.clone(),
126 lng: x.lng.clone(),
127 })
128 .unwrap();
129 }
130 j += 1;
131 if j >= citys_static.len() || j >= max_jj * (i + 1) {
132 break;
133 }
134 }
135 });
136 }
137 drop(tx);
138 for p in rx {
139 citys.push(p.clone());
140 }
141 }
142 citys
143 }
144}
145
146pub fn filter_city(name: &str) -> Vec<City> {
147 let fd = Citys::new(PATH);
148 fd.filter(name)
149 }