use std::future::Future;
use std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;
#[cfg(unix)]
use std::path::Path;
use std::pin::Pin;
use std::time::Duration;
#[allow(async_fn_in_trait)]
pub trait Runtime: Send + Sync + 'static {
type TcpStream: hyper::rt::Read + hyper::rt::Write + Send + Unpin + 'static;
type Sleep: Future<Output = ()> + Send + Sync;
fn connect(addr: SocketAddr) -> impl Future<Output = io::Result<Self::TcpStream>> + Send;
async fn resolve(host: &str, port: u16) -> io::Result<SocketAddr> {
let addrs = Self::resolve_all(host, port).await?;
addrs
.into_iter()
.next()
.ok_or_else(|| io::Error::new(io::ErrorKind::AddrNotAvailable, "no addresses resolved"))
}
fn resolve_all(
host: &str,
port: u16,
) -> impl Future<Output = io::Result<Vec<SocketAddr>>> + Send;
fn sleep(duration: Duration) -> Self::Sleep;
fn spawn<F>(future: F)
where
F: Future<Output = ()> + Send + 'static;
fn set_tcp_keepalive(
_stream: &Self::TcpStream,
_time: Duration,
_interval: Option<Duration>,
_retries: Option<u32>,
) -> io::Result<()> {
Ok(())
}
fn set_tcp_fast_open(_stream: &Self::TcpStream) -> io::Result<()> {
Ok(())
}
#[cfg(target_os = "linux")]
fn bind_device(_stream: &Self::TcpStream, _interface: &str) -> io::Result<()> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"interface binding not supported by this runtime",
))
}
fn from_std_tcp(stream: std::net::TcpStream) -> io::Result<Self::TcpStream>;
fn connect_bound(
addr: SocketAddr,
local: std::net::IpAddr,
) -> impl Future<Output = io::Result<Self::TcpStream>> + Send;
#[cfg(unix)]
type UnixStream: hyper::rt::Read + hyper::rt::Write + Send + Unpin + 'static;
#[cfg(unix)]
fn connect_unix(path: &Path) -> impl Future<Output = io::Result<Self::UnixStream>> + Send;
}
pub trait Resolve: Send + Sync + 'static {
fn resolve(
&self,
host: &str,
port: u16,
) -> Pin<Box<dyn Future<Output = io::Result<SocketAddr>> + Send>>;
fn resolve_all(
&self,
host: &str,
port: u16,
) -> Pin<Box<dyn Future<Output = io::Result<Vec<SocketAddr>>> + Send>> {
let fut = self.resolve(host, port);
Box::pin(async move { fut.await.map(|a| vec![a]) })
}
}
impl<F> Resolve for F
where
F: Fn(&str, u16) -> Pin<Box<dyn Future<Output = io::Result<SocketAddr>> + Send>>
+ Send
+ Sync
+ 'static,
{
fn resolve(
&self,
host: &str,
port: u16,
) -> Pin<Box<dyn Future<Output = io::Result<SocketAddr>> + Send>> {
(self)(host, port)
}
}
pub(crate) struct HyperExecutor<R>(PhantomData<fn() -> R>);
impl<R> Clone for HyperExecutor<R> {
fn clone(&self) -> Self {
*self
}
}
impl<R> Copy for HyperExecutor<R> {}
impl<R, F> hyper::rt::Executor<F> for HyperExecutor<R>
where
R: Runtime,
F: Future<Output = ()> + Send + 'static,
{
fn execute(&self, fut: F) {
R::spawn(fut);
}
}
pub(crate) fn hyper_executor<R: Runtime>() -> HyperExecutor<R> {
HyperExecutor(PhantomData)
}
#[cfg(feature = "tokio")]
pub mod tokio_rt;
#[cfg(feature = "tokio")]
pub use tokio_rt::TokioRuntime;
#[cfg(feature = "smol")]
pub mod smol_rt;
#[cfg(feature = "smol")]
pub use smol_rt::SmolRuntime;
#[cfg(feature = "compio")]
pub mod compio_rt;
#[cfg(feature = "compio")]
pub use compio_rt::CompioRuntime;