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