1
1
use std:: os:: raw:: { c_int, c_void} ;
2
- use std:: ptr;
2
+ use std:: { mem , ptr} ;
3
3
4
4
use crate :: error:: Result ;
5
+ use crate :: userdata:: collect_userdata;
5
6
use crate :: util:: { check_stack, get_metatable_ptr, push_table, rawset_field, TypeKey } ;
6
7
7
8
// Pushes the userdata and attaches a metatable with __gc method.
@@ -10,11 +11,30 @@ pub(crate) unsafe fn push_internal_userdata<T: TypeKey>(
10
11
state : * mut ffi:: lua_State ,
11
12
t : T ,
12
13
protect : bool ,
13
- ) -> Result < ( ) > {
14
- push_userdata ( state, t, protect) ?;
14
+ ) -> Result < * mut T > {
15
+ #[ cfg( not( feature = "luau" ) ) ]
16
+ let ud_ptr = if protect {
17
+ protect_lua ! ( state, 0 , 1 , move |state| {
18
+ let ud_ptr = ffi:: lua_newuserdata( state, const { mem:: size_of:: <T >( ) } ) as * mut T ;
19
+ ptr:: write( ud_ptr, t) ;
20
+ ud_ptr
21
+ } ) ?
22
+ } else {
23
+ let ud_ptr = ffi:: lua_newuserdata ( state, const { mem:: size_of :: < T > ( ) } ) as * mut T ;
24
+ ptr:: write ( ud_ptr, t) ;
25
+ ud_ptr
26
+ } ;
27
+
28
+ #[ cfg( feature = "luau" ) ]
29
+ let ud_ptr = if protect {
30
+ protect_lua ! ( state, 0 , 1 , move |state| ffi:: lua_newuserdata_t:: <T >( state, t) ) ?
31
+ } else {
32
+ ffi:: lua_newuserdata_t :: < T > ( state, t)
33
+ } ;
34
+
15
35
get_internal_metatable :: < T > ( state) ;
16
36
ffi:: lua_setmetatable ( state, -2 ) ;
17
- Ok ( ( ) )
37
+ Ok ( ud_ptr )
18
38
}
19
39
20
40
#[ track_caller]
@@ -35,12 +55,7 @@ pub(crate) unsafe fn init_internal_metatable<T: TypeKey>(
35
55
36
56
#[ cfg( not( feature = "luau" ) ) ]
37
57
{
38
- unsafe extern "C-unwind" fn userdata_destructor < T > ( state : * mut ffi:: lua_State ) -> c_int {
39
- take_userdata :: < T > ( state) ;
40
- 0
41
- }
42
-
43
- ffi:: lua_pushcfunction ( state, userdata_destructor :: < T > ) ;
58
+ ffi:: lua_pushcfunction ( state, collect_userdata :: < T > ) ;
44
59
rawset_field ( state, -2 , "__gc" ) ?;
45
60
}
46
61
@@ -86,24 +101,34 @@ pub(crate) unsafe fn get_internal_userdata<T: TypeKey>(
86
101
pub ( crate ) unsafe fn push_uninit_userdata < T > ( state : * mut ffi:: lua_State , protect : bool ) -> Result < * mut T > {
87
102
if protect {
88
103
protect_lua ! ( state, 0 , 1 , |state| {
89
- ffi:: lua_newuserdata( state, std :: mem:: size_of:: <T >( ) ) as * mut T
104
+ ffi:: lua_newuserdata( state, const { mem:: size_of:: <T >( ) } ) as * mut T
90
105
} )
91
106
} else {
92
- Ok ( ffi:: lua_newuserdata ( state, std :: mem:: size_of :: < T > ( ) ) as * mut T )
107
+ Ok ( ffi:: lua_newuserdata ( state, const { mem:: size_of :: < T > ( ) } ) as * mut T )
93
108
}
94
109
}
95
110
96
111
// Internally uses 3 stack spaces, does not call checkstack.
97
112
#[ inline]
98
113
pub ( crate ) unsafe fn push_userdata < T > ( state : * mut ffi:: lua_State , t : T , protect : bool ) -> Result < * mut T > {
114
+ let size = const { mem:: size_of :: < T > ( ) } ;
115
+
99
116
#[ cfg( not( feature = "luau" ) ) ]
100
- let ud_ptr = push_uninit_userdata ( state, protect) ?;
117
+ let ud_ptr = if protect {
118
+ protect_lua ! ( state, 0 , 1 , move |state| ffi:: lua_newuserdata( state, size) ) ?
119
+ } else {
120
+ ffi:: lua_newuserdata ( state, size)
121
+ } as * mut T ;
122
+
101
123
#[ cfg( feature = "luau" ) ]
102
124
let ud_ptr = if protect {
103
- protect_lua ! ( state, 0 , 1 , |state| { ffi:: lua_newuserdata_t:: <T >( state) } ) ?
125
+ protect_lua ! ( state, 0 , 1 , |state| {
126
+ ffi:: lua_newuserdatadtor( state, size, collect_userdata:: <T >)
127
+ } ) ?
104
128
} else {
105
- ffi:: lua_newuserdata_t :: < T > ( state)
106
- } ;
129
+ ffi:: lua_newuserdatadtor ( state, size, collect_userdata :: < T > )
130
+ } as * mut T ;
131
+
107
132
ptr:: write ( ud_ptr, t) ;
108
133
Ok ( ud_ptr)
109
134
}
0 commit comments