1use std::any::{TypeId, type_name};
2use std::ops::{Deref, DerefMut};
3use std::os::raw::c_int;
4use std::{fmt, mem};
5
6use crate::error::{Error, Result};
7use crate::state::{Lua, RawLua};
8use crate::traits::FromLua;
9use crate::userdata::AnyUserData;
10use crate::util::{check_stack, get_userdata, take_userdata};
11use crate::value::Value;
12
13use super::cell::{UserDataStorage, UserDataVariant};
14use super::lock::{LockGuard, RawLock, UserDataLock};
15
16#[cfg(feature = "userdata-wrappers")]
17use {
18 parking_lot::{
19 Mutex as MutexPL, MutexGuard as MutexGuardPL, RwLock as RwLockPL,
20 RwLockReadGuard as RwLockReadGuardPL, RwLockWriteGuard as RwLockWriteGuardPL,
21 },
22 std::sync::Arc,
23};
24#[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
25use {
26 std::cell::{Ref, RefCell, RefMut},
27 std::rc::Rc,
28};
29
30pub struct UserDataRef<T: 'static> {
34 _guard: LockGuard<'static, RawLock>,
36 inner: UserDataRefInner<T>,
37}
38
39impl<T> Deref for UserDataRef<T> {
40 type Target = T;
41
42 #[inline]
43 fn deref(&self) -> &T {
44 &self.inner
45 }
46}
47
48impl<T: fmt::Debug> fmt::Debug for UserDataRef<T> {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 (**self).fmt(f)
51 }
52}
53
54impl<T: fmt::Display> fmt::Display for UserDataRef<T> {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 (**self).fmt(f)
57 }
58}
59
60impl<T> TryFrom<UserDataVariant<T>> for UserDataRef<T> {
61 type Error = Error;
62
63 #[inline]
64 fn try_from(variant: UserDataVariant<T>) -> Result<Self> {
65 let guard = variant.raw_lock().try_lock_shared_guarded();
70 let guard = guard.map_err(|_| Error::UserDataBorrowError)?;
71 let guard = unsafe { mem::transmute::<LockGuard<_>, LockGuard<'static, _>>(guard) };
72 Ok(UserDataRef::from_parts(UserDataRefInner::Default(variant), guard))
73 }
74}
75
76impl<T: 'static> FromLua for UserDataRef<T> {
77 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
78 try_value_to_userdata::<T>(value)?.borrow()
79 }
80
81 #[inline]
82 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
83 Self::borrow_from_stack(lua, lua.state(), idx)
84 }
85}
86
87impl<T: 'static> UserDataRef<T> {
88 #[inline(always)]
89 fn from_parts(inner: UserDataRefInner<T>, guard: LockGuard<'static, RawLock>) -> Self {
90 Self { _guard: guard, inner }
91 }
92
93 #[cfg(feature = "userdata-wrappers")]
94 fn remap<U>(
95 self,
96 f: impl FnOnce(UserDataVariant<T>) -> Result<UserDataRefInner<U>>,
97 ) -> Result<UserDataRef<U>> {
98 match &self.inner {
99 UserDataRefInner::Default(variant) => {
100 let inner = f(variant.clone())?;
101 Ok(UserDataRef::from_parts(inner, self._guard))
102 }
103 _ => Err(Error::UserDataTypeMismatch),
104 }
105 }
106
107 pub(crate) unsafe fn borrow_from_stack(
108 lua: &RawLua,
109 state: *mut ffi::lua_State,
110 idx: c_int,
111 ) -> Result<Self> {
112 let type_id = lua.get_userdata_type_id::<T>(state, idx)?;
113 match type_id {
114 Some(type_id) if type_id == TypeId::of::<T>() => {
115 let ud = get_userdata::<UserDataStorage<T>>(state, idx);
116 (*ud).try_borrow_owned()
117 }
118
119 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
120 Some(type_id) if type_id == TypeId::of::<Rc<T>>() => {
121 let ud = get_userdata::<UserDataStorage<Rc<T>>>(state, idx);
122 ((*ud).try_borrow_owned()).and_then(|ud| ud.transform_rc())
123 }
124 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
125 Some(type_id) if type_id == TypeId::of::<Rc<RefCell<T>>>() => {
126 let ud = get_userdata::<UserDataStorage<Rc<RefCell<T>>>>(state, idx);
127 ((*ud).try_borrow_owned()).and_then(|ud| ud.transform_rc_refcell())
128 }
129
130 #[cfg(feature = "userdata-wrappers")]
131 Some(type_id) if type_id == TypeId::of::<Arc<T>>() => {
132 let ud = get_userdata::<UserDataStorage<Arc<T>>>(state, idx);
133 ((*ud).try_borrow_owned()).and_then(|ud| ud.transform_arc())
134 }
135 #[cfg(feature = "userdata-wrappers")]
136 Some(type_id) if type_id == TypeId::of::<Arc<MutexPL<T>>>() => {
137 let ud = get_userdata::<UserDataStorage<Arc<MutexPL<T>>>>(state, idx);
138 ((*ud).try_borrow_owned()).and_then(|ud| ud.transform_arc_mutex_pl())
139 }
140 #[cfg(feature = "userdata-wrappers")]
141 Some(type_id) if type_id == TypeId::of::<Arc<RwLockPL<T>>>() => {
142 let ud = get_userdata::<UserDataStorage<Arc<RwLockPL<T>>>>(state, idx);
143 ((*ud).try_borrow_owned()).and_then(|ud| ud.transform_arc_rwlock_pl())
144 }
145 _ => Err(Error::UserDataTypeMismatch),
146 }
147 }
148}
149
150#[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
151impl<T> UserDataRef<Rc<T>> {
152 fn transform_rc(self) -> Result<UserDataRef<T>> {
153 self.remap(|variant| Ok(UserDataRefInner::Rc(variant)))
154 }
155}
156
157#[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
158impl<T> UserDataRef<Rc<RefCell<T>>> {
159 fn transform_rc_refcell(self) -> Result<UserDataRef<T>> {
160 self.remap(|variant| unsafe {
161 let obj = &*variant.as_ptr();
162 let r#ref = obj.try_borrow().map_err(|_| Error::UserDataBorrowError)?;
163 let borrow = std::mem::transmute::<Ref<T>, Ref<'static, T>>(r#ref);
164 Ok(UserDataRefInner::RcRefCell(borrow, variant))
165 })
166 }
167}
168
169#[cfg(feature = "userdata-wrappers")]
170impl<T> UserDataRef<Arc<T>> {
171 fn transform_arc(self) -> Result<UserDataRef<T>> {
172 self.remap(|variant| Ok(UserDataRefInner::Arc(variant)))
173 }
174}
175
176#[cfg(feature = "userdata-wrappers")]
177impl<T> UserDataRef<Arc<MutexPL<T>>> {
178 fn transform_arc_mutex_pl(self) -> Result<UserDataRef<T>> {
179 self.remap(|variant| unsafe {
180 let obj = &*variant.as_ptr();
181 let guard = obj.try_lock().ok_or(Error::UserDataBorrowError)?;
182 let borrow = std::mem::transmute::<MutexGuardPL<T>, MutexGuardPL<'static, T>>(guard);
183 Ok(UserDataRefInner::ArcMutexPL(borrow, variant))
184 })
185 }
186}
187
188#[cfg(feature = "userdata-wrappers")]
189impl<T> UserDataRef<Arc<RwLockPL<T>>> {
190 fn transform_arc_rwlock_pl(self) -> Result<UserDataRef<T>> {
191 self.remap(|variant| unsafe {
192 let obj = &*variant.as_ptr();
193 let guard = obj.try_read().ok_or(Error::UserDataBorrowError)?;
194 let borrow = std::mem::transmute::<RwLockReadGuardPL<T>, RwLockReadGuardPL<'static, T>>(guard);
195 Ok(UserDataRefInner::ArcRwLockPL(borrow, variant))
196 })
197 }
198}
199
200#[allow(unused)]
201enum UserDataRefInner<T: 'static> {
202 Default(UserDataVariant<T>),
203
204 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
205 Rc(UserDataVariant<Rc<T>>),
206 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
207 RcRefCell(Ref<'static, T>, UserDataVariant<Rc<RefCell<T>>>),
208
209 #[cfg(feature = "userdata-wrappers")]
210 Arc(UserDataVariant<Arc<T>>),
211 #[cfg(feature = "userdata-wrappers")]
212 ArcMutexPL(MutexGuardPL<'static, T>, UserDataVariant<Arc<MutexPL<T>>>),
213 #[cfg(feature = "userdata-wrappers")]
214 ArcRwLockPL(RwLockReadGuardPL<'static, T>, UserDataVariant<Arc<RwLockPL<T>>>),
215}
216
217impl<T> Deref for UserDataRefInner<T> {
218 type Target = T;
219
220 #[inline]
221 fn deref(&self) -> &T {
222 match self {
223 Self::Default(inner) => unsafe { &*inner.as_ptr() },
224
225 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
226 Self::Rc(inner) => unsafe { &*Rc::as_ptr(&*inner.as_ptr()) },
227 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
228 Self::RcRefCell(x, ..) => x,
229
230 #[cfg(feature = "userdata-wrappers")]
231 Self::Arc(inner) => unsafe { &*Arc::as_ptr(&*inner.as_ptr()) },
232 #[cfg(feature = "userdata-wrappers")]
233 Self::ArcMutexPL(x, ..) => x,
234 #[cfg(feature = "userdata-wrappers")]
235 Self::ArcRwLockPL(x, ..) => x,
236 }
237 }
238}
239
240pub struct UserDataRefMut<T: 'static> {
244 _guard: LockGuard<'static, RawLock>,
246 inner: UserDataRefMutInner<T>,
247}
248
249impl<T> Deref for UserDataRefMut<T> {
250 type Target = T;
251
252 #[inline]
253 fn deref(&self) -> &Self::Target {
254 &self.inner
255 }
256}
257
258impl<T> DerefMut for UserDataRefMut<T> {
259 #[inline]
260 fn deref_mut(&mut self) -> &mut Self::Target {
261 &mut self.inner
262 }
263}
264
265impl<T: fmt::Debug> fmt::Debug for UserDataRefMut<T> {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 (**self).fmt(f)
268 }
269}
270
271impl<T: fmt::Display> fmt::Display for UserDataRefMut<T> {
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 (**self).fmt(f)
274 }
275}
276
277impl<T> TryFrom<UserDataVariant<T>> for UserDataRefMut<T> {
278 type Error = Error;
279
280 #[inline]
281 fn try_from(variant: UserDataVariant<T>) -> Result<Self> {
282 let guard = variant.raw_lock().try_lock_exclusive_guarded();
283 let guard = guard.map_err(|_| Error::UserDataBorrowMutError)?;
284 let guard = unsafe { mem::transmute::<LockGuard<_>, LockGuard<'static, _>>(guard) };
285 Ok(UserDataRefMut::from_parts(
286 UserDataRefMutInner::Default(variant),
287 guard,
288 ))
289 }
290}
291
292impl<T: 'static> FromLua for UserDataRefMut<T> {
293 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
294 try_value_to_userdata::<T>(value)?.borrow_mut()
295 }
296
297 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
298 Self::borrow_from_stack(lua, lua.state(), idx)
299 }
300}
301
302impl<T: 'static> UserDataRefMut<T> {
303 #[inline(always)]
304 fn from_parts(inner: UserDataRefMutInner<T>, guard: LockGuard<'static, RawLock>) -> Self {
305 Self { _guard: guard, inner }
306 }
307
308 #[cfg(feature = "userdata-wrappers")]
309 fn remap<U>(
310 self,
311 f: impl FnOnce(UserDataVariant<T>) -> Result<UserDataRefMutInner<U>>,
312 ) -> Result<UserDataRefMut<U>> {
313 match &self.inner {
314 UserDataRefMutInner::Default(variant) => {
315 let inner = f(variant.clone())?;
316 Ok(UserDataRefMut::from_parts(inner, self._guard))
317 }
318 _ => Err(Error::UserDataTypeMismatch),
319 }
320 }
321
322 pub(crate) unsafe fn borrow_from_stack(
323 lua: &RawLua,
324 state: *mut ffi::lua_State,
325 idx: c_int,
326 ) -> Result<Self> {
327 let type_id = lua.get_userdata_type_id::<T>(state, idx)?;
328 match type_id {
329 Some(type_id) if type_id == TypeId::of::<T>() => {
330 let ud = get_userdata::<UserDataStorage<T>>(state, idx);
331 (*ud).try_borrow_owned_mut()
332 }
333
334 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
335 Some(type_id) if type_id == TypeId::of::<Rc<T>>() => Err(Error::UserDataBorrowMutError),
336 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
337 Some(type_id) if type_id == TypeId::of::<Rc<RefCell<T>>>() => {
338 let ud = get_userdata::<UserDataStorage<Rc<RefCell<T>>>>(state, idx);
339 ((*ud).try_borrow_owned_mut()).and_then(|ud| ud.transform_rc_refcell())
340 }
341
342 #[cfg(feature = "userdata-wrappers")]
343 Some(type_id) if type_id == TypeId::of::<Arc<T>>() => Err(Error::UserDataBorrowMutError),
344 #[cfg(feature = "userdata-wrappers")]
345 Some(type_id) if type_id == TypeId::of::<Arc<MutexPL<T>>>() => {
346 let ud = get_userdata::<UserDataStorage<Arc<MutexPL<T>>>>(state, idx);
347 ((*ud).try_borrow_owned_mut()).and_then(|ud| ud.transform_arc_mutex_pl())
348 }
349 #[cfg(feature = "userdata-wrappers")]
350 Some(type_id) if type_id == TypeId::of::<Arc<RwLockPL<T>>>() => {
351 let ud = get_userdata::<UserDataStorage<Arc<RwLockPL<T>>>>(state, idx);
352 ((*ud).try_borrow_owned_mut()).and_then(|ud| ud.transform_arc_rwlock_pl())
353 }
354 _ => Err(Error::UserDataTypeMismatch),
355 }
356 }
357}
358
359#[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
360impl<T> UserDataRefMut<Rc<RefCell<T>>> {
361 fn transform_rc_refcell(self) -> Result<UserDataRefMut<T>> {
362 self.remap(|variant| unsafe {
363 let obj = &*variant.as_ptr();
364 let refmut = obj.try_borrow_mut().map_err(|_| Error::UserDataBorrowMutError)?;
365 let borrow = std::mem::transmute::<RefMut<T>, RefMut<'static, T>>(refmut);
366 Ok(UserDataRefMutInner::RcRefCell(borrow, variant))
367 })
368 }
369}
370
371#[cfg(feature = "userdata-wrappers")]
372impl<T> UserDataRefMut<Arc<MutexPL<T>>> {
373 fn transform_arc_mutex_pl(self) -> Result<UserDataRefMut<T>> {
374 self.remap(|variant| unsafe {
375 let obj = &*variant.as_ptr();
376 let guard = obj.try_lock().ok_or(Error::UserDataBorrowMutError)?;
377 let borrow = std::mem::transmute::<MutexGuardPL<T>, MutexGuardPL<'static, T>>(guard);
378 Ok(UserDataRefMutInner::ArcMutexPL(borrow, variant))
379 })
380 }
381}
382
383#[cfg(feature = "userdata-wrappers")]
384impl<T> UserDataRefMut<Arc<RwLockPL<T>>> {
385 fn transform_arc_rwlock_pl(self) -> Result<UserDataRefMut<T>> {
386 self.remap(|variant| unsafe {
387 let obj = &*variant.as_ptr();
388 let guard = obj.try_write().ok_or(Error::UserDataBorrowMutError)?;
389 let borrow = std::mem::transmute::<RwLockWriteGuardPL<T>, RwLockWriteGuardPL<'static, T>>(guard);
390 Ok(UserDataRefMutInner::ArcRwLockPL(borrow, variant))
391 })
392 }
393}
394
395#[allow(unused)]
396enum UserDataRefMutInner<T: 'static> {
397 Default(UserDataVariant<T>),
398
399 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
400 RcRefCell(RefMut<'static, T>, UserDataVariant<Rc<RefCell<T>>>),
401
402 #[cfg(feature = "userdata-wrappers")]
403 ArcMutexPL(MutexGuardPL<'static, T>, UserDataVariant<Arc<MutexPL<T>>>),
404 #[cfg(feature = "userdata-wrappers")]
405 ArcRwLockPL(RwLockWriteGuardPL<'static, T>, UserDataVariant<Arc<RwLockPL<T>>>),
406}
407
408impl<T> Deref for UserDataRefMutInner<T> {
409 type Target = T;
410
411 #[inline]
412 fn deref(&self) -> &T {
413 match self {
414 Self::Default(inner) => unsafe { &*inner.as_ptr() },
415
416 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
417 Self::RcRefCell(x, ..) => x,
418
419 #[cfg(feature = "userdata-wrappers")]
420 Self::ArcMutexPL(x, ..) => x,
421 #[cfg(feature = "userdata-wrappers")]
422 Self::ArcRwLockPL(x, ..) => x,
423 }
424 }
425}
426
427impl<T> DerefMut for UserDataRefMutInner<T> {
428 #[inline]
429 fn deref_mut(&mut self) -> &mut T {
430 match self {
431 Self::Default(inner) => unsafe { &mut *inner.as_ptr() },
432
433 #[cfg(all(feature = "userdata-wrappers", not(feature = "send")))]
434 Self::RcRefCell(x, ..) => x,
435
436 #[cfg(feature = "userdata-wrappers")]
437 Self::ArcMutexPL(x, ..) => x,
438 #[cfg(feature = "userdata-wrappers")]
439 Self::ArcRwLockPL(x, ..) => x,
440 }
441 }
442}
443
444pub struct UserDataOwned<T>(pub T);
450
451impl<T> Deref for UserDataOwned<T> {
452 type Target = T;
453
454 #[inline]
455 fn deref(&self) -> &T {
456 &self.0
457 }
458}
459
460impl<T> DerefMut for UserDataOwned<T> {
461 #[inline]
462 fn deref_mut(&mut self) -> &mut T {
463 &mut self.0
464 }
465}
466
467impl<T: fmt::Debug> fmt::Debug for UserDataOwned<T> {
468 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
469 (**self).fmt(f)
470 }
471}
472
473impl<T: fmt::Display> fmt::Display for UserDataOwned<T> {
474 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475 (**self).fmt(f)
476 }
477}
478
479impl<T: 'static> FromLua for UserDataOwned<T> {
480 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
481 try_value_to_userdata::<T>(value)?.take().map(UserDataOwned)
482 }
483
484 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
485 let state = lua.state();
486 let type_id = lua.get_userdata_type_id::<T>(state, idx)?;
487 match type_id {
488 Some(type_id) if type_id == TypeId::of::<T>() => {
489 let ud = get_userdata::<UserDataStorage<T>>(state, idx);
490 if (*ud).has_exclusive_access() {
491 check_stack(state, 1)?;
492 take_userdata::<UserDataStorage<T>>(state, idx)
493 .into_inner()
494 .map(UserDataOwned)
495 } else {
496 Err(Error::UserDataBorrowMutError)
497 }
498 }
499 _ => Err(Error::UserDataTypeMismatch),
500 }
501 }
502}
503
504#[inline]
505fn try_value_to_userdata<T>(value: Value) -> Result<AnyUserData> {
506 match value {
507 Value::UserData(ud) => Ok(ud),
508 _ => Err(Error::from_lua_conversion(
509 value.type_name(),
510 "userdata",
511 format!("expected userdata of type {}", type_name::<T>()),
512 )),
513 }
514}
515
516#[cfg(test)]
517mod assertions {
518 use super::*;
519
520 #[cfg(feature = "send")]
521 static_assertions::assert_impl_all!(UserDataRef<()>: Send, Sync);
522 #[cfg(feature = "send")]
523 static_assertions::assert_not_impl_all!(UserDataRef<std::rc::Rc<()>>: Send, Sync);
524 #[cfg(feature = "send")]
525 static_assertions::assert_impl_all!(UserDataRefMut<()>: Sync, Send);
526 #[cfg(feature = "send")]
527 static_assertions::assert_not_impl_all!(UserDataRefMut<std::rc::Rc<()>>: Send, Sync);
528 #[cfg(feature = "send")]
529 static_assertions::assert_impl_all!(UserDataOwned<()>: Send, Sync);
530 #[cfg(feature = "send")]
531 static_assertions::assert_not_impl_all!(UserDataOwned<std::rc::Rc<()>>: Send, Sync);
532
533 #[cfg(not(feature = "send"))]
534 static_assertions::assert_not_impl_all!(UserDataRef<()>: Send, Sync);
535 #[cfg(not(feature = "send"))]
536 static_assertions::assert_not_impl_all!(UserDataRefMut<()>: Send, Sync);
537}