1use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
14use itertools::Itertools;
15#[cfg(test)] use ::scanner::ScanFromStr;
16
17parse_scanner! { impl<'a> for Ipv4Addr, matcher match_ipv4, matcher err "expected IPv4 address", err map ScanError::other }
18parse_scanner! { impl<'a> for Ipv6Addr, matcher match_ipv6, matcher err "expected IPv6 address", err map ScanError::other }
19parse_scanner! { impl<'a> for SocketAddr, matcher match_sock_addr, matcher err "expected socket address", err map ScanError::other }
20
21fn match_ipv4(s: &str) -> Option<((usize, usize), usize)> {
22 let ibs = &mut s.bytes().enumerate();
23 try_opt!(eat_dec_digs(ibs));
24 if !matches!(ibs.next(), Some((_, b'.'))) { return None; }
25 try_opt!(eat_dec_digs(ibs));
26 if !matches!(ibs.next(), Some((_, b'.'))) { return None; }
27 try_opt!(eat_dec_digs(ibs));
28 if !matches!(ibs.next(), Some((_, b'.'))) { return None; }
29 eat_dec_digs(ibs)
30}
31
32fn match_ipv6(s: &str) -> Option<((usize, usize), usize)> {
33 fn eat_hex<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
61 let reset = ibs.clone();
62 ibs.take_while_ref(|&(_, b)|
63 matches!(b, b'0'...b'9' | b'a'...b'f' | b'A'...b'F'))
64 .last()
65 .map(|(i, _)| i + 1)
66 .map(|n| ((0, n), n))
67 .or_else(|| { *ibs = reset; None })
68 }
69
70 fn eat_dec<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
71 let reset = ibs.clone();
72 ibs.take_while_ref(|&(_, b)|
73 matches!(b, b'0'...b'9'))
74 .last()
75 .map(|(i, _)| i + 1)
76 .map(|n| ((0, n), n))
77 .or_else(|| { *ibs = reset; None })
78 }
79
80 fn eat_colon_hex<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
81 let reset = ibs.clone();
82 (|| {
83 if !matches!(ibs.next(), Some((_, b':'))) { return None; }
84 eat_hex(ibs)
85 })().or_else(|| { *ibs = reset; None })
86 }
87
88 fn eat_dbl_colon<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
89 let reset = ibs.clone();
90 (|| {
91 if !matches!(ibs.next(), Some((_, b':'))) { return None; }
92 match ibs.next() {
93 Some((i, b':')) => Some(((0, i + 1), i + 1)),
94 _ => None,
95 }
96 })().or_else(|| { *ibs = reset; None })
97 }
98
99 fn eat_ipv4<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
100 let reset = ibs.clone();
101 (|| {
102 let _ = try_opt!(eat_dec(ibs));
103 if !matches!(ibs.next(), Some((_, b'.'))) { return None; }
104 let _ = try_opt!(eat_dec(ibs));
105 if !matches!(ibs.next(), Some((_, b'.'))) { return None; }
106 let _ = try_opt!(eat_dec(ibs));
107 if !matches!(ibs.next(), Some((_, b'.'))) { return None; }
108 eat_dec(ibs)
109 })().or_else(|| { *ibs = reset; None })
110 }
111
112 fn eat_colon_ipv4<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
113 let reset = ibs.clone();
114 (|| {
115 if !matches!(ibs.next(), Some((_, b':'))) { return None; }
116 eat_ipv4(ibs)
117 })().or_else(|| { *ibs = reset; None })
118 }
119
120 fn start<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
121 if let Some(_) = eat_hex(ibs) {
122 one(ibs)
123 } else if let Some(end) = eat_dbl_colon(ibs) {
124 dbl_colon(ibs, end)
125 } else {
126 None
127 }
128 }
129
130 fn one<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
131 if let Some(end) = eat_colon_hex(ibs) {
132 one_plus(ibs, end)
133 } else {
134 None
135 }
136 }
137
138 fn one_plus<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I, mut end: ((usize, usize), usize)) -> Option<((usize, usize), usize)> {
139 loop {
140 if let Some(end) = eat_colon_ipv4(ibs) {
141 return Some(end);
142 } else if let Some(end) = eat_dbl_colon(ibs) {
143 return dbl_colon(ibs, end);
144 } else if let Some(new_end) = eat_colon_hex(ibs) {
145 end = new_end;
146 continue;
147 } else {
148 return Some(end);
149 }
150 }
151 }
152
153 fn dbl_colon<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I, end: ((usize, usize), usize)) -> Option<((usize, usize), usize)> {
154 if let Some(end) = eat_ipv4(ibs) {
155 Some(end)
156 } else if let Some(end) = eat_hex(ibs) {
157 dbl_colon_plus(ibs, end)
158 } else {
159 Some(end)
160 }
161 }
162
163 fn dbl_colon_plus<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I, mut end: ((usize, usize), usize)) -> Option<((usize, usize), usize)> {
164 loop {
165 if let Some(end) = eat_colon_ipv4(ibs) {
166 return Some(end);
167 } else if let Some(new_end) = eat_colon_hex(ibs) {
168 end = new_end;
169 continue;
170 } else {
171 return Some(end);
172 }
173 }
174 }
175
176 let mut ibs = s.bytes().enumerate();
177 match start(&mut ibs) {
178 res => {
179 res
180 }
181 }
182}
183
184fn match_sock_addr(s: &str) -> Option<((usize, usize), usize)> {
185 match_ipv4_sock(s)
186 .or_else(|| match_ipv6_sock(s))
187}
188
189fn match_ipv4_sock(s: &str) -> Option<((usize, usize), usize)> {
190 let ((_, _), off) = try_opt!(match_ipv4(s));
191 let mut ibs = s[off..].bytes().enumerate();
192 if !matches!(ibs.next(), Some((_, b':'))) { return None; }
193 eat_dec_digs(&mut ibs)
194 .map(|((_, b), c)| ((0, b + off), c + off))
195}
196
197fn match_ipv6_sock(s: &str) -> Option<((usize, usize), usize)> {
198 if !s.starts_with("[") { return None; }
199 let ((_, _), off) = try_opt!(match_ipv6(&s[1..]));
200 let off = off + 1;
201 let mut ibs = s[off..].bytes().enumerate();
202 if !matches!(ibs.next(), Some((_, b']'))) { return None; }
203 if !matches!(ibs.next(), Some((_, b':'))) { return None; }
204 eat_dec_digs(&mut ibs)
205 .map(|((_, b), c)| ((0, b + off), c + off))
206}
207
208fn eat_dec_digs<I: Clone + Iterator<Item=(usize, u8)>>(ibs: &mut I) -> Option<((usize, usize), usize)> {
209 ibs.take_while_ref(|&(_, b)| matches!(b, b'0'...b'9'))
210 .last()
211 .map(|(i, _)| i + 1)
212 .map(|n| ((0, n), n))
213}
214
215#[cfg(test)]
216#[test]
217fn test_scan_ipv4addr() {
218 use ::ScanError as SE;
219 use ::ScanErrorKind as SEK;
220
221 macro_rules! check_ipv4 {
222 ($s:expr) => {
223 assert_match!(
224 <Ipv4Addr>::scan_from($s),
225 Ok((v, n)) if v == $s.parse().unwrap() && n == $s.len()
226 )
227 };
228
229 ($s:expr; Ok($v:expr)) => {
230 assert_match!(
231 <Ipv4Addr>::scan_from($s),
232 Ok((v, n)) if v == $v.parse().unwrap() && n == $v.len()
233 )
234 };
235
236 ($s:expr; Err($err:pat)) => {
237 assert_match!(
238 <Ipv4Addr>::scan_from($s),
239 Err($err)
240 )
241 };
242 }
243
244 check_ipv4!("0.0.0.0");
245 check_ipv4!("127.0.0.1");
246 check_ipv4!("255.255.255.255");
247
248 check_ipv4!("256.0.0.1"; Err(SE { kind: SEK::Other(_), .. }));
249 check_ipv4!("255.0.0"; Err(SE { kind: SEK::Syntax(_), .. }));
250 check_ipv4!("255.0.0.1.2"; Ok("255.0.0.1"));
251 check_ipv4!("255.0..1"; Err(SE { kind: SEK::Syntax(_), .. }));
252}
253
254#[cfg(test)]
255#[test]
256fn test_scan_ipv6addr() {
257 use ::ScanError as SE;
258 use ::ScanErrorKind as SEK;
259
260 macro_rules! check_ipv6 {
261 ($s:expr) => {
262 assert_match!(
263 <Ipv6Addr>::scan_from($s),
264 Ok((v, n)) if v == $s.parse().unwrap() && n == $s.len()
265 )
266 };
267
268 ($s:expr; Ok($v:expr)) => {
269 assert_match!(
270 <Ipv6Addr>::scan_from($s),
271 Ok((v, n)) if v == $v.parse().unwrap() && n == $v.len()
272 )
273 };
274
275 ($s:expr; Err($err:pat)) => {
276 assert_match!(
277 <Ipv6Addr>::scan_from($s),
278 Err($err)
279 )
280 };
281 }
282
283 check_ipv6!("0:0:0:0:0:0:0:0");
284 check_ipv6!("0:0:0:0:0:0:0:1");
285 check_ipv6!("::1");
286 check_ipv6!("::");
287 check_ipv6!("2a02:6b8::11:11");
288
289 check_ipv6!("::00000"; Err(SE { kind: SEK::Other(_), .. }));
290 check_ipv6!("1:2:3:4:5:6:7"; Err(SE { kind: SEK::Other(_), .. }));
291 check_ipv6!("1:2:3:4:5:6:7:8:9"; Err(SE { kind: SEK::Other(_), .. }));
292 check_ipv6!("1:2:::6:7:8"; Ok("1:2::"));
293 check_ipv6!("1:2::6::8"; Ok("1:2::6"));
294
295 check_ipv6!("::192.0.2.33");
296 check_ipv6!("::FFFF:192.0.2.33");
297 check_ipv6!("64:ff9b::192.0.2.33");
298 check_ipv6!("2001:db8:122:c000:2:2100:192.0.2.33");
299
300 check_ipv6!("::127.0.0.1:"; Ok("::127.0.0.1"));
301 check_ipv6!("1:2:3:4:5:127.0.0.1"; Err(SE { kind: SEK::Other(_), .. }));
302 check_ipv6!("1:2:3:4:5:6:7:127.0.0.1"; Err(SE { kind: SEK::Other(_), .. }));
303}
304
305#[cfg(test)]
306#[test]
307fn test_scan_socketaddr() {
308 use ::ScanError as SE;
309 use ::ScanErrorKind as SEK;
310
311 macro_rules! check_sockaddr {
312 ($s:expr) => {
313 assert_match!(
314 <SocketAddr>::scan_from($s),
315 Ok((v, n)) if v == $s.parse().unwrap() && n == $s.len()
316 )
317 };
318
319 ($s:expr; Ok($v:expr)) => {
320 assert_match!(
321 <SocketAddr>::scan_from($s),
322 Ok((v, n)) if v == $v.parse().unwrap() && n == $v.len()
323 )
324 };
325
326 ($s:expr; Err($err:pat)) => {
327 assert_match!(
328 <SocketAddr>::scan_from($s),
329 Err($err)
330 )
331 };
332 }
333
334 check_sockaddr!("0.0.0.0:0");
335 check_sockaddr!("127.0.0.1:80");
336 check_sockaddr!("255.255.255.255:65535");
337 check_sockaddr!("255.255.255.255:65536"; Err(SE { kind: SEK::Other(_), .. }));
338
339 check_sockaddr!("[0:0:0:0:0:0:0:0]:0");
340 check_sockaddr!("[0:0:0:0:0:0:0:1]:0");
341 check_sockaddr!("[::1]:0");
342 check_sockaddr!("[::]:0");
343 check_sockaddr!("[2a02:6b8::11:11]:0");
344}
345
346mod socket_addr_vx_scanners {
347 use std::net::{SocketAddrV4, SocketAddrV6};
348 use super::{match_ipv4_sock, match_ipv6_sock};
349 #[cfg(test)] use ::scanner::ScanFromStr;
350
351 parse_scanner! { impl<'a> for SocketAddrV4, matcher match_ipv4_sock, matcher err "expected IPv4 socket address", err map ScanError::other }
352 parse_scanner! { impl<'a> for SocketAddrV6, matcher match_ipv6_sock, matcher err "expected IPv6 socket address", err map ScanError::other }
353
354 #[cfg(test)]
355 #[test]
356 fn test_scan_socketaddrv4() {
357 use ::ScanError as SE;
358 use ::ScanErrorKind as SEK;
359
360 macro_rules! check_ipv4 {
361 ($s:expr) => {
362 assert_match!(
363 <SocketAddrV4>::scan_from($s),
364 Ok((v, n)) if v == $s.parse().unwrap() && n == $s.len()
365 )
366 };
367
368 ($s:expr; Ok($v:expr)) => {
369 assert_match!(
370 <SocketAddrV4>::scan_from($s),
371 Ok((v, n)) if v == $v.parse().unwrap() && n == $v.len()
372 )
373 };
374
375 ($s:expr; Err($err:pat)) => {
376 assert_match!(
377 <SocketAddrV4>::scan_from($s),
378 Err($err)
379 )
380 };
381 }
382
383 check_ipv4!("0.0.0.0:0");
384 check_ipv4!("127.0.0.1:80");
385 check_ipv4!("255.255.255.255:65535");
386 check_ipv4!("255.255.255.255:65536"; Err(SE { kind: SEK::Other(_), .. }));
387 }
388
389 #[cfg(test)]
390 #[test]
391 fn test_scan_socketaddrv6() {
392 macro_rules! check_ipv6 {
393 ($s:expr) => {
394 assert_match!(
395 <SocketAddrV6>::scan_from($s),
396 Ok((v, n)) if v == $s.parse().unwrap() && n == $s.len()
397 )
398 };
399
400 ($s:expr; Ok($v:expr)) => {
401 assert_match!(
402 <SocketAddrV6>::scan_from($s),
403 Ok((v, n)) if v == $v.parse().unwrap() && n == $v.len()
404 )
405 };
406
407 ($s:expr; Err($err:pat)) => {
408 assert_match!(
409 <SocketAddrV6>::scan_from($s),
410 Err($err)
411 )
412 };
413 }
414
415 check_ipv6!("[0:0:0:0:0:0:0:0]:0");
416 check_ipv6!("[0:0:0:0:0:0:0:1]:0");
417 check_ipv6!("[::1]:0");
418 check_ipv6!("[::]:0");
419 check_ipv6!("[2a02:6b8::11:11]:0");
420 }
421}