use core::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(all(feature = "futures-io", feature = "read-write"))]
mod futures_io_read_write;
#[cfg(feature = "stream")]
mod stream;
#[cfg(all(feature = "tokio", feature = "read-write"))]
mod tokio_read_write;
#[cfg(all(feature = "std", unix))]
use std::os::unix::io::{AsRawFd, RawFd};
use crate::{runtime::Runtime, Timeout};
#[derive(Clone)]
enum CowTimeout<'a, R: Runtime> {
#[cfg(feature = "std")]
Arc(Arc<Timeout<R>>),
Ref(&'a Timeout<R>),
}
impl<'a, R: Runtime> AsRef<Timeout<R>> for CowTimeout<'a, R> {
fn as_ref(&self) -> &Timeout<R> {
match self {
#[cfg(feature = "std")]
Self::Arc(x) => x,
Self::Ref(x) => x,
}
}
}
pin_project_lite::pin_project! {
#[cfg_attr(docsrs, doc(cfg(feature = "wrapper")))]
pub struct Wrapper<'a, R: Runtime, T> {
#[pin]
inner: T,
timeout: CowTimeout<'a, R>,
}
}
#[cfg(feature = "tokio")]
pub type TokioWrapper<'a, T> = Wrapper<'a, crate::runtime::Tokio, T>;
impl<'a, R: Runtime, T> Wrapper<'a, R, T> {
#[must_use]
pub fn new(inner: T, timeout: &'a Timeout<R>) -> Self {
Self {
inner,
timeout: CowTimeout::Ref(timeout),
}
}
pub fn timeout(&self) -> &Timeout<R> {
self.timeout.as_ref()
}
pub fn inner(&self) -> &T {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut T {
&mut self.inner
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<R: Runtime, T> Wrapper<'static, R, T> {
#[must_use]
pub fn new_arc(inner: T, timeout: Arc<Timeout<R>>) -> Self {
Self {
inner,
timeout: CowTimeout::Arc(timeout),
}
}
}
impl<T, R: Runtime> AsRef<T> for Wrapper<'_, R, T> {
fn as_ref(&self) -> &T {
&self.inner
}
}
impl<T, R: Runtime> AsMut<T> for Wrapper<'_, R, T> {
fn as_mut(&mut self) -> &mut T {
&mut self.inner
}
}
impl<R: Runtime, T: Future> Future for Wrapper<'_, R, T> {
type Output = T::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let pinned = self.project();
match pinned.inner.poll(cx) {
Poll::Ready(x) => {
pinned.timeout.as_ref().reset();
Poll::Ready(x)
}
Poll::Pending => Poll::Pending,
}
}
}
#[cfg(all(feature = "std", unix))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", unix))))]
impl<R: Runtime, T: AsRawFd> AsRawFd for Wrapper<'_, R, T> {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}