use std::net::{SocketAddr, ToSocketAddrs};
use crate::error::{Error, Result};
pub trait Resolver: Send + Sync + std::fmt::Debug {
fn resolve(&self, host: &str, port: u16) -> Result<Vec<SocketAddr>>;
}
#[derive(Debug, Default, Clone)]
pub struct StdResolver;
impl Resolver for StdResolver {
fn resolve(&self, host: &str, port: u16) -> Result<Vec<SocketAddr>> {
let addrs: Vec<SocketAddr> = (host, port).to_socket_addrs().map_err(Error::Io)?.collect();
if addrs.is_empty() {
return Err(Error::InvalidUrl(host.to_string()));
}
Ok(addrs)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn std_resolver_resolves_localhost() {
let addrs = StdResolver.resolve("127.0.0.1", 80).unwrap();
assert_eq!(addrs[0], "127.0.0.1:80".parse().unwrap());
}
#[derive(Debug)]
struct Fixed(SocketAddr);
impl Resolver for Fixed {
fn resolve(&self, _host: &str, _port: u16) -> Result<Vec<SocketAddr>> {
Ok(vec![self.0])
}
}
#[test]
fn custom_resolver_is_consulted() {
let r = Fixed("10.1.2.3:443".parse().unwrap());
assert_eq!(r.resolve("ignored.example", 443).unwrap()[0].port(), 443);
}
}