feat: Allow for multiple callbacks inside of an ActionCallback

This also results in the conversion being performed when the
ActionCallback is instantiated instead of when it is called, this should
make it easier to catch errors.
This commit is contained in:
2025-09-08 02:11:05 +02:00
parent 0c428d1d9b
commit 379d840158
2 changed files with 31 additions and 6 deletions

View File

@@ -1,11 +1,12 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use futures::future::try_join_all;
use mlua::{FromLua, IntoLua, LuaSerdeExt}; use mlua::{FromLua, IntoLua, LuaSerdeExt};
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Internal { struct Internal {
value: mlua::Value, callbacks: Vec<mlua::Function>,
lua: mlua::Lua, lua: mlua::Lua,
} }
@@ -28,9 +29,28 @@ impl<T, S> Default for ActionCallback<T, S> {
impl<T, S> FromLua for ActionCallback<T, S> { impl<T, S> FromLua for ActionCallback<T, S> {
fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Self> { fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Self> {
let callbacks = match value {
mlua::Value::Function(f) => vec![f],
mlua::Value::Table(table) => table
.pairs::<mlua::Value, mlua::Function>()
.map(|pair| {
let (_, f) = pair?;
Ok::<_, mlua::Error>(f)
})
.try_collect()?,
_ => {
return Err(mlua::Error::FromLuaConversionError {
from: value.type_name(),
to: "ActionCallback".into(),
message: Some("expected function or table of functions".into()),
});
}
};
Ok(ActionCallback { Ok(ActionCallback {
internal: Some(Internal { internal: Some(Internal {
value, callbacks,
lua: lua.clone(), lua: lua.clone(),
}), }),
_this: PhantomData::<T>, _this: PhantomData::<T>,
@@ -52,10 +72,14 @@ where
let state = internal.lua.to_value(state).unwrap(); let state = internal.lua.to_value(state).unwrap();
match &internal.value { try_join_all(
mlua::Value::Function(f) => f.call_async::<()>((this.clone(), state)).await.unwrap(), internal
_ => todo!("Only functions are currently supported"), .callbacks
} .iter()
.map(async |f| f.call_async::<()>((this.clone(), state.clone())).await),
)
.await
.unwrap();
} }
pub fn is_set(&self) -> bool { pub fn is_set(&self) -> bool {

View File

@@ -1,4 +1,5 @@
#![allow(incomplete_features)] #![allow(incomplete_features)]
#![feature(iterator_try_collect)]
pub mod action_callback; pub mod action_callback;
pub mod config; pub mod config;