use core::ffi::c_int;
use std::fmt;
use std::ptr;
use itertools::Itertools;
use crate::error::{Error, Result};
use crate::host::{HostAliasResultsIter, HostResults};
use crate::record::QueryRecord;
use crate::types::QueryType;
#[derive(Debug)]
pub struct CNameResults {
hostent: HostResults,
}
impl CNameResults {
pub fn parse_from(data: &[u8]) -> Result<CNameResults> {
let mut hostent: *mut c_types::hostent = ptr::null_mut();
let parse_status = unsafe {
c_ares_sys::ares_parse_a_reply(
data.as_ptr(),
data.len() as c_int,
&raw mut hostent,
ptr::null_mut(),
ptr::null_mut(),
)
};
if parse_status == c_ares_sys::ares_status_t::ARES_SUCCESS as i32 {
let result = CNameResults::new(hostent);
Ok(result)
} else {
Err(Error::from(parse_status))
}
}
fn new(hostent: *mut c_types::hostent) -> Self {
CNameResults {
hostent: HostResults::new(hostent),
}
}
pub fn hostname(&self) -> &str {
self.hostent.hostname()
}
pub fn aliases(&self) -> HostAliasResultsIter<'_> {
self.hostent.aliases()
}
}
impl fmt::Display for CNameResults {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "Hostname: {}, ", self.hostname())?;
let aliases = self.aliases().format(", ");
write!(fmt, "Aliases: [{aliases}]")
}
}
impl QueryRecord for CNameResults {
const QUERY_TYPE: QueryType = QueryType::CNAME;
fn parse(data: &[u8]) -> Result<Self> {
Self::parse_from(data)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_invalid_data() {
let result = CNameResults::parse_from(&[]);
assert!(result.is_err());
}
#[test]
fn is_send() {
fn assert_send<T: Send>() {}
assert_send::<CNameResults>();
}
#[test]
fn is_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<CNameResults>();
}
}