validator_async/validation/
ip.rs

1use std::net::IpAddr;
2use std::str::FromStr;
3
4pub trait ValidateIp {
5    /// Validates whether the given string is an IP V4
6    fn validate_ipv4(&self) -> bool;
7    /// Validates whether the given string is an IP V6
8    fn validate_ipv6(&self) -> bool;
9    /// Validates whether the given string is an IP
10    fn validate_ip(&self) -> bool;
11}
12
13impl<T> ValidateIp for T
14where
15    T: ToString,
16{
17    fn validate_ipv4(&self) -> bool {
18        IpAddr::from_str(&self.to_string()).is_ok_and(|i| i.is_ipv4())
19    }
20
21    fn validate_ipv6(&self) -> bool {
22        IpAddr::from_str(&self.to_string()).is_ok_and(|i| i.is_ipv6())
23    }
24
25    fn validate_ip(&self) -> bool {
26        IpAddr::from_str(&self.to_string()).is_ok()
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use super::ValidateIp;
33    use std::borrow::Cow;
34
35    #[test]
36    fn test_validate_ip() {
37        let tests = vec![
38            ("1.1.1.1", true),
39            ("255.0.0.0", true),
40            ("0.0.0.0", true),
41            ("256.1.1.1", false),
42            ("25.1.1.", false),
43            ("25,1,1,1", false),
44            ("fe80::223:6cff:fe8a:2e8a", true),
45            ("::ffff:254.42.16.14", true),
46            ("2a02::223:6cff :fe8a:2e8a", false),
47        ];
48
49        for (input, expected) in tests {
50            assert_eq!(input.validate_ip(), expected);
51        }
52    }
53
54    #[test]
55    fn test_validate_ip_cow() {
56        let test: Cow<'static, str> = "1.1.1.1".into();
57        assert!(test.validate_ip());
58        let test: Cow<'static, str> = String::from("1.1.1.1").into();
59        assert!(test.validate_ip());
60        let test: Cow<'static, str> = "2a02::223:6cff :fe8a:2e8a".into();
61        assert!(!test.validate_ip());
62        let test: Cow<'static, str> = String::from("2a02::223:6cff :fe8a:2e8a").into();
63        assert!(!test.validate_ip());
64    }
65
66    #[test]
67    fn test_validate_ip_v4() {
68        let tests = vec![
69            ("1.1.1.1", true),
70            ("255.0.0.0", true),
71            ("0.0.0.0", true),
72            ("256.1.1.1", false),
73            ("25.1.1.", false),
74            ("25,1,1,1", false),
75            ("25.1 .1.1", false),
76            ("1.1.1.1\n", false),
77            ("٧.2٥.3٣.243", false),
78        ];
79
80        for (input, expected) in tests {
81            assert_eq!(input.validate_ipv4(), expected);
82        }
83    }
84
85    #[test]
86    fn test_validate_ip_v4_cow() {
87        let test: Cow<'static, str> = "1.1.1.1".into();
88        assert!(test.validate_ipv4());
89        let test: Cow<'static, str> = String::from("1.1.1.1").into();
90        assert!(test.validate_ipv4());
91        let test: Cow<'static, str> = "٧.2٥.3٣.243".into();
92        assert!(!test.validate_ipv4());
93        let test: Cow<'static, str> = String::from("٧.2٥.3٣.243").into();
94        assert!(!test.validate_ipv4());
95    }
96
97    #[test]
98    fn test_validate_ip_v6() {
99        let tests = vec![
100            ("fe80::223:6cff:fe8a:2e8a", true),
101            ("2a02::223:6cff:fe8a:2e8a", true),
102            ("1::2:3:4:5:6:7", true),
103            ("::", true),
104            ("::a", true),
105            ("2::", true),
106            ("::ffff:254.42.16.14", true),
107            ("::ffff:0a0a:0a0a", true),
108            ("::254.42.16.14", true),
109            ("::0a0a:0a0a", true),
110            ("foo", false),
111            ("127.0.0.1", false),
112            ("12345::", false),
113            ("1::2::3::4", false),
114            ("1::zzz", false),
115            ("1:2", false),
116            ("fe80::223: 6cff:fe8a:2e8a", false),
117            ("2a02::223:6cff :fe8a:2e8a", false),
118            ("::ffff:999.42.16.14", false),
119            ("::ffff:zzzz:0a0a", false),
120        ];
121
122        for (input, expected) in tests {
123            assert_eq!(input.validate_ipv6(), expected);
124        }
125    }
126
127    #[test]
128    fn test_validate_ip_v6_cow() {
129        let test: Cow<'static, str> = "fe80::223:6cff:fe8a:2e8a".into();
130        assert!(test.validate_ipv6());
131        let test: Cow<'static, str> = String::from("fe80::223:6cff:fe8a:2e8a").into();
132        assert!(test.validate_ipv6());
133        let test: Cow<'static, str> = "::ffff:zzzz:0a0a".into();
134        assert!(!test.validate_ipv6());
135        let test: Cow<'static, str> = String::from("::ffff:zzzz:0a0a").into();
136        assert!(!test.validate_ipv6());
137    }
138}