borrow_owned/
asynchronous.rs

1use std::{
2    future::Future,
3    ops::{Deref, DerefMut},
4    pin::Pin,
5    task::{Context, Poll},
6};
7
8use futures_channel::oneshot::{self, Receiver, Sender};
9
10/// Trait allowing objects to be temporarily moved elsewhere.
11#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
12pub trait AsyncBorrowOwned: Sized {
13    /// Borrow this object.
14    ///
15    /// The method returns an [`AsyncBorrowed`](AsyncBorrowed) wrapper which
16    /// can be easily moved elsewhere (e.g. a separate thread) and an
17    /// [`AsyncReturn`](AsyncReturn) handle which can be used to wait until the
18    /// borrow ends.
19    fn async_borrow_owned(self) -> (AsyncBorrowed<Self>, AsyncReturn<Self>);
20}
21
22impl<T> AsyncBorrowOwned for T
23where
24    T: Sized,
25{
26    fn async_borrow_owned(self) -> (AsyncBorrowed<Self>, AsyncReturn<Self>) {
27        let (tx, rx) = oneshot::channel();
28
29        let borrowed = AsyncBorrowed {
30            inner: Some((self, tx)),
31        };
32        let ret = AsyncReturn { rx };
33
34        (borrowed, ret)
35    }
36}
37
38/// Return handle.
39#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
40pub struct AsyncReturn<T> {
41    rx: Receiver<T>,
42}
43
44impl<T> Future for AsyncReturn<T> {
45    type Output = T;
46
47    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
48        let rx = Pin::new(&mut self.rx);
49
50        if let Poll::Ready(res) = rx.poll(cx) {
51            Poll::Ready(res.unwrap())
52        } else {
53            Poll::Pending
54        }
55    }
56}
57
58/// Borrowed object.
59#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
60pub struct AsyncBorrowed<T> {
61    inner: Option<(T, Sender<T>)>,
62}
63
64impl<T> Drop for AsyncBorrowed<T> {
65    fn drop(&mut self) {
66        if let Some((val, tx)) = self.inner.take() {
67            tx.send(val).unwrap_or_default();
68        }
69    }
70}
71
72impl<T> Deref for AsyncBorrowed<T> {
73    type Target = T;
74
75    fn deref(&self) -> &Self::Target {
76        self.inner.as_ref().map(|(val, _)| val).unwrap()
77    }
78}
79
80impl<T> DerefMut for AsyncBorrowed<T> {
81    fn deref_mut(&mut self) -> &mut Self::Target {
82        self.inner.as_mut().map(|(val, _)| val).unwrap()
83    }
84}