validator_async/validation/
ip.rs1use std::net::IpAddr;
2use std::str::FromStr;
3
4pub trait ValidateIp {
5 fn validate_ipv4(&self) -> bool;
7 fn validate_ipv6(&self) -> bool;
9 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}