1use std::net::{
2 AddrParseError,
3 IpAddr,
4 Ipv4Addr,
5};
6
7pub fn inet_addr(s: &str) -> Option<Ipv4Addr> {
19 let mut slots = [0u32; 4];
20 let mut last_slot = 0;
21 for (ndx, part) in s.split('.').enumerate() {
22 if ndx >= 4 {
23 return None;
25 }
26 let slot = if part.starts_with("0x") || part.starts_with("0X") {
27 let part = &part[2..];
28 if part.starts_with('+') {
29 return None;
31 }
32 u32::from_str_radix(part, 16)
33 } else if part.starts_with('0') {
34 u32::from_str_radix(part, 8)
35 } else {
36 part.parse::<u32>()
37 };
38 slots[ndx] = slot.ok()?;
39 last_slot = ndx;
40 }
41 debug_assert!(last_slot <= 3, "can't have more than 4");
42
43 let num = if last_slot == 0 {
44 slots[0]
45 } else {
46 let mut base: u32 = 0;
47 for (ndx, &slot) in slots.iter().enumerate().take(last_slot) {
48 if slot >= 256 {
49 return None;
51 }
52 base |= slots[ndx] << ((3 - ndx) * 8);
54 }
55 let last_slot_bit_limit = (4 - last_slot) * 8;
57 if slots[last_slot] >= 1 << last_slot_bit_limit {
58 return None;
60 }
61 base | slots[last_slot]
63 };
64
65 Some(Ipv4Addr::from(num))
66}
67
68pub fn parse_loose_ipv4(s: &str) -> Result<Ipv4Addr, AddrParseError> {
70 match s.parse() {
71 Ok(a) => Ok(a),
72 Err(e) => {
73 if let Some(a) = inet_addr(s) {
74 Ok(a)
75 } else {
76 Err(e)
77 }
78 },
79 }
80}
81
82pub fn parse_loose_ip(s: &str) -> Result<IpAddr, AddrParseError> {
84 match s.parse() {
85 Ok(a) => Ok(a),
86 Err(e) => {
87 if let Some(a) = inet_addr(s) {
88 Ok(IpAddr::V4(a))
89 } else {
90 Err(e)
91 }
92 },
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use std::net::{
99 AddrParseError,
100 IpAddr,
101 Ipv4Addr,
102 };
103
104 fn run(s: &str, expect: Ipv4Addr) {
105 assert_eq!(super::inet_addr(s), Some(expect));
106 assert_eq!(super::parse_loose_ipv4(s), Ok::<_, AddrParseError>(expect));
107 assert_eq!(
108 super::parse_loose_ip(s),
109 Ok::<_, AddrParseError>(IpAddr::V4(expect))
110 );
111 }
112
113 #[test]
114 fn test_loose_ipv4() {
115 run("10.0.1.2", Ipv4Addr::from([10, 0, 1, 2]));
116 run("10.0.258", Ipv4Addr::from([10, 0, 1, 2]));
117 run("0xA000102", Ipv4Addr::from([10, 0, 1, 2]));
118 run("0XA000102", Ipv4Addr::from([10, 0, 1, 2]));
119 run("012.0x102", Ipv4Addr::from([10, 0, 1, 2]));
120
121 run("127.0.0.1", Ipv4Addr::from([127, 0, 0, 1]));
122 run("127.0.1", Ipv4Addr::from([127, 0, 0, 1]));
123 run("127.1", Ipv4Addr::from([127, 0, 0, 1]));
124
125 run("0", Ipv4Addr::from([0, 0, 0, 0]));
126 run("1", Ipv4Addr::from([0, 0, 0, 1]));
127 }
128}