From 1feedb402a0283c13f9e674cc14ae1091f10a7cc Mon Sep 17 00:00:00 2001 From: Radiant <69520693+RadiantUwU@users.noreply.github.com> Date: Sat, 25 Jan 2025 21:45:48 +0200 Subject: [PATCH] Add yielding support. --- src/error.rs | 9 +++++++++ src/state/util.rs | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index 1f243967..9b555c35 100644 --- a/src/error.rs +++ b/src/error.rs @@ -205,6 +205,12 @@ pub enum Error { /// Underlying error. cause: Arc, }, + /// Yield. + /// + /// Not an error. + /// Returning `Err(Yielding(...))` from a Rust callback will yield the value as a Lua value. + /// If it cannot yield, it will raise an error. + Yielding(MultiValue), } /// A specialized `Result` type used by `mlua`'s API. @@ -321,6 +327,9 @@ impl fmt::Display for Error { Error::WithContext { context, cause } => { writeln!(fmt, "{context}")?; write!(fmt, "{cause}") + }, + Error::Yielding(_) => { + write!(fmt, "yield across Rust/Lua boundary") } } } diff --git a/src/state/util.rs b/src/state/util.rs index ec701eaf..680fa671 100644 --- a/src/state/util.rs +++ b/src/state/util.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use crate::error::{Error, Result}; use crate::state::{ExtraData, RawLua}; use crate::util::{self, get_internal_metatable, WrappedFailure}; +use crate::IntoLuaMulti; pub(super) struct StateGuard<'a>(&'a RawLua, *mut ffi::lua_State); @@ -107,7 +108,14 @@ where prealloc_failure.release(state, extra); r } - Ok(Err(err)) => { + Ok(Err(mut err)) => { + if let Error::Yielding(tuple) = err { + let raw = extra.as_ref().unwrap_unchecked().raw_lua(); + match tuple.push_into_stack_multi(lua) { + Ok(nargs) => ffi::lua_yield(state, nargs), + Err(new_err) => err = new_err, + } + } let wrapped_error = prealloc_failure.r#use(state, extra); // Build `CallbackError` with traceback