diff --git a/crates/lune/src/lib.rs b/crates/lune/src/lib.rs index 4369179..9795f8d 100644 --- a/crates/lune/src/lib.rs +++ b/crates/lune/src/lib.rs @@ -8,4 +8,4 @@ pub use lune_roblox as roblox; #[cfg(test)] mod tests; -pub use crate::rt::{Runtime, RuntimeError}; +pub use crate::rt::{Runtime, RuntimeError, RuntimeResult}; diff --git a/crates/lune/src/rt/mod.rs b/crates/lune/src/rt/mod.rs index e3744e2..16393f1 100644 --- a/crates/lune/src/rt/mod.rs +++ b/crates/lune/src/rt/mod.rs @@ -1,104 +1,5 @@ -#![allow(clippy::missing_panics_doc)] +mod result; +mod runtime; -use std::{ - process::ExitCode, - rc::Rc, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, -}; - -use mlua::Lua; -use mlua_luau_scheduler::Scheduler; - -use lune_std::inject_globals; - -mod error; - -pub use error::RuntimeError; - -#[derive(Debug)] -pub struct Runtime { - lua: Rc, - args: Vec, -} - -impl Runtime { - /** - Creates a new Lune runtime, with a new Luau VM. - */ - #[must_use] - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - let lua = Rc::new(Lua::new()); - - lua.set_app_data(Rc::downgrade(&lua)); - lua.set_app_data(Vec::::new()); - - inject_globals(&lua).expect("Failed to inject globals"); - - Self { - lua, - args: Vec::new(), - } - } - - /** - Sets arguments to give in `process.args` for Lune scripts. - */ - #[must_use] - pub fn with_args(mut self, args: V) -> Self - where - V: Into>, - { - self.args = args.into(); - self.lua.set_app_data(self.args.clone()); - self - } - - /** - Runs a Lune script inside of the current runtime. - - This will preserve any modifications to global values / context. - - # Errors - - This function will return an error if the script fails to run. - */ - pub async fn run( - &mut self, - script_name: impl AsRef, - script_contents: impl AsRef<[u8]>, - ) -> Result { - // Create a new scheduler for this run - let sched = Scheduler::new(&self.lua); - - // Add error callback to format errors nicely + store status - let got_any_error = Arc::new(AtomicBool::new(false)); - let got_any_inner = Arc::clone(&got_any_error); - sched.set_error_callback(move |e| { - got_any_inner.store(true, Ordering::SeqCst); - eprintln!("{}", RuntimeError::from(e)); - }); - - // Load our "main" thread - let main = self - .lua - .load(script_contents.as_ref()) - .set_name(script_name.as_ref()); - - // Run it on our scheduler until it and any other spawned threads complete - sched.push_thread_back(main, ())?; - sched.run().await; - - // Return the exit code - default to FAILURE if we got any errors - Ok(sched.get_exit_code().unwrap_or({ - if got_any_error.load(Ordering::SeqCst) { - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } - })) - } -} +pub use self::result::{RuntimeError, RuntimeResult}; +pub use self::runtime::Runtime; diff --git a/crates/lune/src/rt/error.rs b/crates/lune/src/rt/result.rs similarity index 96% rename from crates/lune/src/rt/error.rs rename to crates/lune/src/rt/result.rs index 1a66e55..f3c9c3a 100644 --- a/crates/lune/src/rt/error.rs +++ b/crates/lune/src/rt/result.rs @@ -7,6 +7,8 @@ use mlua::prelude::*; use lune_utils::fmt::ErrorComponents; +pub type RuntimeResult = Result; + /** An opaque error type for formatted lua errors. */ diff --git a/crates/lune/src/rt/runtime.rs b/crates/lune/src/rt/runtime.rs new file mode 100644 index 0000000..61b64dd --- /dev/null +++ b/crates/lune/src/rt/runtime.rs @@ -0,0 +1,102 @@ +#![allow(clippy::missing_panics_doc)] + +use std::{ + process::ExitCode, + rc::Rc, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, +}; + +use mlua::Lua; +use mlua_luau_scheduler::Scheduler; + +use lune_std::inject_globals; + +use super::{RuntimeError, RuntimeResult}; + +#[derive(Debug)] +pub struct Runtime { + lua: Rc, + args: Vec, +} + +impl Runtime { + /** + Creates a new Lune runtime, with a new Luau VM. + */ + #[must_use] + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + let lua = Rc::new(Lua::new()); + + lua.set_app_data(Rc::downgrade(&lua)); + lua.set_app_data(Vec::::new()); + + inject_globals(&lua).expect("Failed to inject globals"); + + Self { + lua, + args: Vec::new(), + } + } + + /** + Sets arguments to give in `process.args` for Lune scripts. + */ + #[must_use] + pub fn with_args(mut self, args: V) -> Self + where + V: Into>, + { + self.args = args.into(); + self.lua.set_app_data(self.args.clone()); + self + } + + /** + Runs a Lune script inside of the current runtime. + + This will preserve any modifications to global values / context. + + # Errors + + This function will return an error if the script fails to run. + */ + pub async fn run( + &mut self, + script_name: impl AsRef, + script_contents: impl AsRef<[u8]>, + ) -> RuntimeResult { + // Create a new scheduler for this run + let sched = Scheduler::new(&self.lua); + + // Add error callback to format errors nicely + store status + let got_any_error = Arc::new(AtomicBool::new(false)); + let got_any_inner = Arc::clone(&got_any_error); + sched.set_error_callback(move |e| { + got_any_inner.store(true, Ordering::SeqCst); + eprintln!("{}", RuntimeError::from(e)); + }); + + // Load our "main" thread + let main = self + .lua + .load(script_contents.as_ref()) + .set_name(script_name.as_ref()); + + // Run it on our scheduler until it and any other spawned threads complete + sched.push_thread_back(main, ())?; + sched.run().await; + + // Return the exit code - default to FAILURE if we got any errors + Ok(sched.get_exit_code().unwrap_or({ + if got_any_error.load(Ordering::SeqCst) { + ExitCode::FAILURE + } else { + ExitCode::SUCCESS + } + })) + } +}