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
88
89
90
91
92
93
use serde::{Deserialize, Serialize};
use crate::err::{DeserializeErr};
use std::str::FromStr;
use rust_decimal::Decimal;
use chrono::{DateTime, Utc, TimeZone};
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct GeoName {
pub geonameid: i32,
pub name: String,
pub asciiname: Option<String>,
pub alternatenames: Vec<String>,
pub latitude: Decimal,
pub longitude: Decimal,
pub feature_class: Option<String>,
pub feature_code: Option<String>,
pub country_code: Option<String>,
pub cc2: Option<String>,
pub admin1_code : Option<String>,
pub admin2_code : Option<String>,
pub admin3_code : Option<String>,
pub admin4_code : Option<String>,
pub population: Option<i64>,
pub elevation: Option<i32>,
pub dem: String,
pub timezone: Option<String>,
pub modification: DateTime<Utc>,
}
impl GeoName {
pub fn deserialize_from_string(str: &str) -> Result<Self, DeserializeErr> {
let vec = str.split(" ").collect::<Vec<&str>>();
let elevation = match vec[15].to_owned().is_empty() {
true => None,
false => Some(vec[15].parse::<i32>()?)
};
Ok(Self {
geonameid: vec[0].parse::<i32>()?,
name: vec[1].to_owned(),
asciiname: Some(vec[2].to_owned()).filter(|x| !x.is_empty()),
alternatenames: vec[3].split(",").collect::<Vec<&str>>().into_iter().map(|x| x.to_owned()).collect::<Vec<String>>(),
latitude: Decimal::from_str(&vec[4])?,
longitude: Decimal::from_str(&vec[5])?,
feature_class: Some(vec[6].to_owned()).filter(|x| !x.is_empty()),
feature_code: Some(vec[7].to_owned()).filter(|x| !x.is_empty()),
country_code: Some(vec[8].to_owned()).filter(|x| !x.is_empty()),
cc2: Some(vec[9].to_owned()).filter(|x| !x.is_empty()),
admin1_code: Some(vec[10].to_owned()).filter(|x| !x.is_empty()),
admin2_code: Some(vec[11].to_owned()).filter(|x| !x.is_empty()),
admin3_code: Some(vec[12].to_owned()).filter(|x| !x.is_empty()),
admin4_code: Some(vec[13].to_owned()).filter(|x| !x.is_empty()),
population: Some(vec[14].parse::<i64>()?).filter(|x| x != &0),
elevation,
dem: vec[16].to_owned(),
timezone: Some(vec[17].to_owned()).filter(|x| !x.is_empty()),
modification: Utc.datetime_from_str(&(vec[18].to_string() + " 00:00:00 +00:00"), "%Y-%m-%d %H:%M:%S %z")?
})
}
}
#[cfg(test)]
mod tests {
use crate::model::GeoName;
#[test]
fn deserialize_string_to_geo_name() {
let _ = GeoName::deserialize_from_string("1485680 Yurty Yurty Jurty,Yurty,Юрты 56.0498 97.6348 P PPL RU 20 5902 301 Asia/Irkutsk 2012-01-17").unwrap();
}
}