zng_var/var_impl/
response_var.rs

1//! Special `Var<Response>` type impls
2
3use crate::{AnyVar, Var};
4
5use super::*;
6
7/// New paired [`ResponderVar`] and [`ResponseVar`] in the waiting state.
8pub fn response_var<T: VarValue>() -> (ResponderVar<T>, ResponseVar<T>) {
9    let responder = var(Response::Waiting::<T>);
10    let response = responder.read_only();
11    (ResponderVar(responder), ResponseVar(response))
12}
13
14/// New [`ResponseVar`] in the done state.
15pub fn response_done_var<T: VarValue>(response: T) -> ResponseVar<T> {
16    ResponseVar(var(Response::Done(response)).read_only())
17}
18
19/// Represents a read-write variable used to notify the completion of an async operation.
20///
21/// Use [`response_var`] to init.
22#[derive(Clone)]
23pub struct ResponderVar<T: VarValue>(Var<Response<T>>);
24
25/// Represents a read-only variable used to listen to a one time signal that an async operation has completed.
26///
27/// Use [`response_var`] or [`response_done_var`] to init.
28#[derive(Clone)]
29pub struct ResponseVar<T: VarValue>(Var<Response<T>>);
30
31impl<T: VarValue> ops::Deref for ResponderVar<T> {
32    type Target = Var<Response<T>>;
33
34    fn deref(&self) -> &Self::Target {
35        &self.0
36    }
37}
38impl<T: VarValue> IntoVar<Response<T>> for ResponderVar<T> {
39    fn into_var(self) -> Var<Response<T>> {
40        self.0
41    }
42}
43impl<T: VarValue> From<ResponderVar<T>> for Var<Response<T>> {
44    fn from(var: ResponderVar<T>) -> Self {
45        var.0
46    }
47}
48impl<T: VarValue> From<ResponderVar<T>> for AnyVar {
49    fn from(var: ResponderVar<T>) -> Self {
50        var.0.into()
51    }
52}
53
54impl<T: VarValue> ops::Deref for ResponseVar<T> {
55    type Target = Var<Response<T>>;
56
57    fn deref(&self) -> &Self::Target {
58        &self.0
59    }
60}
61impl<T: VarValue> IntoVar<Response<T>> for ResponseVar<T> {
62    fn into_var(self) -> Var<Response<T>> {
63        self.0
64    }
65}
66impl<T: VarValue> From<ResponseVar<T>> for Var<Response<T>> {
67    fn from(var: ResponseVar<T>) -> Self {
68        var.0
69    }
70}
71impl<T: VarValue> From<ResponseVar<T>> for AnyVar {
72    fn from(var: ResponseVar<T>) -> Self {
73        var.0.into()
74    }
75}
76
77/// Raw value in a [`ResponseVar`].
78#[derive(Clone, Copy, PartialEq)]
79pub enum Response<T: VarValue> {
80    /// Responder has not set the response yet.
81    Waiting,
82    /// Responder has set the response.
83    Done(T),
84}
85impl<T: VarValue> Response<T> {
86    /// Has response.
87    pub fn is_done(&self) -> bool {
88        matches!(self, Response::Done(_))
89    }
90
91    /// Does not have response.
92    pub fn is_waiting(&self) -> bool {
93        matches!(self, Response::Waiting)
94    }
95
96    /// Gets the response if done.
97    pub fn done(&self) -> Option<&T> {
98        match self {
99            Response::Waiting => None,
100            Response::Done(r) => Some(r),
101        }
102    }
103}
104impl<T: VarValue> fmt::Debug for Response<T> {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        if f.alternate() {
107            match self {
108                Response::Waiting => {
109                    write!(f, "Response::Waiting")
110                }
111                Response::Done(v) => f.debug_tuple("Response::Done").field(v).finish(),
112            }
113        } else {
114            match self {
115                Response::Waiting => {
116                    write!(f, "Waiting")
117                }
118                Response::Done(v) => fmt::Debug::fmt(v, f),
119            }
120        }
121    }
122}
123impl<T: VarValue> From<Response<T>> for Option<T> {
124    fn from(value: Response<T>) -> Self {
125        match value {
126            Response::Waiting => None,
127            Response::Done(r) => Some(r),
128        }
129    }
130}
131impl<T: VarValue> From<Response<Option<T>>> for Option<T> {
132    fn from(value: Response<Option<T>>) -> Self {
133        match value {
134            Response::Waiting => None,
135            Response::Done(r) => r,
136        }
137    }
138}
139
140impl<T: VarValue> ResponseVar<T> {
141    /// Visit the response, if present.
142    pub fn with_rsp<R>(&self, read: impl FnOnce(&T) -> R) -> Option<R> {
143        self.with(|value| match value {
144            Response::Waiting => None,
145            Response::Done(value) => Some(read(value)),
146        })
147    }
148
149    /// Visit the response, if present and new.
150    pub fn with_new_rsp<R>(&self, read: impl FnOnce(&T) -> R) -> Option<R> {
151        self.with_new(|value| match value {
152            Response::Waiting => None,
153            Response::Done(value) => Some(read(value)),
154        })
155        .flatten()
156    }
157
158    /// If the response is received.
159    pub fn is_done(&self) -> bool {
160        self.with(Response::is_done)
161    }
162
163    /// If the response is not received yet.
164    pub fn is_waiting(&self) -> bool {
165        self.with(Response::is_waiting)
166    }
167
168    /// Clone the response value, if present.
169    pub fn rsp(&self) -> Option<T> {
170        self.with_rsp(Clone::clone)
171    }
172
173    /// Returns a future that awaits until a response is received and then returns a clone.
174    pub async fn wait_rsp(&self) -> T {
175        self.wait_done().await;
176        self.rsp().unwrap()
177    }
178
179    /// Returns a future that awaits until a response is received.
180    ///
181    /// [`rsp`]: Self::rsp
182    pub async fn wait_done(&self) {
183        self.wait_match(Response::is_done).await;
184    }
185
186    /// Clone the response, if present and new.
187    pub fn rsp_new(&self) -> Option<T> {
188        self.with_new_rsp(Clone::clone)
189    }
190
191    /// Map the response value using `map`, if the variable is awaiting a response uses the `waiting_value` first.
192    pub fn map_rsp<O, I, M>(&self, waiting_value: I, map: M) -> Var<O>
193    where
194        O: VarValue,
195        I: Fn() -> O + Send + Sync + 'static,
196        M: FnOnce(&T) -> O + Send + 'static,
197    {
198        let mut map = Some(map);
199        self.filter_map(
200            move |r| match r {
201                Response::Waiting => None,
202                Response::Done(r) => map.take().map(|m| m(r)),
203            },
204            waiting_value,
205        )
206    }
207
208    /// Map to another response variable.
209    pub fn map_response<O, M>(&self, mut map: M) -> ResponseVar<O>
210    where
211        O: VarValue,
212        M: FnMut(&T) -> O + Send + 'static,
213    {
214        ResponseVar(self.map(move |r| match r {
215            Response::Waiting => Response::Waiting,
216            Response::Done(t) => Response::Done(map(t)),
217        }))
218    }
219}
220impl<T: VarValue> IntoFuture for ResponseVar<T> {
221    type Output = T;
222
223    // refactor after 'impl_trait_in_assoc_type' is stable
224    type IntoFuture = std::pin::Pin<Box<dyn Future<Output = T> + Send + Sync>>;
225
226    fn into_future(self) -> Self::IntoFuture {
227        Box::pin(async move { self.wait_rsp().await })
228    }
229}
230
231impl<T: VarValue> ResponderVar<T> {
232    /// Sets the one time response.
233    pub fn respond(&self, response: T) {
234        self.set(Response::Done(response));
235    }
236
237    /// Creates a [`ResponseVar`] linked to this responder.
238    pub fn response_var(&self) -> ResponseVar<T> {
239        ResponseVar(self.read_only())
240    }
241}