1#![warn(
11 clippy::default_trait_access,
12 clippy::dbg_macro,
13 clippy::print_stdout,
14 clippy::unimplemented,
15 clippy::use_self,
16 missing_copy_implementations,
17 missing_docs,
18 non_snake_case,
19 non_upper_case_globals,
20 rust_2018_idioms,
21 unreachable_pub
22)]
23#![allow(
24 clippy::single_component_path_imports,
25 clippy::upper_case_acronyms, clippy::bool_to_int_with_if,
27)]
28#![recursion_limit = "2048"]
29#![cfg_attr(docsrs, feature(doc_cfg))]
30
31use async_trait::async_trait;
36use futures_util::future::Future;
37
38use std::marker::Send;
39use std::time::Duration;
40#[cfg(any(test, feature = "tokio-runtime"))]
41use tokio::runtime::Runtime;
42#[cfg(any(test, feature = "tokio-runtime"))]
43use tokio::task::JoinHandle;
44
45macro_rules! try_ready_stream {
46 ($e:expr) => {{
47 match $e {
48 Poll::Ready(Some(Ok(t))) => t,
49 Poll::Ready(None) => return Poll::Ready(None),
50 Poll::Pending => return Poll::Pending,
51 Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(From::from(e)))),
52 }
53 }};
54}
55
56#[cfg(any(test, feature = "tokio-runtime"))]
58#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
59pub fn spawn_bg<F: Future<Output = R> + Send + 'static, R: Send + 'static>(
60 runtime: &Runtime,
61 background: F,
62) -> JoinHandle<R> {
63 runtime.spawn(background)
64}
65
66pub mod error;
67#[cfg(feature = "dns-over-https")]
68#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
69pub mod https;
70#[cfg(feature = "mdns")]
71#[cfg_attr(docsrs, doc(cfg(feature = "mdns")))]
72pub mod multicast;
73#[cfg(feature = "dns-over-native-tls")]
74#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-native-tls")))]
75pub mod native_tls;
76pub mod op;
77#[cfg(feature = "dns-over-openssl")]
78#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-openssl")))]
79pub mod openssl;
80#[cfg(all(feature = "dns-over-quic", feature = "tokio-runtime"))]
81#[cfg_attr(
82 docsrs,
83 doc(cfg(all(feature = "dns-over-quic", feature = "tokio-runtime")))
84)]
85pub mod quic;
86pub mod rr;
87#[cfg(feature = "dns-over-rustls")]
88#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-rustls")))]
89pub mod rustls;
90pub mod serialize;
91pub mod tcp;
92#[cfg(any(test, feature = "testing"))]
93#[cfg_attr(docsrs, doc(cfg(feature = "testing")))]
94pub mod tests;
95pub mod udp;
96pub mod xfer;
97
98#[doc(hidden)]
99pub use crate::xfer::dns_handle::{DnsHandle, DnsStreamHandle};
100#[doc(hidden)]
101pub use crate::xfer::dns_multiplexer::DnsMultiplexer;
102#[doc(hidden)]
103#[cfg(feature = "dnssec")]
104pub use crate::xfer::dnssec_dns_handle::DnssecDnsHandle;
105#[doc(hidden)]
106pub use crate::xfer::retry_dns_handle::RetryDnsHandle;
107#[doc(hidden)]
108pub use crate::xfer::BufDnsStreamHandle;
109#[cfg(feature = "backtrace")]
110#[cfg_attr(docsrs, doc(cfg(feature = "backtrace")))]
111pub use error::ExtBacktrace;
112
113#[cfg(feature = "tokio-runtime")]
114#[doc(hidden)]
115pub mod iocompat {
116 use std::io;
117 use std::pin::Pin;
118 use std::task::{Context, Poll};
119
120 use futures_io::{AsyncRead, AsyncWrite};
121 use tokio::io::{AsyncRead as TokioAsyncRead, AsyncWrite as TokioAsyncWrite, ReadBuf};
122
123 pub struct AsyncIoTokioAsStd<T: TokioAsyncRead + TokioAsyncWrite>(pub T);
125
126 impl<T: TokioAsyncRead + TokioAsyncWrite + Unpin> Unpin for AsyncIoTokioAsStd<T> {}
127 impl<R: TokioAsyncRead + TokioAsyncWrite + Unpin> AsyncRead for AsyncIoTokioAsStd<R> {
128 fn poll_read(
129 mut self: Pin<&mut Self>,
130 cx: &mut Context<'_>,
131 buf: &mut [u8],
132 ) -> Poll<io::Result<usize>> {
133 let mut buf = ReadBuf::new(buf);
134 let polled = Pin::new(&mut self.0).poll_read(cx, &mut buf);
135
136 polled.map_ok(|_| buf.filled().len())
137 }
138 }
139
140 impl<W: TokioAsyncRead + TokioAsyncWrite + Unpin> AsyncWrite for AsyncIoTokioAsStd<W> {
141 fn poll_write(
142 mut self: Pin<&mut Self>,
143 cx: &mut Context<'_>,
144 buf: &[u8],
145 ) -> Poll<io::Result<usize>> {
146 Pin::new(&mut self.0).poll_write(cx, buf)
147 }
148 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
149 Pin::new(&mut self.0).poll_flush(cx)
150 }
151 fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
152 Pin::new(&mut self.0).poll_shutdown(cx)
153 }
154 }
155
156 pub struct AsyncIoStdAsTokio<T: AsyncRead + AsyncWrite>(pub T);
158
159 impl<T: AsyncRead + AsyncWrite + Unpin> Unpin for AsyncIoStdAsTokio<T> {}
160 impl<R: AsyncRead + AsyncWrite + Unpin> TokioAsyncRead for AsyncIoStdAsTokio<R> {
161 fn poll_read(
162 self: Pin<&mut Self>,
163 cx: &mut Context<'_>,
164 buf: &mut ReadBuf<'_>,
165 ) -> Poll<io::Result<()>> {
166 Pin::new(&mut self.get_mut().0)
167 .poll_read(cx, buf.initialized_mut())
168 .map_ok(|len| buf.advance(len))
169 }
170 }
171
172 impl<W: AsyncRead + AsyncWrite + Unpin> TokioAsyncWrite for AsyncIoStdAsTokio<W> {
173 fn poll_write(
174 self: Pin<&mut Self>,
175 cx: &mut Context<'_>,
176 buf: &[u8],
177 ) -> Poll<Result<usize, io::Error>> {
178 Pin::new(&mut self.get_mut().0).poll_write(cx, buf)
179 }
180
181 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
182 Pin::new(&mut self.get_mut().0).poll_flush(cx)
183 }
184
185 fn poll_shutdown(
186 self: Pin<&mut Self>,
187 cx: &mut Context<'_>,
188 ) -> Poll<Result<(), io::Error>> {
189 Pin::new(&mut self.get_mut().0).poll_close(cx)
190 }
191 }
192}
193
194pub trait Executor {
198 fn new() -> Self;
200
201 fn block_on<F: Future>(&mut self, future: F) -> F::Output;
204}
205
206#[cfg(feature = "tokio-runtime")]
207#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
208impl Executor for Runtime {
209 fn new() -> Self {
210 Self::new().expect("failed to create tokio runtime")
211 }
212
213 fn block_on<F: Future>(&mut self, future: F) -> F::Output {
214 Self::block_on(self, future)
215 }
216}
217
218#[async_trait]
221pub trait Time {
222 async fn delay_for(duration: Duration);
225
226 async fn timeout<F: 'static + Future + Send>(
228 duration: Duration,
229 future: F,
230 ) -> Result<F::Output, std::io::Error>;
231}
232
233#[cfg(any(test, feature = "tokio-runtime"))]
235#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
236#[derive(Clone, Copy, Debug)]
237pub struct TokioTime;
238
239#[cfg(any(test, feature = "tokio-runtime"))]
240#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
241#[async_trait]
242impl Time for TokioTime {
243 async fn delay_for(duration: Duration) {
244 tokio::time::sleep(duration).await
245 }
246
247 async fn timeout<F: 'static + Future + Send>(
248 duration: Duration,
249 future: F,
250 ) -> Result<F::Output, std::io::Error> {
251 tokio::time::timeout(duration, future)
252 .await
253 .map_err(move |_| std::io::Error::new(std::io::ErrorKind::TimedOut, "future timed out"))
254 }
255}