Skip to main content

object_rainbow/
nested_mut.rs

1use std::{
2    ops::{Deref, DerefMut},
3    pin::Pin,
4    task::{Context, Poll, ready},
5};
6
7use futures_channel::oneshot;
8use futures_util::{FutureExt, future::BoxFuture};
9
10struct NestedGuard<'a, T> {
11    original: &'a mut T,
12    returned: oneshot::Receiver<T>,
13}
14
15impl<T> Drop for NestedGuard<'_, T> {
16    fn drop(&mut self) {
17        if let Ok(Some(returned)) = self.returned.try_recv() {
18            *self.original = returned;
19        }
20    }
21}
22
23struct Lent<T> {
24    value: T,
25    return_to: oneshot::Sender<T>,
26}
27
28impl<T> Deref for Lent<T> {
29    type Target = T;
30
31    fn deref(&self) -> &Self::Target {
32        &self.value
33    }
34}
35
36impl<T> DerefMut for Lent<T> {
37    fn deref_mut(&mut self) -> &mut Self::Target {
38        &mut self.value
39    }
40}
41
42impl<T> Lent<T> {
43    fn finish(self) {
44        self.return_to.send(self.value).ok();
45    }
46}
47
48pub struct Borrower<T>(oneshot::Sender<Lent<T>>);
49
50impl<'a, T: Clone> NestedGuard<'a, T> {
51    fn new(original: &'a mut T, borrower: Borrower<T>) -> Self {
52        let (return_to, returned) = oneshot::channel();
53        borrower
54            .0
55            .send(Lent {
56                value: original.clone(),
57                return_to,
58            })
59            .ok();
60        Self { original, returned }
61    }
62}
63
64pub trait LendTo: Clone {
65    fn lend_to<T>(&mut self, borrower: Borrower<Self>) -> impl Future<Output = T> {
66        async move {
67            let _guard = NestedGuard::new(self, borrower);
68            std::future::pending().await
69        }
70    }
71}
72
73impl<T: Clone> LendTo for T {}
74
75pub struct NestedMut<'a, T> {
76    lent: Option<Lent<T>>,
77    _guard: oneshot::Receiver<BoxFuture<'a, object_rainbow::Result<()>>>,
78}
79
80impl<T> Deref for NestedMut<'_, T> {
81    type Target = T;
82
83    fn deref(&self) -> &Self::Target {
84        self.lent.as_ref().expect("invalid state")
85    }
86}
87
88impl<T> DerefMut for NestedMut<'_, T> {
89    fn deref_mut(&mut self) -> &mut Self::Target {
90        self.lent.as_mut().expect("invalid state")
91    }
92}
93
94impl<T> Drop for NestedMut<'_, T> {
95    fn drop(&mut self) {
96        self.lent.take().expect("invalid state").finish();
97    }
98}
99
100struct WaitingLease<'a, T> {
101    borrowing: oneshot::Receiver<Lent<T>>,
102    future: Option<BoxFuture<'a, object_rainbow::Result<()>>>,
103}
104
105impl<'a, T> Future for WaitingLease<'a, T> {
106    type Output = object_rainbow::Result<Option<NestedMut<'a, T>>>;
107
108    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
109        let this = self.get_mut();
110        if this
111            .future
112            .as_mut()
113            .expect("invalid state")
114            .poll_unpin(cx)?
115            .is_ready()
116        {
117            Poll::Ready(Ok(None))
118        } else {
119            let Ok(lent) = ready!(this.borrowing.poll_unpin(cx)) else {
120                return Poll::Ready(Ok(None));
121            };
122            Poll::Ready(Ok(Some(NestedMut::new(
123                lent,
124                this.future.take().expect("invalid state"),
125            ))))
126        }
127    }
128}
129
130impl<'a, T> NestedMut<'a, T> {
131    fn new(lent: Lent<T>, future: BoxFuture<'a, object_rainbow::Result<()>>) -> Self {
132        let (send, recv) = oneshot::channel();
133        send.send(future).ok();
134        Self {
135            lent: Some(lent),
136            _guard: recv,
137        }
138    }
139
140    pub async fn from_fn<F: 'a + Send + Future<Output = object_rainbow::Result<()>>>(
141        f: impl FnOnce(Borrower<T>) -> F,
142    ) -> object_rainbow::Result<Option<Self>> {
143        let (lending, borrowing) = oneshot::channel();
144        let future = f(Borrower(lending)).boxed();
145        WaitingLease {
146            borrowing,
147            future: Some(future),
148        }
149        .await
150    }
151}