1use std::{
4 fmt::{self, Display, Formatter},
5 net::{IpAddr, Ipv4Addr, Ipv6Addr},
6 str::FromStr,
7};
8
9use str_reader::StringReader;
10
11use crate::{NetworkType, ParseError};
12
13#[derive(Clone)]
15pub struct ConnectionInfo {
16 network_type: NetworkType,
17 address: ConnectionAddress,
18}
19
20impl ConnectionInfo {
21 #[inline]
23 pub fn new<T>(network_type: NetworkType, address: T) -> Self
24 where
25 T: Into<ConnectionAddress>,
26 {
27 let address = address.into();
28
29 Self {
30 network_type,
31 address,
32 }
33 }
34
35 #[inline]
37 pub fn network_type(&self) -> &NetworkType {
38 &self.network_type
39 }
40
41 #[inline]
43 pub fn address(&self) -> &ConnectionAddress {
44 &self.address
45 }
46}
47
48impl Display for ConnectionInfo {
49 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
50 write!(f, "{} {}", self.network_type, self.address)
51 }
52}
53
54impl FromStr for ConnectionInfo {
55 type Err = ParseError;
56
57 fn from_str(s: &str) -> Result<Self, Self::Err> {
58 let mut reader = StringReader::new(s);
59
60 let network_type = reader.parse_word()?;
61 let address = reader.as_str().parse()?;
62
63 let res = Self {
64 network_type,
65 address,
66 };
67
68 Ok(res)
69 }
70}
71
72#[derive(Clone)]
74pub enum ConnectionAddress {
75 IPv4(IPv4Address),
76 IPv6(IPv6Address),
77 Other(OtherAddress),
78}
79
80impl ConnectionAddress {
81 #[inline]
83 pub fn unicast<A>(addr: A) -> Self
84 where
85 A: Into<IpAddr>,
86 {
87 match addr.into() {
88 IpAddr::V4(addr) => Self::IPv4(IPv4Address::unicast(addr)),
89 IpAddr::V6(addr) => Self::IPv6(IPv6Address::unicast(addr)),
90 }
91 }
92}
93
94impl Display for ConnectionAddress {
95 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
96 match self {
97 Self::IPv4(addr) => write!(f, "IP4 {addr}"),
98 Self::IPv6(addr) => write!(f, "IP6 {addr}"),
99 Self::Other(addr) => write!(f, "{} {}", addr.address_type, addr),
100 }
101 }
102}
103
104impl FromStr for ConnectionAddress {
105 type Err = ParseError;
106
107 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 let mut reader = StringReader::new(s);
109
110 let address_type = reader.read_word();
111 let address = reader.as_str();
112
113 let res = match address_type {
114 "IP4" => Self::IPv4(address.parse()?),
115 "IP6" => Self::IPv6(address.parse()?),
116 _ => Self::Other(OtherAddress::new(address_type, address.trim())),
117 };
118
119 Ok(res)
120 }
121}
122
123impl From<IPv4Address> for ConnectionAddress {
124 #[inline]
125 fn from(addr: IPv4Address) -> Self {
126 Self::IPv4(addr)
127 }
128}
129
130impl From<IPv6Address> for ConnectionAddress {
131 #[inline]
132 fn from(addr: IPv6Address) -> Self {
133 Self::IPv6(addr)
134 }
135}
136
137impl From<OtherAddress> for ConnectionAddress {
138 #[inline]
139 fn from(addr: OtherAddress) -> Self {
140 Self::Other(addr)
141 }
142}
143
144#[derive(Copy, Clone)]
146pub struct IPv4Address {
147 address: Ipv4Addr,
148 ttl: Option<u8>,
149 count: Option<u32>,
150}
151
152impl IPv4Address {
153 #[inline]
155 pub const fn unicast(address: Ipv4Addr) -> Self {
156 Self {
157 address,
158 ttl: None,
159 count: None,
160 }
161 }
162
163 #[inline]
165 pub const fn multicast(address: Ipv4Addr, ttl: u8, count: Option<u32>) -> Self {
166 Self {
167 address,
168 ttl: Some(ttl),
169 count,
170 }
171 }
172
173 #[inline]
175 pub fn address(&self) -> Ipv4Addr {
176 self.address
177 }
178
179 #[inline]
181 pub fn ttl(&self) -> Option<u8> {
182 self.ttl
183 }
184
185 #[inline]
187 pub fn count(&self) -> Option<u32> {
188 self.count
189 }
190}
191
192impl Display for IPv4Address {
193 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
194 write!(f, "{}", self.address)?;
195
196 if let Some(ttl) = self.ttl {
197 write!(f, "/{ttl}")?;
198
199 if let Some(count) = self.count {
200 write!(f, "/{count}")?;
201 }
202 }
203
204 Ok(())
205 }
206}
207
208impl FromStr for IPv4Address {
209 type Err = ParseError;
210
211 fn from_str(s: &str) -> Result<Self, Self::Err> {
212 let mut reader = StringReader::new(s);
213
214 let address = reader.parse_word()?;
215
216 reader.skip_whitespace();
217
218 let ttl = if reader.is_empty() {
219 None
220 } else {
221 reader.match_char('/')?;
222
223 Some(reader.read_u8()?)
224 };
225
226 reader.skip_whitespace();
227
228 let count = if reader.is_empty() {
229 None
230 } else {
231 reader.match_char('/')?;
232
233 Some(reader.read_u32()?)
234 };
235
236 reader.skip_whitespace();
237
238 if !reader.is_empty() {
239 return Err(ParseError::plain());
240 }
241
242 let res = Self {
243 address,
244 ttl,
245 count,
246 };
247
248 Ok(res)
249 }
250}
251
252#[derive(Copy, Clone)]
254pub struct IPv6Address {
255 address: Ipv6Addr,
256 count: Option<u32>,
257}
258
259impl IPv6Address {
260 #[inline]
262 pub const fn unicast(address: Ipv6Addr) -> Self {
263 Self {
264 address,
265 count: None,
266 }
267 }
268
269 #[inline]
271 pub const fn multicast(address: Ipv6Addr, count: Option<u32>) -> Self {
272 Self { address, count }
273 }
274
275 #[inline]
277 pub fn address(&self) -> Ipv6Addr {
278 self.address
279 }
280
281 #[inline]
283 pub fn count(&self) -> Option<u32> {
284 self.count
285 }
286}
287
288impl Display for IPv6Address {
289 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
290 write!(f, "{}", self.address)?;
291
292 if let Some(count) = self.count {
293 write!(f, "/{count}")?;
294 }
295
296 Ok(())
297 }
298}
299
300impl FromStr for IPv6Address {
301 type Err = ParseError;
302
303 fn from_str(s: &str) -> Result<Self, Self::Err> {
304 let mut reader = StringReader::new(s);
305
306 let address = reader.parse_word()?;
307
308 reader.skip_whitespace();
309
310 let count = if reader.is_empty() {
311 None
312 } else {
313 reader.match_char('/')?;
314
315 Some(reader.read_u32()?)
316 };
317
318 reader.skip_whitespace();
319
320 if !reader.is_empty() {
321 return Err(ParseError::plain());
322 }
323
324 let res = Self { address, count };
325
326 Ok(res)
327 }
328}
329
330#[derive(Clone)]
332pub struct OtherAddress {
333 address_type: String,
334 address: String,
335}
336
337impl OtherAddress {
338 #[inline]
340 pub fn new<T, A>(address_type: T, address: A) -> Self
341 where
342 T: ToString,
343 A: ToString,
344 {
345 Self {
346 address_type: address_type.to_string(),
347 address: address.to_string(),
348 }
349 }
350
351 #[inline]
353 pub fn address_type(&self) -> &str {
354 &self.address_type
355 }
356
357 #[inline]
359 pub fn address(&self) -> &str {
360 &self.address
361 }
362}
363
364impl Display for OtherAddress {
365 #[inline]
366 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
367 f.write_str(&self.address)
368 }
369}