From c3a2b2d56658dfef8829c0d34eee7de387a3d4b9 Mon Sep 17 00:00:00 2001 From: Soispha Date: Mon, 17 Jul 2023 07:27:51 +0200 Subject: [PATCH] Fix(lua): Switch to mlua library, as it's better than rlua --- Cargo.lock | 49 +++++++++---------- Cargo.toml | 2 +- flake.nix | 1 + lua_macros/src/mark_as_ci_command.rs | 37 +++++++------- lua_macros/src/struct_to_ci_enum.rs | 14 +++--- src/app/command_interface.rs | 7 +-- .../event_types/event/handlers/lua_command.rs | 20 ++++---- src/app/mod.rs | 13 +++-- src/app/transmitter.rs | 11 ----- 9 files changed, 74 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0664b60..c5ca408 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1533,6 +1533,23 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "mlua" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07366ed2cd22a3b000aed076e2b68896fb46f06f1f5786c5962da73c0af01577" +dependencies = [ + "bstr", + "cc", + "futures-core", + "futures-task", + "futures-util", + "num-traits", + "once_cell", + "pkg-config", + "rustc-hash", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -2125,30 +2142,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "rlua" -version = "0.19.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d33e5ba15c3d43178f283ed5863d4531e292fc0e56fb773f3bea45f18e3a42a" -dependencies = [ - "bitflags", - "bstr", - "libc", - "num-traits", - "rlua-lua54-sys", -] - -[[package]] -name = "rlua-lua54-sys" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aafabafe1895cb4a2be81a56d7ff3d46bf4b5d2f9cfdbea2ed404cdabe96474" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "ruma" version = "0.7.4" @@ -2254,6 +2247,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.37.23" @@ -2706,7 +2705,7 @@ dependencies = [ "indexmap 2.0.0", "lua_macros", "matrix-sdk", - "rlua", + "mlua", "serde", "tokio", "tokio-util", diff --git a/Cargo.toml b/Cargo.toml index 55e4b6d..a714f8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,4 @@ tokio-util = "0.7" serde = "1.0" cli-log = "2.0" indexmap = "2.0.0" -rlua = "0.19.7" +mlua = { version = "0.8.9", features = ["lua54", "async"] } diff --git a/flake.nix b/flake.nix index 72bee03..e3a5d47 100644 --- a/flake.nix +++ b/flake.nix @@ -55,6 +55,7 @@ ]; buildInputs = with pkgs; [ openssl + lua54Packages.stdlib ]; craneBuild = craneLib.buildPackage { diff --git a/lua_macros/src/mark_as_ci_command.rs b/lua_macros/src/mark_as_ci_command.rs index 3a865db..f8185dc 100644 --- a/lua_macros/src/mark_as_ci_command.rs +++ b/lua_macros/src/mark_as_ci_command.rs @@ -97,35 +97,38 @@ fn append_tx_send_code(input: &mut syn::ItemFn) -> &mut syn::ItemFn { } _ => unimplemented!("Only for path types"), }; - match return_type { + let send_data = match return_type { ReturnType::Default => { quote! { { - let tx: std::sync::mpsc::Sender = - context - .named_registry_value("sender_for_ci_commands") - .expect("This exists, it was set before"); - - tx - .send(Event::CommandEvent(Command::#function_name_pascal)) - .expect("This should work, as the reciever is not dropped"); + Event::CommandEvent(Command::#function_name_pascal) } } } ReturnType::Type(_, _) => { quote! { { - let tx: std::sync::mpsc::Sender = - context - .named_registry_value("sender_for_ci_commands") - .expect("This exists, it was set before"); - - tx - .send(Event::CommandEvent(Command::#function_name_pascal(input_str))) - .expect("This should work, as the reciever is not dropped"); + Event::CommandEvent(Command::#function_name_pascal(input_str)) } } } + }; + quote! { + { + let tx: std::sync::Arc>> = + lua + .named_registry_value("sender_for_ci_commands") + .expect("This exists, it was set before"); + + tx + // FIXME: This is sync code, it needs to be run in a blocking allowed + // executor + .lock() + .expect("This should work, as only one function is executed. It wil however fail, when concurrency is added"); + .send(#send_data) + .await + .expect("This should work, as the reciever is not dropped"); + } } } }; diff --git a/lua_macros/src/struct_to_ci_enum.rs b/lua_macros/src/struct_to_ci_enum.rs index f231249..76b3fd1 100644 --- a/lua_macros/src/struct_to_ci_enum.rs +++ b/lua_macros/src/struct_to_ci_enum.rs @@ -22,10 +22,10 @@ pub fn generate_generate_ci_function(input: &syn::DeriveInput) -> TokenStream2 { .expect("These are only the named field, thus they all should have a name."); functions_to_generate.push(quote! { #[ci_command] - fn #function_name(context: Context, input_str: String) -> Result<(), rlua::Error> { + async fn #function_name(lua: &mlua::Lua, input_str: String) -> Result<(), mlua::Error> { Ok(()) } - }); + }); generate_ci_part(field) } else { generate_ci_part(field) @@ -41,11 +41,11 @@ pub fn generate_generate_ci_function(input: &syn::DeriveInput) -> TokenStream2 { let functions_to_generate: TokenStream2 = functions_to_generate.into_iter().collect(); let gen = quote! { pub fn generate_ci_functions( - context: &mut rlua::Context, - tx: std::sync::mpsc::Sender) + lua: &mut mlua::Lua, + tx: tokio::sync::mpsc::Sender) { - context.set_named_registry_value("sender_for_ci_commands", tx).expect("This should always work, as the value is added before all else"); - let globals = context.globals(); + lua.set_named_registry_value("sender_for_ci_commands", std::sync::Arc::new(std::sync::Mutex::new(tx))).expect("This should always work, as the value is added before all else"); + let globals = lua.globals(); #input_tokens } #functions_to_generate @@ -61,7 +61,7 @@ fn generate_ci_part(field: &syn::Field) -> TokenStream2 { let function_name_ident = format_ident!("fun_{}", field_ident); let function_name = format!("{}", field_ident); quote! { - let #function_name_ident = context.create_function(#field_ident).expect( + let #function_name_ident = lua.create_async_function(#field_ident).expect( &format!( "The function: `{}` should be defined", #function_name diff --git a/src/app/command_interface.rs b/src/app/command_interface.rs index 87f184d..6f09452 100644 --- a/src/app/command_interface.rs +++ b/src/app/command_interface.rs @@ -1,4 +1,5 @@ // FIXME: This file needs documentation with examples of how the proc macros work. +// for now use `cargo expand app::command_interface` for an overview use lua_macros::{ci_command, turn_struct_to_ci_commands}; use rlua::Context; @@ -21,7 +22,7 @@ use super::events::event_types::Event; /// where $return_type is the type returned by the function (the only supported ones are right now /// `String` and `()`). #[turn_struct_to_ci_commands] -struct Commands<'lua> { +struct Commands { greet: fn(usize) -> String, // Closes the application @@ -42,11 +43,11 @@ struct Commands<'lua> { } #[ci_command] -fn greet(context: Context, input_str: String) -> Result { +async fn greet(lua: &mlua::Lua, input_str: String) -> Result { Ok(format!("Name is {}", input_str)) } #[ci_command] -fn room_message_send(context: Context, input_str: String) -> Result { +async fn room_message_send(lua: &mlua::Lua, input_str: String) -> Result { Ok(format!("Sent message: {}", input_str)) } diff --git a/src/app/events/event_types/event/handlers/lua_command.rs b/src/app/events/event_types/event/handlers/lua_command.rs index ac459e6..5994a4f 100644 --- a/src/app/events/event_types/event/handlers/lua_command.rs +++ b/src/app/events/event_types/event/handlers/lua_command.rs @@ -1,20 +1,22 @@ use anyhow::{Context, Result}; use cli_log::info; -use crate::app::{App, events::event_types::{EventStatus, Event}}; +use crate::app::{ + events::event_types::{Event, EventStatus}, + App, +}; pub async fn handle(app: &mut App<'_>, command: &str) -> Result { info!("Recieved ci command: `{command}`; executing.."); // TODO: Should the ci support more than strings? - let output = app.lua.context(|context| -> Result { - let output = context - .load(&command) - .eval::() - .with_context(|| format!("Failed to execute: `{command}`"))?; - info!("Function evaluated to: `{output}`"); - Ok(output) - })?; + let output = app + .lua + .load(command) + .eval_async::() + .await + .with_context(|| format!("Failed to execute: `{command}`"))?; + info!("Function evaluated to: `{output}`"); app.transmitter.send(Event::CiOutput(output)); diff --git a/src/app/mod.rs b/src/app/mod.rs index d4fc374..058f8ef 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -3,13 +3,14 @@ pub mod events; pub mod status; pub mod transmitter; -use std::{path::Path, sync::mpsc::Sender as StdSender}; +use std::path::Path; use anyhow::{Context, Error, Result}; use cli_log::info; use matrix_sdk::Client; -use rlua::Lua; +use mlua::Lua; use status::{State, Status}; +use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; use crate::{ @@ -34,12 +35,10 @@ pub struct App<'ui> { impl App<'_> { pub fn new() -> Result { - fn set_up_lua(tx: StdSender) -> Lua { + fn set_up_lua(tx: mpsc::Sender) -> Lua { let lua = Lua::new(); - lua.context(|mut lua_context| { - generate_ci_functions(&mut lua_context, tx); - }); + generate_ci_functions(&mut lua, tx); lua } @@ -61,7 +60,7 @@ impl App<'_> { input_listener_killer: CancellationToken::new(), matrix_listener_killer: CancellationToken::new(), - lua: set_up_lua(transmitter.std_tx()), + lua: set_up_lua(transmitter.tx()), }) } diff --git a/src/app/transmitter.rs b/src/app/transmitter.rs index c887459..aaa96b6 100644 --- a/src/app/transmitter.rs +++ b/src/app/transmitter.rs @@ -1,5 +1,3 @@ -use std::sync::mpsc as StdMpsc; - use anyhow::{bail, Context, Result}; use tokio::sync::mpsc; @@ -8,29 +6,20 @@ use super::events::event_types::Event; pub struct Transmitter { tx: mpsc::Sender, rx: mpsc::Receiver, - std_tx: StdMpsc::Sender, - std_rx: StdMpsc::Receiver, } impl Transmitter { pub fn new() -> Transmitter { - let (std_tx, std_rx) = StdMpsc::channel(); let (tx, rx) = mpsc::channel(256); Transmitter { tx, rx, - std_tx, - std_rx, } } pub fn tx(&self) -> mpsc::Sender { self.tx.to_owned() } - pub fn std_tx(&self) -> StdMpsc::Sender { - self.std_tx.to_owned() - } - pub async fn recv(&mut self) -> Result { match self.rx.recv().await { Some(event) => Ok(event),