Remove generic from RawLua::push_userdata_metatable.

This should help to reduce amount of generated code.
This commit is contained in:
Alex Orlenko
2024-11-16 01:44:17 +00:00
parent cbf805f492
commit 89b68e2a24
6 changed files with 115 additions and 93 deletions
+2 -2
View File
@@ -176,7 +176,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> {
// Push the metatable and register it with no TypeId
let mut registry = UserDataRegistry::new_unique(ud_ptr as *mut _);
T::register(&mut registry);
self.lua.push_userdata_metatable(registry)?;
self.lua.push_userdata_metatable(registry.into_raw())?;
let mt_ptr = ffi::lua_topointer(state, -1);
self.lua.register_userdata_metatable(mt_ptr, None);
@@ -224,7 +224,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> {
// Push the metatable and register it with no TypeId
let mut registry = UserDataRegistry::new_unique(ud_ptr as *mut _);
register(&mut registry);
self.lua.push_userdata_metatable(registry)?;
self.lua.push_userdata_metatable(registry.into_raw())?;
let mt_ptr = ffi::lua_topointer(state, -1);
self.lua.register_userdata_metatable(mt_ptr, None);
+1 -1
View File
@@ -1317,7 +1317,7 @@ impl Lua {
}
// Register the type
lua.create_userdata_metatable(registry)?;
lua.create_userdata_metatable(registry.into_raw())?;
}
Ok(())
}
+11 -23
View File
@@ -22,12 +22,14 @@ use crate::types::{
AppDataRef, AppDataRefMut, Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData,
MaybeSend, ReentrantMutex, RegistryKey, ValueRef, XRc,
};
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataRegistry, UserDataStorage};
use crate::userdata::{
AnyUserData, MetaMethod, RawUserDataRegistry, UserData, UserDataRegistry, UserDataStorage,
};
use crate::util::{
assert_stack, check_stack, get_destructed_userdata_metatable, get_internal_userdata, get_main_state,
get_metatable_ptr, get_userdata, init_error_registry, init_internal_metatable, init_userdata_metatable,
pop_error, push_internal_userdata, push_string, push_table, rawset_field, safe_pcall, safe_xpcall,
short_type_name, take_userdata, StackGuard, WrappedFailure,
short_type_name, StackGuard, WrappedFailure,
};
use crate::value::{Nil, Value};
@@ -757,7 +759,7 @@ impl RawLua {
let mut registry = UserDataRegistry::new(type_id);
T::register(&mut registry);
self.create_userdata_metatable(registry)
self.create_userdata_metatable(registry.into_raw())
})
}
@@ -774,7 +776,7 @@ impl RawLua {
// Create an empty metatable
let registry = UserDataRegistry::<T>::new(type_id);
self.create_userdata_metatable(registry)
self.create_userdata_metatable(registry.into_raw())
})
}
@@ -810,12 +812,9 @@ impl RawLua {
Ok(AnyUserData(self.pop_ref()))
}
pub(crate) unsafe fn create_userdata_metatable<T>(
&self,
registry: UserDataRegistry<T>,
) -> Result<Integer> {
pub(crate) unsafe fn create_userdata_metatable(&self, registry: RawUserDataRegistry) -> Result<Integer> {
let state = self.state();
let type_id = registry.type_id();
let type_id = registry.type_id;
self.push_userdata_metatable(registry)?;
@@ -832,7 +831,7 @@ impl RawLua {
Ok(id as Integer)
}
pub(crate) unsafe fn push_userdata_metatable<T>(&self, mut registry: UserDataRegistry<T>) -> Result<()> {
pub(crate) unsafe fn push_userdata_metatable(&self, mut registry: RawUserDataRegistry) -> Result<()> {
let state = self.state();
let mut stack_guard = StackGuard::new(state);
check_stack(state, 13)?;
@@ -859,7 +858,7 @@ impl RawLua {
}
// Set `__name/__type` if not provided
if !has_name {
let type_name = short_type_name::<T>();
let type_name = registry.type_name;
push_string(state, type_name.as_bytes(), !self.unlikely_memory_error())?;
rawset_field(state, -2, MetaMethod::Type.name())?;
}
@@ -960,18 +959,7 @@ impl RawLua {
}
}
unsafe extern "C-unwind" fn userdata_destructor<T>(state: *mut ffi::lua_State) -> c_int {
let ud = get_userdata::<UserDataStorage<T>>(state, -1);
if !(*ud).is_borrowed() {
take_userdata::<UserDataStorage<T>>(state);
ffi::lua_pushboolean(state, 1);
} else {
ffi::lua_pushboolean(state, 0);
}
1
}
ffi::lua_pushcfunction(state, userdata_destructor::<T>);
ffi::lua_pushcfunction(state, registry.destructor);
rawset_field(state, metatable_index, "__gc")?;
init_userdata_metatable(
+1 -1
View File
@@ -27,8 +27,8 @@ use {
// Re-export for convenience
pub(crate) use cell::UserDataStorage;
pub use cell::{UserDataRef, UserDataRefMut};
pub(crate) use registry::UserDataProxy;
pub use registry::UserDataRegistry;
pub(crate) use registry::{RawUserDataRegistry, UserDataProxy};
/// Kinds of metamethods that can be overridden.
///
+85 -66
View File
@@ -51,6 +51,12 @@ enum UserDataTypeId {
/// Handle to registry for userdata methods and metamethods.
pub struct UserDataRegistry<T> {
raw: RawUserDataRegistry,
ud_type_id: UserDataTypeId,
_type: PhantomData<T>,
}
pub(crate) struct RawUserDataRegistry {
// Fields
pub(crate) fields: Vec<(String, StaticFieldCallback)>,
pub(crate) field_getters: Vec<(String, Callback)>,
@@ -65,42 +71,15 @@ pub struct UserDataRegistry<T> {
#[cfg(feature = "async")]
pub(crate) async_meta_methods: Vec<(String, AsyncCallback)>,
type_id: UserDataTypeId,
_type: PhantomData<T>,
pub(crate) destructor: ffi::lua_CFunction,
pub(crate) type_id: Option<TypeId>,
pub(crate) type_name: StdString,
}
impl<T> UserDataRegistry<T> {
#[inline(always)]
pub(crate) fn new(type_id: TypeId) -> Self {
Self::with_type_id(UserDataTypeId::Shared(type_id))
}
#[inline(always)]
pub(crate) fn new_unique(ud_ptr: *mut c_void) -> Self {
Self::with_type_id(UserDataTypeId::Unique(ud_ptr))
}
#[inline(always)]
fn with_type_id(type_id: UserDataTypeId) -> Self {
UserDataRegistry {
fields: Vec::new(),
field_getters: Vec::new(),
field_setters: Vec::new(),
meta_fields: Vec::new(),
methods: Vec::new(),
#[cfg(feature = "async")]
async_methods: Vec::new(),
meta_methods: Vec::new(),
#[cfg(feature = "async")]
async_meta_methods: Vec::new(),
type_id,
_type: PhantomData,
}
}
impl UserDataTypeId {
#[inline]
pub(crate) fn type_id(&self) -> Option<TypeId> {
match self.type_id {
pub(crate) fn type_id(self) -> Option<TypeId> {
match self {
UserDataTypeId::Shared(type_id) => Some(type_id),
UserDataTypeId::Unique(_) => None,
#[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
@@ -119,6 +98,43 @@ impl<T> UserDataRegistry<T> {
UserDataTypeId::ArcParkingLotRwLock(type_id) => Some(type_id),
}
}
}
impl<T> UserDataRegistry<T> {
#[inline(always)]
pub(crate) fn new(type_id: TypeId) -> Self {
Self::with_type_id(UserDataTypeId::Shared(type_id))
}
#[inline(always)]
pub(crate) fn new_unique(ud_ptr: *mut c_void) -> Self {
Self::with_type_id(UserDataTypeId::Unique(ud_ptr))
}
#[inline(always)]
fn with_type_id(ud_type_id: UserDataTypeId) -> Self {
let raw = RawUserDataRegistry {
fields: Vec::new(),
field_getters: Vec::new(),
field_setters: Vec::new(),
meta_fields: Vec::new(),
methods: Vec::new(),
#[cfg(feature = "async")]
async_methods: Vec::new(),
meta_methods: Vec::new(),
#[cfg(feature = "async")]
async_meta_methods: Vec::new(),
destructor: super::util::userdata_destructor::<T>,
type_id: ud_type_id.type_id(),
type_name: short_type_name::<T>(),
};
UserDataRegistry {
raw,
ud_type_id,
_type: PhantomData,
}
}
fn box_method<M, A, R>(&self, name: &str, method: M) -> Callback
where
@@ -133,7 +149,7 @@ impl<T> UserDataRegistry<T> {
};
}
let target_type_id = self.type_id;
let target_type_id = self.ud_type_id;
Box::new(move |rawlua, nargs| unsafe {
if nargs == 0 {
let err = Error::from_lua_conversion("missing argument", "userdata", None);
@@ -260,7 +276,7 @@ impl<T> UserDataRegistry<T> {
}
let method = RefCell::new(method);
let target_type_id = self.type_id;
let target_type_id = self.ud_type_id;
Box::new(move |rawlua, nargs| unsafe {
let mut method = method.try_borrow_mut().map_err(|_| Error::RecursiveMutCallback)?;
if nargs == 0 {
@@ -514,6 +530,11 @@ impl<T> UserDataRegistry<T> {
}
value.into_lua(lua)
}
#[inline(always)]
pub(crate) fn into_raw(self) -> RawUserDataRegistry {
self.raw
}
}
// Returns function name for the type `T`, without the module path
@@ -527,7 +548,7 @@ impl<T> UserDataFields<T> for UserDataRegistry<T> {
V: IntoLua + 'static,
{
let name = name.to_string();
self.fields.push((
self.raw.fields.push((
name,
Box::new(move |rawlua| unsafe { value.push_into_stack(rawlua) }),
));
@@ -540,7 +561,7 @@ impl<T> UserDataFields<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_method(&name, move |lua, data, ()| method(lua, data));
self.field_getters.push((name, callback));
self.raw.field_getters.push((name, callback));
}
fn add_field_method_set<M, A>(&mut self, name: impl ToString, method: M)
@@ -550,7 +571,7 @@ impl<T> UserDataFields<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_method_mut(&name, method);
self.field_setters.push((name, callback));
self.raw.field_setters.push((name, callback));
}
fn add_field_function_get<F, R>(&mut self, name: impl ToString, function: F)
@@ -560,7 +581,7 @@ impl<T> UserDataFields<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_function(&name, function);
self.field_getters.push((name, callback));
self.raw.field_getters.push((name, callback));
}
fn add_field_function_set<F, A>(&mut self, name: impl ToString, mut function: F)
@@ -570,7 +591,7 @@ impl<T> UserDataFields<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_function_mut(&name, move |lua, (data, val)| function(lua, data, val));
self.field_setters.push((name, callback));
self.raw.field_setters.push((name, callback));
}
fn add_meta_field<V>(&mut self, name: impl ToString, value: V)
@@ -578,7 +599,7 @@ impl<T> UserDataFields<T> for UserDataRegistry<T> {
V: IntoLua + 'static,
{
let name = name.to_string();
self.meta_fields.push((
self.raw.meta_fields.push((
name.clone(),
Box::new(move |rawlua| unsafe {
Self::check_meta_field(rawlua.lua(), &name, value)?.push_into_stack(rawlua)
@@ -592,7 +613,7 @@ impl<T> UserDataFields<T> for UserDataRegistry<T> {
R: IntoLua,
{
let name = name.to_string();
self.meta_fields.push((
self.raw.meta_fields.push((
name.clone(),
Box::new(move |rawlua| unsafe {
let lua = rawlua.lua();
@@ -611,7 +632,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_method(&name, method);
self.methods.push((name, callback));
self.raw.methods.push((name, callback));
}
fn add_method_mut<M, A, R>(&mut self, name: impl ToString, method: M)
@@ -622,7 +643,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_method_mut(&name, method);
self.methods.push((name, callback));
self.raw.methods.push((name, callback));
}
#[cfg(feature = "async")]
@@ -636,7 +657,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_async_method(&name, method);
self.async_methods.push((name, callback));
self.raw.async_methods.push((name, callback));
}
#[cfg(feature = "async")]
@@ -650,7 +671,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_async_method_mut(&name, method);
self.async_methods.push((name, callback));
self.raw.async_methods.push((name, callback));
}
fn add_function<F, A, R>(&mut self, name: impl ToString, function: F)
@@ -661,7 +682,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_function(&name, function);
self.methods.push((name, callback));
self.raw.methods.push((name, callback));
}
fn add_function_mut<F, A, R>(&mut self, name: impl ToString, function: F)
@@ -672,7 +693,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_function_mut(&name, function);
self.methods.push((name, callback));
self.raw.methods.push((name, callback));
}
#[cfg(feature = "async")]
@@ -685,7 +706,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_async_function(&name, function);
self.async_methods.push((name, callback));
self.raw.async_methods.push((name, callback));
}
fn add_meta_method<M, A, R>(&mut self, name: impl ToString, method: M)
@@ -696,7 +717,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_method(&name, method);
self.meta_methods.push((name, callback));
self.raw.meta_methods.push((name, callback));
}
fn add_meta_method_mut<M, A, R>(&mut self, name: impl ToString, method: M)
@@ -707,7 +728,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_method_mut(&name, method);
self.meta_methods.push((name, callback));
self.raw.meta_methods.push((name, callback));
}
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
@@ -721,7 +742,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_async_method(&name, method);
self.async_meta_methods.push((name, callback));
self.raw.async_meta_methods.push((name, callback));
}
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
@@ -735,7 +756,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_async_method_mut(&name, method);
self.async_meta_methods.push((name, callback));
self.raw.async_meta_methods.push((name, callback));
}
fn add_meta_function<F, A, R>(&mut self, name: impl ToString, function: F)
@@ -746,7 +767,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_function(&name, function);
self.meta_methods.push((name, callback));
self.raw.meta_methods.push((name, callback));
}
fn add_meta_function_mut<F, A, R>(&mut self, name: impl ToString, function: F)
@@ -757,7 +778,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_function_mut(&name, function);
self.meta_methods.push((name, callback));
self.raw.meta_methods.push((name, callback));
}
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
@@ -770,7 +791,7 @@ impl<T> UserDataMethods<T> for UserDataRegistry<T> {
{
let name = name.to_string();
let callback = self.box_async_function(&name, function);
self.async_meta_methods.push((name, callback));
self.raw.async_meta_methods.push((name, callback));
}
}
@@ -786,18 +807,16 @@ macro_rules! lua_userdata_impl {
T::register(&mut orig_registry);
// Copy all fields, methods, etc. from the original registry
registry.fields.extend(orig_registry.fields);
registry.field_getters.extend(orig_registry.field_getters);
registry.field_setters.extend(orig_registry.field_setters);
registry.meta_fields.extend(orig_registry.meta_fields);
registry.methods.extend(orig_registry.methods);
(registry.raw.fields).extend(orig_registry.raw.fields);
(registry.raw.field_getters).extend(orig_registry.raw.field_getters);
(registry.raw.field_setters).extend(orig_registry.raw.field_setters);
(registry.raw.meta_fields).extend(orig_registry.raw.meta_fields);
(registry.raw.methods).extend(orig_registry.raw.methods);
#[cfg(feature = "async")]
registry.async_methods.extend(orig_registry.async_methods);
registry.meta_methods.extend(orig_registry.meta_methods);
(registry.raw.async_methods).extend(orig_registry.raw.async_methods);
(registry.raw.meta_methods).extend(orig_registry.raw.meta_methods);
#[cfg(feature = "async")]
registry
.async_meta_methods
.extend(orig_registry.async_meta_methods);
(registry.raw.async_meta_methods).extend(orig_registry.raw.async_meta_methods);
}
}
};
+15
View File
@@ -1,5 +1,9 @@
use std::cell::Cell;
use std::marker::PhantomData;
use std::os::raw::c_int;
use super::UserDataStorage;
use crate::util::{get_userdata, take_userdata};
// This is a trick to check if a type is `Sync` or not.
// It uses leaked specialization feature from stdlib.
@@ -29,3 +33,14 @@ pub(crate) fn is_sync<T>() -> bool {
.clone();
is_sync.get()
}
pub(super) unsafe extern "C-unwind" fn userdata_destructor<T>(state: *mut ffi::lua_State) -> c_int {
let ud = get_userdata::<UserDataStorage<T>>(state, -1);
if !(*ud).is_borrowed() {
take_userdata::<UserDataStorage<T>>(state);
ffi::lua_pushboolean(state, 1);
} else {
ffi::lua_pushboolean(state, 0);
}
1
}