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 From<ScopedIp> for IpAddr {
35 fn from(val: ScopedIp) -> Self {
36 match val {
37 ScopedIp::V4(ip) => IpAddr::from(ip),
38 ScopedIp::V6(ip, _) => IpAddr::from(ip),
39 }
40 }
41}
42
43impl From<&ScopedIp> for IpAddr {
44 fn from(val: &ScopedIp) -> Self {
45 match *val {
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)) => {
89 if let Some(scope_id) = parts.next() {
90 if scope_id.is_empty() {
91 return Err(AddrParseError);
92 }
93 for c in scope_id.chars() {
94 if !c.is_alphanumeric() {
95 return Err(AddrParseError);
96 }
97 }
98 Ok(ScopedIp::V6(ip, Some(scope_id.to_string())))
99 } else {
100 Ok(ScopedIp::V6(ip, None))
101 }
102 }
103 Err(e) => Err(e.into()),
104 }
105 }
106}
107
108impl fmt::Display for ScopedIp {
109 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
110 match *self {
111 ScopedIp::V4(ref address) => address.fmt(fmt),
112 ScopedIp::V6(ref address, None) => address.fmt(fmt),
113 ScopedIp::V6(ref address, Some(ref scope)) => write!(fmt, "{}%{}", address, scope),
114 }
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct AddrParseError;
121
122impl fmt::Display for AddrParseError {
123 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
124 fmt.write_str("invalid IP address syntax")
125 }
126}
127
128impl Error for AddrParseError {}
129
130impl From<::std::net::AddrParseError> for AddrParseError {
131 fn from(_: ::std::net::AddrParseError) -> Self {
132 AddrParseError
133 }
134}