use core::fmt;
use core::net::{Ipv4Addr, Ipv6Addr};
#[cfg(feature = "feat-uni-addr")]
use std::io;
#[cfg(feature = "feat-codec-decode")]
use crate::v1::Header;
#[cfg(feature = "feat-codec-v2")]
use crate::v2;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AddressPair {
Unspecified,
Inet {
src_ip: Ipv4Addr,
dst_ip: Ipv4Addr,
src_port: u16,
dst_port: u16,
},
Inet6 {
src_ip: Ipv6Addr,
dst_ip: Ipv6Addr,
src_port: u16,
dst_port: u16,
},
}
#[cfg(feature = "feat-codec-v2")]
impl TryFrom<v2::AddressPair> for AddressPair {
type Error = Unsupported;
fn try_from(value: v2::AddressPair) -> Result<Self, Self::Error> {
AddressPair::try_from_v2(value)
}
}
#[cfg(feature = "feat-codec-v2")]
#[derive(Debug)]
pub struct Unsupported;
#[cfg(feature = "feat-codec-v2")]
impl fmt::Display for Unsupported {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "unsupported address type")
}
}
impl AddressPair {
#[cfg(feature = "feat-codec-v2")]
#[inline]
pub const fn try_from_v2(value: v2::AddressPair) -> Result<Self, Unsupported> {
match value {
v2::AddressPair::Unspecified => Ok(Self::Unspecified),
v2::AddressPair::Inet {
src_ip,
dst_ip,
src_port,
dst_port,
} => Ok(Self::Inet {
src_ip,
dst_ip,
src_port,
dst_port,
}),
v2::AddressPair::Inet6 {
src_ip,
dst_ip,
src_port,
dst_port,
} => Ok(Self::Inet6 {
src_ip,
dst_ip,
src_port,
dst_port,
}),
v2::AddressPair::Unix { .. } => Err(Unsupported),
}
}
#[cfg(feature = "feat-uni-addr")]
pub fn src_uni_addr(&self) -> io::Result<Option<uni_addr::UniAddr>> {
use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
match self {
Self::Unspecified => Ok(None),
Self::Inet { src_ip, src_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V4(
SocketAddrV4::new(*src_ip, *src_port),
)))),
Self::Inet6 { src_ip, src_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V6(
SocketAddrV6::new(*src_ip, *src_port, 0, 0),
)))),
}
}
#[cfg(feature = "feat-uni-addr")]
pub fn dst_uni_addr(&self) -> io::Result<Option<uni_addr::UniAddr>> {
use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
match self {
Self::Unspecified => Ok(None),
Self::Inet { dst_ip, dst_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V4(
SocketAddrV4::new(*dst_ip, *dst_port),
)))),
Self::Inet6 { dst_ip, dst_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V6(
SocketAddrV6::new(*dst_ip, *dst_port, 0, 0),
)))),
}
}
}
#[cfg(feature = "feat-codec-decode")]
#[derive(Debug)]
pub enum Decoded {
Some(Header),
Partial,
None,
}