1use std::fmt;
2use std::os::raw::{c_int, c_uchar, c_void};
3use std::ptr;
4use std::slice;
5
6use itertools::Itertools;
7
8use crate::error::{Error, Result};
9use crate::hostent::{HasHostent, HostAliasResultsIter, HostentOwned};
10use crate::panic;
11
12#[derive(Debug)]
14pub struct NSResults {
15 hostent: HostentOwned,
16}
17
18impl NSResults {
19 pub fn parse_from(data: &[u8]) -> Result<NSResults> {
21 let mut hostent: *mut c_types::hostent = ptr::null_mut();
22 let parse_status = unsafe {
23 c_ares_sys::ares_parse_ns_reply(data.as_ptr(), data.len() as c_int, &mut hostent)
24 };
25 if parse_status == c_ares_sys::ares_status_t::ARES_SUCCESS as i32 {
26 let result = NSResults::new(hostent);
27 Ok(result)
28 } else {
29 Err(Error::from(parse_status))
30 }
31 }
32
33 fn new(hostent: *mut c_types::hostent) -> Self {
34 NSResults {
35 hostent: HostentOwned::new(hostent),
36 }
37 }
38
39 pub fn hostname(&self) -> &str {
41 self.hostent.hostname()
42 }
43
44 pub fn aliases(&self) -> HostAliasResultsIter {
46 self.hostent.aliases()
47 }
48}
49
50impl fmt::Display for NSResults {
51 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
52 write!(fmt, "Hostname: {}, ", self.hostname())?;
53 let aliases = self.aliases().format(", ");
54 write!(fmt, "Aliases: [{aliases}]")
55 }
56}
57
58pub(crate) unsafe extern "C" fn query_ns_callback<F>(
59 arg: *mut c_void,
60 status: c_int,
61 _timeouts: c_int,
62 abuf: *mut c_uchar,
63 alen: c_int,
64) where
65 F: FnOnce(Result<NSResults>) + Send + 'static,
66{
67 ares_callback!(arg.cast::<F>(), status, abuf, alen, NSResults::parse_from);
68}