mlua_codemp_patch/userdata/
cell.rs

1use std::any::{type_name, TypeId};
2use std::cell::UnsafeCell;
3use std::fmt;
4use std::ops::{Deref, DerefMut};
5use std::os::raw::c_int;
6
7#[cfg(feature = "serialize")]
8use serde::ser::{Serialize, Serializer};
9
10use crate::error::{Error, Result};
11use crate::state::{Lua, RawLua};
12use crate::types::{MaybeSend, XRc};
13use crate::userdata::AnyUserData;
14use crate::util::get_userdata;
15use crate::value::{FromLua, Value};
16
17use super::lock::{RawLock, UserDataLock};
18
19#[cfg(all(feature = "serialize", not(feature = "send")))]
20type DynSerialize = dyn erased_serde::Serialize;
21
22#[cfg(all(feature = "serialize", feature = "send"))]
23type DynSerialize = dyn erased_serde::Serialize + Send;
24
25// A enum for storing userdata values.
26// It's stored inside a Lua VM and protected by the outer `ReentrantMutex`.
27pub(crate) enum UserDataVariant<T> {
28    Default(XRc<UserDataCell<T>>),
29    #[cfg(feature = "serialize")]
30    Serializable(XRc<UserDataCell<Box<DynSerialize>>>),
31}
32
33impl<T> Clone for UserDataVariant<T> {
34    #[inline]
35    fn clone(&self) -> Self {
36        match self {
37            Self::Default(inner) => Self::Default(XRc::clone(inner)),
38            #[cfg(feature = "serialize")]
39            Self::Serializable(inner) => Self::Serializable(XRc::clone(inner)),
40        }
41    }
42}
43
44impl<T> UserDataVariant<T> {
45    #[inline(always)]
46    pub(crate) fn new(data: T) -> Self {
47        Self::Default(XRc::new(UserDataCell::new(data)))
48    }
49
50    // Immutably borrows the wrapped value in-place.
51    #[inline(always)]
52    pub(crate) fn try_borrow(&self) -> Result<UserDataBorrowRef<T>> {
53        UserDataBorrowRef::try_from(self)
54    }
55
56    // Immutably borrows the wrapped value and returns an owned reference.
57    #[inline(always)]
58    pub(crate) fn try_borrow_owned(&self) -> Result<UserDataRef<T>> {
59        UserDataRef::try_from(self.clone())
60    }
61
62    // Mutably borrows the wrapped value in-place.
63    #[inline(always)]
64    pub(crate) fn try_borrow_mut(&self) -> Result<UserDataBorrowMut<T>> {
65        UserDataBorrowMut::try_from(self)
66    }
67
68    // Mutably borrows the wrapped value and returns an owned reference.
69    #[inline(always)]
70    pub(crate) fn try_borrow_owned_mut(&self) -> Result<UserDataRefMut<T>> {
71        UserDataRefMut::try_from(self.clone())
72    }
73
74    // Returns the wrapped value.
75    //
76    // This method checks that we have exclusive access to the value.
77    pub(crate) fn into_inner(self) -> Result<T> {
78        if !self.raw_lock().try_lock_exclusive() {
79            return Err(Error::UserDataBorrowMutError);
80        }
81        Ok(match self {
82            Self::Default(inner) => XRc::into_inner(inner).unwrap().value.into_inner(),
83            #[cfg(feature = "serialize")]
84            Self::Serializable(inner) => unsafe {
85                let raw = Box::into_raw(XRc::into_inner(inner).unwrap().value.into_inner());
86                *Box::from_raw(raw as *mut T)
87            },
88        })
89    }
90
91    #[inline(always)]
92    fn raw_lock(&self) -> &RawLock {
93        match self {
94            Self::Default(inner) => &inner.raw_lock,
95            #[cfg(feature = "serialize")]
96            Self::Serializable(inner) => &inner.raw_lock,
97        }
98    }
99
100    #[inline(always)]
101    fn as_ptr(&self) -> *mut T {
102        match self {
103            Self::Default(inner) => inner.value.get(),
104            #[cfg(feature = "serialize")]
105            Self::Serializable(inner) => unsafe { &mut **(inner.value.get() as *mut Box<T>) },
106        }
107    }
108}
109
110#[cfg(feature = "serialize")]
111impl<T: Serialize + MaybeSend + 'static> UserDataVariant<T> {
112    #[inline(always)]
113    pub(crate) fn new_ser(data: T) -> Self {
114        let data = Box::new(data) as Box<DynSerialize>;
115        Self::Serializable(XRc::new(UserDataCell::new(data)))
116    }
117}
118
119#[cfg(feature = "serialize")]
120impl Serialize for UserDataVariant<()> {
121    fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
122        match self {
123            Self::Default(_) => Err(serde::ser::Error::custom("cannot serialize <userdata>")),
124            Self::Serializable(inner) => unsafe {
125                // We need to borrow the inner value exclusively to serialize it.
126                #[cfg(feature = "send")]
127                let _guard = self.try_borrow_mut().map_err(serde::ser::Error::custom)?;
128                // No need to do this if the `send` feature is disabled.
129                #[cfg(not(feature = "send"))]
130                let _guard = self.try_borrow().map_err(serde::ser::Error::custom)?;
131                (*inner.value.get()).serialize(serializer)
132            },
133        }
134    }
135}
136
137/// A type that provides interior mutability for a userdata value (thread-safe).
138pub(crate) struct UserDataCell<T> {
139    raw_lock: RawLock,
140    value: UnsafeCell<T>,
141}
142
143unsafe impl<T: Send> Send for UserDataCell<T> {}
144unsafe impl<T: Send> Sync for UserDataCell<T> {}
145
146impl<T> UserDataCell<T> {
147    #[inline(always)]
148    pub fn new(value: T) -> Self {
149        UserDataCell {
150            raw_lock: RawLock::INIT,
151            value: UnsafeCell::new(value),
152        }
153    }
154}
155
156/// A wrapper type for a [`UserData`] value that provides read access.
157///
158/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
159pub struct UserDataRef<T>(UserDataVariant<T>);
160
161impl<T> Deref for UserDataRef<T> {
162    type Target = T;
163
164    #[inline]
165    fn deref(&self) -> &T {
166        unsafe { &*self.0.as_ptr() }
167    }
168}
169
170impl<T> Drop for UserDataRef<T> {
171    #[inline]
172    fn drop(&mut self) {
173        unsafe { self.0.raw_lock().unlock_shared() };
174    }
175}
176
177impl<T: fmt::Debug> fmt::Debug for UserDataRef<T> {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        (**self).fmt(f)
180    }
181}
182
183impl<T: fmt::Display> fmt::Display for UserDataRef<T> {
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        (**self).fmt(f)
186    }
187}
188
189impl<T> TryFrom<UserDataVariant<T>> for UserDataRef<T> {
190    type Error = Error;
191
192    #[inline]
193    fn try_from(variant: UserDataVariant<T>) -> Result<Self> {
194        if !variant.raw_lock().try_lock_shared() {
195            return Err(Error::UserDataBorrowError);
196        }
197        Ok(UserDataRef(variant))
198    }
199}
200
201impl<T: 'static> FromLua for UserDataRef<T> {
202    fn from_lua(value: Value, _: &Lua) -> Result<Self> {
203        try_value_to_userdata::<T>(value)?.borrow()
204    }
205
206    unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
207        let type_id = lua.get_userdata_type_id(idx)?;
208        match type_id {
209            Some(type_id) if type_id == TypeId::of::<T>() => {
210                (*get_userdata::<UserDataVariant<T>>(lua.state(), idx)).try_borrow_owned()
211            }
212            _ => Err(Error::UserDataTypeMismatch),
213        }
214    }
215}
216
217/// A wrapper type for a mutably borrowed value from a `AnyUserData`.
218///
219/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
220pub struct UserDataRefMut<T>(UserDataVariant<T>);
221
222impl<T> Deref for UserDataRefMut<T> {
223    type Target = T;
224
225    #[inline]
226    fn deref(&self) -> &Self::Target {
227        unsafe { &*self.0.as_ptr() }
228    }
229}
230
231impl<T> DerefMut for UserDataRefMut<T> {
232    #[inline]
233    fn deref_mut(&mut self) -> &mut Self::Target {
234        unsafe { &mut *self.0.as_ptr() }
235    }
236}
237
238impl<T> Drop for UserDataRefMut<T> {
239    #[inline]
240    fn drop(&mut self) {
241        unsafe { self.0.raw_lock().unlock_exclusive() };
242    }
243}
244
245impl<T: fmt::Debug> fmt::Debug for UserDataRefMut<T> {
246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247        (**self).fmt(f)
248    }
249}
250
251impl<T: fmt::Display> fmt::Display for UserDataRefMut<T> {
252    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253        (**self).fmt(f)
254    }
255}
256
257impl<T> TryFrom<UserDataVariant<T>> for UserDataRefMut<T> {
258    type Error = Error;
259
260    #[inline]
261    fn try_from(variant: UserDataVariant<T>) -> Result<Self> {
262        if !variant.raw_lock().try_lock_exclusive() {
263            return Err(Error::UserDataBorrowMutError);
264        }
265        Ok(UserDataRefMut(variant))
266    }
267}
268
269impl<T: 'static> FromLua for UserDataRefMut<T> {
270    fn from_lua(value: Value, _: &Lua) -> Result<Self> {
271        try_value_to_userdata::<T>(value)?.borrow_mut()
272    }
273
274    unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
275        let type_id = lua.get_userdata_type_id(idx)?;
276        match type_id {
277            Some(type_id) if type_id == TypeId::of::<T>() => {
278                (*get_userdata::<UserDataVariant<T>>(lua.state(), idx)).try_borrow_owned_mut()
279            }
280            _ => Err(Error::UserDataTypeMismatch),
281        }
282    }
283}
284
285/// A type that provides read access to a userdata value (borrowing the value).
286pub(crate) struct UserDataBorrowRef<'a, T>(&'a UserDataVariant<T>);
287
288impl<'a, T> Drop for UserDataBorrowRef<'a, T> {
289    #[inline]
290    fn drop(&mut self) {
291        unsafe { self.0.raw_lock().unlock_shared() };
292    }
293}
294
295impl<'a, T> Deref for UserDataBorrowRef<'a, T> {
296    type Target = T;
297
298    #[inline]
299    fn deref(&self) -> &T {
300        // SAFETY: `UserDataBorrowRef` is only created with shared access to the value.
301        unsafe { &*self.0.as_ptr() }
302    }
303}
304
305impl<'a, T> TryFrom<&'a UserDataVariant<T>> for UserDataBorrowRef<'a, T> {
306    type Error = Error;
307
308    #[inline(always)]
309    fn try_from(variant: &'a UserDataVariant<T>) -> Result<Self> {
310        if !variant.raw_lock().try_lock_shared() {
311            return Err(Error::UserDataBorrowError);
312        }
313        Ok(UserDataBorrowRef(variant))
314    }
315}
316
317pub(crate) struct UserDataBorrowMut<'a, T>(&'a UserDataVariant<T>);
318
319impl<'a, T> Drop for UserDataBorrowMut<'a, T> {
320    #[inline]
321    fn drop(&mut self) {
322        unsafe { self.0.raw_lock().unlock_exclusive() };
323    }
324}
325
326impl<'a, T> Deref for UserDataBorrowMut<'a, T> {
327    type Target = T;
328
329    #[inline]
330    fn deref(&self) -> &T {
331        unsafe { &*self.0.as_ptr() }
332    }
333}
334
335impl<'a, T> DerefMut for UserDataBorrowMut<'a, T> {
336    #[inline]
337    fn deref_mut(&mut self) -> &mut T {
338        unsafe { &mut *self.0.as_ptr() }
339    }
340}
341
342impl<'a, T> TryFrom<&'a UserDataVariant<T>> for UserDataBorrowMut<'a, T> {
343    type Error = Error;
344
345    #[inline(always)]
346    fn try_from(variant: &'a UserDataVariant<T>) -> Result<Self> {
347        if !variant.raw_lock().try_lock_exclusive() {
348            return Err(Error::UserDataBorrowMutError);
349        }
350        Ok(UserDataBorrowMut(variant))
351    }
352}
353
354#[inline]
355fn try_value_to_userdata<T>(value: Value) -> Result<AnyUserData> {
356    match value {
357        Value::UserData(ud) => Ok(ud),
358        _ => Err(Error::FromLuaConversionError {
359            from: value.type_name(),
360            to: "userdata",
361            message: Some(format!("expected userdata of type {}", type_name::<T>())),
362        }),
363    }
364}
365
366#[cfg(test)]
367mod assertions {
368    use super::*;
369
370    #[cfg(feature = "send")]
371    static_assertions::assert_impl_all!(UserDataRef<()>: Send, Sync);
372    #[cfg(feature = "send")]
373    static_assertions::assert_not_impl_all!(UserDataRef<std::rc::Rc<()>>: Send, Sync);
374    #[cfg(feature = "send")]
375    static_assertions::assert_impl_all!(UserDataRefMut<()>: Sync, Send);
376    #[cfg(feature = "send")]
377    static_assertions::assert_not_impl_all!(UserDataRefMut<std::rc::Rc<()>>: Send, Sync);
378    #[cfg(feature = "send")]
379    static_assertions::assert_impl_all!(UserDataBorrowRef<'_, ()>: Send, Sync);
380    #[cfg(feature = "send")]
381    static_assertions::assert_impl_all!(UserDataBorrowMut<'_, ()>: Send, Sync);
382
383    #[cfg(not(feature = "send"))]
384    static_assertions::assert_not_impl_all!(UserDataRef<()>: Send, Sync);
385    #[cfg(not(feature = "send"))]
386    static_assertions::assert_not_impl_all!(UserDataRefMut<()>: Send, Sync);
387    #[cfg(not(feature = "send"))]
388    static_assertions::assert_not_impl_all!(UserDataBorrowRef<'_, ()>: Send, Sync);
389    #[cfg(not(feature = "send"))]
390    static_assertions::assert_not_impl_all!(UserDataBorrowMut<'_, ()>: Send, Sync);
391}