1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
23use std::str::FromStr;
24
25use crate::{AddrParseError, Host, Localhost};
26
27#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, From)]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32#[display(inner)]
33#[cfg(feature = "dns")]
34pub enum InetHost {
35 #[from]
37 #[from(Ipv4Addr)]
38 #[from(Ipv6Addr)]
39 Ip(IpAddr),
40
41 Dns(String),
43}
44
45#[cfg(feature = "dns")]
46impl Host for InetHost {
47 fn requires_proxy(&self) -> bool { false }
48}
49
50#[cfg(feature = "dns")]
51impl Localhost for InetHost {
52 fn localhost() -> Self { Self::Ip(Localhost::localhost()) }
53}
54
55#[cfg(feature = "dns")]
56impl FromStr for InetHost {
57 type Err = AddrParseError;
58
59 fn from_str(s: &str) -> Result<Self, Self::Err> {
60 match IpAddr::from_str(s) {
61 Ok(addr) => Ok(Self::Ip(addr)),
62 Err(_) => Ok(Self::Dns(s.to_owned())),
64 }
65 }
66}
67
68#[derive(Clone, PartialEq, Eq, Hash, Debug, Display, From)]
73#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
74#[display(inner)]
75#[non_exhaustive]
76pub enum HostName {
77 #[from]
78 #[from(Ipv4Addr)]
79 #[from(Ipv6Addr)]
80 Ip(IpAddr),
81
82 #[cfg(feature = "dns")]
83 Dns(String),
84
85 #[cfg(feature = "tor")]
86 #[from]
87 Tor(super::tor::OnionAddrV3),
88
89 #[cfg(feature = "i2p")]
90 #[from]
91 I2p(super::i2p::I2pAddr),
92
93 #[cfg(feature = "nym")]
94 #[from]
95 Nym(super::nym::NymAddr),
96}
97
98impl Host for HostName {
99 fn requires_proxy(&self) -> bool {
100 match self {
101 HostName::Ip(_) => false,
102 #[cfg(feature = "dns")]
103 HostName::Dns(_) => false,
104 #[allow(unreachable_patterns)]
105 _ => true,
106 }
107 }
108}
109
110impl Localhost for HostName {
111 fn localhost() -> Self { Self::Ip(Localhost::localhost()) }
112}
113
114#[cfg(feature = "dns")]
115impl From<InetHost> for HostName {
116 fn from(host: InetHost) -> Self {
117 match host {
118 InetHost::Ip(ip) => HostName::Ip(ip),
119 InetHost::Dns(dns) => HostName::Dns(dns),
120 }
121 }
122}
123
124impl FromStr for HostName {
125 type Err = AddrParseError;
126
127 fn from_str(s: &str) -> Result<Self, Self::Err> {
128 if let Ok(addr) = IpAddr::from_str(s) {
129 return Ok(Self::Ip(addr));
130 }
131 #[cfg(feature = "tor")]
132 if s.ends_with(".onion") {
133 return super::tor::OnionAddrV3::from_str(s)
134 .map(Self::Tor)
135 .map_err(AddrParseError::from);
136 }
137 #[cfg(feature = "dns")]
139 {
140 Ok(Self::Dns(s.to_owned()))
141 }
142 #[cfg(not(feature = "dns"))]
143 {
144 Err(AddrParseError::UnknownAddressFormat)
145 }
146 }
147}