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