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