use std::future::IntoFuture;
use super::*;
pub fn response_var<T: VarValue>() -> (ResponderVar<T>, ResponseVar<T>) {
let responder = var(Response::Waiting::<T>);
let response = responder.read_only();
(responder, response)
}
pub fn response_done_var<T: VarValue>(response: T) -> ResponseVar<T> {
var(Response::Done(response)).read_only()
}
pub type ResponderVar<T> = ArcVar<Response<T>>;
pub type ResponseVar<T> = types::ReadOnlyVar<Response<T>, ArcVar<Response<T>>>;
#[derive(Clone, Copy, PartialEq)]
pub enum Response<T: VarValue> {
Waiting,
Done(T),
}
impl<T: VarValue> Response<T> {
pub fn is_done(&self) -> bool {
matches!(self, Response::Done(_))
}
pub fn is_waiting(&self) -> bool {
matches!(self, Response::Waiting)
}
pub fn done(&self) -> Option<&T> {
match self {
Response::Waiting => None,
Response::Done(r) => Some(r),
}
}
}
impl<T: VarValue> fmt::Debug for Response<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
match self {
Response::Waiting => {
write!(f, "Response::Waiting")
}
Response::Done(v) => f.debug_tuple("Response::Done").field(v).finish(),
}
} else {
match self {
Response::Waiting => {
write!(f, "Waiting")
}
Response::Done(v) => fmt::Debug::fmt(v, f),
}
}
}
}
impl<T: VarValue> From<Response<T>> for Option<T> {
fn from(value: Response<T>) -> Self {
match value {
Response::Waiting => None,
Response::Done(r) => Some(r),
}
}
}
impl<T: VarValue> ResponseVar<T> {
pub fn with_rsp<R>(&self, read: impl FnOnce(&T) -> R) -> Option<R> {
self.with(|value| match value {
Response::Waiting => None,
Response::Done(value) => Some(read(value)),
})
}
pub fn with_new_rsp<R>(&self, read: impl FnOnce(&T) -> R) -> Option<R> {
self.with_new(|value| match value {
Response::Waiting => None,
Response::Done(value) => Some(read(value)),
})
.flatten()
}
pub fn is_done(&self) -> bool {
self.with(Response::is_done)
}
pub fn is_waiting(&self) -> bool {
self.with(Response::is_waiting)
}
pub fn rsp(&self) -> Option<T> {
self.with_rsp(Clone::clone)
}
pub async fn wait_rsp(&self) -> T {
self.wait_done().await;
self.rsp().unwrap()
}
pub async fn wait_into_rsp(self) -> T {
self.wait_done().await;
self.into_rsp().unwrap()
}
pub async fn wait_done(&self) {
self.wait_value(Response::is_done).await;
}
pub fn rsp_new(&self) -> Option<T> {
self.with_new_rsp(Clone::clone)
}
pub fn into_rsp(self) -> Option<T> {
self.into_value().into()
}
pub fn map_rsp<O, I, M>(&self, waiting_value: I, map: M) -> impl Var<O>
where
O: VarValue,
I: Fn() -> O + Send + Sync + 'static,
M: FnOnce(&T) -> O + Send + 'static,
{
let mut map = Some(map);
self.filter_map(
move |r| match r {
Response::Waiting => None,
Response::Done(r) => map.take().map(|m| m(r)),
},
waiting_value,
)
}
pub fn map_response<O, M>(&self, mut map: M) -> ResponseVar<O>
where
O: VarValue,
M: FnMut(&T) -> O + Send + 'static,
{
self.map(move |r| match r {
Response::Waiting => Response::Waiting,
Response::Done(t) => Response::Done(map(t)),
})
}
}
impl<T: VarValue> IntoFuture for ResponseVar<T> {
type Output = T;
type IntoFuture = std::pin::Pin<Box<dyn Future<Output = T> + Send + Sync>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.wait_into_rsp())
}
}
impl<T: VarValue> ResponderVar<T> {
pub fn respond(&self, response: T) {
self.set(Response::Done(response));
}
pub fn response_var(&self) -> ResponseVar<T> {
self.read_only()
}
}