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
//! [Ref](https://lite.ip2location.com/database/px2-ip-proxytype-country#proxy-type)

//
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
    feature = "serde",
    derive(
        serde_enum_str::Deserialize_enum_str,
        serde_enum_str::Serialize_enum_str
    )
)]
#[cfg_attr(feature = "serde", serde(rename_all = "UPPERCASE"))]
pub enum ProxyType {
    VPN,
    TOR,
    DCH,
    PUB,
    WEB,
    SES,
    RES,
    #[cfg_attr(feature = "serde", serde(other))]
    Other(Box<str>),
}

#[cfg(not(feature = "serde"))]
impl core::str::FromStr for ProxyType {
    type Err = core::convert::Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "VPN" => Ok(Self::VPN),
            "TOR" => Ok(Self::TOR),
            "DCH" => Ok(Self::DCH),
            "PUB" => Ok(Self::PUB),
            "WEB" => Ok(Self::WEB),
            "SES" => Ok(Self::SES),
            "RES" => Ok(Self::RES),
            s => Ok(Self::Other(s.into())),
        }
    }
}

#[cfg(not(feature = "serde"))]
impl core::fmt::Display for ProxyType {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::VPN => write!(f, "VPN"),
            Self::TOR => write!(f, "TOR"),
            Self::DCH => write!(f, "DCH"),
            Self::PUB => write!(f, "PUB"),
            Self::WEB => write!(f, "WEB"),
            Self::SES => write!(f, "SES"),
            Self::RES => write!(f, "RES"),
            Self::Other(s) => write!(f, "{}", s),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn from_str() {
        assert_eq!("PUB".parse::<ProxyType>().unwrap(), ProxyType::PUB);
    }
}