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 fmt::Display for Network {
16 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
17 match *self {
18 Network::V4(address, mask) => write!(fmt, "{}/{}", address, mask),
19 Network::V6(address, mask) => write!(fmt, "{}/{}", address, mask),
20 }
21 }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
27pub enum ScopedIp {
28 V4(Ipv4Addr),
30 V6(Ipv6Addr, Option<String>),
32}
33
34impl Into<IpAddr> for ScopedIp {
35 fn into(self) -> IpAddr {
36 match self {
37 ScopedIp::V4(ip) => IpAddr::from(ip),
38 ScopedIp::V6(ip, _) => IpAddr::from(ip),
39 }
40 }
41}
42
43impl<'a> Into<IpAddr> for &'a ScopedIp {
44 fn into(self) -> IpAddr {
45 match *self {
46 ScopedIp::V4(ref ip) => IpAddr::from(*ip),
47 ScopedIp::V6(ref ip, _) => IpAddr::from(*ip),
48 }
49 }
50}
51
52impl From<Ipv6Addr> for ScopedIp {
53 fn from(value: Ipv6Addr) -> Self {
54 ScopedIp::V6(value, None)
55 }
56}
57
58impl From<Ipv4Addr> for ScopedIp {
59 fn from(value: Ipv4Addr) -> Self {
60 ScopedIp::V4(value)
61 }
62}
63
64impl From<IpAddr> for ScopedIp {
65 fn from(value: IpAddr) -> Self {
66 match value {
67 IpAddr::V4(ip) => ScopedIp::from(ip),
68 IpAddr::V6(ip) => ScopedIp::from(ip),
69 }
70 }
71}
72
73impl FromStr for ScopedIp {
74 type Err = AddrParseError;
75 fn from_str(s: &str) -> Result<ScopedIp, AddrParseError> {
77 let mut parts = s.split('%');
78 let addr = parts.next().unwrap();
79 match IpAddr::from_str(addr) {
80 Ok(IpAddr::V4(ip)) => {
81 if parts.next().is_some() {
82 Err(AddrParseError)
84 } else {
85 Ok(ScopedIp::from(ip))
86 }
87 }
88 Ok(IpAddr::V6(ip)) => if let Some(scope_id) = parts.next() {
89 if scope_id.is_empty() {
90 return Err(AddrParseError);
91 }
92 for c in scope_id.chars() {
93 if !c.is_alphanumeric() {
94 return Err(AddrParseError);
95 }
96 }
97 Ok(ScopedIp::V6(ip, Some(scope_id.to_string())))
98 } else {
99 Ok(ScopedIp::V6(ip, None))
100 },
101 Err(e) => Err(e.into()),
102 }
103 }
104}
105
106impl fmt::Display for ScopedIp {
107 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
108 match *self {
109 ScopedIp::V4(ref address) => address.fmt(fmt),
110 ScopedIp::V6(ref address, None) => address.fmt(fmt),
111 ScopedIp::V6(ref address, Some(ref scope)) => write!(fmt, "{}%{}", address, scope),
112 }
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
118pub struct AddrParseError;
119
120impl fmt::Display for AddrParseError {
121 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
122 fmt.write_str(self.description())
123 }
124}
125
126impl Error for AddrParseError {
127 fn description(&self) -> &str {
128 "invalid IP address syntax"
129 }
130}
131
132impl From<::std::net::AddrParseError> for AddrParseError {
133 fn from(_: ::std::net::AddrParseError) -> Self {
134 AddrParseError
135 }
136}