1use super::{Error, NetAddr, Result};
2use crate::Netv4Addr;
3use crate::Netv6Addr;
4use core::str::FromStr;
5
6impl FromStr for NetAddr {
7 type Err = Error;
8
9 fn from_str(string: &str) -> Result<Self> {
10 let as_v4: Result<Netv4Addr> = string.parse::<Netv4Addr>();
11 let as_v6: Result<Netv6Addr> = string.parse::<Netv6Addr>();
12
13 match (as_v4, as_v6) {
14 (Ok(v4), _) => Ok(Self::V4(v4)),
15 (_, Ok(v6)) => Ok(Self::V6(v6)),
16 (Err(_e4), Err(e6)) => Err(e6),
17 }
18 }
19}
20
21#[cfg(test)]
22mod tests {
23 use super::*;
24
25 #[test]
26 fn invalid_is_safe() {
27 let _: Result<NetAddr> = "zoop".parse::<NetAddr>();
28 }
29
30 #[test]
31 fn addr_only_returns_full_bitstring() {
32 let net: NetAddr = "127.0.0.1/zoop".parse().unwrap();
33 assert_eq!(net, "127.0.0.1/32".parse().unwrap());
34 let net: NetAddr = "ff02::1/zoop".parse().unwrap();
35 assert_eq!(net, "ff02::1/128".parse().unwrap());
36 }
37
38 #[test]
39 fn non_addr_passes_out_error() {
40 let result = "zoop".parse::<NetAddr>();
41 assert_eq!(
42 result,
43 Err(Error::ParseError(
44 "could not split provided input".to_string()
45 ))
46 );
47 }
48
49 mod v4 {
50 use super::NetAddr;
51 use std::net::{IpAddr, Ipv4Addr};
52
53 #[test]
54 fn cidr_32_correct_network_and_netmask() {
55 let net: NetAddr = "192.0.2.0/32".parse().unwrap();
56 assert_eq!(net.mask(), IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)));
57 assert_eq!(net.addr(), IpAddr::V4(Ipv4Addr::new(192, 0, 2, 0)));
58 }
59
60 #[test]
61 fn cidr_8_correct_network_and_netmask() {
62 let net: NetAddr = "127.0.0.1/8".parse().unwrap();
63 assert_eq!(net.mask(), IpAddr::V4(Ipv4Addr::new(255, 0, 0, 0)));
64 assert_eq!(net.addr(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 0)));
65 }
66
67 #[test]
68 fn cidr_22_correct_network_and_netmask() {
69 let net: NetAddr = "192.168.16.1/22".parse().unwrap();
70 assert_eq!(net.mask(), IpAddr::V4(Ipv4Addr::new(255, 255, 252, 0)));
71 assert_eq!(net.addr(), IpAddr::V4(Ipv4Addr::new(192, 168, 16, 0)));
72 }
73
74 #[test]
75 fn localhost_extended_correct_network_and_netmask() {
76 let net: NetAddr = "127.0.0.1 255.0.0.0".parse().unwrap();
77 assert_eq!(net.mask(), IpAddr::V4(Ipv4Addr::new(255, 0, 0, 0)));
78 assert_eq!(net.addr(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 0)));
79 }
80
81 #[test]
82 fn localhost_slashed_extended_correct_network_and_netmask() {
83 let net: NetAddr = "127.0.0.1/255.0.0.0".parse().unwrap();
84 assert_eq!(net.mask(), IpAddr::V4(Ipv4Addr::new(255, 0, 0, 0)));
85 assert_eq!(net.addr(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 0)));
86 }
87 }
88
89 mod v6 {
90 use super::NetAddr;
91 use std::net::{IpAddr, Ipv6Addr};
92
93 #[test]
94 fn cidr_8_correct_network_and_netmask() {
95 let net: NetAddr = "ff02::1/8".parse().unwrap();
96 assert_eq!(
97 net.mask(),
98 IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0x0000))
99 );
100 assert_eq!(
101 net.addr(),
102 IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0x0000))
103 );
104 }
105
106 #[test]
107 fn cidr_128_correct_network_and_netmask() {
108 let net: NetAddr = "ff02::1/128".parse().unwrap();
109 assert_eq!(
110 net.mask(),
111 IpAddr::V6(Ipv6Addr::new(
112 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
113 ))
114 );
115 assert_eq!(
116 net.addr(),
117 IpAddr::V6(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0x0001))
118 );
119 }
120
121 #[test]
122 fn extended_correct_network_and_netmask() {
123 let net: NetAddr = "ff02::1 ffff::0".parse().unwrap();
124 assert_eq!(
125 net.mask(),
126 IpAddr::V6(Ipv6Addr::new(0xffff, 0, 0, 0, 0, 0, 0, 0))
127 );
128 assert_eq!(
129 net.addr(),
130 IpAddr::V6(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0))
131 );
132 }
133
134 #[test]
135 fn extended_slashed_correct_network_and_netmask() {
136 let net: NetAddr = "ff02::1/128".parse().unwrap();
137 assert_eq!(
138 net.mask(),
139 IpAddr::V6(Ipv6Addr::new(
140 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
141 ))
142 );
143 assert_eq!(
144 net.addr(),
145 IpAddr::V6(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0x0001))
146 );
147 }
148 }
149}