1#![allow(clippy::await_holding_refcell_ref, clippy::await_holding_lock)]
2
3use std::any::TypeId;
4use std::cell::RefCell;
5use std::marker::PhantomData;
6use std::os::raw::c_void;
7
8use crate::error::{Error, Result};
9use crate::state::{Lua, LuaGuard};
10use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
11use crate::types::{Callback, MaybeSend};
12use crate::userdata::{
13 AnyUserData, MetaMethod, TypeIdHints, UserData, UserDataFields, UserDataMethods, UserDataStorage,
14 borrow_userdata_scoped, borrow_userdata_scoped_mut,
15};
16use crate::util::short_type_name;
17use crate::value::Value;
18
19#[cfg(feature = "async")]
20use {
21 crate::types::AsyncCallback,
22 crate::userdata::{UserDataRef, UserDataRefMut},
23 std::future::{self, Future},
24};
25
26#[derive(Clone, Copy)]
27enum UserDataType {
28 Shared(TypeIdHints),
29 Unique(*mut c_void),
30}
31
32pub struct UserDataRegistry<T> {
34 lua: LuaGuard,
35 raw: RawUserDataRegistry,
36 r#type: UserDataType,
37 _phantom: PhantomData<T>,
38}
39
40pub(crate) struct RawUserDataRegistry {
41 pub(crate) fields: Vec<(String, Result<Value>)>,
43 pub(crate) field_getters: Vec<(String, Callback)>,
44 pub(crate) field_setters: Vec<(String, Callback)>,
45 pub(crate) meta_fields: Vec<(String, Result<Value>)>,
46
47 pub(crate) methods: Vec<(String, Callback)>,
49 #[cfg(feature = "async")]
50 pub(crate) async_methods: Vec<(String, AsyncCallback)>,
51 pub(crate) meta_methods: Vec<(String, Callback)>,
52 #[cfg(feature = "async")]
53 pub(crate) async_meta_methods: Vec<(String, AsyncCallback)>,
54
55 pub(crate) destructor: ffi::lua_CFunction,
56 pub(crate) type_id: Option<TypeId>,
57 pub(crate) type_name: String,
58
59 #[cfg(feature = "luau")]
60 pub(crate) enable_namecall: bool,
61}
62
63impl UserDataType {
64 #[inline]
65 pub(crate) fn type_id(&self) -> Option<TypeId> {
66 match self {
67 UserDataType::Shared(hints) => Some(hints.type_id()),
68 UserDataType::Unique(_) => None,
69 }
70 }
71}
72
73#[cfg(feature = "send")]
74unsafe impl Send for UserDataType {}
75
76impl<T: 'static> UserDataRegistry<T> {
77 #[inline(always)]
78 pub(crate) fn new(lua: &Lua) -> Self {
79 Self::with_type(lua, UserDataType::Shared(TypeIdHints::new::<T>()))
80 }
81}
82
83impl<T> UserDataRegistry<T> {
84 #[inline(always)]
85 pub(crate) fn new_unique(lua: &Lua, ud_ptr: *mut c_void) -> Self {
86 Self::with_type(lua, UserDataType::Unique(ud_ptr))
87 }
88
89 #[inline(always)]
90 fn with_type(lua: &Lua, r#type: UserDataType) -> Self {
91 let raw = RawUserDataRegistry {
92 fields: Vec::new(),
93 field_getters: Vec::new(),
94 field_setters: Vec::new(),
95 meta_fields: Vec::new(),
96 methods: Vec::new(),
97 #[cfg(feature = "async")]
98 async_methods: Vec::new(),
99 meta_methods: Vec::new(),
100 #[cfg(feature = "async")]
101 async_meta_methods: Vec::new(),
102 destructor: super::util::destroy_userdata_storage::<T>,
103 type_id: r#type.type_id(),
104 type_name: short_type_name::<T>(),
105 #[cfg(feature = "luau")]
106 enable_namecall: false,
107 };
108
109 UserDataRegistry {
110 lua: lua.lock_arc(),
111 raw,
112 r#type,
113 _phantom: PhantomData,
114 }
115 }
116
117 #[doc(hidden)]
128 #[cfg(feature = "luau")]
129 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
130 pub fn enable_namecall(&mut self) {
131 self.raw.enable_namecall = true;
132 }
133
134 fn box_method<M, A, R>(&self, name: &str, method: M) -> Callback
135 where
136 M: Fn(&Lua, &T, A) -> Result<R> + MaybeSend + 'static,
137 A: FromLuaMulti,
138 R: IntoLuaMulti,
139 {
140 let name = get_function_name::<T>(name);
141 macro_rules! try_self_arg {
142 ($res:expr) => {
143 $res.map_err(|err| Error::bad_self_argument(&name, err))?
144 };
145 }
146
147 let target_type = self.r#type;
148 Box::new(move |rawlua, nargs| unsafe {
149 if nargs == 0 {
150 let err = Error::from_lua_conversion("missing argument", "userdata", None);
151 try_self_arg!(Err(err));
152 }
153 let state = rawlua.state();
154 let self_index = ffi::lua_absindex(state, -nargs);
156 let args = A::from_stack_args(nargs - 1, 2, Some(&name), rawlua);
158
159 match target_type {
160 #[rustfmt::skip]
161 UserDataType::Shared(type_hints) => {
162 let type_id = try_self_arg!(rawlua.get_userdata_type_id::<T>(state, self_index));
163 try_self_arg!(borrow_userdata_scoped(state, self_index, type_id, type_hints, |ud| {
164 method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
165 }))
166 }
167 UserDataType::Unique(target_ptr) if ffi::lua_touserdata(state, self_index) == target_ptr => {
168 let ud = target_ptr as *mut UserDataStorage<T>;
169 try_self_arg!((*ud).try_borrow_scoped(|ud| {
170 method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
171 }))
172 }
173 UserDataType::Unique(_) => {
174 try_self_arg!(rawlua.get_userdata_type_id::<T>(state, self_index));
175 Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch))
176 }
177 }
178 })
179 }
180
181 fn box_method_mut<M, A, R>(&self, name: &str, method: M) -> Callback
182 where
183 M: FnMut(&Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
184 A: FromLuaMulti,
185 R: IntoLuaMulti,
186 {
187 let name = get_function_name::<T>(name);
188 macro_rules! try_self_arg {
189 ($res:expr) => {
190 $res.map_err(|err| Error::bad_self_argument(&name, err))?
191 };
192 }
193
194 let method = RefCell::new(method);
195 let target_type = self.r#type;
196 Box::new(move |rawlua, nargs| unsafe {
197 let mut method = method.try_borrow_mut().map_err(|_| Error::RecursiveMutCallback)?;
198 if nargs == 0 {
199 let err = Error::from_lua_conversion("missing argument", "userdata", None);
200 try_self_arg!(Err(err));
201 }
202 let state = rawlua.state();
203 let self_index = ffi::lua_absindex(state, -nargs);
205 let args = A::from_stack_args(nargs - 1, 2, Some(&name), rawlua);
207
208 match target_type {
209 #[rustfmt::skip]
210 UserDataType::Shared(type_hints) => {
211 let type_id = try_self_arg!(rawlua.get_userdata_type_id::<T>(state, self_index));
212 try_self_arg!(borrow_userdata_scoped_mut(state, self_index, type_id, type_hints, |ud| {
213 method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
214 }))
215 }
216 UserDataType::Unique(target_ptr) if ffi::lua_touserdata(state, self_index) == target_ptr => {
217 let ud = target_ptr as *mut UserDataStorage<T>;
218 try_self_arg!((*ud).try_borrow_scoped_mut(|ud| {
219 method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
220 }))
221 }
222 UserDataType::Unique(_) => {
223 try_self_arg!(rawlua.get_userdata_type_id::<T>(state, self_index));
224 Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch))
225 }
226 }
227 })
228 }
229
230 #[cfg(feature = "async")]
231 fn box_async_method<M, A, MR, R>(&self, name: &str, method: M) -> AsyncCallback
232 where
233 T: 'static,
234 M: Fn(Lua, UserDataRef<T>, A) -> MR + MaybeSend + 'static,
235 A: FromLuaMulti,
236 MR: Future<Output = Result<R>> + MaybeSend + 'static,
237 R: IntoLuaMulti,
238 {
239 let name = get_function_name::<T>(name);
240 macro_rules! try_self_arg {
241 ($res:expr) => {
242 match $res {
243 Ok(res) => res,
244 Err(err) => return Box::pin(future::ready(Err(Error::bad_self_argument(&name, err)))),
245 }
246 };
247 }
248
249 Box::new(move |rawlua, nargs| unsafe {
250 if nargs == 0 {
251 let err = Error::from_lua_conversion("missing argument", "userdata", None);
252 try_self_arg!(Err(err));
253 }
254 let self_ud = try_self_arg!(AnyUserData::from_stack(-nargs, rawlua));
256 let args = A::from_stack_args(nargs - 1, 2, Some(&name), rawlua);
257
258 let self_ud = try_self_arg!(self_ud.borrow());
259 let args = match args {
260 Ok(args) => args,
261 Err(e) => return Box::pin(future::ready(Err(e))),
262 };
263 let lua = rawlua.lua();
264 let fut = method(lua.clone(), self_ud, args);
265 Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
267 })
268 }
269
270 #[cfg(feature = "async")]
271 fn box_async_method_mut<M, A, MR, R>(&self, name: &str, method: M) -> AsyncCallback
272 where
273 T: 'static,
274 M: Fn(Lua, UserDataRefMut<T>, A) -> MR + MaybeSend + 'static,
275 A: FromLuaMulti,
276 MR: Future<Output = Result<R>> + MaybeSend + 'static,
277 R: IntoLuaMulti,
278 {
279 let name = get_function_name::<T>(name);
280 macro_rules! try_self_arg {
281 ($res:expr) => {
282 match $res {
283 Ok(res) => res,
284 Err(err) => return Box::pin(future::ready(Err(Error::bad_self_argument(&name, err)))),
285 }
286 };
287 }
288
289 Box::new(move |rawlua, nargs| unsafe {
290 if nargs == 0 {
291 let err = Error::from_lua_conversion("missing argument", "userdata", None);
292 try_self_arg!(Err(err));
293 }
294 let self_ud = try_self_arg!(AnyUserData::from_stack(-nargs, rawlua));
296 let args = A::from_stack_args(nargs - 1, 2, Some(&name), rawlua);
297
298 let self_ud = try_self_arg!(self_ud.borrow_mut());
299 let args = match args {
300 Ok(args) => args,
301 Err(e) => return Box::pin(future::ready(Err(e))),
302 };
303 let lua = rawlua.lua();
304 let fut = method(lua.clone(), self_ud, args);
305 Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
307 })
308 }
309
310 fn box_function<F, A, R>(&self, name: &str, function: F) -> Callback
311 where
312 F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
313 A: FromLuaMulti,
314 R: IntoLuaMulti,
315 {
316 let name = get_function_name::<T>(name);
317 Box::new(move |lua, nargs| unsafe {
318 let args = A::from_stack_args(nargs, 1, Some(&name), lua)?;
319 function(lua.lua(), args)?.push_into_stack_multi(lua)
320 })
321 }
322
323 fn box_function_mut<F, A, R>(&self, name: &str, function: F) -> Callback
324 where
325 F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
326 A: FromLuaMulti,
327 R: IntoLuaMulti,
328 {
329 let name = get_function_name::<T>(name);
330 let function = RefCell::new(function);
331 Box::new(move |lua, nargs| unsafe {
332 let function = &mut *function
333 .try_borrow_mut()
334 .map_err(|_| Error::RecursiveMutCallback)?;
335 let args = A::from_stack_args(nargs, 1, Some(&name), lua)?;
336 function(lua.lua(), args)?.push_into_stack_multi(lua)
337 })
338 }
339
340 #[cfg(feature = "async")]
341 fn box_async_function<F, A, FR, R>(&self, name: &str, function: F) -> AsyncCallback
342 where
343 F: Fn(Lua, A) -> FR + MaybeSend + 'static,
344 A: FromLuaMulti,
345 FR: Future<Output = Result<R>> + MaybeSend + 'static,
346 R: IntoLuaMulti,
347 {
348 let name = get_function_name::<T>(name);
349 Box::new(move |rawlua, nargs| unsafe {
350 let args = match A::from_stack_args(nargs, 1, Some(&name), rawlua) {
351 Ok(args) => args,
352 Err(e) => return Box::pin(future::ready(Err(e))),
353 };
354 let lua = rawlua.lua();
355 let fut = function(lua.clone(), args);
356 Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
357 })
358 }
359
360 pub(crate) fn check_meta_field(lua: &Lua, name: &str, value: impl IntoLua) -> Result<Value> {
361 let value = value.into_lua(lua)?;
362 if name == MetaMethod::Index || name == MetaMethod::NewIndex {
363 match value {
364 Value::Nil | Value::Table(_) | Value::Function(_) => {}
365 _ => {
366 return Err(Error::MetaMethodTypeError {
367 method: name.to_string(),
368 type_name: value.type_name(),
369 message: Some("expected nil, table or function".to_string()),
370 });
371 }
372 }
373 }
374 value.into_lua(lua)
375 }
376
377 #[inline(always)]
378 pub(crate) fn into_raw(self) -> RawUserDataRegistry {
379 self.raw
380 }
381}
382
383fn get_function_name<T>(name: &str) -> String {
385 format!("{}.{name}", short_type_name::<T>())
386}
387
388impl<T> UserDataFields<T> for UserDataRegistry<T> {
389 fn add_field<V>(&mut self, name: impl Into<String>, value: V)
390 where
391 V: IntoLua + 'static,
392 {
393 let name = name.into();
394 self.raw.fields.push((name, value.into_lua(self.lua.lua())));
395 }
396
397 fn add_field_method_get<M, R>(&mut self, name: impl Into<String>, method: M)
398 where
399 M: Fn(&Lua, &T) -> Result<R> + MaybeSend + 'static,
400 R: IntoLua,
401 {
402 let name = name.into();
403 let callback = self.box_method(&name, move |lua, data, ()| method(lua, data));
404 self.raw.field_getters.push((name, callback));
405 }
406
407 fn add_field_method_set<M, A>(&mut self, name: impl Into<String>, method: M)
408 where
409 M: FnMut(&Lua, &mut T, A) -> Result<()> + MaybeSend + 'static,
410 A: FromLua,
411 {
412 let name = name.into();
413 let callback = self.box_method_mut(&name, method);
414 self.raw.field_setters.push((name, callback));
415 }
416
417 fn add_field_function_get<F, R>(&mut self, name: impl Into<String>, function: F)
418 where
419 F: Fn(&Lua, AnyUserData) -> Result<R> + MaybeSend + 'static,
420 R: IntoLua,
421 {
422 let name = name.into();
423 let callback = self.box_function(&name, function);
424 self.raw.field_getters.push((name, callback));
425 }
426
427 fn add_field_function_set<F, A>(&mut self, name: impl Into<String>, mut function: F)
428 where
429 F: FnMut(&Lua, AnyUserData, A) -> Result<()> + MaybeSend + 'static,
430 A: FromLua,
431 {
432 let name = name.into();
433 let callback = self.box_function_mut(&name, move |lua, (data, val)| function(lua, data, val));
434 self.raw.field_setters.push((name, callback));
435 }
436
437 fn add_meta_field<V>(&mut self, name: impl Into<String>, value: V)
438 where
439 V: IntoLua + 'static,
440 {
441 let lua = self.lua.lua();
442 let name = name.into();
443 let field = Self::check_meta_field(lua, &name, value).and_then(|v| v.into_lua(lua));
444 self.raw.meta_fields.push((name, field));
445 }
446
447 fn add_meta_field_with<F, R>(&mut self, name: impl Into<String>, f: F)
448 where
449 F: FnOnce(&Lua) -> Result<R> + 'static,
450 R: IntoLua,
451 {
452 let lua = self.lua.lua();
453 let name = name.into();
454 let field = f(lua).and_then(|v| Self::check_meta_field(lua, &name, v).and_then(|v| v.into_lua(lua)));
455 self.raw.meta_fields.push((name, field));
456 }
457}
458
459impl<T> UserDataMethods<T> for UserDataRegistry<T> {
460 fn add_method<M, A, R>(&mut self, name: impl Into<String>, method: M)
461 where
462 M: Fn(&Lua, &T, A) -> Result<R> + MaybeSend + 'static,
463 A: FromLuaMulti,
464 R: IntoLuaMulti,
465 {
466 let name = name.into();
467 let callback = self.box_method(&name, method);
468 self.raw.methods.push((name, callback));
469 }
470
471 fn add_method_mut<M, A, R>(&mut self, name: impl Into<String>, method: M)
472 where
473 M: FnMut(&Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
474 A: FromLuaMulti,
475 R: IntoLuaMulti,
476 {
477 let name = name.into();
478 let callback = self.box_method_mut(&name, method);
479 self.raw.methods.push((name, callback));
480 }
481
482 #[cfg(feature = "async")]
483 fn add_async_method<M, A, MR, R>(&mut self, name: impl Into<String>, method: M)
484 where
485 T: 'static,
486 M: Fn(Lua, UserDataRef<T>, A) -> MR + MaybeSend + 'static,
487 A: FromLuaMulti,
488 MR: Future<Output = Result<R>> + MaybeSend + 'static,
489 R: IntoLuaMulti,
490 {
491 let name = name.into();
492 let callback = self.box_async_method(&name, method);
493 self.raw.async_methods.push((name, callback));
494 }
495
496 #[cfg(feature = "async")]
497 fn add_async_method_mut<M, A, MR, R>(&mut self, name: impl Into<String>, method: M)
498 where
499 T: 'static,
500 M: Fn(Lua, UserDataRefMut<T>, A) -> MR + MaybeSend + 'static,
501 A: FromLuaMulti,
502 MR: Future<Output = Result<R>> + MaybeSend + 'static,
503 R: IntoLuaMulti,
504 {
505 let name = name.into();
506 let callback = self.box_async_method_mut(&name, method);
507 self.raw.async_methods.push((name, callback));
508 }
509
510 fn add_function<F, A, R>(&mut self, name: impl Into<String>, function: F)
511 where
512 F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
513 A: FromLuaMulti,
514 R: IntoLuaMulti,
515 {
516 let name = name.into();
517 let callback = self.box_function(&name, function);
518 self.raw.methods.push((name, callback));
519 }
520
521 fn add_function_mut<F, A, R>(&mut self, name: impl Into<String>, function: F)
522 where
523 F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
524 A: FromLuaMulti,
525 R: IntoLuaMulti,
526 {
527 let name = name.into();
528 let callback = self.box_function_mut(&name, function);
529 self.raw.methods.push((name, callback));
530 }
531
532 #[cfg(feature = "async")]
533 fn add_async_function<F, A, FR, R>(&mut self, name: impl Into<String>, function: F)
534 where
535 F: Fn(Lua, A) -> FR + MaybeSend + 'static,
536 A: FromLuaMulti,
537 FR: Future<Output = Result<R>> + MaybeSend + 'static,
538 R: IntoLuaMulti,
539 {
540 let name = name.into();
541 let callback = self.box_async_function(&name, function);
542 self.raw.async_methods.push((name, callback));
543 }
544
545 fn add_meta_method<M, A, R>(&mut self, name: impl Into<String>, method: M)
546 where
547 M: Fn(&Lua, &T, A) -> Result<R> + MaybeSend + 'static,
548 A: FromLuaMulti,
549 R: IntoLuaMulti,
550 {
551 let name = name.into();
552 let callback = self.box_method(&name, method);
553 self.raw.meta_methods.push((name, callback));
554 }
555
556 fn add_meta_method_mut<M, A, R>(&mut self, name: impl Into<String>, method: M)
557 where
558 M: FnMut(&Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
559 A: FromLuaMulti,
560 R: IntoLuaMulti,
561 {
562 let name = name.into();
563 let callback = self.box_method_mut(&name, method);
564 self.raw.meta_methods.push((name, callback));
565 }
566
567 #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
568 fn add_async_meta_method<M, A, MR, R>(&mut self, name: impl Into<String>, method: M)
569 where
570 T: 'static,
571 M: Fn(Lua, UserDataRef<T>, A) -> MR + MaybeSend + 'static,
572 A: FromLuaMulti,
573 MR: Future<Output = Result<R>> + MaybeSend + 'static,
574 R: IntoLuaMulti,
575 {
576 let name = name.into();
577 let callback = self.box_async_method(&name, method);
578 self.raw.async_meta_methods.push((name, callback));
579 }
580
581 #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
582 fn add_async_meta_method_mut<M, A, MR, R>(&mut self, name: impl Into<String>, method: M)
583 where
584 T: 'static,
585 M: Fn(Lua, UserDataRefMut<T>, A) -> MR + MaybeSend + 'static,
586 A: FromLuaMulti,
587 MR: Future<Output = Result<R>> + MaybeSend + 'static,
588 R: IntoLuaMulti,
589 {
590 let name = name.into();
591 let callback = self.box_async_method_mut(&name, method);
592 self.raw.async_meta_methods.push((name, callback));
593 }
594
595 fn add_meta_function<F, A, R>(&mut self, name: impl Into<String>, function: F)
596 where
597 F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
598 A: FromLuaMulti,
599 R: IntoLuaMulti,
600 {
601 let name = name.into();
602 let callback = self.box_function(&name, function);
603 self.raw.meta_methods.push((name, callback));
604 }
605
606 fn add_meta_function_mut<F, A, R>(&mut self, name: impl Into<String>, function: F)
607 where
608 F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
609 A: FromLuaMulti,
610 R: IntoLuaMulti,
611 {
612 let name = name.into();
613 let callback = self.box_function_mut(&name, function);
614 self.raw.meta_methods.push((name, callback));
615 }
616
617 #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
618 fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl Into<String>, function: F)
619 where
620 F: Fn(Lua, A) -> FR + MaybeSend + 'static,
621 A: FromLuaMulti,
622 FR: Future<Output = Result<R>> + MaybeSend + 'static,
623 R: IntoLuaMulti,
624 {
625 let name = name.into();
626 let callback = self.box_async_function(&name, function);
627 self.raw.async_meta_methods.push((name, callback));
628 }
629}
630
631macro_rules! lua_userdata_impl {
632 ($type:ty) => {
633 impl<T: UserData + 'static> UserData for $type {
634 fn register(registry: &mut UserDataRegistry<Self>) {
635 let mut orig_registry = UserDataRegistry::new(registry.lua.lua());
636 T::register(&mut orig_registry);
637
638 (registry.raw.fields).extend(orig_registry.raw.fields);
640 (registry.raw.field_getters).extend(orig_registry.raw.field_getters);
641 (registry.raw.field_setters).extend(orig_registry.raw.field_setters);
642 (registry.raw.meta_fields).extend(orig_registry.raw.meta_fields);
643 (registry.raw.methods).extend(orig_registry.raw.methods);
644 #[cfg(feature = "async")]
645 (registry.raw.async_methods).extend(orig_registry.raw.async_methods);
646 (registry.raw.meta_methods).extend(orig_registry.raw.meta_methods);
647 #[cfg(feature = "async")]
648 (registry.raw.async_meta_methods).extend(orig_registry.raw.async_meta_methods);
649 }
650 }
651 };
652}
653
654pub(crate) struct UserDataProxy<T>(pub(crate) PhantomData<T>);
656
657#[cfg(feature = "send")]
659unsafe impl<T> Send for UserDataProxy<T> {}
660#[cfg(feature = "send")]
661unsafe impl<T> Sync for UserDataProxy<T> {}
662
663lua_userdata_impl!(UserDataProxy<T>);
664
665#[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
666lua_userdata_impl!(std::rc::Rc<T>);
667#[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
668lua_userdata_impl!(std::rc::Rc<std::cell::RefCell<T>>);
669#[cfg(feature = "userdata-wrappers")]
670lua_userdata_impl!(std::sync::Arc<T>);
671#[cfg(feature = "userdata-wrappers")]
672lua_userdata_impl!(std::sync::Arc<std::sync::Mutex<T>>);
673#[cfg(feature = "userdata-wrappers")]
674lua_userdata_impl!(std::sync::Arc<std::sync::RwLock<T>>);
675#[cfg(feature = "userdata-wrappers")]
676lua_userdata_impl!(std::sync::Arc<parking_lot::Mutex<T>>);
677#[cfg(feature = "userdata-wrappers")]
678lua_userdata_impl!(std::sync::Arc<parking_lot::RwLock<T>>);
679
680#[cfg(test)]
681mod assertions {
682 #[cfg(feature = "send")]
683 static_assertions::assert_impl_all!(super::RawUserDataRegistry: Send);
684}