use std::fmt;
use std::net::IpAddr;
#[derive(Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct HostResults {
hostname: String,
addresses: Vec<IpAddr>,
aliases: Vec<String>,
}
impl HostResults {
pub fn hostname(&self) -> &str {
&self.hostname
}
pub fn addresses(&self) -> &[IpAddr] {
&self.addresses
}
pub fn aliases(&self) -> &[String] {
&self.aliases
}
}
impl From<&c_ares::HostResults> for HostResults {
fn from(results: &c_ares::HostResults) -> Self {
Self {
hostname: results.hostname().to_owned(),
addresses: results.addresses().collect(),
aliases: results
.aliases()
.map(std::borrow::ToOwned::to_owned)
.collect(),
}
}
}
impl fmt::Display for HostResults {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "Hostname: {}, ", self.hostname())?;
for address in self.addresses() {
write!(fmt, "Address: {address}, ")?;
}
for alias in self.aliases() {
write!(fmt, "Alias: {alias}, ")?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
#[test]
fn host_results_is_send() {
assert_send::<HostResults>();
}
#[test]
fn host_results_is_sync() {
assert_sync::<HostResults>();
}
#[test]
fn host_results_clone() {
let results = HostResults {
hostname: "example.com".to_string(),
addresses: vec!["127.0.0.1".parse().unwrap()],
aliases: vec!["alias.example.com".to_string()],
};
let cloned = results.clone();
assert_eq!(results, cloned);
}
#[test]
fn host_results_eq() {
let results1 = HostResults {
hostname: "example.com".to_string(),
addresses: vec![],
aliases: vec![],
};
let results2 = HostResults {
hostname: "example.com".to_string(),
addresses: vec![],
aliases: vec![],
};
assert_eq!(results1, results2);
}
#[test]
fn host_results_ne() {
let results1 = HostResults {
hostname: "example.com".to_string(),
addresses: vec![],
aliases: vec![],
};
let results2 = HostResults {
hostname: "other.com".to_string(),
addresses: vec![],
aliases: vec![],
};
assert_ne!(results1, results2);
}
#[test]
fn host_results_debug() {
let results = HostResults {
hostname: "example.com".to_string(),
addresses: vec![],
aliases: vec![],
};
let debug = format!("{results:?}");
assert!(debug.contains("example.com"));
}
#[test]
fn host_results_hash() {
let results = HostResults {
hostname: "example.com".to_string(),
addresses: vec![],
aliases: vec![],
};
let mut hasher = DefaultHasher::new();
results.hash(&mut hasher);
let hash1 = hasher.finish();
let mut hasher = DefaultHasher::new();
results.clone().hash(&mut hasher);
let hash2 = hasher.finish();
assert_eq!(hash1, hash2);
}
#[test]
fn host_results_ord() {
let results1 = HostResults {
hostname: "a.com".to_string(),
addresses: vec![],
aliases: vec![],
};
let results2 = HostResults {
hostname: "b.com".to_string(),
addresses: vec![],
aliases: vec![],
};
assert!(results1 < results2);
}
#[test]
fn host_results_with_addresses() {
let results = HostResults {
hostname: "example.com".to_string(),
addresses: vec!["127.0.0.1".parse().unwrap(), "::1".parse().unwrap()],
aliases: vec!["www.example.com".to_string()],
};
assert_eq!(results.addresses().len(), 2);
assert_eq!(results.aliases().len(), 1);
}
#[test]
fn host_results_display() {
let results = HostResults {
hostname: "example.com".to_string(),
addresses: vec!["127.0.0.1".parse().unwrap()],
aliases: vec!["www.example.com".to_string()],
};
let display = format!("{results}");
assert!(display.contains("example.com"));
assert!(display.contains("127.0.0.1"));
}
}