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