1use std::error::Error;
2use std::fmt;
3use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4use std::str::FromStr;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum Network {
9 V4(Ipv4Addr, Ipv4Addr),
11 V6(Ipv6Addr, Ipv6Addr),
13}
14
15impl FromStr for Network {
16 type Err = AddrParseError;
17
18 fn from_str(val: &str) -> Result<Self, Self::Err> {
19 let (ip, mask) = match val.split_once('/') {
20 Some((ip, mask)) => (ip, Some(mask)),
21 None => (val, None),
22 };
23
24 match IpAddr::from_str(ip)? {
25 IpAddr::V4(ip) => {
26 if ip.is_unspecified() {
27 return Err(AddrParseError);
28 }
29
30 let mask = match mask {
31 Some(mask) => {
32 let mask = Ipv4Addr::from_str(mask)?;
33 let value = ip.octets().iter().fold(0, |acc, &x| acc + u32::from(x));
35 match value == 0 || (value & !value != 0) {
36 true => return Err(AddrParseError),
37 false => mask,
38 }
39 }
40 None => {
52 let octets = ip.octets();
53 if octets[3] == 0 {
54 if octets[2] == 0 {
55 if octets[1] == 0 {
56 Ipv4Addr::new(255, 0, 0, 0)
57 } else {
58 Ipv4Addr::new(255, 255, 0, 0)
59 }
60 } else {
61 Ipv4Addr::new(255, 255, 255, 0)
62 }
63 } else {
64 Ipv4Addr::new(255, 255, 255, 255)
65 }
66 }
67 };
68
69 Ok(Self::V4(ip, mask))
70 }
71 IpAddr::V6(ip) => {
72 let mask = match mask {
73 Some(mask) => Ipv6Addr::from_str(mask)?,
75 None => Ipv6Addr::new(
77 65_535, 65_535, 65_535, 65_535, 65_535, 65_535, 65_535, 65_535,
78 ),
79 };
80
81 Ok(Self::V6(ip, mask))
82 }
83 }
84 }
85}
86
87impl fmt::Display for Network {
88 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
89 match *self {
90 Self::V4(address, mask) => write!(fmt, "{address}/{mask}"),
91 Self::V6(address, mask) => write!(fmt, "{address}/{mask}"),
92 }
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq)]
99pub enum ScopedIp {
100 V4(Ipv4Addr),
102 V6(Ipv6Addr, Option<String>),
104}
105
106impl From<ScopedIp> for IpAddr {
107 fn from(val: ScopedIp) -> Self {
108 match val {
109 ScopedIp::V4(ip) => Self::from(ip),
110 ScopedIp::V6(ip, _) => Self::from(ip),
111 }
112 }
113}
114
115impl From<&ScopedIp> for IpAddr {
116 fn from(val: &ScopedIp) -> Self {
117 match val {
118 ScopedIp::V4(ip) => Self::from(*ip),
119 ScopedIp::V6(ip, _) => Self::from(*ip),
120 }
121 }
122}
123
124impl From<Ipv6Addr> for ScopedIp {
125 fn from(value: Ipv6Addr) -> Self {
126 Self::V6(value, None)
127 }
128}
129
130impl From<Ipv4Addr> for ScopedIp {
131 fn from(value: Ipv4Addr) -> Self {
132 Self::V4(value)
133 }
134}
135
136impl From<IpAddr> for ScopedIp {
137 fn from(value: IpAddr) -> Self {
138 match value {
139 IpAddr::V4(ip) => Self::from(ip),
140 IpAddr::V6(ip) => Self::from(ip),
141 }
142 }
143}
144
145impl FromStr for ScopedIp {
146 type Err = AddrParseError;
147 fn from_str(s: &str) -> Result<Self, AddrParseError> {
149 let mut parts = s.split('%');
150 let addr = parts.next().unwrap();
151 match IpAddr::from_str(addr) {
152 Ok(IpAddr::V4(ip)) => {
153 if parts.next().is_some() {
154 Err(AddrParseError)
156 } else {
157 Ok(Self::from(ip))
158 }
159 }
160 Ok(IpAddr::V6(ip)) => {
161 if let Some(scope_id) = parts.next() {
162 if scope_id.is_empty() {
163 return Err(AddrParseError);
164 }
165 for c in scope_id.chars() {
166 if !c.is_alphanumeric() {
167 return Err(AddrParseError);
168 }
169 }
170 Ok(Self::V6(ip, Some(scope_id.to_string())))
171 } else {
172 Ok(Self::V6(ip, None))
173 }
174 }
175 Err(e) => Err(e.into()),
176 }
177 }
178}
179
180impl fmt::Display for ScopedIp {
181 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
182 match self {
183 Self::V4(address) => address.fmt(fmt),
184 Self::V6(address, None) => address.fmt(fmt),
185 Self::V6(address, Some(scope)) => write!(fmt, "{address}%{scope}"),
186 }
187 }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
192pub struct AddrParseError;
193
194impl fmt::Display for AddrParseError {
195 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
196 fmt.write_str("invalid IP address syntax")
197 }
198}
199
200impl Error for AddrParseError {}
201
202impl From<::std::net::AddrParseError> for AddrParseError {
203 fn from(_: ::std::net::AddrParseError) -> Self {
204 Self
205 }
206}