async_rs/implementors/
hickory.rs1use crate::{
2 traits::AsyncToSocketAddrs,
3 util::{self, SocketAddrsFromIpAddrs},
4};
5use hickory_resolver::{IntoName, Resolver, lookup_ip::LookupIpIntoIter};
6use std::{
7 io,
8 net::{SocketAddr, ToSocketAddrs},
9 str::FromStr,
10};
11
12#[derive(Debug, Clone)]
14pub struct HickoryToSocketAddrs<T: IntoName + Send + 'static> {
15 host: T,
16 port: u16,
17}
18
19impl<H: IntoName + Send + 'static> HickoryToSocketAddrs<H> {
20 pub fn new(host: H, port: u16) -> Self {
22 Self { host, port }
23 }
24
25 async fn lookup(self) -> io::Result<SocketAddrsFromIpAddrs<LookupIpIntoIter>> {
26 if !util::inside_tokio() {
27 return Err(io::Error::other(
28 "hickory-dns is only supported in a tokio context",
29 ));
30 }
31
32 Ok(SocketAddrsFromIpAddrs(
33 Resolver::builder_tokio()?
34 .build()
35 .lookup_ip(self.host)
36 .await?
37 .into_iter(),
38 self.port,
39 ))
40 }
41}
42
43impl FromStr for HickoryToSocketAddrs<String> {
44 type Err = io::Error;
45
46 fn from_str(s: &str) -> io::Result<Self> {
47 let (host, port_str) = s
48 .rsplit_once(':')
49 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "invalid socket address"))?;
50 let port = port_str
51 .parse()
52 .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid port value"))?;
53 Ok(Self::new(host.to_owned(), port))
54 }
55}
56
57impl<T: IntoName + Clone + Send + 'static> ToSocketAddrs for HickoryToSocketAddrs<T> {
58 type Iter = SocketAddrsFromIpAddrs<LookupIpIntoIter>;
59
60 fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
61 util::block_on_tokio(self.clone().lookup())
62 }
63}
64
65impl<T: IntoName + Send + 'static> AsyncToSocketAddrs for HickoryToSocketAddrs<T> {
66 fn to_socket_addrs(
67 self,
68 ) -> impl Future<Output = io::Result<impl Iterator<Item = SocketAddr> + Send + 'static>>
69 + Send
70 + 'static {
71 self.lookup()
72 }
73}