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