mlua/
userdata.rs

1use std::any::{type_name, TypeId};
2use std::cell::{Ref, RefCell, RefMut};
3use std::ffi::CStr;
4use std::fmt;
5use std::hash::Hash;
6use std::mem;
7use std::ops::{Deref, DerefMut};
8use std::os::raw::{c_char, c_int, c_void};
9use std::string::String as StdString;
10
11#[cfg(feature = "async")]
12use std::future::Future;
13
14#[cfg(feature = "serialize")]
15use {
16    serde::ser::{self, Serialize, Serializer},
17    std::result::Result as StdResult,
18};
19
20use crate::error::{Error, Result};
21use crate::function::Function;
22use crate::lua::Lua;
23use crate::string::String;
24use crate::table::{Table, TablePairs};
25use crate::types::{LuaRef, MaybeSend, SubtypeId};
26use crate::util::{check_stack, get_userdata, take_userdata, StackGuard};
27use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value};
28use crate::UserDataRegistry;
29
30#[cfg(feature = "lua54")]
31pub(crate) const USER_VALUE_MAXSLOT: usize = 8;
32
33/// Kinds of metamethods that can be overridden.
34///
35/// Currently, this mechanism does not allow overriding the `__gc` metamethod, since there is
36/// generally no need to do so: [`UserData`] implementors can instead just implement `Drop`.
37///
38/// [`UserData`]: crate::UserData
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40#[non_exhaustive]
41pub enum MetaMethod {
42    /// The `+` operator.
43    Add,
44    /// The `-` operator.
45    Sub,
46    /// The `*` operator.
47    Mul,
48    /// The `/` operator.
49    Div,
50    /// The `%` operator.
51    Mod,
52    /// The `^` operator.
53    Pow,
54    /// The unary minus (`-`) operator.
55    Unm,
56    /// The floor division (//) operator.
57    /// Requires `feature = "lua54/lua53/luau"`
58    #[cfg(any(feature = "lua54", feature = "lua53", feature = "luau"))]
59    IDiv,
60    /// The bitwise AND (&) operator.
61    /// Requires `feature = "lua54/lua53"`
62    #[cfg(any(feature = "lua54", feature = "lua53"))]
63    BAnd,
64    /// The bitwise OR (|) operator.
65    /// Requires `feature = "lua54/lua53"`
66    #[cfg(any(feature = "lua54", feature = "lua53"))]
67    BOr,
68    /// The bitwise XOR (binary ~) operator.
69    /// Requires `feature = "lua54/lua53"`
70    #[cfg(any(feature = "lua54", feature = "lua53"))]
71    BXor,
72    /// The bitwise NOT (unary ~) operator.
73    /// Requires `feature = "lua54/lua53"`
74    #[cfg(any(feature = "lua54", feature = "lua53"))]
75    BNot,
76    /// The bitwise left shift (<<) operator.
77    #[cfg(any(feature = "lua54", feature = "lua53"))]
78    Shl,
79    /// The bitwise right shift (>>) operator.
80    #[cfg(any(feature = "lua54", feature = "lua53"))]
81    Shr,
82    /// The string concatenation operator `..`.
83    Concat,
84    /// The length operator `#`.
85    Len,
86    /// The `==` operator.
87    Eq,
88    /// The `<` operator.
89    Lt,
90    /// The `<=` operator.
91    Le,
92    /// Index access `obj[key]`.
93    Index,
94    /// Index write access `obj[key] = value`.
95    NewIndex,
96    /// The call "operator" `obj(arg1, args2, ...)`.
97    Call,
98    /// The `__tostring` metamethod.
99    ///
100    /// This is not an operator, but will be called by methods such as `tostring` and `print`.
101    ToString,
102    /// The `__pairs` metamethod.
103    ///
104    /// This is not an operator, but it will be called by the built-in `pairs` function.
105    ///
106    /// Requires `feature = "lua54/lua53/lua52"`
107    #[cfg(any(
108        feature = "lua54",
109        feature = "lua53",
110        feature = "lua52",
111        feature = "luajit52",
112    ))]
113    Pairs,
114    /// The `__ipairs` metamethod.
115    ///
116    /// This is not an operator, but it will be called by the built-in [`ipairs`] function.
117    ///
118    /// Requires `feature = "lua52"`
119    ///
120    /// [`ipairs`]: https://www.lua.org/manual/5.2/manual.html#pdf-ipairs
121    #[cfg(any(feature = "lua52", feature = "luajit52", doc))]
122    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua52", feature = "luajit52"))))]
123    IPairs,
124    /// The `__iter` metamethod.
125    ///
126    /// Executed before the iteration begins, and should return an iterator function like `next`
127    /// (or a custom one).
128    ///
129    /// Requires `feature = "lua"`
130    #[cfg(any(feature = "luau", doc))]
131    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
132    Iter,
133    /// The `__close` metamethod.
134    ///
135    /// Executed when a variable, that marked as to-be-closed, goes out of scope.
136    ///
137    /// More information about to-be-closed variabled can be found in the Lua 5.4
138    /// [documentation][lua_doc].
139    ///
140    /// Requires `feature = "lua54"`
141    ///
142    /// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#3.3.8
143    #[cfg(feature = "lua54")]
144    #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
145    Close,
146    /// The `__name`/`__type` metafield.
147    ///
148    /// This is not a function, but it's value can be used by `tostring` and `typeof` built-in functions.
149    #[doc(hidden)]
150    Type,
151}
152
153impl PartialEq<MetaMethod> for &str {
154    fn eq(&self, other: &MetaMethod) -> bool {
155        *self == other.name()
156    }
157}
158
159impl PartialEq<MetaMethod> for StdString {
160    fn eq(&self, other: &MetaMethod) -> bool {
161        self == other.name()
162    }
163}
164
165impl fmt::Display for MetaMethod {
166    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
167        write!(fmt, "{}", self.name())
168    }
169}
170
171impl MetaMethod {
172    /// Returns Lua metamethod name, usually prefixed by two underscores.
173    pub const fn name(self) -> &'static str {
174        match self {
175            MetaMethod::Add => "__add",
176            MetaMethod::Sub => "__sub",
177            MetaMethod::Mul => "__mul",
178            MetaMethod::Div => "__div",
179            MetaMethod::Mod => "__mod",
180            MetaMethod::Pow => "__pow",
181            MetaMethod::Unm => "__unm",
182
183            #[cfg(any(feature = "lua54", feature = "lua53", feature = "luau"))]
184            MetaMethod::IDiv => "__idiv",
185            #[cfg(any(feature = "lua54", feature = "lua53"))]
186            MetaMethod::BAnd => "__band",
187            #[cfg(any(feature = "lua54", feature = "lua53"))]
188            MetaMethod::BOr => "__bor",
189            #[cfg(any(feature = "lua54", feature = "lua53"))]
190            MetaMethod::BXor => "__bxor",
191            #[cfg(any(feature = "lua54", feature = "lua53"))]
192            MetaMethod::BNot => "__bnot",
193            #[cfg(any(feature = "lua54", feature = "lua53"))]
194            MetaMethod::Shl => "__shl",
195            #[cfg(any(feature = "lua54", feature = "lua53"))]
196            MetaMethod::Shr => "__shr",
197
198            MetaMethod::Concat => "__concat",
199            MetaMethod::Len => "__len",
200            MetaMethod::Eq => "__eq",
201            MetaMethod::Lt => "__lt",
202            MetaMethod::Le => "__le",
203            MetaMethod::Index => "__index",
204            MetaMethod::NewIndex => "__newindex",
205            MetaMethod::Call => "__call",
206            MetaMethod::ToString => "__tostring",
207
208            #[cfg(any(
209                feature = "lua54",
210                feature = "lua53",
211                feature = "lua52",
212                feature = "luajit52"
213            ))]
214            MetaMethod::Pairs => "__pairs",
215            #[cfg(any(feature = "lua52", feature = "luajit52"))]
216            MetaMethod::IPairs => "__ipairs",
217            #[cfg(feature = "luau")]
218            MetaMethod::Iter => "__iter",
219
220            #[cfg(feature = "lua54")]
221            MetaMethod::Close => "__close",
222
223            #[rustfmt::skip]
224            MetaMethod::Type => if cfg!(feature = "luau") { "__type" } else { "__name" },
225        }
226    }
227
228    pub(crate) const fn as_cstr(self) -> &'static CStr {
229        match self {
230            #[rustfmt::skip]
231            MetaMethod::Type => unsafe {
232                CStr::from_bytes_with_nul_unchecked(if cfg!(feature = "luau") { b"__type\0" } else { b"__name\0" })
233            },
234            _ => unreachable!(),
235        }
236    }
237
238    pub(crate) fn validate(name: &str) -> Result<&str> {
239        match name {
240            "__gc" => Err(Error::MetaMethodRestricted(name.to_string())),
241            "__metatable" => Err(Error::MetaMethodRestricted(name.to_string())),
242            _ if name.starts_with("__mlua") => Err(Error::MetaMethodRestricted(name.to_string())),
243            name => Ok(name),
244        }
245    }
246}
247
248impl AsRef<str> for MetaMethod {
249    fn as_ref(&self) -> &str {
250        self.name()
251    }
252}
253
254/// Method registry for [`UserData`] implementors.
255///
256/// [`UserData`]: crate::UserData
257pub trait UserDataMethods<'lua, T> {
258    /// Add a regular method which accepts a `&T` as the first parameter.
259    ///
260    /// Regular methods are implemented by overriding the `__index` metamethod and returning the
261    /// accessed method. This allows them to be used with the expected `userdata:method()` syntax.
262    ///
263    /// If `add_meta_method` is used to set the `__index` metamethod, the `__index` metamethod will
264    /// be used as a fall-back if no regular method is found.
265    fn add_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
266    where
267        M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
268        A: FromLuaMulti<'lua>,
269        R: IntoLuaMulti<'lua>;
270
271    /// Add a regular method which accepts a `&mut T` as the first parameter.
272    ///
273    /// Refer to [`add_method`] for more information about the implementation.
274    ///
275    /// [`add_method`]: #method.add_method
276    fn add_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
277    where
278        M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
279        A: FromLuaMulti<'lua>,
280        R: IntoLuaMulti<'lua>;
281
282    /// Add an async method which accepts a `&T` as the first parameter and returns Future.
283    ///
284    /// Refer to [`add_method`] for more information about the implementation.
285    ///
286    /// Requires `feature = "async"`
287    ///
288    /// [`add_method`]: #method.add_method
289    #[cfg(feature = "async")]
290    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
291    fn add_async_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
292    where
293        'lua: 's,
294        T: 'static,
295        M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
296        A: FromLuaMulti<'lua>,
297        MR: Future<Output = Result<R>> + 's,
298        R: IntoLuaMulti<'lua>;
299
300    /// Add an async method which accepts a `&mut T` as the first parameter and returns Future.
301    ///
302    /// Refer to [`add_method`] for more information about the implementation.
303    ///
304    /// Requires `feature = "async"`
305    ///
306    /// [`add_method`]: #method.add_method
307    #[cfg(feature = "async")]
308    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
309    fn add_async_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
310    where
311        'lua: 's,
312        T: 'static,
313        M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
314        A: FromLuaMulti<'lua>,
315        MR: Future<Output = Result<R>> + 's,
316        R: IntoLuaMulti<'lua>;
317
318    /// Add a regular method as a function which accepts generic arguments, the first argument will
319    /// be a [`AnyUserData`] of type `T` if the method is called with Lua method syntax:
320    /// `my_userdata:my_method(arg1, arg2)`, or it is passed in as the first argument:
321    /// `my_userdata.my_method(my_userdata, arg1, arg2)`.
322    ///
323    /// Prefer to use [`add_method`] or [`add_method_mut`] as they are easier to use.
324    ///
325    /// [`AnyUserData`]: crate::AnyUserData
326    /// [`add_method`]: #method.add_method
327    /// [`add_method_mut`]: #method.add_method_mut
328    fn add_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
329    where
330        F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
331        A: FromLuaMulti<'lua>,
332        R: IntoLuaMulti<'lua>;
333
334    /// Add a regular method as a mutable function which accepts generic arguments.
335    ///
336    /// This is a version of [`add_function`] that accepts a FnMut argument.
337    ///
338    /// [`add_function`]: #method.add_function
339    fn add_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
340    where
341        F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
342        A: FromLuaMulti<'lua>,
343        R: IntoLuaMulti<'lua>;
344
345    /// Add a regular method as an async function which accepts generic arguments
346    /// and returns Future.
347    ///
348    /// This is an async version of [`add_function`].
349    ///
350    /// Requires `feature = "async"`
351    ///
352    /// [`add_function`]: #method.add_function
353    #[cfg(feature = "async")]
354    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
355    fn add_async_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
356    where
357        F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
358        A: FromLuaMulti<'lua>,
359        FR: Future<Output = Result<R>> + 'lua,
360        R: IntoLuaMulti<'lua>;
361
362    /// Add a metamethod which accepts a `&T` as the first parameter.
363    ///
364    /// # Note
365    ///
366    /// This can cause an error with certain binary metamethods that can trigger if only the right
367    /// side has a metatable. To prevent this, use [`add_meta_function`].
368    ///
369    /// [`add_meta_function`]: #method.add_meta_function
370    fn add_meta_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
371    where
372        M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
373        A: FromLuaMulti<'lua>,
374        R: IntoLuaMulti<'lua>;
375
376    /// Add a metamethod as a function which accepts a `&mut T` as the first parameter.
377    ///
378    /// # Note
379    ///
380    /// This can cause an error with certain binary metamethods that can trigger if only the right
381    /// side has a metatable. To prevent this, use [`add_meta_function`].
382    ///
383    /// [`add_meta_function`]: #method.add_meta_function
384    fn add_meta_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
385    where
386        M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
387        A: FromLuaMulti<'lua>,
388        R: IntoLuaMulti<'lua>;
389
390    /// Add an async metamethod which accepts a `&T` as the first parameter and returns Future.
391    ///
392    /// This is an async version of [`add_meta_method`].
393    ///
394    /// Requires `feature = "async"`
395    ///
396    /// [`add_meta_method`]: #method.add_meta_method
397    #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
398    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
399    fn add_async_meta_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
400    where
401        'lua: 's,
402        T: 'static,
403        M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
404        A: FromLuaMulti<'lua>,
405        MR: Future<Output = Result<R>> + 's,
406        R: IntoLuaMulti<'lua>;
407
408    /// Add an async metamethod which accepts a `&mut T` as the first parameter and returns Future.
409    ///
410    /// This is an async version of [`add_meta_method_mut`].
411    ///
412    /// Requires `feature = "async"`
413    ///
414    /// [`add_meta_method_mut`]: #method.add_meta_method_mut
415    #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
416    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
417    fn add_async_meta_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
418    where
419        'lua: 's,
420        T: 'static,
421        M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
422        A: FromLuaMulti<'lua>,
423        MR: Future<Output = Result<R>> + 's,
424        R: IntoLuaMulti<'lua>;
425
426    /// Add a metamethod which accepts generic arguments.
427    ///
428    /// Metamethods for binary operators can be triggered if either the left or right argument to
429    /// the binary operator has a metatable, so the first argument here is not necessarily a
430    /// userdata of type `T`.
431    fn add_meta_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
432    where
433        F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
434        A: FromLuaMulti<'lua>,
435        R: IntoLuaMulti<'lua>;
436
437    /// Add a metamethod as a mutable function which accepts generic arguments.
438    ///
439    /// This is a version of [`add_meta_function`] that accepts a FnMut argument.
440    ///
441    /// [`add_meta_function`]: #method.add_meta_function
442    fn add_meta_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
443    where
444        F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
445        A: FromLuaMulti<'lua>,
446        R: IntoLuaMulti<'lua>;
447
448    /// Add a metamethod which accepts generic arguments and returns Future.
449    ///
450    /// This is an async version of [`add_meta_function`].
451    ///
452    /// Requires `feature = "async"`
453    ///
454    /// [`add_meta_function`]: #method.add_meta_function
455    #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
456    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
457    fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
458    where
459        F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
460        A: FromLuaMulti<'lua>,
461        FR: Future<Output = Result<R>> + 'lua,
462        R: IntoLuaMulti<'lua>;
463
464    //
465    // Below are internal methods used in generated code
466    //
467
468    #[doc(hidden)]
469    fn append_methods_from<S>(&mut self, _other: UserDataRegistry<'lua, S>) {}
470}
471
472/// Field registry for [`UserData`] implementors.
473///
474/// [`UserData`]: crate::UserData
475pub trait UserDataFields<'lua, T> {
476    /// Add a static field to the `UserData`.
477    ///
478    /// Static fields are implemented by updating the `__index` metamethod and returning the
479    /// accessed field. This allows them to be used with the expected `userdata.field` syntax.
480    ///
481    /// Static fields are usually shared between all instances of the `UserData` of the same type.
482    ///
483    /// If `add_meta_method` is used to set the `__index` metamethod, it will
484    /// be used as a fall-back if no regular field or method are found.
485    fn add_field<V>(&mut self, name: impl AsRef<str>, value: V)
486    where
487        V: IntoLua<'lua> + Clone + 'static;
488
489    /// Add a regular field getter as a method which accepts a `&T` as the parameter.
490    ///
491    /// Regular field getters are implemented by overriding the `__index` metamethod and returning the
492    /// accessed field. This allows them to be used with the expected `userdata.field` syntax.
493    ///
494    /// If `add_meta_method` is used to set the `__index` metamethod, the `__index` metamethod will
495    /// be used as a fall-back if no regular field or method are found.
496    fn add_field_method_get<M, R>(&mut self, name: impl AsRef<str>, method: M)
497    where
498        M: Fn(&'lua Lua, &T) -> Result<R> + MaybeSend + 'static,
499        R: IntoLua<'lua>;
500
501    /// Add a regular field setter as a method which accepts a `&mut T` as the first parameter.
502    ///
503    /// Regular field setters are implemented by overriding the `__newindex` metamethod and setting the
504    /// accessed field. This allows them to be used with the expected `userdata.field = value` syntax.
505    ///
506    /// If `add_meta_method` is used to set the `__newindex` metamethod, the `__newindex` metamethod will
507    /// be used as a fall-back if no regular field is found.
508    fn add_field_method_set<M, A>(&mut self, name: impl AsRef<str>, method: M)
509    where
510        M: FnMut(&'lua Lua, &mut T, A) -> Result<()> + MaybeSend + 'static,
511        A: FromLua<'lua>;
512
513    /// Add a regular field getter as a function which accepts a generic [`AnyUserData`] of type `T`
514    /// argument.
515    ///
516    /// Prefer to use [`add_field_method_get`] as it is easier to use.
517    ///
518    /// [`AnyUserData`]: crate::AnyUserData
519    /// [`add_field_method_get`]: #method.add_field_method_get
520    fn add_field_function_get<F, R>(&mut self, name: impl AsRef<str>, function: F)
521    where
522        F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R> + MaybeSend + 'static,
523        R: IntoLua<'lua>;
524
525    /// Add a regular field setter as a function which accepts a generic [`AnyUserData`] of type `T`
526    /// first argument.
527    ///
528    /// Prefer to use [`add_field_method_set`] as it is easier to use.
529    ///
530    /// [`AnyUserData`]: crate::AnyUserData
531    /// [`add_field_method_set`]: #method.add_field_method_set
532    fn add_field_function_set<F, A>(&mut self, name: impl AsRef<str>, function: F)
533    where
534        F: FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()> + MaybeSend + 'static,
535        A: FromLua<'lua>;
536
537    /// Add a metatable field.
538    ///
539    /// This will initialize the metatable field with `value` on `UserData` creation.
540    ///
541    /// # Note
542    ///
543    /// `mlua` will trigger an error on an attempt to define a protected metamethod,
544    /// like `__gc` or `__metatable`.
545    fn add_meta_field<V>(&mut self, name: impl AsRef<str>, value: V)
546    where
547        V: IntoLua<'lua> + Clone + 'static;
548
549    /// Add a metatable field computed from `f`.
550    ///
551    /// This will initialize the metatable field from `f` on `UserData` creation.
552    ///
553    /// # Note
554    ///
555    /// `mlua` will trigger an error on an attempt to define a protected metamethod,
556    /// like `__gc` or `__metatable`.
557    fn add_meta_field_with<F, R>(&mut self, name: impl AsRef<str>, f: F)
558    where
559        F: Fn(&'lua Lua) -> Result<R> + MaybeSend + 'static,
560        R: IntoLua<'lua>;
561
562    //
563    // Below are internal methods used in generated code
564    //
565
566    #[doc(hidden)]
567    fn append_fields_from<S>(&mut self, _other: UserDataRegistry<'lua, S>) {}
568}
569
570/// Trait for custom userdata types.
571///
572/// By implementing this trait, a struct becomes eligible for use inside Lua code.
573/// Implementation of [`IntoLua`] is automatically provided, [`FromLua`] needs to be implemented
574/// manually.
575///
576///
577/// # Examples
578///
579/// ```
580/// # use mlua::{Lua, Result, UserData};
581/// # fn main() -> Result<()> {
582/// # let lua = Lua::new();
583/// struct MyUserData;
584///
585/// impl UserData for MyUserData {}
586///
587/// // `MyUserData` now implements `IntoLua`:
588/// lua.globals().set("myobject", MyUserData)?;
589///
590/// lua.load("assert(type(myobject) == 'userdata')").exec()?;
591/// # Ok(())
592/// # }
593/// ```
594///
595/// Custom fields, methods and operators can be provided by implementing `add_fields` or `add_methods`
596/// (refer to [`UserDataFields`] and [`UserDataMethods`] for more information):
597///
598/// ```
599/// # use mlua::{Lua, MetaMethod, Result, UserData, UserDataFields, UserDataMethods};
600/// # fn main() -> Result<()> {
601/// # let lua = Lua::new();
602/// struct MyUserData(i32);
603///
604/// impl UserData for MyUserData {
605///     fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
606///         fields.add_field_method_get("val", |_, this| Ok(this.0));
607///     }
608///
609///     fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
610///         methods.add_method_mut("add", |_, this, value: i32| {
611///             this.0 += value;
612///             Ok(())
613///         });
614///
615///         methods.add_meta_method(MetaMethod::Add, |_, this, value: i32| {
616///             Ok(this.0 + value)
617///         });
618///     }
619/// }
620///
621/// lua.globals().set("myobject", MyUserData(123))?;
622///
623/// lua.load(r#"
624///     assert(myobject.val == 123)
625///     myobject:add(7)
626///     assert(myobject.val == 130)
627///     assert(myobject + 10 == 140)
628/// "#).exec()?;
629/// # Ok(())
630/// # }
631/// ```
632///
633/// [`IntoLua`]: crate::IntoLua
634/// [`FromLua`]: crate::FromLua
635/// [`UserDataFields`]: crate::UserDataFields
636/// [`UserDataMethods`]: crate::UserDataMethods
637pub trait UserData: Sized {
638    /// Adds custom fields specific to this userdata.
639    #[allow(unused_variables)]
640    fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {}
641
642    /// Adds custom methods and operators specific to this userdata.
643    #[allow(unused_variables)]
644    fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {}
645}
646
647// Wraps UserData in a way to always implement `serde::Serialize` trait.
648pub(crate) struct UserDataCell<T>(RefCell<UserDataVariant<T>>);
649
650impl<T> UserDataCell<T> {
651    #[inline]
652    pub(crate) fn new(data: T) -> Self {
653        UserDataCell(RefCell::new(UserDataVariant::new(data)))
654    }
655
656    #[inline]
657    pub(crate) fn new_ref(data: &T) -> Self {
658        UserDataCell(RefCell::new(UserDataVariant::new_ref(data)))
659    }
660
661    #[inline]
662    pub(crate) fn new_ref_mut(data: &mut T) -> Self {
663        UserDataCell(RefCell::new(UserDataVariant::new_ref_mut(data)))
664    }
665
666    #[cfg(feature = "serialize")]
667    #[inline]
668    pub(crate) fn new_ser(data: T) -> Self
669    where
670        T: Serialize + 'static,
671    {
672        UserDataCell(RefCell::new(UserDataVariant::new_ser(data)))
673    }
674
675    // Immutably borrows the wrapped value.
676    #[inline]
677    pub(crate) fn try_borrow(&self) -> Result<Ref<T>> {
678        self.0
679            .try_borrow()
680            .map(|r| Ref::map(r, |r| r.deref()))
681            .map_err(|_| Error::UserDataBorrowError)
682    }
683
684    // Mutably borrows the wrapped value.
685    #[inline]
686    pub(crate) fn try_borrow_mut(&self) -> Result<RefMut<T>> {
687        self.0
688            .try_borrow_mut()
689            .map_err(|_| Error::UserDataBorrowMutError)
690            .and_then(|r| {
691                RefMut::filter_map(r, |r| r.try_deref_mut().ok())
692                    .map_err(|_| Error::UserDataBorrowMutError)
693            })
694    }
695
696    // Consumes this `UserDataCell`, returning the wrapped value.
697    #[inline]
698    fn into_inner(self) -> Result<T> {
699        self.0.into_inner().into_inner()
700    }
701}
702
703pub(crate) enum UserDataVariant<T> {
704    Default(Box<T>),
705    Ref(*const T),
706    RefMut(*mut T),
707    #[cfg(feature = "serialize")]
708    Serializable(Box<dyn erased_serde::Serialize>),
709}
710
711impl<T> UserDataVariant<T> {
712    #[inline]
713    fn new(data: T) -> Self {
714        UserDataVariant::Default(Box::new(data))
715    }
716
717    #[inline]
718    fn new_ref(data: &T) -> Self {
719        UserDataVariant::Ref(data)
720    }
721
722    #[inline]
723    fn new_ref_mut(data: &mut T) -> Self {
724        UserDataVariant::RefMut(data)
725    }
726
727    #[cfg(feature = "serialize")]
728    #[inline]
729    fn new_ser(data: T) -> Self
730    where
731        T: Serialize + 'static,
732    {
733        UserDataVariant::Serializable(Box::new(data))
734    }
735
736    #[inline]
737    fn try_deref_mut(&mut self) -> Result<&mut T> {
738        match self {
739            Self::Default(data) => Ok(data.deref_mut()),
740            Self::Ref(_) => Err(Error::UserDataBorrowMutError),
741            Self::RefMut(data) => unsafe { Ok(&mut **data) },
742            #[cfg(feature = "serialize")]
743            Self::Serializable(data) => unsafe { Ok(&mut *(data.as_mut() as *mut _ as *mut T)) },
744        }
745    }
746
747    #[inline]
748    fn into_inner(self) -> Result<T> {
749        match self {
750            Self::Default(data) => Ok(*data),
751            Self::Ref(_) | Self::RefMut(_) => Err(Error::UserDataTypeMismatch),
752            #[cfg(feature = "serialize")]
753            Self::Serializable(data) => unsafe {
754                Ok(*Box::from_raw(Box::into_raw(data) as *mut T))
755            },
756        }
757    }
758}
759
760impl<T> Deref for UserDataVariant<T> {
761    type Target = T;
762
763    #[inline]
764    fn deref(&self) -> &Self::Target {
765        match self {
766            Self::Default(data) => data,
767            Self::Ref(data) => unsafe { &**data },
768            Self::RefMut(data) => unsafe { &**data },
769            #[cfg(feature = "serialize")]
770            Self::Serializable(data) => unsafe {
771                &*(data.as_ref() as *const _ as *const Self::Target)
772            },
773        }
774    }
775}
776
777/// Handle to an internal Lua userdata for any type that implements [`UserData`].
778///
779/// Similar to `std::any::Any`, this provides an interface for dynamic type checking via the [`is`]
780/// and [`borrow`] methods.
781///
782/// Internally, instances are stored in a `RefCell`, to best match the mutable semantics of the Lua
783/// language.
784///
785/// # Note
786///
787/// This API should only be used when necessary. Implementing [`UserData`] already allows defining
788/// methods which check the type and acquire a borrow behind the scenes.
789///
790/// [`UserData`]: crate::UserData
791/// [`is`]: crate::AnyUserData::is
792/// [`borrow`]: crate::AnyUserData::borrow
793#[derive(Clone, Debug)]
794pub struct AnyUserData<'lua>(pub(crate) LuaRef<'lua>, pub(crate) SubtypeId);
795
796/// Owned handle to an internal Lua userdata.
797///
798/// The owned handle holds a *strong* reference to the current Lua instance.
799/// Be warned, if you place it into a Lua type (eg. [`UserData`] or a Rust callback), it is *very easy*
800/// to accidentally cause reference cycles that would prevent destroying Lua instance.
801#[cfg(feature = "unstable")]
802#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
803#[derive(Clone, Debug)]
804pub struct OwnedAnyUserData(pub(crate) crate::types::LuaOwnedRef, pub(crate) SubtypeId);
805
806#[cfg(feature = "unstable")]
807impl OwnedAnyUserData {
808    /// Get borrowed handle to the underlying Lua userdata.
809    #[cfg_attr(feature = "send", allow(unused))]
810    pub const fn to_ref(&self) -> AnyUserData {
811        AnyUserData(self.0.to_ref(), self.1)
812    }
813}
814
815impl<'lua> AnyUserData<'lua> {
816    /// Checks whether the type of this userdata is `T`.
817    pub fn is<T: 'static>(&self) -> bool {
818        self.inspect(|_: &UserDataCell<T>| Ok(())).is_ok()
819    }
820
821    /// Borrow this userdata immutably if it is of type `T`.
822    ///
823    /// # Errors
824    ///
825    /// Returns a `UserDataBorrowError` if the userdata is already mutably borrowed. Returns a
826    /// `UserDataTypeMismatch` if the userdata is not of type `T`.
827    #[inline]
828    pub fn borrow<T: 'static>(&self) -> Result<Ref<T>> {
829        self.inspect(|cell| cell.try_borrow())
830    }
831
832    /// Borrow this userdata mutably if it is of type `T`.
833    ///
834    /// # Errors
835    ///
836    /// Returns a `UserDataBorrowMutError` if the userdata cannot be mutably borrowed.
837    /// Returns a `UserDataTypeMismatch` if the userdata is not of type `T`.
838    #[inline]
839    pub fn borrow_mut<T: 'static>(&self) -> Result<RefMut<T>> {
840        self.inspect(|cell| cell.try_borrow_mut())
841    }
842
843    /// Takes the value out of this userdata.
844    /// Sets the special "destructed" metatable that prevents any further operations with this userdata.
845    ///
846    /// Keeps associated user values unchanged (they will be collected by Lua's GC).
847    pub fn take<T: 'static>(&self) -> Result<T> {
848        let lua = self.0.lua;
849        let state = lua.state();
850        unsafe {
851            let _sg = StackGuard::new(state);
852            check_stack(state, 2)?;
853
854            let type_id = lua.push_userdata_ref(&self.0)?;
855            match type_id {
856                Some(type_id) if type_id == TypeId::of::<T>() => {
857                    // Try to borrow userdata exclusively
858                    let _ = (*get_userdata::<UserDataCell<T>>(state, -1)).try_borrow_mut()?;
859                    take_userdata::<UserDataCell<T>>(state).into_inner()
860                }
861                _ => Err(Error::UserDataTypeMismatch),
862            }
863        }
864    }
865
866    /// Sets an associated value to this `AnyUserData`.
867    ///
868    /// The value may be any Lua value whatsoever, and can be retrieved with [`user_value`].
869    ///
870    /// This is the same as calling [`set_nth_user_value`] with `n` set to 1.
871    ///
872    /// [`user_value`]: #method.user_value
873    /// [`set_nth_user_value`]: #method.set_nth_user_value
874    #[inline]
875    pub fn set_user_value<V: IntoLua<'lua>>(&self, v: V) -> Result<()> {
876        self.set_nth_user_value(1, v)
877    }
878
879    /// Returns an associated value set by [`set_user_value`].
880    ///
881    /// This is the same as calling [`nth_user_value`] with `n` set to 1.
882    ///
883    /// [`set_user_value`]: #method.set_user_value
884    /// [`nth_user_value`]: #method.nth_user_value
885    #[inline]
886    pub fn user_value<V: FromLua<'lua>>(&self) -> Result<V> {
887        self.nth_user_value(1)
888    }
889
890    #[doc(hidden)]
891    #[deprecated(since = "0.9.0", note = "please use `user_value` instead")]
892    pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
893        self.nth_user_value(1)
894    }
895
896    /// Sets an associated `n`th value to this `AnyUserData`.
897    ///
898    /// The value may be any Lua value whatsoever, and can be retrieved with [`nth_user_value`].
899    /// `n` starts from 1 and can be up to 65535.
900    ///
901    /// This is supported for all Lua versions.
902    /// In Lua 5.4 first 7 elements are stored in a most efficient way.
903    /// For other Lua versions this functionality is provided using a wrapping table.
904    ///
905    /// [`nth_user_value`]: #method.nth_user_value
906    pub fn set_nth_user_value<V: IntoLua<'lua>>(&self, n: usize, v: V) -> Result<()> {
907        if n < 1 || n > u16::MAX as usize {
908            return Err(Error::runtime("user value index out of bounds"));
909        }
910
911        let lua = self.0.lua;
912        let state = lua.state();
913        unsafe {
914            let _sg = StackGuard::new(state);
915            check_stack(state, 5)?;
916
917            lua.push_userdata_ref(&self.0)?;
918            lua.push(v)?;
919
920            #[cfg(feature = "lua54")]
921            if n < USER_VALUE_MAXSLOT {
922                ffi::lua_setiuservalue(state, -2, n as c_int);
923                return Ok(());
924            }
925
926            // Multiple (extra) user values are emulated by storing them in a table
927            protect_lua!(state, 2, 0, |state| {
928                if getuservalue_table(state, -2) != ffi::LUA_TTABLE {
929                    // Create a new table to use as uservalue
930                    ffi::lua_pop(state, 1);
931                    ffi::lua_newtable(state);
932                    ffi::lua_pushvalue(state, -1);
933
934                    #[cfg(feature = "lua54")]
935                    ffi::lua_setiuservalue(state, -4, USER_VALUE_MAXSLOT as c_int);
936                    #[cfg(not(feature = "lua54"))]
937                    ffi::lua_setuservalue(state, -4);
938                }
939                ffi::lua_pushvalue(state, -2);
940                #[cfg(feature = "lua54")]
941                ffi::lua_rawseti(state, -2, (n - USER_VALUE_MAXSLOT + 1) as ffi::lua_Integer);
942                #[cfg(not(feature = "lua54"))]
943                ffi::lua_rawseti(state, -2, n as ffi::lua_Integer);
944            })?;
945
946            Ok(())
947        }
948    }
949
950    /// Returns an associated `n`th value set by [`set_nth_user_value`].
951    ///
952    /// `n` starts from 1 and can be up to 65535.
953    ///
954    /// This is supported for all Lua versions.
955    /// In Lua 5.4 first 7 elements are stored in a most efficient way.
956    /// For other Lua versions this functionality is provided using a wrapping table.
957    ///
958    /// [`set_nth_user_value`]: #method.set_nth_user_value
959    pub fn nth_user_value<V: FromLua<'lua>>(&self, n: usize) -> Result<V> {
960        if n < 1 || n > u16::MAX as usize {
961            return Err(Error::runtime("user value index out of bounds"));
962        }
963
964        let lua = self.0.lua;
965        let state = lua.state();
966        unsafe {
967            let _sg = StackGuard::new(state);
968            check_stack(state, 4)?;
969
970            lua.push_userdata_ref(&self.0)?;
971
972            #[cfg(feature = "lua54")]
973            if n < USER_VALUE_MAXSLOT {
974                ffi::lua_getiuservalue(state, -1, n as c_int);
975                return V::from_lua(lua.pop_value(), lua);
976            }
977
978            // Multiple (extra) user values are emulated by storing them in a table
979            protect_lua!(state, 1, 1, |state| {
980                if getuservalue_table(state, -1) != ffi::LUA_TTABLE {
981                    ffi::lua_pushnil(state);
982                    return;
983                }
984                #[cfg(feature = "lua54")]
985                ffi::lua_rawgeti(state, -1, (n - USER_VALUE_MAXSLOT + 1) as ffi::lua_Integer);
986                #[cfg(not(feature = "lua54"))]
987                ffi::lua_rawgeti(state, -1, n as ffi::lua_Integer);
988            })?;
989
990            V::from_lua(lua.pop_value(), lua)
991        }
992    }
993
994    #[doc(hidden)]
995    #[deprecated(since = "0.9.0", note = "please use `nth_user_value` instead")]
996    pub fn get_nth_user_value<V: FromLua<'lua>>(&self, n: usize) -> Result<V> {
997        self.nth_user_value(n)
998    }
999
1000    /// Sets an associated value to this `AnyUserData` by name.
1001    ///
1002    /// The value can be retrieved with [`named_user_value`].
1003    ///
1004    /// [`named_user_value`]: #method.named_user_value
1005    pub fn set_named_user_value<V: IntoLua<'lua>>(&self, name: &str, v: V) -> Result<()> {
1006        let lua = self.0.lua;
1007        let state = lua.state();
1008        unsafe {
1009            let _sg = StackGuard::new(state);
1010            check_stack(state, 5)?;
1011
1012            lua.push_userdata_ref(&self.0)?;
1013            lua.push(v)?;
1014
1015            // Multiple (extra) user values are emulated by storing them in a table
1016            protect_lua!(state, 2, 0, |state| {
1017                if getuservalue_table(state, -2) != ffi::LUA_TTABLE {
1018                    // Create a new table to use as uservalue
1019                    ffi::lua_pop(state, 1);
1020                    ffi::lua_newtable(state);
1021                    ffi::lua_pushvalue(state, -1);
1022
1023                    #[cfg(feature = "lua54")]
1024                    ffi::lua_setiuservalue(state, -4, USER_VALUE_MAXSLOT as c_int);
1025                    #[cfg(not(feature = "lua54"))]
1026                    ffi::lua_setuservalue(state, -4);
1027                }
1028                ffi::lua_pushlstring(state, name.as_ptr() as *const c_char, name.len());
1029                ffi::lua_pushvalue(state, -3);
1030                ffi::lua_rawset(state, -3);
1031            })?;
1032
1033            Ok(())
1034        }
1035    }
1036
1037    /// Returns an associated value by name set by [`set_named_user_value`].
1038    ///
1039    /// [`set_named_user_value`]: #method.set_named_user_value
1040    pub fn named_user_value<V: FromLua<'lua>>(&self, name: &str) -> Result<V> {
1041        let lua = self.0.lua;
1042        let state = lua.state();
1043        unsafe {
1044            let _sg = StackGuard::new(state);
1045            check_stack(state, 4)?;
1046
1047            lua.push_userdata_ref(&self.0)?;
1048
1049            // Multiple (extra) user values are emulated by storing them in a table
1050            protect_lua!(state, 1, 1, |state| {
1051                if getuservalue_table(state, -1) != ffi::LUA_TTABLE {
1052                    ffi::lua_pushnil(state);
1053                    return;
1054                }
1055                ffi::lua_pushlstring(state, name.as_ptr() as *const c_char, name.len());
1056                ffi::lua_rawget(state, -2);
1057            })?;
1058
1059            V::from_lua(lua.pop_value(), lua)
1060        }
1061    }
1062
1063    #[doc(hidden)]
1064    #[deprecated(since = "0.9.0", note = "please use `named_user_value` instead")]
1065    pub fn get_named_user_value<V: FromLua<'lua>>(&self, name: &str) -> Result<V> {
1066        self.named_user_value(name)
1067    }
1068
1069    /// Returns a metatable of this `UserData`.
1070    ///
1071    /// Returned [`UserDataMetatable`] object wraps the original metatable and
1072    /// provides safe access to its methods.
1073    ///
1074    /// For `T: 'static` returned metatable is shared among all instances of type `T`.
1075    ///
1076    /// [`UserDataMetatable`]: crate::UserDataMetatable
1077    #[inline]
1078    pub fn get_metatable(&self) -> Result<UserDataMetatable<'lua>> {
1079        self.get_raw_metatable().map(UserDataMetatable)
1080    }
1081
1082    fn get_raw_metatable(&self) -> Result<Table<'lua>> {
1083        let lua = self.0.lua;
1084        let state = lua.state();
1085        unsafe {
1086            let _sg = StackGuard::new(state);
1087            check_stack(state, 3)?;
1088
1089            lua.push_userdata_ref(&self.0)?;
1090            ffi::lua_getmetatable(state, -1); // Checked that non-empty on the previous call
1091            Ok(Table(lua.pop_ref()))
1092        }
1093    }
1094
1095    /// Converts this userdata to a generic C pointer.
1096    ///
1097    /// There is no way to convert the pointer back to its original value.
1098    ///
1099    /// Typically this function is used only for hashing and debug information.
1100    #[inline]
1101    pub fn to_pointer(&self) -> *const c_void {
1102        self.0.to_pointer()
1103    }
1104
1105    /// Convert this handle to owned version.
1106    #[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
1107    #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
1108    #[inline]
1109    pub fn into_owned(self) -> OwnedAnyUserData {
1110        OwnedAnyUserData(self.0.into_owned(), self.1)
1111    }
1112
1113    #[cfg(feature = "async")]
1114    #[inline]
1115    pub(crate) fn type_id(&self) -> Result<Option<TypeId>> {
1116        unsafe { self.0.lua.get_userdata_ref_type_id(&self.0) }
1117    }
1118
1119    /// Returns a type name of this `UserData` (from a metatable field).
1120    pub(crate) fn type_name(&self) -> Result<Option<StdString>> {
1121        match self.1 {
1122            SubtypeId::None => {}
1123            #[cfg(feature = "luau")]
1124            SubtypeId::Buffer => return Ok(Some("buffer".to_owned())),
1125            #[cfg(feature = "luajit")]
1126            SubtypeId::CData => return Ok(Some("cdata".to_owned())),
1127        }
1128
1129        let lua = self.0.lua;
1130        let state = lua.state();
1131        unsafe {
1132            let _sg = StackGuard::new(state);
1133            check_stack(state, 3)?;
1134
1135            lua.push_userdata_ref(&self.0)?;
1136            let protect = !lua.unlikely_memory_error();
1137            let name_type = if protect {
1138                protect_lua!(state, 1, 1, |state| {
1139                    ffi::luaL_getmetafield(state, -1, MetaMethod::Type.as_cstr().as_ptr())
1140                })?
1141            } else {
1142                ffi::luaL_getmetafield(state, -1, MetaMethod::Type.as_cstr().as_ptr())
1143            };
1144            match name_type {
1145                ffi::LUA_TSTRING => Ok(Some(String(lua.pop_ref()).to_str()?.to_owned())),
1146                _ => Ok(None),
1147            }
1148        }
1149    }
1150
1151    pub(crate) fn equals<T: AsRef<Self>>(&self, other: T) -> Result<bool> {
1152        let other = other.as_ref();
1153        // Uses lua_rawequal() under the hood
1154        if self == other {
1155            return Ok(true);
1156        }
1157
1158        let mt = self.get_raw_metatable()?;
1159        if mt != other.get_raw_metatable()? {
1160            return Ok(false);
1161        }
1162
1163        if mt.contains_key("__eq")? {
1164            return mt
1165                .get::<_, Function>("__eq")?
1166                .call((self.clone(), other.clone()));
1167        }
1168
1169        Ok(false)
1170    }
1171
1172    /// Returns `true` if this `AnyUserData` is serializable (eg. was created using `create_ser_userdata`).
1173    #[cfg(feature = "serialize")]
1174    pub(crate) fn is_serializable(&self) -> bool {
1175        let lua = self.0.lua;
1176        let is_serializable = || unsafe {
1177            // Userdata can be unregistered or destructed
1178            let _ = lua.get_userdata_ref_type_id(&self.0)?;
1179
1180            let ud = &*get_userdata::<UserDataCell<()>>(lua.ref_thread(), self.0.index);
1181            match &*ud.0.try_borrow().map_err(|_| Error::UserDataBorrowError)? {
1182                UserDataVariant::Serializable(_) => Result::Ok(true),
1183                _ => Result::Ok(false),
1184            }
1185        };
1186        is_serializable().unwrap_or(false)
1187    }
1188
1189    fn inspect<'a, T, F, R>(&'a self, func: F) -> Result<R>
1190    where
1191        T: 'static,
1192        F: FnOnce(&'a UserDataCell<T>) -> Result<R>,
1193    {
1194        let lua = self.0.lua;
1195        unsafe {
1196            let type_id = lua.get_userdata_ref_type_id(&self.0)?;
1197            match type_id {
1198                Some(type_id) if type_id == TypeId::of::<T>() => {
1199                    let ref_thread = lua.ref_thread();
1200                    func(&*get_userdata::<UserDataCell<T>>(ref_thread, self.0.index))
1201                }
1202                _ => Err(Error::UserDataTypeMismatch),
1203            }
1204        }
1205    }
1206}
1207
1208impl<'lua> PartialEq for AnyUserData<'lua> {
1209    fn eq(&self, other: &Self) -> bool {
1210        self.0 == other.0
1211    }
1212}
1213
1214impl<'lua> AsRef<AnyUserData<'lua>> for AnyUserData<'lua> {
1215    #[inline]
1216    fn as_ref(&self) -> &Self {
1217        self
1218    }
1219}
1220
1221unsafe fn getuservalue_table(state: *mut ffi::lua_State, idx: c_int) -> c_int {
1222    #[cfg(feature = "lua54")]
1223    return ffi::lua_getiuservalue(state, idx, USER_VALUE_MAXSLOT as c_int);
1224    #[cfg(not(feature = "lua54"))]
1225    return ffi::lua_getuservalue(state, idx);
1226}
1227
1228// Additional shortcuts
1229#[cfg(feature = "unstable")]
1230impl OwnedAnyUserData {
1231    /// Borrow this userdata immutably if it is of type `T`.
1232    ///
1233    /// This is a shortcut for [`AnyUserData::borrow()`]
1234    #[inline]
1235    pub fn borrow<T: 'static>(&self) -> Result<Ref<T>> {
1236        let ud = self.to_ref();
1237        let t = ud.borrow::<T>()?;
1238        // Reattach lifetime to &self
1239        Ok(unsafe { mem::transmute::<Ref<T>, Ref<T>>(t) })
1240    }
1241
1242    /// Borrow this userdata mutably if it is of type `T`.
1243    ///
1244    /// This is a shortcut for [`AnyUserData::borrow_mut()`]
1245    #[inline]
1246    pub fn borrow_mut<T: 'static>(&self) -> Result<RefMut<T>> {
1247        let ud = self.to_ref();
1248        let t = ud.borrow_mut::<T>()?;
1249        // Reattach lifetime to &self
1250        Ok(unsafe { mem::transmute::<RefMut<T>, RefMut<T>>(t) })
1251    }
1252
1253    /// Takes the value out of this userdata.
1254    ///
1255    /// This is a shortcut for [`AnyUserData::take()`]
1256    #[inline]
1257    pub fn take<T: 'static>(&self) -> Result<T> {
1258        self.to_ref().take()
1259    }
1260}
1261
1262/// Handle to a `UserData` metatable.
1263#[derive(Clone, Debug)]
1264pub struct UserDataMetatable<'lua>(pub(crate) Table<'lua>);
1265
1266impl<'lua> UserDataMetatable<'lua> {
1267    /// Gets the value associated to `key` from the metatable.
1268    ///
1269    /// If no value is associated to `key`, returns the `Nil` value.
1270    /// Access to restricted metamethods such as `__gc` or `__metatable` will cause an error.
1271    pub fn get<V: FromLua<'lua>>(&self, key: impl AsRef<str>) -> Result<V> {
1272        self.0.raw_get(MetaMethod::validate(key.as_ref())?)
1273    }
1274
1275    /// Sets a key-value pair in the metatable.
1276    ///
1277    /// If the value is `Nil`, this will effectively remove the `key`.
1278    /// Access to restricted metamethods such as `__gc` or `__metatable` will cause an error.
1279    /// Setting `__index` or `__newindex` metamethods is also restricted because their values are cached
1280    /// for `mlua` internal usage.
1281    pub fn set<V: IntoLua<'lua>>(&self, key: impl AsRef<str>, value: V) -> Result<()> {
1282        let key = MetaMethod::validate(key.as_ref())?;
1283        // `__index` and `__newindex` cannot be changed in runtime, because values are cached
1284        if key == MetaMethod::Index || key == MetaMethod::NewIndex {
1285            return Err(Error::MetaMethodRestricted(key.to_string()));
1286        }
1287        self.0.raw_set(key, value)
1288    }
1289
1290    /// Checks whether the metatable contains a non-nil value for `key`.
1291    pub fn contains(&self, key: impl AsRef<str>) -> Result<bool> {
1292        self.0.contains_key(MetaMethod::validate(key.as_ref())?)
1293    }
1294
1295    /// Consumes this metatable and returns an iterator over the pairs of the metatable.
1296    ///
1297    /// The pairs are wrapped in a [`Result`], since they are lazily converted to `V` type.
1298    ///
1299    /// [`Result`]: crate::Result
1300    pub fn pairs<V: FromLua<'lua>>(self) -> UserDataMetatablePairs<'lua, V> {
1301        UserDataMetatablePairs(self.0.pairs())
1302    }
1303}
1304
1305/// An iterator over the pairs of a [`UserData`] metatable.
1306///
1307/// It skips restricted metamethods, such as `__gc` or `__metatable`.
1308///
1309/// This struct is created by the [`UserDataMetatable::pairs`] method.
1310///
1311/// [`UserData`]: crate::UserData
1312/// [`UserDataMetatable::pairs`]: crate::UserDataMetatable::method.pairs
1313pub struct UserDataMetatablePairs<'lua, V>(TablePairs<'lua, StdString, V>);
1314
1315impl<'lua, V> Iterator for UserDataMetatablePairs<'lua, V>
1316where
1317    V: FromLua<'lua>,
1318{
1319    type Item = Result<(StdString, V)>;
1320
1321    fn next(&mut self) -> Option<Self::Item> {
1322        loop {
1323            match self.0.next()? {
1324                Ok((key, value)) => {
1325                    // Skip restricted metamethods
1326                    if MetaMethod::validate(&key).is_ok() {
1327                        break Some(Ok((key, value)));
1328                    }
1329                }
1330                Err(e) => break Some(Err(e)),
1331            }
1332        }
1333    }
1334}
1335
1336#[cfg(feature = "serialize")]
1337impl<'lua> Serialize for AnyUserData<'lua> {
1338    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
1339    where
1340        S: Serializer,
1341    {
1342        let lua = self.0.lua;
1343
1344        // Special case for Luau buffer type
1345        #[cfg(feature = "luau")]
1346        if self.1 == SubtypeId::Buffer {
1347            let buf = unsafe {
1348                let mut size = 0usize;
1349                let buf = ffi::lua_tobuffer(lua.ref_thread(), self.0.index, &mut size);
1350                mlua_assert!(!buf.is_null(), "invalid Luau buffer");
1351                std::slice::from_raw_parts(buf as *const u8, size)
1352            };
1353            return serializer.serialize_bytes(buf);
1354        }
1355
1356        let data = unsafe {
1357            let _ = lua
1358                .get_userdata_ref_type_id(&self.0)
1359                .map_err(ser::Error::custom)?;
1360            let ud = &*get_userdata::<UserDataCell<()>>(lua.ref_thread(), self.0.index);
1361            ud.0.try_borrow()
1362                .map_err(|_| ser::Error::custom(Error::UserDataBorrowError))?
1363        };
1364        match &*data {
1365            UserDataVariant::Serializable(ser) => ser.serialize(serializer),
1366            _ => Err(ser::Error::custom("cannot serialize <userdata>")),
1367        }
1368    }
1369}
1370
1371/// A wrapper type for an immutably borrowed value from a `AnyUserData`.
1372///
1373/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
1374pub struct UserDataRef<'lua, T: 'static>(#[allow(unused)] AnyUserData<'lua>, Ref<'lua, T>);
1375
1376impl<'lua, T: 'static> Deref for UserDataRef<'lua, T> {
1377    type Target = T;
1378
1379    fn deref(&self) -> &Self::Target {
1380        &self.1
1381    }
1382}
1383
1384impl<'lua, T: 'static> UserDataRef<'lua, T> {
1385    pub(crate) fn from_value(value: Value<'lua>) -> Result<Self> {
1386        let ud = try_value_to_userdata::<T>(value)?;
1387        // It's safe to lift lifetime of `Ref<T>` to `'lua` as long as we hold AnyUserData to it.
1388        let this = unsafe { mem::transmute(ud.borrow::<T>()?) };
1389        Ok(UserDataRef(ud, this))
1390    }
1391}
1392
1393/// A wrapper type for a mutably borrowed value from a `AnyUserData`.
1394///
1395/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
1396pub struct UserDataRefMut<'lua, T: 'static>(#[allow(unused)] AnyUserData<'lua>, RefMut<'lua, T>);
1397
1398impl<'lua, T: 'static> Deref for UserDataRefMut<'lua, T> {
1399    type Target = T;
1400
1401    fn deref(&self) -> &Self::Target {
1402        &self.1
1403    }
1404}
1405
1406impl<'lua, T: 'static> DerefMut for UserDataRefMut<'lua, T> {
1407    fn deref_mut(&mut self) -> &mut Self::Target {
1408        &mut self.1
1409    }
1410}
1411
1412impl<'lua, T: 'static> UserDataRefMut<'lua, T> {
1413    pub(crate) fn from_value(value: Value<'lua>) -> Result<Self> {
1414        let ud = try_value_to_userdata::<T>(value)?;
1415        // It's safe to lift lifetime of `RefMut<T>` to `'lua` as long as we hold AnyUserData to it.
1416        let this = unsafe { mem::transmute(ud.borrow_mut::<T>()?) };
1417        Ok(UserDataRefMut(ud, this))
1418    }
1419}
1420
1421pub(crate) struct WrappedUserdata<F: for<'lua> FnOnce(&'lua Lua) -> Result<AnyUserData<'lua>>>(F);
1422
1423impl<'lua> AnyUserData<'lua> {
1424    /// Wraps any Rust type, returning an opaque type that implements [`IntoLua`] trait.
1425    ///
1426    /// This function uses [`Lua::create_any_userdata()`] under the hood.
1427    pub fn wrap<T: MaybeSend + 'static>(data: T) -> impl IntoLua<'lua> {
1428        WrappedUserdata(move |lua| lua.create_any_userdata(data))
1429    }
1430}
1431
1432impl<'lua, F> IntoLua<'lua> for WrappedUserdata<F>
1433where
1434    F: for<'l> FnOnce(&'l Lua) -> Result<AnyUserData<'l>>,
1435{
1436    fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
1437        (self.0)(lua).map(Value::UserData)
1438    }
1439}
1440
1441#[inline]
1442fn try_value_to_userdata<T>(value: Value) -> Result<AnyUserData> {
1443    match value {
1444        Value::UserData(ud) => Ok(ud),
1445        _ => Err(Error::FromLuaConversionError {
1446            from: value.type_name(),
1447            to: "userdata",
1448            message: Some(format!("expected userdata of type {}", type_name::<T>())),
1449        }),
1450    }
1451}
1452
1453#[cfg(test)]
1454mod assertions {
1455    use super::*;
1456
1457    static_assertions::assert_not_impl_any!(AnyUserData: Send);
1458
1459    #[cfg(all(feature = "unstable", not(feature = "send")))]
1460    static_assertions::assert_not_impl_any!(OwnedAnyUserData: Send);
1461}