Files
orchid/orchid-extension/src/cmd_atom.rs
Lawrence Bethlenfalvy 9b4c7fa7d7
Some checks failed
Rust / build (push) Has been cancelled
partway through fixes, macro system needs resdesign
2026-04-08 18:02:20 +02:00

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),
})))
}