use crate::proxy::ProxyScheme;
use std::{
fmt,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
};
#[derive(Clone, Hash, PartialEq, Eq, Default)]
pub enum NetworkScheme {
Scheme {
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
))]
interface: Option<std::borrow::Cow<'static, str>>,
addresses: (Option<Ipv4Addr>, Option<Ipv6Addr>),
proxy_scheme: Option<ProxyScheme>,
},
#[default]
Default,
}
impl NetworkScheme {
pub fn builder() -> NetworkSchemeBuilder {
NetworkSchemeBuilder::default()
}
#[inline(always)]
pub fn take_proxy_scheme(&mut self) -> Option<ProxyScheme> {
match self {
NetworkScheme::Scheme { proxy_scheme, .. } => proxy_scheme.take(),
_ => None,
}
}
#[inline(always)]
pub fn take_addresses(&mut self) -> (Option<Ipv4Addr>, Option<Ipv6Addr>) {
match self {
NetworkScheme::Scheme {
addresses: (ipv4, ipv6),
..
} => (ipv4.take(), ipv6.take()),
_ => (None, None),
}
}
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
))]
#[inline(always)]
pub fn take_interface(&mut self) -> Option<std::borrow::Cow<'static, str>> {
match self {
NetworkScheme::Scheme { interface, .. } => interface.take(),
_ => None,
}
}
}
impl fmt::Debug for NetworkScheme {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
NetworkScheme::Scheme {
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
))]
interface,
addresses,
proxy_scheme,
} => {
write!(f, "{{")?;
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
))]
if let Some(interface) = interface {
write!(f, " interface={:?},", interface)?;
}
if let Some(v4) = &addresses.0 {
write!(f, " ipv4={:?},", v4)?;
}
if let Some(v6) = &addresses.1 {
write!(f, " ipv6={:?},", v6)?;
}
if let Some(proxy) = proxy_scheme {
write!(f, " proxy={:?},", proxy)?;
}
write!(f, "}}")
}
NetworkScheme::Default => {
write!(f, "default")
}
}
}
}
#[derive(Clone, Debug, Default)]
pub struct NetworkSchemeBuilder {
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
))]
interface: Option<std::borrow::Cow<'static, str>>,
addresses: (Option<Ipv4Addr>, Option<Ipv6Addr>),
proxy_scheme: Option<ProxyScheme>,
}
impl NetworkSchemeBuilder {
#[inline]
pub fn address(&mut self, addr: impl Into<Option<IpAddr>>) -> &mut Self {
self.addresses = match addr.into() {
Some(IpAddr::V4(addr)) => (Some(addr), None),
Some(IpAddr::V6(addr)) => (None, Some(addr)),
_ => (None, None),
};
self
}
#[inline]
pub fn addresses<V4, V6>(&mut self, ipv4: V4, ipv6: V6) -> &mut Self
where
V4: Into<Option<Ipv4Addr>>,
V6: Into<Option<Ipv6Addr>>,
{
self.addresses = (ipv4.into(), ipv6.into());
self
}
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
))]
#[inline]
pub fn interface<I>(&mut self, interface: I) -> &mut Self
where
I: Into<std::borrow::Cow<'static, str>>,
{
self.interface = Some(interface.into());
self
}
#[inline]
pub fn proxy_scheme(&mut self, proxy: impl Into<Option<ProxyScheme>>) -> &mut Self {
self.proxy_scheme = proxy.into();
self
}
#[inline]
pub fn build(self) -> NetworkScheme {
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
))]
{
if matches!(
(&self.proxy_scheme, &self.addresses, &self.interface),
(None, (None, None), None)
) {
return NetworkScheme::Default;
}
NetworkScheme::Scheme {
interface: self.interface,
addresses: self.addresses,
proxy_scheme: self.proxy_scheme,
}
}
#[cfg(not(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
all(
feature = "apple-network-device-binding",
any(
target_os = "ios",
target_os = "visionos",
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
)
)
)))]
{
if matches!((&self.proxy_scheme, &self.addresses), (None, (None, None))) {
return NetworkScheme::Default;
}
NetworkScheme::Scheme {
addresses: self.addresses,
proxy_scheme: self.proxy_scheme,
}
}
}
}