diff --git a/Cargo.lock b/Cargo.lock index d72e08ebd..4837e341c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -523,7 +523,7 @@ dependencies = [ "proc-macro2 1.0.86", "quote 1.0.36", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", "syn 2.0.68", ] @@ -595,15 +595,6 @@ dependencies = [ "toml", ] -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "memchr", -] - [[package]] name = "bstr" version = "1.9.1" @@ -1495,11 +1486,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.3.31" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" dependencies = [ "serde", + "typeid", ] [[package]] @@ -1608,7 +1600,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f40529622e8c4e7c28f600abb501b0ca07047d4e15d576aff1837cca8318ab6" dependencies = [ "anyhow", - "bstr 1.9.1", + "bstr", "regex", "walkdir", ] @@ -2014,7 +2006,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98bf257dbe2c3df82648395943dfbcb113100235e4f7dea079fdf012e6a7ff3" dependencies = [ - "rustc-hash", + "rustc-hash 1.1.0", ] [[package]] @@ -2991,12 +2983,12 @@ dependencies = [ [[package]] name = "luajit-src" -version = "210.4.8+resty107baaf" +version = "210.5.8+5790d25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05167e8b2a2185758d83ed23541e5bd8bce37072e4204e0ef2c9b322bc87c4e" +checksum = "441f18d9ad792e871fc2f7f2cb8902c386f6f56fdbddef3b835b61475e375346" dependencies = [ "cc", - "which 4.4.2", + "which 6.0.1", ] [[package]] @@ -3294,23 +3286,48 @@ dependencies = [ [[package]] name = "mlua" -version = "0.8.10" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb37b0ba91f017aa7ca2b98ef99496827770cd635b4a932a6047c5b4bbe678e" +checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7" dependencies = [ - "bstr 0.2.17", - "cc", + "bstr", "erased-serde", - "futures-core", - "futures-task", "futures-util", - "lua-src", - "luajit-src", + "mlua-sys", + "mlua_derive", "num-traits", "once_cell", - "pkg-config", - "rustc-hash", + "rustc-hash 2.0.0", "serde", + "serde-value", +] + +[[package]] +name = "mlua-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a088ed0723df7567f569ba018c5d48c23c501f3878b190b04144dfa5ebfa8abc" +dependencies = [ + "cc", + "cfg-if", + "lua-src", + "luajit-src", + "pkg-config", +] + +[[package]] +name = "mlua_derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09697a6cec88e7f58a02c7ab5c18c611c6907c8654613df9cc0192658a4fb859" +dependencies = [ + "itertools 0.12.1", + "once_cell", + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.36", + "regex", + "syn 2.0.68", ] [[package]] @@ -3840,6 +3857,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-float" version = "4.2.0" @@ -4698,6 +4724,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc_version" version = "0.4.0" @@ -4941,6 +4973,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float 2.10.1", + "serde", +] + [[package]] name = "serde-xml-rs" version = "0.5.1" @@ -6151,6 +6193,12 @@ dependencies = [ "utf-8", ] +[[package]] +name = "typeid" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf" + [[package]] name = "typenum" version = "1.17.0" diff --git a/Cargo.toml b/Cargo.toml index 8db6c6eb6..513b7cbd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ ed25519-dalek = "2.0" futures = "0.3.28" libunbound = {git="https://github.com/KumoCorp/libunbound-rs.git", rev="f00c353e7d0f37952206e41e3f4615edc1a606e4"} metrics = "0.22" -mlua = "0.8" +mlua = "0.9" once_cell = "1.17" openssl = { version="=0.10.60" } # pinned; see patch below openssl-sys = { version="0.9" } diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 3b7c2e60a..02e53808a 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -1,5 +1,5 @@ use anyhow::Context; -use mlua::{FromLua, FromLuaMulti, Lua, LuaSerdeExt, RegistryKey, Table, ToLuaMulti, Value}; +use mlua::{FromLua, FromLuaMulti, IntoLuaMulti, Lua, LuaSerdeExt, RegistryKey, Table, Value}; use parking_lot::FairMutex as Mutex; use serde::Serialize; use std::borrow::Cow; @@ -215,7 +215,7 @@ pub async fn load_config() -> anyhow::Result { let func = { let chunk = lua.load(&code); - let chunk = chunk.set_name(policy.to_string_lossy())?; + let chunk = chunk.set_name(policy.to_string_lossy()); chunk.into_function()? }; @@ -260,7 +260,7 @@ impl LuaConfig { match lua .lua - .named_registry_value::<_, mlua::Function>(&decorated_name) + .named_registry_value::(&decorated_name) { Ok(func) => Ok(func.call_async(args).await?), _ => anyhow::bail!("{name} has not been registered"), @@ -269,7 +269,7 @@ impl LuaConfig { pub async fn async_call_callback< 'lua, - A: ToLuaMulti<'lua> + Clone, + A: IntoLuaMulti<'lua> + Clone, R: FromLuaMulti<'lua> + Default, >( &'lua mut self, @@ -284,7 +284,7 @@ impl LuaConfig { if sig.allow_multiple() { return match lua .lua - .named_registry_value::<_, mlua::Value>(&decorated_name)? + .named_registry_value::(&decorated_name)? { Value::Table(tbl) => { for func in tbl.sequence_values::() { @@ -305,7 +305,7 @@ impl LuaConfig { match lua .lua - .named_registry_value::<_, mlua::Function>(&decorated_name) + .named_registry_value::(&decorated_name) { Ok(func) => Ok(func.call_async(args.clone()).await?), _ => Ok(R::default()), @@ -314,7 +314,7 @@ impl LuaConfig { pub async fn async_call_callback_non_default< 'lua, - A: ToLuaMulti<'lua> + Clone, + A: IntoLuaMulti<'lua> + Clone, R: FromLuaMulti<'lua>, >( &'lua mut self, @@ -329,7 +329,7 @@ impl LuaConfig { if sig.allow_multiple() { match lua .lua - .named_registry_value::<_, mlua::Value>(&decorated_name)? + .named_registry_value::(&decorated_name)? { Value::Table(tbl) => { for func in tbl.sequence_values::() { @@ -350,7 +350,7 @@ impl LuaConfig { match lua .lua - .named_registry_value::<_, mlua::Function>(&decorated_name) + .named_registry_value::(&decorated_name) { Ok(func) => Ok(func.call_async(args.clone()).await?), _ => anyhow::bail!("Event {name} has not been registered"), @@ -359,7 +359,7 @@ impl LuaConfig { pub async fn async_call_callback_non_default_opt< 'lua, - A: ToLuaMulti<'lua> + Clone, + A: IntoLuaMulti<'lua> + Clone, R: FromLua<'lua>, >( &'lua mut self, @@ -374,7 +374,7 @@ impl LuaConfig { if sig.allow_multiple() { return match lua .lua - .named_registry_value::<_, mlua::Value>(&decorated_name)? + .named_registry_value::(&decorated_name)? { Value::Table(tbl) => { for func in tbl.sequence_values::() { @@ -423,7 +423,7 @@ impl LuaConfig { /// Call a constructor registered via `on`. Returns a registry key that can be /// used to reference the returned value again later on this same Lua instance - pub async fn async_call_ctor<'lua, A: ToLuaMulti<'lua> + Clone>( + pub async fn async_call_ctor<'lua, A: IntoLuaMulti<'lua> + Clone>( &'lua mut self, sig: &CallbackSignature<'lua, A, Value<'lua>>, args: A, @@ -441,7 +441,7 @@ impl LuaConfig { let func = inner .lua - .named_registry_value::<_, mlua::Function>(&decorated_name)?; + .named_registry_value::(&decorated_name)?; let value: Value = func.call_async(args.clone()).await?; drop(func); @@ -536,7 +536,7 @@ pub fn any_err(err: E) -> mlua::Error { /// with a slightly more helpful error message in case of failure. pub fn from_lua_value<'lua, R>(lua: &'lua Lua, value: mlua::Value<'lua>) -> mlua::Result where - R: serde::Deserialize<'lua>, + R: serde::de::DeserializeOwned, { let value_cloned = value.clone(); lua.from_value(value).map_err(|err| { @@ -569,7 +569,7 @@ where /// until one of them returns a value. pub struct CallbackSignature<'lua, A, R> where - A: ToLuaMulti<'lua>, + A: IntoLuaMulti<'lua>, R: FromLuaMulti<'lua>, { marker: std::marker::PhantomData<&'lua (A, R)>, @@ -579,7 +579,7 @@ where impl<'lua, A, R> CallbackSignature<'lua, A, R> where - A: ToLuaMulti<'lua>, + A: IntoLuaMulti<'lua>, R: FromLuaMulti<'lua>, { pub fn new>>(name: S) -> Self { diff --git a/crates/kumo-api-types/src/egress_path.rs b/crates/kumo-api-types/src/egress_path.rs index 0e4ec283a..c94d49f1e 100644 --- a/crates/kumo-api-types/src/egress_path.rs +++ b/crates/kumo-api-types/src/egress_path.rs @@ -42,6 +42,7 @@ impl Default for Tls { } #[derive(Deserialize, Debug, Clone, PartialEq)] +#[cfg_attr(feature = "lua", derive(FromLua))] #[serde(deny_unknown_fields)] pub struct EgressPathConfig { #[serde(default = "EgressPathConfig::default_connection_limit")] diff --git a/crates/kumo-api-types/src/shaping.rs b/crates/kumo-api-types/src/shaping.rs index 4d571db3a..3743165fb 100644 --- a/crates/kumo-api-types/src/shaping.rs +++ b/crates/kumo-api-types/src/shaping.rs @@ -337,7 +337,7 @@ impl ShapingInner { } #[cfg(feature = "lua")] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, mlua::FromLua)] pub struct Shaping { inner: Arc, } diff --git a/crates/kumo-server-common/src/lib.rs b/crates/kumo-server-common/src/lib.rs index 6f685827d..d3b2b4f03 100644 --- a/crates/kumo-server-common/src/lib.rs +++ b/crates/kumo-server-common/src/lib.rs @@ -59,7 +59,7 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { source .short_src .as_ref() - .map(|b| String::from_utf8_lossy(b).to_string()) + .map(|b| b.to_string()) .unwrap_or_else(String::new), info.curr_line() )); @@ -140,10 +140,8 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { Value::Nil => {} Value::Function(func) => { let info = func.info(); - let src = String::from_utf8_lossy( - info.source.as_ref().map(|v| v.as_slice()).unwrap_or(b"?"), - ); - let line = info.line_defined; + let src = info.source.unwrap_or_else(|| "?".into()); + let line = info.line_defined.unwrap_or(0); return Err(mlua::Error::external(format!( "{name} event already has a handler defined at {src}:{line}" ))); @@ -225,9 +223,9 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { name_what: Option, source: Option, short_src: Option, - line_defined: i32, - last_line_defined: i32, - what: Option, + line_defined: Option, + last_line_defined: Option, + what: &'static str, curr_line: i32, is_tail_call: bool, } @@ -244,26 +242,11 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { event: format!("{:?}", info.event()), last_line_defined: source.last_line_defined, line_defined: source.line_defined, - name: names - .name - .as_ref() - .map(|b| String::from_utf8_lossy(b).to_string()), - name_what: names - .name_what - .as_ref() - .map(|b| String::from_utf8_lossy(b).to_string()), - source: source - .source - .as_ref() - .map(|b| String::from_utf8_lossy(b).to_string()), - short_src: source - .short_src - .as_ref() - .map(|b| String::from_utf8_lossy(b).to_string()), - what: source - .what - .as_ref() - .map(|b| String::from_utf8_lossy(b).to_string()), + name: names.name.as_ref().map(|b| b.to_string()), + name_what: names.name_what.as_ref().map(|b| b.to_string()), + source: source.source.as_ref().map(|b| b.to_string()), + short_src: source.short_src.as_ref().map(|b| b.to_string()), + what: source.what, }); } None => break, diff --git a/crates/kumod/src/egress_source.rs b/crates/kumod/src/egress_source.rs index fc279e440..1fb71f2a6 100644 --- a/crates/kumod/src/egress_source.rs +++ b/crates/kumod/src/egress_source.rs @@ -23,7 +23,7 @@ lazy_static::lazy_static! { static ref POOLS: Mutex> = Mutex::new(LruCacheWithTtl::new(128)); } -#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Debug, Clone, PartialEq, Eq, mlua::FromLua)] #[serde(deny_unknown_fields)] pub struct EgressSource { /// Give it a friendly name for use in reporting and referencing @@ -206,7 +206,7 @@ impl EgressSource { } } -#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, mlua::FromLua)] #[serde(deny_unknown_fields)] pub struct EgressPoolEntry { /// Name of an EgressSource to include in this pool @@ -229,7 +229,7 @@ impl EgressPoolEntry { } } -#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, mlua::FromLua)] #[serde(deny_unknown_fields)] pub struct EgressPool { /// Name of the pool diff --git a/crates/kumod/src/queue.rs b/crates/kumod/src/queue.rs index cc2a8afb6..f232252c6 100644 --- a/crates/kumod/src/queue.rs +++ b/crates/kumod/src/queue.rs @@ -155,7 +155,7 @@ impl Default for DeliveryProto { } } -#[derive(Deserialize, Serialize, Debug, Clone)] +#[derive(Deserialize, Serialize, Debug, Clone, FromLua)] #[serde(deny_unknown_fields)] pub struct QueueConfig { /// Base retry interval to use in exponential backoff diff --git a/crates/kumod/src/smtp_server.rs b/crates/kumod/src/smtp_server.rs index bec92d4a6..f2ffa863c 100644 --- a/crates/kumod/src/smtp_server.rs +++ b/crates/kumod/src/smtp_server.rs @@ -18,7 +18,7 @@ use mailparsing::ConformanceDisposition; use memchr::memmem::Finder; use message::{EnvelopeAddress, Message}; use mlua::prelude::LuaUserData; -use mlua::{FromLuaMulti, LuaSerdeExt, ToLuaMulti, UserData, UserDataMethods}; +use mlua::{FromLuaMulti, IntoLuaMulti, LuaSerdeExt, UserData, UserDataMethods}; use once_cell::sync::{Lazy, OnceCell}; use parking_lot::FairMutex as Mutex; use prometheus::{IntCounter, IntGauge}; @@ -58,7 +58,7 @@ pub fn set_smtpsrv_threads(n: usize) { SMTPSRV_THREADS.store(n, Ordering::SeqCst); } -#[derive(Deserialize, Clone, Debug, Default, Serialize)] +#[derive(Deserialize, Clone, Debug, Default, Serialize, mlua::FromLua)] #[serde(deny_unknown_fields)] pub struct EsmtpDomain { #[serde(default)] @@ -846,7 +846,7 @@ impl SmtpServer { 'lua, R: for<'a> FromLuaMulti<'a> + Default + serde::Serialize, S: Into>, - A: for<'a> ToLuaMulti<'a> + Clone, + A: for<'a> IntoLuaMulti<'a> + Clone, >( &'lua mut self, name: S, diff --git a/crates/message/src/dkim.rs b/crates/message/src/dkim.rs index 34b270b39..9103e05d0 100644 --- a/crates/message/src/dkim.rs +++ b/crates/message/src/dkim.rs @@ -109,7 +109,7 @@ impl SignerConfig { } } -#[derive(Clone)] +#[derive(Clone, mlua::FromLua)] pub struct Signer(Arc); impl Signer { diff --git a/crates/message/src/message.rs b/crates/message/src/message.rs index b5d8eb5a0..44c6d9991 100644 --- a/crates/message/src/message.rs +++ b/crates/message/src/message.rs @@ -69,6 +69,7 @@ struct MessageInner { } #[derive(Clone, Debug)] +#[cfg_attr(feature = "impl", derive(mlua::FromLua))] pub struct Message { id: SpoolId, inner: Arc>, diff --git a/crates/mod-http/src/lib.rs b/crates/mod-http/src/lib.rs index 616f059c2..453c47828 100644 --- a/crates/mod-http/src/lib.rs +++ b/crates/mod-http/src/lib.rs @@ -314,7 +314,7 @@ impl LuaUserData for ResponseWrapper { // Headermap --- -#[derive(Clone)] +#[derive(Clone, mlua::FromLua)] struct HeaderMapWrapper(HeaderMap); impl LuaUserData for HeaderMapWrapper { diff --git a/crates/mod-memoize/Cargo.toml b/crates/mod-memoize/Cargo.toml index 26acf41b9..4da0864b3 100644 --- a/crates/mod-memoize/Cargo.toml +++ b/crates/mod-memoize/Cargo.toml @@ -12,6 +12,6 @@ duration-serde = {path="../duration-serde"} lruttl = {path="../lruttl"} tokio = {workspace=true, features=["sync"]} once_cell = "1.17" -mlua = {workspace=true, features=["vendored", "lua54", "async", "send", "serialize"]} +mlua = {workspace=true, features=["vendored", "lua54", "async", "macros", "send", "serialize"]} serde = {version="1.0", features=["derive"]} serde_json = "1.0" diff --git a/crates/mod-memoize/src/lib.rs b/crates/mod-memoize/src/lib.rs index 0660a8d34..e027ace1d 100644 --- a/crates/mod-memoize/src/lib.rs +++ b/crates/mod-memoize/src/lib.rs @@ -1,6 +1,6 @@ use config::{any_err, from_lua_value, get_or_create_module, serialize_options}; use lruttl::LruCacheWithTtl; -use mlua::{FromLua, Function, Lua, LuaSerdeExt, MultiValue, ToLua, UserData, UserDataMethods}; +use mlua::{FromLua, Function, IntoLua, Lua, LuaSerdeExt, MultiValue, UserData, UserDataMethods}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -21,7 +21,7 @@ use tokio::sync::{OwnedSemaphorePermit, Semaphore, TryAcquireError}; /// /// Since Clone is used, it is recommended that you use an Arc inside your /// type to avoid making large or expensive clones. -#[derive(Clone)] +#[derive(Clone, mlua::FromLua)] pub struct Memoized { pub to_value: Arc mlua::Result + Send + Sync>, } @@ -45,7 +45,7 @@ impl Memoized { move |_lua, this, _: ()| -> mlua::Result { let this = this.clone(); Ok(Memoized { - to_value: Arc::new(move |lua| this.clone().to_lua(lua)), + to_value: Arc::new(move |lua| this.clone().into_lua(lua)), }) }, ); @@ -117,8 +117,8 @@ impl<'lua> FromLua<'lua> for CacheValue { } } -impl<'lua> ToLua<'lua> for CacheValue { - fn to_lua(self, lua: &'lua Lua) -> mlua::Result> { +impl<'lua> IntoLua<'lua> for CacheValue { + fn into_lua(self, lua: &'lua Lua) -> mlua::Result> { self.as_lua(lua) } } @@ -156,7 +156,7 @@ impl CacheEntry { for v in values { result.push(v.as_lua(lua)?); } - result.to_lua(lua) + result.into_lua(lua) } } } diff --git a/crates/mod-sqlite/src/lib.rs b/crates/mod-sqlite/src/lib.rs index 77b95dbae..98472a148 100644 --- a/crates/mod-sqlite/src/lib.rs +++ b/crates/mod-sqlite/src/lib.rs @@ -141,6 +141,15 @@ impl Conn { Ok(JsonValue::Array(table)) } + + async fn async_execute(self, sql: String, params: JsonValue) -> anyhow::Result { + tokio::task::Builder::new() + .name(&format!("sqlite {sql}")) + .spawn_blocking(move || -> anyhow::Result { self.execute(sql, params) }) + .map_err(any_err)? + .await + .map_err(any_err)? + } } impl UserData for Conn { @@ -149,14 +158,10 @@ impl UserData for Conn { "execute", |lua, this, (sql, params): (String, MultiValue)| async move { let json_params = params_to_json(lua, params)?; - let result: JsonValue = tokio::task::Builder::new() - .name(&format!("sqlite {sql}")) - .spawn_blocking(move || -> anyhow::Result { - this.execute(sql, json_params) - }) - .map_err(any_err)? + let result = this + .clone() + .async_execute(sql, json_params) .await - .map_err(any_err)? .map_err(any_err)?; let result: Value = lua