use std::{
fmt::Debug,
io::{Error, ErrorKind},
net::{SocketAddr, ToSocketAddrs},
};
pub enum AddrResolver {
ToSocketAddrs(ToSocketAddrResolver),
Dyn(Box<dyn ResolveAddr<IntoAddr = Box<dyn IntoAddr>>>),
}
impl ResolveAddr for AddrResolver {
type IntoAddr = AnyIntoAddr;
fn resolve_addr(&self, s: String) -> Result<Self::IntoAddr, Error> {
match self {
Self::ToSocketAddrs(x) => Ok(AnyIntoAddr::ToSocketAddrIntoAddr(x.resolve_addr(s)?)),
Self::Dyn(x) => Ok(AnyIntoAddr::Dyn(Box::new(x.resolve_addr(s)?))),
}
}
}
impl Debug for AddrResolver {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ToSocketAddrs(_) => write!(f, "ToSocketAddrs"),
Self::Dyn(_) => write!(f, "Dyn"),
}
}
}
impl Default for AddrResolver {
fn default() -> Self {
Self::ToSocketAddrs(ToSocketAddrResolver)
}
}
pub trait ResolveAddr {
type IntoAddr: IntoAddr;
fn resolve_addr(&self, s: String) -> Result<Self::IntoAddr, Error>;
}
pub enum IntoAddrOutcome {
Idle,
Active,
Finished(Vec<SocketAddr>),
}
pub trait IntoAddr: Send {
fn poll(&mut self) -> Result<IntoAddrOutcome, Error>;
}
impl IntoAddr for Box<dyn IntoAddr> {
fn poll(&mut self) -> Result<IntoAddrOutcome, Error> {
self.as_mut().poll()
}
}
pub enum AnyIntoAddr {
ToSocketAddrIntoAddr(ToSocketAddrIntoAddr),
Dyn(Box<dyn IntoAddr>),
}
impl IntoAddr for AnyIntoAddr {
fn poll(&mut self) -> Result<IntoAddrOutcome, Error> {
match self {
Self::ToSocketAddrIntoAddr(x) => x.poll(),
Self::Dyn(x) => x.poll(),
}
}
}
pub struct ToSocketAddrResolver;
impl ResolveAddr for ToSocketAddrResolver {
type IntoAddr = ToSocketAddrIntoAddr;
fn resolve_addr(&self, s: String) -> Result<Self::IntoAddr, Error> {
Ok(ToSocketAddrIntoAddr { s: Some(s) })
}
}
pub struct ToSocketAddrIntoAddr {
s: Option<String>,
}
impl IntoAddr for ToSocketAddrIntoAddr {
fn poll(&mut self) -> Result<IntoAddrOutcome, Error> {
match self.s.take() {
Some(x) => x
.to_socket_addrs()
.map(|x| IntoAddrOutcome::Finished(x.collect())),
None => Err(Error::new(ErrorKind::Other, "done!")),
}
}
}