diff --git a/mlua-sys/src/luau/compat.rs b/mlua-sys/src/luau/compat.rs index 192e812..bd777b5 100644 --- a/mlua-sys/src/luau/compat.rs +++ b/mlua-sys/src/luau/compat.rs @@ -11,6 +11,7 @@ use super::lauxlib::*; use super::lua::*; use super::luacode::*; +#[inline(always)] unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) { while a < b { lua_pushvalue(L, a); @@ -88,6 +89,7 @@ unsafe fn compat53_pushfuncname(L: *mut lua_State, level: c_int, ar: *mut lua_De // lua ported functions // +#[inline(always)] pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) { idx = lua_absindex(L, idx); if n > 0 { @@ -135,6 +137,7 @@ pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer { lua_tointegerx(L, i, ptr::null_mut()) } +#[inline] pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer { let mut ok = 0; let n = lua_tonumberx(L, i, &mut ok); diff --git a/mlua-sys/src/luau/lua.rs b/mlua-sys/src/luau/lua.rs index d9c10ab..24a2335 100644 --- a/mlua-sys/src/luau/lua.rs +++ b/mlua-sys/src/luau/lua.rs @@ -17,6 +17,7 @@ pub const LUA_REGISTRYINDEX: c_int = -LUAI_MAXCSTACK - 2000; pub const LUA_ENVIRONINDEX: c_int = -LUAI_MAXCSTACK - 2001; pub const LUA_GLOBALSINDEX: c_int = -LUAI_MAXCSTACK - 2002; +#[inline(always)] pub const fn lua_upvalueindex(i: c_int) -> c_int { LUA_GLOBALSINDEX - i } @@ -85,6 +86,7 @@ pub type lua_Alloc = unsafe extern "C" fn( ) -> *mut c_void; /// Returns Luau release version (eg. `0.xxx`). +#[inline(always)] pub const fn luau_version() -> Option<&'static str> { option_env!("LUAU_VERSION") } diff --git a/src/function.rs b/src/function.rs index de20570..59a66ac 100644 --- a/src/function.rs +++ b/src/function.rs @@ -83,6 +83,12 @@ pub struct CoverageInfo { } impl<'lua> Function<'lua> { + /// Unsafe because we omit type checks. + #[inline] + pub unsafe fn from_ref(r: LuaRef<'lua>) -> Self { + Self(r) + } + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { &self.0 } diff --git a/src/lua.rs b/src/lua.rs index 0ed0cf1..cca250c 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -1566,6 +1566,26 @@ impl Lua { Ok(Function(self.pop_ref())) } + /// Wraps a C function, creating a callable Lua function handle to it. + /// + /// # Safety + /// This function is unsafe because provides a way to execute unsafe C function. + #[inline] + pub unsafe fn create_c_closure<'lua>(&'lua self, func: ffi::lua_CFunction, upvalues: impl IntoLuaMulti<'lua>) -> Result { + let state = self.state(); + let upvalues = upvalues.into_lua_multi(self)?; + let Ok(n) = i32::try_from(upvalues.len()) else { + return Err(Error::BadArgument { to: Some("create_c_closure".to_owned()), pos: 3, name: Some("upvalues".to_owned()), cause: Arc::new(Error::BindError) }) + }; + // number of upvalues plus 1 extra needed by push_value for each + check_stack(state, n + 1)?; + for upvalue in upvalues { + self.push_value(upvalue)?; + } + ffi::lua_pushcclosure(state, func, n); + Ok(Function(self.pop_ref())) + } + /// Wraps a Rust async function or closure, creating a callable Lua function handle to it. /// /// While executing the function Rust will poll Future and if the result is not ready, call @@ -2283,7 +2303,7 @@ impl Lua { } /// Uses 2 stack spaces, does not call checkstack - pub(crate) unsafe fn push_value(&self, value: Value) -> Result<()> { + pub unsafe fn push_value(&self, value: Value) -> Result<()> { let state = self.state(); match value { Value::Nil => { @@ -2344,7 +2364,7 @@ impl Lua { } /// Uses 2 stack spaces, does not call checkstack - pub(crate) unsafe fn pop_value(&self) -> Value { + pub unsafe fn pop_value(&self) -> Value { let state = self.state(); match ffi::lua_type(state, -1) { ffi::LUA_TNIL => { @@ -2445,8 +2465,8 @@ impl Lua { } } - // Pushes a LuaRef value onto the stack, uses 1 stack space, does not call checkstack - pub(crate) unsafe fn push_ref(&self, lref: &LuaRef) { + /// Pushes a LuaRef value onto the stack, uses 1 stack space, does not call checkstack + pub unsafe fn push_ref(&self, lref: &LuaRef) { assert!( Arc::ptr_eq(&lref.lua.0, &self.0), "Lua instance passed Value created from a different main Lua state" @@ -2454,28 +2474,28 @@ impl Lua { ffi::lua_xpush(self.ref_thread(), self.state(), lref.index); } - // Pops the topmost element of the stack and stores a reference to it. This pins the object, - // preventing garbage collection until the returned `LuaRef` is dropped. - // - // References are stored in the stack of a specially created auxiliary thread that exists only - // to store reference values. This is much faster than storing these in the registry, and also - // much more flexible and requires less bookkeeping than storing them directly in the currently - // used stack. The implementation is somewhat biased towards the use case of a relatively small - // number of short term references being created, and `RegistryKey` being used for long term - // references. - pub(crate) unsafe fn pop_ref(&self) -> LuaRef { + /// Pops the topmost element of the stack and stores a reference to it. This pins the object, + /// preventing garbage collection until the returned `LuaRef` is dropped. + /// + /// References are stored in the stack of a specially created auxiliary thread that exists only + /// to store reference values. This is much faster than storing these in the registry, and also + /// much more flexible and requires less bookkeeping than storing them directly in the currently + /// used stack. The implementation is somewhat biased towards the use case of a relatively small + /// number of short term references being created, and `RegistryKey` being used for long term + /// references. + pub unsafe fn pop_ref(&self) -> LuaRef { ffi::lua_xmove(self.state(), self.ref_thread(), 1); let index = ref_stack_pop(self.extra.get()); LuaRef::new(self, index) } - // Same as `pop_ref` but assumes the value is already on the reference thread - pub(crate) unsafe fn pop_ref_thread(&self) -> LuaRef { + /// Same as `pop_ref` but assumes the value is already on the reference thread + pub unsafe fn pop_ref_thread(&self) -> LuaRef { let index = ref_stack_pop(self.extra.get()); LuaRef::new(self, index) } - pub(crate) fn clone_ref(&self, lref: &LuaRef) -> LuaRef { + pub fn clone_ref(&self, lref: &LuaRef) -> LuaRef { unsafe { ffi::lua_pushvalue(self.ref_thread(), lref.index); let index = ref_stack_pop(self.extra.get()); diff --git a/src/string.rs b/src/string.rs index 5ef5f0e..f0e4676 100644 --- a/src/string.rs +++ b/src/string.rs @@ -41,6 +41,12 @@ impl OwnedString { } impl<'lua> String<'lua> { + /// Unsafe because we omit type checks. + #[inline] + pub unsafe fn from_ref(r: LuaRef<'lua>) -> Self { + Self(r) + } + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { &self.0 } diff --git a/src/table.rs b/src/table.rs index dd7bfc4..5dd2a51 100644 --- a/src/table.rs +++ b/src/table.rs @@ -46,6 +46,12 @@ impl OwnedTable { } impl<'lua> Table<'lua> { + /// Unsafe because we omit type checks. + #[inline] + pub unsafe fn from_ref(r: LuaRef<'lua>) -> Self { + Self(r) + } + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { &self.0 } diff --git a/src/thread.rs b/src/thread.rs index ccc38eb..000c0b3 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -73,6 +73,12 @@ pub struct AsyncThread<'lua, R> { } impl<'lua> Thread<'lua> { + /// Unsafe because we omit type checks. + #[inline] + pub unsafe fn from_ref(r: LuaRef<'lua>) -> Self { + Self(r) + } + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { &self.0 } diff --git a/src/types.rs b/src/types.rs index 7541c87..7dc39b2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -280,6 +280,7 @@ pub struct LuaRef<'lua> { } impl<'lua> LuaRef<'lua> { + #[inline(always)] pub(crate) const fn new(lua: &'lua Lua, index: c_int) -> Self { LuaRef { lua, @@ -311,12 +312,14 @@ impl<'lua> fmt::Debug for LuaRef<'lua> { } impl<'lua> Clone for LuaRef<'lua> { + #[inline] fn clone(&self) -> Self { self.lua.clone_ref(self) } } impl<'lua> Drop for LuaRef<'lua> { + #[inline] fn drop(&mut self) { if self.drop { self.lua.drop_ref_index(self.index); @@ -325,6 +328,7 @@ impl<'lua> Drop for LuaRef<'lua> { } impl<'lua> PartialEq for LuaRef<'lua> { + #[inline] fn eq(&self, other: &Self) -> bool { let lua = self.lua; let state = lua.state(); diff --git a/src/userdata.rs b/src/userdata.rs index 11f7d37..e035f4e 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -806,6 +806,12 @@ impl OwnedAnyUserData { } impl<'lua> AnyUserData<'lua> { + /// Unsafe because we omit type checks. + #[inline] + pub unsafe fn from_ref(r: LuaRef<'lua>) -> Self { + Self(r) + } + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { &self.0 }