1use std::future::Future;
2use std::io;
3use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
4use std::pin::Pin;
5
6pub type ResolveFuture<'a> =
7 Pin<Box<dyn Future<Output = Result<Vec<SocketAddr>, io::Error>> + Send + 'a>>;
8
9pub trait Resolver: Send + Sync + 'static {
10 fn resolve<'a>(&'a self, host: &'a str, port: u16) -> ResolveFuture<'a>;
11}
12
13#[derive(Debug, Default, Clone, Copy)]
14pub struct SystemResolver;
15
16impl Resolver for SystemResolver {
17 fn resolve<'a>(&'a self, host: &'a str, port: u16) -> ResolveFuture<'a> {
18 if let Ok(ip) = host.parse::<IpAddr>() {
19 let addr = SocketAddr::new(ip, port);
20 return Box::pin(async move { Ok(vec![addr]) });
21 }
22 let host = host.to_owned();
23 Box::pin(async move {
24 let addr = format!("{host}:{port}");
25 tokio::task::spawn_blocking(move || {
26 addr.to_socket_addrs().map(|it| it.collect::<Vec<_>>())
27 })
28 .await
29 .map_err(io::Error::other)?
30 })
31 }
32}
33
34#[cfg(test)]
35mod tests;