use std::marker::PhantomData; use mlua::{FromLua, IntoLua, LuaSerdeExt}; use serde::Serialize; #[derive(Debug, Clone)] struct Internal { uuid: uuid::Uuid, lua: mlua::Lua, } #[derive(Debug, Clone)] pub struct ActionCallback { internal: Option, _this: PhantomData, _state: PhantomData, } impl Default for ActionCallback { fn default() -> Self { Self { internal: None, _this: PhantomData::, _state: PhantomData::, } } } impl FromLua for ActionCallback { fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result { let uuid = uuid::Uuid::new_v4(); lua.set_named_registry_value(&uuid.to_string(), value)?; Ok(ActionCallback { internal: Some(Internal { uuid, lua: lua.clone(), }), _this: PhantomData::, _state: PhantomData::, }) } } // TODO: Return proper error here impl ActionCallback where T: IntoLua + Sync + Send + Clone + 'static, S: Serialize, { pub async fn call(&self, this: &T, state: &S) { let Some(internal) = self.internal.as_ref() else { return; }; let state = internal.lua.to_value(state).unwrap(); let callback: mlua::Value = internal .lua .named_registry_value(&internal.uuid.to_string()) .unwrap(); match callback { mlua::Value::Function(f) => f.call_async::<()>((this.clone(), state)).await.unwrap(), _ => todo!("Only functions are currently supported"), } } pub fn is_set(&self) -> bool { self.internal.is_some() } }