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
use std::net::IpAddr;
use std::str::FromStr;
use crate::rr::{Name, RData};
pub trait TryParseIp {
fn try_parse_ip(&self) -> Option<RData>;
}
impl TryParseIp for str {
fn try_parse_ip(&self) -> Option<RData> {
match IpAddr::from_str(self) {
Ok(IpAddr::V4(ip4)) => Some(RData::A(ip4)),
Ok(IpAddr::V6(ip6)) => Some(RData::AAAA(ip6)),
Err(_) => None,
}
}
}
impl TryParseIp for String {
fn try_parse_ip(&self) -> Option<RData> {
let this = self as &str;
this.try_parse_ip()
}
}
impl TryParseIp for Name {
fn try_parse_ip(&self) -> Option<RData> {
None
}
}
impl<'a, T> TryParseIp for &'a T
where
T: TryParseIp + ?Sized,
{
fn try_parse_ip(&self) -> Option<RData> {
TryParseIp::try_parse_ip(*self)
}
}
#[test]
fn test_try_parse_ip() {
use std::net::{Ipv4Addr, Ipv6Addr};
assert_eq!(
"127.0.0.1".try_parse_ip().expect("failed"),
RData::A(Ipv4Addr::new(127, 0, 0, 1))
);
assert_eq!(
"::1".try_parse_ip().expect("failed"),
RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))
);
assert!("example.com".try_parse_ip().is_none());
}