filter_city/
lib.rs

1/******************************************************************************
2 * This program allows to search a city in ASCII all over the world in a json
3 * file.
4 *
5 * Initalliy I have done a script with Python but thas was very slow.
6 *
7 * By Stéphane Bressani
8 *  ____  _             _
9 * / ___|| |_ ___ _ __ | |__   __ _ _ __   ___
10 * \___ \| __/ _ \ '_ \| '_ \ / _` | '_ \ / _ \
11 *  ___) | ||  __/ |_) | | | | (_| | | | |  __/
12 * |____/ \__\___| .__/|_| |_|\__,_|_| |_|\___|
13 *               | |stephane-bressani.ch
14 *               |_|github.com/stephaneworkspace
15 *
16 *****************************************************************************/
17extern 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
28//use std::io::{self, Write};
29use std::sync::mpsc::channel;
30use std::thread;
31
32const PATH: &str = "assets/citys.json";
33
34/// Format of json file in PATH
35#[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/// Concat all City in one struct
44#[derive(Debug, Clone)]
45pub struct Citys {
46    pub citys: Vec<City>,
47}
48
49/// Trait fd
50pub trait Fd {
51    /// Filter city monothread
52    fn filter(&self, name: &str) -> Vec<City>;
53    /// Filter city multithread
54    fn filter_multithread(&self, name: &str) -> Vec<City>;
55}
56
57/// Constructor for City impl
58impl 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        // println!("{:?}", file_path.as_path());
65        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
75/// Impl of Fd for City
76impl Fd for Citys {
77    /// Filter city monothread
78    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    /// Filter city multithread
99    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                            /*
119                            print!(".");
120                            io::stdout().flush().unwrap();
121                            */
122                            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    //fd.filter_multithread(name)
150}