diff --git a/Cargo.toml b/Cargo.toml
index e75bc90..c3309c3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,9 +2,12 @@
name = "mlua-luau-runtime"
version = "0.0.0"
edition = "2021"
-
-[lib]
-path = "lib/lib.rs"
+license = "MPL-2.0"
+repository = "https://github.com/lune-org/mlua-luau-runtime"
+description = "Luau-based async runtime, using mlua and async-executor"
+readme = "README.md"
+keywords = ["async", "luau", "runtime"]
+categories = ["async"]
[dependencies]
async-executor = "1.8"
@@ -23,6 +26,14 @@ mlua = { version = "0.9.5", features = [
async-fs = "2.1"
async-io = "2.3"
+[lints.clippy]
+all = { level = "deny", priority = -3 }
+cargo = { level = "warn", priority = -2 }
+pedantic = { level = "warn", priority = -1 }
+
+[lib]
+path = "lib/lib.rs"
+
[[example]]
name = "basic_sleep"
test = true
diff --git a/README.md b/README.md
index 22bebc8..53ba5b3 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
-Luau-based async runtime for [`mlua`](https://crates.io/crates/mlua), built on top of [`async-executor`](https://crates.io/crates/async-executor).
+Luau-based async runtime, using [`mlua`](https://crates.io/crates/mlua) and [`async-executor`](https://crates.io/crates/async-executor).
## Example Usage
diff --git a/examples/basic_sleep.rs b/examples/basic_sleep.rs
index ed22106..1add4b4 100644
--- a/examples/basic_sleep.rs
+++ b/examples/basic_sleep.rs
@@ -1,9 +1,11 @@
+#![allow(clippy::missing_errors_doc)]
+
use std::time::{Duration, Instant};
use async_io::{block_on, Timer};
use mlua::prelude::*;
-use mlua_luau_runtime::*;
+use mlua_luau_runtime::Runtime;
const MAIN_SCRIPT: &str = include_str!("./lua/basic_sleep.luau");
@@ -20,7 +22,7 @@ pub fn main() -> LuaResult<()> {
)?;
// Load the main script into a runtime
- let rt = Runtime::new(&lua)?;
+ let rt = Runtime::new(&lua);
let main = lua.load(MAIN_SCRIPT);
rt.spawn_thread(main, ())?;
diff --git a/examples/basic_spawn.rs b/examples/basic_spawn.rs
index 3277d4e..1e9e319 100644
--- a/examples/basic_spawn.rs
+++ b/examples/basic_spawn.rs
@@ -1,10 +1,12 @@
+#![allow(clippy::missing_errors_doc)]
+
use std::io::ErrorKind;
use async_fs::read_to_string;
use async_io::block_on;
use mlua::prelude::*;
-use mlua_luau_runtime::*;
+use mlua_luau_runtime::{LuaSpawnExt, Runtime};
const MAIN_SCRIPT: &str = include_str!("./lua/basic_spawn.luau");
@@ -27,7 +29,7 @@ pub fn main() -> LuaResult<()> {
)?;
// Load the main script into a runtime
- let rt = Runtime::new(&lua)?;
+ let rt = Runtime::new(&lua);
let main = lua.load(MAIN_SCRIPT);
rt.spawn_thread(main, ())?;
diff --git a/examples/callbacks.rs b/examples/callbacks.rs
index 5b7cb9e..4c52a47 100644
--- a/examples/callbacks.rs
+++ b/examples/callbacks.rs
@@ -1,5 +1,7 @@
+#![allow(clippy::missing_errors_doc)]
+
use mlua::prelude::*;
-use mlua_luau_runtime::*;
+use mlua_luau_runtime::Runtime;
use async_io::block_on;
@@ -10,7 +12,7 @@ pub fn main() -> LuaResult<()> {
let lua = Lua::new();
// Create a new runtime with custom callbacks
- let rt = Runtime::new(&lua)?;
+ let rt = Runtime::new(&lua);
rt.set_error_callback(|e| {
println!(
"Captured error from Lua!\n{}\n{e}\n{}",
diff --git a/examples/lots_of_threads.rs b/examples/lots_of_threads.rs
index fc7e45b..ef6345c 100644
--- a/examples/lots_of_threads.rs
+++ b/examples/lots_of_threads.rs
@@ -1,9 +1,11 @@
+#![allow(clippy::missing_errors_doc)]
+
use std::time::Duration;
use async_io::{block_on, Timer};
use mlua::prelude::*;
-use mlua_luau_runtime::*;
+use mlua_luau_runtime::Runtime;
const MAIN_SCRIPT: &str = include_str!("./lua/lots_of_threads.luau");
@@ -12,7 +14,7 @@ const ONE_NANOSECOND: Duration = Duration::from_nanos(1);
pub fn main() -> LuaResult<()> {
// Set up persistent Lua environment
let lua = Lua::new();
- let rt = Runtime::new(&lua)?;
+ let rt = Runtime::new(&lua);
lua.globals().set("spawn", rt.create_spawn_function()?)?;
lua.globals().set(
diff --git a/examples/scheduler_ordering.rs b/examples/scheduler_ordering.rs
index 3817270..23f29bd 100644
--- a/examples/scheduler_ordering.rs
+++ b/examples/scheduler_ordering.rs
@@ -1,16 +1,18 @@
+#![allow(clippy::missing_errors_doc)]
+
use std::time::{Duration, Instant};
use async_io::{block_on, Timer};
use mlua::prelude::*;
-use mlua_luau_runtime::*;
+use mlua_luau_runtime::Runtime;
const MAIN_SCRIPT: &str = include_str!("./lua/scheduler_ordering.luau");
pub fn main() -> LuaResult<()> {
// Set up persistent Lua environment
let lua = Lua::new();
- let rt = Runtime::new(&lua)?;
+ let rt = Runtime::new(&lua);
lua.globals().set("spawn", rt.create_spawn_function()?)?;
lua.globals().set("defer", rt.create_defer_function()?)?;
diff --git a/lib/error_callback.rs b/lib/error_callback.rs
index 0e60908..9d8e0a2 100644
--- a/lib/error_callback.rs
+++ b/lib/error_callback.rs
@@ -31,6 +31,7 @@ impl ThreadErrorCallback {
}
}
+#[allow(clippy::needless_pass_by_value)]
fn default_error_callback(e: LuaError) {
eprintln!("{e}");
}
diff --git a/lib/queue.rs b/lib/queue.rs
index 56ace40..51e9ebf 100644
--- a/lib/queue.rs
+++ b/lib/queue.rs
@@ -6,8 +6,6 @@ use mlua::prelude::*;
use crate::IntoLuaThread;
-const ERR_OOM: &str = "out of memory";
-
/**
Queue for storing [`LuaThread`]s with associated arguments.
@@ -15,7 +13,7 @@ const ERR_OOM: &str = "out of memory";
well as listening for new items being pushed to the queue.
*/
#[derive(Debug, Clone)]
-pub struct ThreadQueue {
+pub(crate) struct ThreadQueue {
queue: Arc>,
event: Arc,
}
@@ -35,9 +33,9 @@ impl ThreadQueue {
) -> LuaResult<()> {
let thread = thread.into_lua_thread(lua)?;
let args = args.into_lua_multi(lua)?;
- let stored = ThreadWithArgs::new(lua, thread, args);
+ let stored = ThreadWithArgs::new(lua, thread, args)?;
- self.queue.push(stored).unwrap();
+ self.queue.push(stored).into_lua_err()?;
self.event.notify(usize::MAX);
Ok(())
@@ -61,7 +59,7 @@ impl ThreadQueue {
}
/**
- Representation of a [`LuaThread`] with associated arguments currently stored in the Lua registry.
+ Representation of a [`LuaThread`] with its associated arguments currently stored in the Lua registry.
*/
#[derive(Debug)]
struct ThreadWithArgs {
@@ -70,19 +68,23 @@ struct ThreadWithArgs {
}
impl ThreadWithArgs {
- pub fn new<'lua>(lua: &'lua Lua, thread: LuaThread<'lua>, args: LuaMultiValue<'lua>) -> Self {
+ fn new<'lua>(
+ lua: &'lua Lua,
+ thread: LuaThread<'lua>,
+ args: LuaMultiValue<'lua>,
+ ) -> LuaResult {
let argsv = args.into_vec();
- let key_thread = lua.create_registry_value(thread).expect(ERR_OOM);
- let key_args = lua.create_registry_value(argsv).expect(ERR_OOM);
+ let key_thread = lua.create_registry_value(thread)?;
+ let key_args = lua.create_registry_value(argsv)?;
- Self {
+ Ok(Self {
key_thread,
key_args,
- }
+ })
}
- pub fn into_inner(self, lua: &Lua) -> (LuaThread<'_>, LuaMultiValue<'_>) {
+ fn into_inner(self, lua: &Lua) -> (LuaThread<'_>, LuaMultiValue<'_>) {
let thread = lua.registry_value(&self.key_thread).unwrap();
let argsv = lua.registry_value(&self.key_args).unwrap();
diff --git a/lib/runtime.rs b/lib/runtime.rs
index 449c95d..9e48b86 100644
--- a/lib/runtime.rs
+++ b/lib/runtime.rs
@@ -23,17 +23,18 @@ impl<'lua> Runtime<'lua> {
This runtime will have a default error callback that prints errors to stderr.
*/
- pub fn new(lua: &'lua Lua) -> LuaResult> {
+ #[must_use]
+ pub fn new(lua: &'lua Lua) -> Runtime<'lua> {
let queue_spawn = ThreadQueue::new();
let queue_defer = ThreadQueue::new();
let error_callback = ThreadErrorCallback::default();
- Ok(Runtime {
+ Runtime {
lua,
queue_spawn,
queue_defer,
error_callback,
- })
+ }
}
/**
@@ -60,6 +61,10 @@ impl<'lua> Runtime<'lua> {
Spawns a chunk / function / thread onto the runtime queue.
Threads are guaranteed to be resumed in the order that they were pushed to the queue.
+
+ # Errors
+
+ Errors when out of memory.
*/
pub fn spawn_thread(
&self,
@@ -75,6 +80,10 @@ impl<'lua> Runtime<'lua> {
Deferred threads are guaranteed to run after all spawned threads either yield or complete.
Threads are guaranteed to be resumed in the order that they were pushed to the queue.
+
+ # Errors
+
+ Errors when out of memory.
*/
pub fn defer_thread(
&self,
@@ -88,6 +97,10 @@ impl<'lua> Runtime<'lua> {
Creates a Lua function that can be used to spawn threads / functions onto the runtime queue.
The function takes a thread or function as the first argument, and any variadic arguments as the rest.
+
+ # Errors
+
+ Errors when out of memory.
*/
pub fn create_spawn_function(&self) -> LuaResult> {
let error_callback = self.error_callback.clone();
@@ -123,6 +136,10 @@ impl<'lua> Runtime<'lua> {
The function takes a thread or function as the first argument, and any variadic arguments as the rest.
Deferred threads are guaranteed to run after all spawned threads either yield or complete.
+
+ # Errors
+
+ Errors when out of memory.
*/
pub fn create_defer_function(&self) -> LuaResult> {
let defer_queue = self.queue_defer.clone();
@@ -142,6 +159,10 @@ impl<'lua> Runtime<'lua> {
Note that the given Lua state must be the same one that was
used to create this runtime, otherwise this method will panic.
+
+ # Panics
+
+ Panics if the given Lua state already has a runtime attached to it.
*/
pub async fn run(&self) {
/*
@@ -164,13 +185,14 @@ impl<'lua> Runtime<'lua> {
Also ensure we do not already have an executor - this is a definite user error
and may happen if the user tries to run multiple runtimes on the same Lua state.
*/
- if self.lua.app_data_ref::>().is_some() {
- panic!(
- "Lua state already has an executor attached!\
- \nThis may be caused by running multiple runtimes on the same lua state, or a call to Runtime::run being cancelled.\
- \nOnly one runtime can be used per lua state at once, and runtimes must always run until completion."
- );
- }
+ assert!(
+ self.lua.app_data_ref::>().is_none(),
+ "\
+ Lua state already has an executor attached!\
+ \nThis may be caused by running multiple runtimes on the same Lua state, or a call to Runtime::run being cancelled.\
+ \nOnly one runtime can be used per Lua state at once, and runtimes must always run until completion.\
+ "
+ );
self.lua.set_app_data(Arc::downgrade(&main_exec));
/*
diff --git a/lib/traits.rs b/lib/traits.rs
index 6cfc2dc..c9f5170 100644
--- a/lib/traits.rs
+++ b/lib/traits.rs
@@ -15,6 +15,10 @@ use async_executor::{Executor, Task};
pub trait IntoLuaThread<'lua> {
/**
Converts the value into a Lua thread.
+
+ # Errors
+
+ Errors when out of memory.
*/
fn into_lua_thread(self, lua: &'lua Lua) -> LuaResult>;
}