cidr/
local_addr_parser.rs1use core::str::FromStr;
2use std::net::{
3 AddrParseError,
4 IpAddr,
5 Ipv4Addr,
6 Ipv6Addr,
7};
8
9pub trait ParseableAddress: Sized {
10 fn address_from_str(s: &str) -> Result<Self, AddrParseError>;
11}
12
13fn special_ipv4_parser(s: &str) -> Option<Ipv4Addr> {
14 Some(
15 crate::parsers::parse_short_ipv4_address_as_cidr(s)
16 .ok()?
17 .first_address(),
18 )
19}
20
21impl ParseableAddress for Ipv4Addr {
22 fn address_from_str(s: &str) -> Result<Self, AddrParseError> {
23 match FromStr::from_str(s) {
24 Ok(addr) => Ok(addr),
25 Err(err) => match special_ipv4_parser(s) {
26 Some(addr) => Ok(addr),
27 None => Err(err),
28 },
29 }
30 }
31}
32
33impl ParseableAddress for Ipv6Addr {
34 fn address_from_str(s: &str) -> Result<Self, AddrParseError> {
35 FromStr::from_str(s)
36 }
37}
38
39impl ParseableAddress for IpAddr {
40 fn address_from_str(s: &str) -> Result<Self, AddrParseError> {
41 match FromStr::from_str(s) {
42 Ok(addr) => Ok(addr),
43 Err(err) => match special_ipv4_parser(s) {
44 Some(addr) => Ok(Self::V4(addr)),
45 None => Err(err),
46 },
47 }
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::ParseableAddress;
54 use std::net::{
55 IpAddr,
56 Ipv4Addr,
57 };
58
59 fn test_addr(s: &str, a: Ipv4Addr) {
60 assert_eq!(
61 Ipv4Addr::address_from_str(s).unwrap(),
62 a,
63 "{} didn't match {:?} (through Ipv4Addr)",
64 s,
65 a
66 );
67
68 assert_eq!(
69 IpAddr::address_from_str(s).unwrap(),
70 IpAddr::V4(a),
71 "{} didn't match {:?} (through IpAddr)",
72 s,
73 a
74 );
75 }
76
77 #[test]
78 fn invalid_short() {
79 assert!(IpAddr::address_from_str("").is_err());
80 assert!(Ipv4Addr::address_from_str("").is_err());
81 }
82
83 #[test]
84 fn short_10() {
85 test_addr("10", Ipv4Addr::new(10, 0, 0, 0));
86 test_addr("10.0", Ipv4Addr::new(10, 0, 0, 0));
87 test_addr("10.0.0", Ipv4Addr::new(10, 0, 0, 0));
88 test_addr("10.0.0.0", Ipv4Addr::new(10, 0, 0, 0));
89 }
90
91 #[test]
92 fn short_192_168() {
93 test_addr("192.168", Ipv4Addr::new(192, 168, 0, 0));
94 test_addr("192.168.0", Ipv4Addr::new(192, 168, 0, 0));
95 test_addr("192.168.0.0", Ipv4Addr::new(192, 168, 0, 0));
96 }
97
98 #[test]
99 fn short_192_0_2() {
100 test_addr("192.0.2", Ipv4Addr::new(192, 0, 2, 0));
101 test_addr("192.0.2.0", Ipv4Addr::new(192, 0, 2, 0));
102 }
103}