1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::os::raw::{c_char, c_int, c_uchar, c_void};
use std::ptr;
use std::slice;
use itertools::Itertools;
use crate::error::{Error, Result};
use crate::panic;
#[derive(Debug)]
pub struct URIResults {
uri_reply: *mut c_ares_sys::ares_uri_reply,
phantom: PhantomData<c_ares_sys::ares_uri_reply>,
}
#[derive(Clone, Copy)]
pub struct URIResult<'a> {
uri_reply: &'a c_ares_sys::ares_uri_reply,
}
impl URIResults {
pub fn parse_from(data: &[u8]) -> Result<URIResults> {
let mut uri_reply: *mut c_ares_sys::ares_uri_reply = ptr::null_mut();
let parse_status = unsafe {
c_ares_sys::ares_parse_uri_reply(data.as_ptr(), data.len() as c_int, &mut uri_reply)
};
if parse_status == c_ares_sys::ARES_SUCCESS {
let uri_result = URIResults::new(uri_reply);
Ok(uri_result)
} else {
Err(Error::from(parse_status))
}
}
fn new(uri_reply: *mut c_ares_sys::ares_uri_reply) -> Self {
URIResults {
uri_reply,
phantom: PhantomData,
}
}
pub fn iter(&self) -> URIResultsIter {
URIResultsIter {
next: unsafe { self.uri_reply.as_ref() },
}
}
}
impl fmt::Display for URIResults {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let results = self.iter().format("}, {");
write!(fmt, "[{{{}}}]", results)
}
}
#[derive(Clone, Copy)]
pub struct URIResultsIter<'a> {
next: Option<&'a c_ares_sys::ares_uri_reply>,
}
impl<'a> Iterator for URIResultsIter<'a> {
type Item = URIResult<'a>;
fn next(&mut self) -> Option<Self::Item> {
let opt_reply = self.next;
self.next = opt_reply.and_then(|reply| unsafe { reply.next.as_ref() });
opt_reply.map(|reply| URIResult { uri_reply: reply })
}
}
impl<'a> IntoIterator for &'a URIResults {
type Item = URIResult<'a>;
type IntoIter = URIResultsIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl Drop for URIResults {
fn drop(&mut self) {
unsafe {
c_ares_sys::ares_free_data(self.uri_reply as *mut c_void);
}
}
}
unsafe impl Send for URIResults {}
unsafe impl Sync for URIResults {}
unsafe impl<'a> Send for URIResult<'a> {}
unsafe impl<'a> Sync for URIResult<'a> {}
unsafe impl<'a> Send for URIResultsIter<'a> {}
unsafe impl<'a> Sync for URIResultsIter<'a> {}
impl<'a> URIResult<'a> {
pub fn weight(self) -> u16 {
self.uri_reply.weight
}
pub fn priority(self) -> u16 {
self.uri_reply.priority
}
pub fn uri(self) -> &'a CStr {
unsafe { CStr::from_ptr(self.uri_reply.uri as *const c_char) }
}
pub fn ttl(self) -> i32 {
self.uri_reply.ttl as i32
}
}
impl<'a> fmt::Display for URIResult<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(
fmt,
"URI: {}, ",
self.uri().to_str().unwrap_or("<not utf8>")
)?;
write!(fmt, "Priority: {}, ", self.priority())?;
write!(fmt, "Weight: {}", self.weight())?;
write!(fmt, "TTL: {}", self.ttl())
}
}
pub(crate) unsafe extern "C" fn query_uri_callback<F>(
arg: *mut c_void,
status: c_int,
_timeouts: c_int,
abuf: *mut c_uchar,
alen: c_int,
) where
F: FnOnce(Result<URIResults>) + Send + 'static,
{
ares_callback!(arg as *mut F, status, abuf, alen, URIResults::parse_from);
}