More inline, make some methods and constructors public, add create_c_closure

This commit is contained in:
Michael Pfaff 2023-07-06 13:03:53 -04:00
parent 11d81209d9
commit 96575e6ab5
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
9 changed files with 76 additions and 17 deletions

View File

@ -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);

View File

@ -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")
}

View File

@ -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
}

View File

@ -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<Function> {
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());

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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();

View File

@ -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
}