Coverage Report

Created: 2025-02-25 06:39

/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
}