50 lines
1.4 KiB
Rust
50 lines
1.4 KiB
Rust
use std::borrow::Cow;
|
|
use std::rc::Rc;
|
|
|
|
use futures::future::LocalBoxFuture;
|
|
use never::Never;
|
|
use orchid_base::{Receipt, ReqHandle, ReqHandleExt};
|
|
|
|
use crate::gen_expr::{GExpr, new_atom, serialize};
|
|
use crate::std_reqs::RunCommand;
|
|
use crate::{Atomic, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports, ToExpr};
|
|
|
|
pub trait AsyncFnDyn {
|
|
fn call<'a>(&'a self) -> LocalBoxFuture<'a, Option<GExpr>>;
|
|
}
|
|
impl<T: AsyncFn() -> Option<GExpr>> AsyncFnDyn for T {
|
|
fn call<'a>(&'a self) -> LocalBoxFuture<'a, Option<GExpr>> { Box::pin(async { (self)().await }) }
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct CmdAtom(Rc<dyn AsyncFnDyn>);
|
|
impl Atomic for CmdAtom {
|
|
type Data = ();
|
|
type Variant = OwnedVariant;
|
|
fn reg_methods() -> MethodSetBuilder<Self> { MethodSetBuilder::new().handle::<RunCommand>() }
|
|
}
|
|
impl Supports<RunCommand> for CmdAtom {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: RunCommand,
|
|
) -> std::io::Result<Receipt<'a>> {
|
|
let reply = self.0.call().await;
|
|
match reply {
|
|
None => hand.reply(&req, &None).await,
|
|
Some(next) => hand.reply(&req, &Some(serialize(next).await)).await,
|
|
}
|
|
}
|
|
}
|
|
impl OwnedAtom for CmdAtom {
|
|
type Refs = Never;
|
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
|
}
|
|
|
|
pub fn cmd<R: ToExpr>(f: impl AsyncFn() -> Option<R> + Clone + 'static) -> GExpr {
|
|
new_atom(CmdAtom(Rc::new(async move || match f().await {
|
|
None => None,
|
|
Some(r) => Some(r.to_gen().await),
|
|
})))
|
|
}
|