use core::{fmt, option, str};
use crate::{
io::Write,
net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr},
};
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum SocketAddr {
V4(SocketAddrV4),
V6(SocketAddrV6),
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SocketAddrV4 {
ip: Ipv4Addr,
port: u16,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SocketAddrV6 {
ip: Ipv6Addr,
port: u16,
flowinfo: u32,
scope_id: u32,
}
impl SocketAddr {
pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
match ip {
IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
}
}
pub const fn ip(&self) -> IpAddr {
match *self {
SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
}
}
pub fn set_ip(&mut self, new_ip: IpAddr) {
match (self, new_ip) {
(&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip),
(&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip),
(self_, new_ip) => *self_ = Self::new(new_ip, self_.port()),
}
}
pub const fn port(&self) -> u16 {
match *self {
SocketAddr::V4(ref a) => a.port(),
SocketAddr::V6(ref a) => a.port(),
}
}
pub fn set_port(&mut self, new_port: u16) {
match *self {
SocketAddr::V4(ref mut a) => a.set_port(new_port),
SocketAddr::V6(ref mut a) => a.set_port(new_port),
}
}
pub const fn is_ipv4(&self) -> bool {
matches!(*self, SocketAddr::V4(_))
}
pub const fn is_ipv6(&self) -> bool {
matches!(*self, SocketAddr::V6(_))
}
}
impl SocketAddrV4 {
pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
SocketAddrV4 { ip, port }
}
pub const fn ip(&self) -> &Ipv4Addr {
&self.ip
}
pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
self.ip = new_ip
}
pub const fn port(&self) -> u16 {
self.port
}
pub fn set_port(&mut self, new_port: u16) {
self.port = new_port
}
}
impl SocketAddrV6 {
pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
SocketAddrV6 {
ip,
port,
flowinfo,
scope_id,
}
}
pub const fn ip(&self) -> &Ipv6Addr {
&self.ip
}
pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
self.ip = new_ip
}
pub const fn port(&self) -> u16 {
self.port
}
pub fn set_port(&mut self, new_port: u16) {
self.port = new_port
}
pub const fn flowinfo(&self) -> u32 {
self.flowinfo
}
pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
self.flowinfo = new_flowinfo
}
pub const fn scope_id(&self) -> u32 {
self.scope_id
}
pub fn set_scope_id(&mut self, new_scope_id: u32) {
self.scope_id = new_scope_id
}
}
impl From<SocketAddrV4> for SocketAddr {
fn from(sock4: SocketAddrV4) -> SocketAddr {
SocketAddr::V4(sock4)
}
}
impl From<SocketAddrV6> for SocketAddr {
fn from(sock6: SocketAddrV6) -> SocketAddr {
SocketAddr::V6(sock6)
}
}
impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
fn from(pieces: (I, u16)) -> SocketAddr {
SocketAddr::new(pieces.0.into(), pieces.1)
}
}
impl fmt::Display for SocketAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
SocketAddr::V4(ref a) => a.fmt(f),
SocketAddr::V6(ref a) => a.fmt(f),
}
}
}
impl fmt::Debug for SocketAddr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, fmt)
}
}
impl fmt::Display for SocketAddrV4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.precision().is_none() && f.width().is_none() {
write!(f, "{}:{}", self.ip(), self.port())
} else {
const IPV4_SOCKET_BUF_LEN: usize = (3 * 4) + 3 + 1 + 5; let mut buf = [0; IPV4_SOCKET_BUF_LEN];
let mut buf_slice = &mut buf[..];
write!(buf_slice, "{}:{}", self.ip(), self.port()).unwrap();
let len = IPV4_SOCKET_BUF_LEN - buf_slice.len();
let buf = unsafe { str::from_utf8_unchecked(&buf[..len]) };
f.pad(buf)
}
}
}
impl fmt::Debug for SocketAddrV4 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, fmt)
}
}
impl fmt::Display for SocketAddrV6 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.precision().is_none() && f.width().is_none() {
match self.scope_id() {
0 => write!(f, "[{}]:{}", self.ip(), self.port()),
scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
}
} else {
const IPV6_SOCKET_BUF_LEN: usize = (4 * 8) + 7 + 2 + 1 + 10 + 1 + 5;
let mut buf = [0; IPV6_SOCKET_BUF_LEN];
let mut buf_slice = &mut buf[..];
match self.scope_id() {
0 => write!(buf_slice, "[{}]:{}", self.ip(), self.port()),
scope_id => write!(buf_slice, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
}
.unwrap();
let len = IPV6_SOCKET_BUF_LEN - buf_slice.len();
let buf = unsafe { str::from_utf8_unchecked(&buf[..len]) };
f.pad(buf)
}
}
}
impl fmt::Debug for SocketAddrV6 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, fmt)
}
}
pub trait GetSocketAddrs {
type Iter: Iterator<Item = SocketAddr>;
type Error: From<AddrParseError>;
fn get_socket_addrs(&self, host: &str, port: u16) -> Result<Self::Iter, Self::Error>;
}
pub enum OneOrMany<I: Iterator> {
One(option::IntoIter<I::Item>),
Many(I),
}
impl<I: Iterator> OneOrMany<I> {
pub fn one(item: I::Item) -> Self {
Self::One(Some(item).into_iter())
}
}
pub trait ToSocketAddrs<T: GetSocketAddrs> {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error>;
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for SocketAddr {
fn to_socket_addrs(&self, _get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
Ok(OneOrMany::one(*self))
}
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for SocketAddrV4 {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
SocketAddr::V4(*self).to_socket_addrs(get)
}
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for SocketAddrV6 {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
SocketAddr::V6(*self).to_socket_addrs(get)
}
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for (IpAddr, u16) {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
let (ip, port) = *self;
match ip {
IpAddr::V4(ref a) => (*a, port).to_socket_addrs(get),
IpAddr::V6(ref a) => (*a, port).to_socket_addrs(get),
}
}
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for (Ipv4Addr, u16) {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
let (ip, port) = *self;
SocketAddrV4::new(ip, port).to_socket_addrs(get)
}
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for (Ipv6Addr, u16) {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
let (ip, port) = *self;
SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs(get)
}
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for (&str, u16) {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
let (host, port) = *self;
if let Ok(addr) = host.parse::<Ipv4Addr>() {
let addr = SocketAddrV4::new(addr, port);
return Ok(OneOrMany::one(SocketAddr::V4(addr)));
}
if let Ok(addr) = host.parse::<Ipv6Addr>() {
let addr = SocketAddrV6::new(addr, port, 0, 0);
return Ok(OneOrMany::one(SocketAddr::V6(addr)));
}
get.get_socket_addrs(host, port)
.map(|iter| OneOrMany::Many(iter))
}
}
impl<T: GetSocketAddrs> ToSocketAddrs<T> for str {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
if let Ok(addr) = self.parse() {
return Ok(OneOrMany::one(addr));
}
let (host, port_str) = self.rsplit_once(':').ok_or(AddrParseError(()))?;
let port: u16 = port_str.parse().map_err(|_| AddrParseError(()))?;
get.get_socket_addrs(host, port)
.map(|iter| OneOrMany::Many(iter))
}
}
impl<T: GetSocketAddrs, U: ToSocketAddrs<T> + ?Sized> ToSocketAddrs<T> for &U {
fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
(**self).to_socket_addrs(get)
}
}
#[cfg(feature = "std")]
impl From<std::net::SocketAddrV4> for SocketAddrV4 {
fn from(addr: std::net::SocketAddrV4) -> Self {
Self::new((*addr.ip()).into(), addr.port())
}
}
#[cfg(feature = "std")]
impl From<std::net::SocketAddrV4> for SocketAddr {
fn from(addr: std::net::SocketAddrV4) -> Self {
let a: SocketAddrV4 = addr.into();
a.into()
}
}
#[cfg(feature = "std")]
impl From<std::net::SocketAddrV6> for SocketAddrV6 {
fn from(addr: std::net::SocketAddrV6) -> Self {
Self::new(
(*addr.ip()).into(),
addr.port(),
addr.flowinfo(),
addr.scope_id(),
)
}
}
#[cfg(feature = "std")]
impl From<std::net::SocketAddrV6> for SocketAddr {
fn from(addr: std::net::SocketAddrV6) -> Self {
let a: SocketAddrV6 = addr.into();
a.into()
}
}
#[cfg(feature = "std")]
impl From<std::net::SocketAddr> for SocketAddr {
fn from(addr: std::net::SocketAddr) -> Self {
match addr {
std::net::SocketAddr::V4(ip) => ip.into(),
std::net::SocketAddr::V6(ip) => ip.into(),
}
}
}
#[cfg(feature = "std")]
impl From<SocketAddrV4> for std::net::SocketAddrV4 {
fn from(addr: SocketAddrV4) -> Self {
Self::new((*addr.ip()).into(), addr.port())
}
}
#[cfg(feature = "std")]
impl From<SocketAddrV4> for std::net::SocketAddr {
fn from(addr: SocketAddrV4) -> Self {
let a: std::net::SocketAddrV4 = addr.into();
a.into()
}
}
#[cfg(feature = "std")]
impl From<SocketAddrV6> for std::net::SocketAddrV6 {
fn from(addr: SocketAddrV6) -> Self {
Self::new(
(*addr.ip()).into(),
addr.port(),
addr.flowinfo(),
addr.scope_id(),
)
}
}
#[cfg(feature = "std")]
impl From<SocketAddrV6> for std::net::SocketAddr {
fn from(addr: SocketAddrV6) -> Self {
let a: std::net::SocketAddrV6 = addr.into();
a.into()
}
}
#[cfg(feature = "std")]
impl From<SocketAddr> for std::net::SocketAddr {
fn from(addr: SocketAddr) -> Self {
match addr {
SocketAddr::V4(ip) => ip.into(),
SocketAddr::V6(ip) => ip.into(),
}
}
}