use std::{
future::Future,
ops::{Deref, DerefMut},
pin::Pin,
task::{Context, Poll},
};
use futures_channel::oneshot::{self, Receiver, Sender};
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub trait AsyncBorrowOwned: Sized {
fn async_borrow_owned(self) -> (AsyncBorrowed<Self>, AsyncReturn<Self>);
}
impl<T> AsyncBorrowOwned for T
where
T: Sized,
{
fn async_borrow_owned(self) -> (AsyncBorrowed<Self>, AsyncReturn<Self>) {
let (tx, rx) = oneshot::channel();
let borrowed = AsyncBorrowed {
inner: Some((self, tx)),
};
let ret = AsyncReturn { rx };
(borrowed, ret)
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub struct AsyncReturn<T> {
rx: Receiver<T>,
}
impl<T> Future for AsyncReturn<T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let rx = Pin::new(&mut self.rx);
if let Poll::Ready(res) = rx.poll(cx) {
Poll::Ready(res.unwrap())
} else {
Poll::Pending
}
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub struct AsyncBorrowed<T> {
inner: Option<(T, Sender<T>)>,
}
impl<T> Drop for AsyncBorrowed<T> {
fn drop(&mut self) {
if let Some((val, tx)) = self.inner.take() {
tx.send(val).unwrap_or_default();
}
}
}
impl<T> Deref for AsyncBorrowed<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner.as_ref().map(|(val, _)| val).unwrap()
}
}
impl<T> DerefMut for AsyncBorrowed<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner.as_mut().map(|(val, _)| val).unwrap()
}
}