use std::future::Future;
use std::io;
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
use std::pin::Pin;
pub type ResolveFuture<'a> =
Pin<Box<dyn Future<Output = Result<Vec<SocketAddr>, io::Error>> + Send + 'a>>;
pub trait Resolver: Send + Sync + 'static {
fn resolve<'a>(&'a self, host: &'a str, port: u16) -> ResolveFuture<'a>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct SystemResolver;
impl Resolver for SystemResolver {
fn resolve<'a>(&'a self, host: &'a str, port: u16) -> ResolveFuture<'a> {
if let Ok(ip) = host.parse::<IpAddr>() {
let addr = SocketAddr::new(ip, port);
return Box::pin(async move { Ok(vec![addr]) });
}
let host = host.to_owned();
Box::pin(async move {
let addr = format!("{host}:{port}");
tokio::task::spawn_blocking(move || {
addr.to_socket_addrs().map(|it| it.collect::<Vec<_>>())
})
.await
.map_err(io::Error::other)?
})
}
}
#[cfg(test)]
mod tests;