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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#[cfg(feature = "std")]
use std::str::{from_utf8_unchecked, FromStr};
#[cfg(feature = "std")]
use std::net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr};
#[cfg(feature = "std")]
#[inline]
pub fn is_local_ip(addr: IpAddr) -> bool {
match addr {
IpAddr::V4(addr) => is_local_ipv4(addr),
IpAddr::V6(addr) => is_local_ipv6(addr),
}
}
#[cfg(feature = "std")]
#[inline]
pub fn is_local_ipv4(addr: Ipv4Addr) -> bool {
addr.is_private()
|| addr.is_loopback()
|| addr.is_link_local()
|| addr.is_broadcast()
|| addr.is_documentation()
|| addr.is_unspecified()
}
#[cfg(feature = "std")]
#[inline]
pub fn is_local_ipv6(addr: Ipv6Addr) -> bool {
let segments = addr.segments();
let first = segments[0];
if (first & 0xff00) == 0xff00 {
first & 0x000f != 14
} else {
if segments.starts_with(&[0, 0, 0, 0, 0, 0, 0]) {
match segments[7] {
0 | 1 => {
return true;
}
_ => (),
}
}
match first & 0xffc0 {
0xfe80 | 0xfec0 => {
return true;
}
_ => (),
}
if first & 0xfe00 == 0xfc00 || (first == 0x2001) && (segments[1] == 0xdb8) {
return true;
}
match addr.to_ipv4() {
Some(addr) => is_local_ipv4(addr),
None => false,
}
}
}
#[inline]
pub fn is_local_domain<S: AsRef<str>>(s: S) -> bool {
let bytes = s.as_ref().as_bytes();
debug_assert!(!bytes.is_empty());
let length_dec = bytes.len() - 1;
let bytes = if bytes[length_dec] == b'.' {
&bytes[..length_dec]
} else {
bytes
};
bytes.eq_ignore_ascii_case(b"localhost")
}
#[inline]
pub fn is_at_least_two_labels_domain<S: AsRef<str>>(s: S) -> bool {
let s = s.as_ref();
debug_assert!(!s.is_empty());
s
.bytes()
.take(s.len() - 1)
.any(|e| e == b'.')
}
#[cfg(feature = "std")]
#[inline]
pub fn parse_ipv4_allow_an_ended_dot<S: AsRef<str>>(s: S) -> Result<Ipv4Addr, AddrParseError> {
let s = s.as_ref();
let bytes = s.as_bytes();
debug_assert!(!bytes.is_empty());
let length = bytes.len();
let s = if length > 0 && bytes[length - 1] == b'.' {
unsafe { from_utf8_unchecked(&bytes[..(length - 1)]) }
} else {
s
};
Ipv4Addr::from_str(s)
}