Skip to main content

threexui_rs/models/
custom_geo.rs

1use serde::{Deserialize, Deserializer, Serialize};
2
3fn null_or_vec<'de, D>(de: D) -> Result<Vec<String>, D::Error>
4where
5    D: Deserializer<'de>,
6{
7    Ok(Option::<Vec<String>>::deserialize(de)?.unwrap_or_default())
8}
9
10#[derive(Debug, Clone, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct CustomGeoResource {
13    pub id: i64,
14    #[serde(rename = "type")]
15    pub geo_type: String,
16    pub alias: String,
17    pub url: String,
18    #[serde(default)]
19    pub local_path: String,
20    #[serde(default)]
21    pub last_updated_at: i64,
22    #[serde(default)]
23    pub created_at: i64,
24    #[serde(default)]
25    pub updated_at: i64,
26}
27
28#[derive(Debug, Clone, Serialize)]
29pub struct CreateCustomGeo {
30    #[serde(rename = "type")]
31    pub geo_type: String,
32    pub alias: String,
33    pub url: String,
34}
35
36#[derive(Debug, Clone, Default, Deserialize)]
37pub struct CustomGeoAliases {
38    #[serde(default, deserialize_with = "null_or_vec")]
39    pub geosite: Vec<String>,
40    #[serde(default, deserialize_with = "null_or_vec")]
41    pub geoip: Vec<String>,
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn custom_geo_deserializes() {
50        let raw = r#"{"id":1,"type":"geoip","alias":"myip","url":"https://example.com/ip.dat","localPath":"","lastUpdatedAt":0,"createdAt":0,"updatedAt":0}"#;
51        let r: CustomGeoResource = serde_json::from_str(raw).unwrap();
52        assert_eq!(r.id, 1);
53        assert_eq!(r.geo_type, "geoip");
54        assert_eq!(r.alias, "myip");
55    }
56}