mlua/
value.rs

1use std::borrow::Cow;
2use std::cmp::Ordering;
3use std::collections::HashSet;
4use std::iter;
5use std::ops::Index;
6use std::os::raw::{c_int, c_void};
7use std::string::String as StdString;
8use std::sync::Arc;
9use std::{fmt, mem, ptr, slice, str, vec};
10
11use num_traits::FromPrimitive;
12
13#[cfg(feature = "serialize")]
14use {
15    crate::table::SerializableTable,
16    rustc_hash::FxHashSet,
17    serde::ser::{self, Serialize, Serializer},
18    std::{cell::RefCell, rc::Rc, result::Result as StdResult},
19};
20
21use crate::error::{Error, Result};
22use crate::function::Function;
23use crate::lua::Lua;
24use crate::string::String;
25use crate::table::Table;
26use crate::thread::Thread;
27use crate::types::{Integer, LightUserData, Number, SubtypeId};
28use crate::userdata::AnyUserData;
29use crate::util::{check_stack, StackGuard};
30
31/// A dynamically typed Lua value. The `String`, `Table`, `Function`, `Thread`, and `UserData`
32/// variants contain handle types into the internal Lua state. It is a logic error to mix handle
33/// types between separate `Lua` instances, and doing so will result in a panic.
34#[derive(Clone)]
35pub enum Value<'lua> {
36    /// The Lua value `nil`.
37    Nil,
38    /// The Lua value `true` or `false`.
39    Boolean(bool),
40    /// A "light userdata" object, equivalent to a raw pointer.
41    LightUserData(LightUserData),
42    /// An integer number.
43    ///
44    /// Any Lua number convertible to a `Integer` will be represented as this variant.
45    Integer(Integer),
46    /// A floating point number.
47    Number(Number),
48    /// A Luau vector.
49    #[cfg(any(feature = "luau", doc))]
50    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
51    Vector(crate::types::Vector),
52    /// An interned string, managed by Lua.
53    ///
54    /// Unlike Rust strings, Lua strings may not be valid UTF-8.
55    String(String<'lua>),
56    /// Reference to a Lua table.
57    Table(Table<'lua>),
58    /// Reference to a Lua function (or closure).
59    Function(Function<'lua>),
60    /// Reference to a Lua thread (or coroutine).
61    Thread(Thread<'lua>),
62    /// Reference to a userdata object that holds a custom type which implements `UserData`.
63    /// Special builtin userdata types will be represented as other `Value` variants.
64    UserData(AnyUserData<'lua>),
65    /// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned.
66    Error(Error),
67}
68
69pub use self::Value::Nil;
70
71impl<'lua> Value<'lua> {
72    /// A special value (lightuserdata) to represent null value.
73    ///
74    /// It can be used in Lua tables without downsides of `nil`.
75    pub const NULL: Value<'static> = Value::LightUserData(LightUserData(ptr::null_mut()));
76
77    /// Returns type name of this value.
78    pub const fn type_name(&self) -> &'static str {
79        match *self {
80            Value::Nil => "nil",
81            Value::Boolean(_) => "boolean",
82            Value::LightUserData(_) => "lightuserdata",
83            Value::Integer(_) => "integer",
84            Value::Number(_) => "number",
85            #[cfg(feature = "luau")]
86            Value::Vector(_) => "vector",
87            Value::String(_) => "string",
88            Value::Table(_) => "table",
89            Value::Function(_) => "function",
90            Value::Thread(_) => "thread",
91            Value::UserData(AnyUserData(_, SubtypeId::None)) => "userdata",
92            #[cfg(feature = "luau")]
93            Value::UserData(AnyUserData(_, SubtypeId::Buffer)) => "buffer",
94            #[cfg(feature = "luajit")]
95            Value::UserData(AnyUserData(_, SubtypeId::CData)) => "cdata",
96            Value::Error(_) => "error",
97        }
98    }
99
100    /// Compares two values for equality.
101    ///
102    /// Equality comparisons do not convert strings to numbers or vice versa.
103    /// Tables, Functions, Threads, and Userdata are compared by reference:
104    /// two objects are considered equal only if they are the same object.
105    ///
106    /// If Tables or Userdata have `__eq` metamethod then mlua will try to invoke it.
107    /// The first value is checked first. If that value does not define a metamethod
108    /// for `__eq`, then mlua will check the second value.
109    /// Then mlua calls the metamethod with the two values as arguments, if found.
110    pub fn equals<T: AsRef<Self>>(&self, other: T) -> Result<bool> {
111        match (self, other.as_ref()) {
112            (Value::Table(a), Value::Table(b)) => a.equals(b),
113            (Value::UserData(a), Value::UserData(b)) => a.equals(b),
114            (a, b) => Ok(a == b),
115        }
116    }
117
118    /// Converts the value to a generic C pointer.
119    ///
120    /// The value can be a userdata, a table, a thread, a string, or a function; otherwise it returns NULL.
121    /// Different objects will give different pointers.
122    /// There is no way to convert the pointer back to its original value.
123    ///
124    /// Typically this function is used only for hashing and debug information.
125    #[inline]
126    pub fn to_pointer(&self) -> *const c_void {
127        match self {
128            Value::LightUserData(ud) => ud.0,
129            Value::String(String(r))
130            | Value::Table(Table(r))
131            | Value::Function(Function(r))
132            | Value::Thread(Thread(r, ..))
133            | Value::UserData(AnyUserData(r, ..)) => r.to_pointer(),
134            _ => ptr::null(),
135        }
136    }
137
138    /// Converts the value to a string.
139    ///
140    /// If the value has a metatable with a `__tostring` method, then it will be called to get the result.
141    pub fn to_string(&self) -> Result<StdString> {
142        match self {
143            Value::Nil => Ok("nil".to_string()),
144            Value::Boolean(b) => Ok(b.to_string()),
145            Value::LightUserData(ud) if ud.0.is_null() => Ok("null".to_string()),
146            Value::LightUserData(ud) => Ok(format!("lightuserdata: {:p}", ud.0)),
147            Value::Integer(i) => Ok(i.to_string()),
148            Value::Number(n) => Ok(n.to_string()),
149            #[cfg(feature = "luau")]
150            Value::Vector(v) => Ok(v.to_string()),
151            Value::String(s) => Ok(s.to_str()?.to_string()),
152            Value::Table(Table(r))
153            | Value::Function(Function(r))
154            | Value::Thread(Thread(r, ..))
155            | Value::UserData(AnyUserData(r, ..)) => unsafe {
156                let state = r.lua.state();
157                let _guard = StackGuard::new(state);
158                check_stack(state, 3)?;
159
160                r.lua.push_ref(r);
161                protect_lua!(state, 1, 1, fn(state) {
162                    ffi::luaL_tolstring(state, -1, ptr::null_mut());
163                })?;
164                Ok(String(r.lua.pop_ref()).to_str()?.to_string())
165            },
166            Value::Error(err) => Ok(err.to_string()),
167        }
168    }
169
170    /// Returns `true` if the value is a [`Nil`].
171    #[inline]
172    pub fn is_nil(&self) -> bool {
173        self == &Nil
174    }
175
176    /// Returns `true` if the value is a [`NULL`].
177    #[inline]
178    pub fn is_null(&self) -> bool {
179        self == &Self::NULL
180    }
181
182    /// Returns `true` if the value is a boolean.
183    #[inline]
184    pub fn is_boolean(&self) -> bool {
185        self.as_boolean().is_some()
186    }
187
188    /// Cast the value to boolean.
189    ///
190    /// If the value is a Boolean, returns it or `None` otherwise.
191    #[inline]
192    pub fn as_boolean(&self) -> Option<bool> {
193        match *self {
194            Value::Boolean(b) => Some(b),
195            _ => None,
196        }
197    }
198
199    /// Returns `true` if the value is a [`LightUserData`].
200    #[inline]
201    pub fn is_light_userdata(&self) -> bool {
202        self.as_light_userdata().is_some()
203    }
204
205    /// Cast the value to [`LightUserData`].
206    ///
207    /// If the value is a [`LightUserData`], returns it or `None` otherwise.
208    #[inline]
209    pub fn as_light_userdata(&self) -> Option<LightUserData> {
210        match *self {
211            Value::LightUserData(l) => Some(l),
212            _ => None,
213        }
214    }
215
216    /// Returns `true` if the value is an [`Integer`].
217    #[inline]
218    pub fn is_integer(&self) -> bool {
219        self.as_integer().is_some()
220    }
221
222    /// Cast the value to [`Integer`].
223    ///
224    /// If the value is a Lua [`Integer`], returns it or `None` otherwise.
225    #[inline]
226    pub fn as_integer(&self) -> Option<Integer> {
227        match *self {
228            Value::Integer(i) => Some(i),
229            _ => None,
230        }
231    }
232
233    /// Cast the value to `i32`.
234    ///
235    /// If the value is a Lua [`Integer`], try to convert it to `i32` or return `None` otherwise.
236    #[inline]
237    pub fn as_i32(&self) -> Option<i32> {
238        #[allow(clippy::useless_conversion)]
239        self.as_integer().and_then(|i| i32::try_from(i).ok())
240    }
241
242    /// Cast the value to `u32`.
243    ///
244    /// If the value is a Lua [`Integer`], try to convert it to `u32` or return `None` otherwise.
245    #[inline]
246    pub fn as_u32(&self) -> Option<u32> {
247        self.as_integer().and_then(|i| u32::try_from(i).ok())
248    }
249
250    /// Cast the value to `i64`.
251    ///
252    /// If the value is a Lua [`Integer`], try to convert it to `i64` or return `None` otherwise.
253    #[inline]
254    pub fn as_i64(&self) -> Option<i64> {
255        self.as_integer().map(i64::from)
256    }
257
258    /// Cast the value to `u64`.
259    ///
260    /// If the value is a Lua [`Integer`], try to convert it to `u64` or return `None` otherwise.
261    #[inline]
262    pub fn as_u64(&self) -> Option<u64> {
263        self.as_integer().and_then(|i| u64::try_from(i).ok())
264    }
265
266    /// Cast the value to `isize`.
267    ///
268    /// If the value is a Lua [`Integer`], try to convert it to `isize` or return `None` otherwise.
269    #[inline]
270    pub fn as_isize(&self) -> Option<isize> {
271        self.as_integer().and_then(|i| isize::try_from(i).ok())
272    }
273
274    /// Cast the value to `usize`.
275    ///
276    /// If the value is a Lua [`Integer`], try to convert it to `usize` or return `None` otherwise.
277    #[inline]
278    pub fn as_usize(&self) -> Option<usize> {
279        self.as_integer().and_then(|i| usize::try_from(i).ok())
280    }
281
282    /// Returns `true` if the value is a Lua [`Number`].
283    #[inline]
284    pub fn is_number(&self) -> bool {
285        self.as_number().is_some()
286    }
287
288    /// Cast the value to [`Number`].
289    ///
290    /// If the value is a Lua [`Number`], returns it or `None` otherwise.
291    #[inline]
292    pub fn as_number(&self) -> Option<Number> {
293        match *self {
294            Value::Number(n) => Some(n),
295            _ => None,
296        }
297    }
298
299    /// Cast the value to `f32`.
300    ///
301    /// If the value is a Lua [`Number`], try to convert it to `f32` or return `None` otherwise.
302    #[inline]
303    pub fn as_f32(&self) -> Option<f32> {
304        self.as_number().and_then(f32::from_f64)
305    }
306
307    /// Cast the value to `f64`.
308    ///
309    /// If the value is a Lua [`Number`], try to convert it to `f64` or return `None` otherwise.
310    #[inline]
311    pub fn as_f64(&self) -> Option<f64> {
312        self.as_number()
313    }
314
315    /// Returns `true` if the value is a Lua [`String`].
316    #[inline]
317    pub fn is_string(&self) -> bool {
318        self.as_string().is_some()
319    }
320
321    /// Cast the value to Lua [`String`].
322    ///
323    /// If the value is a Lua [`String`], returns it or `None` otherwise.
324    #[inline]
325    pub fn as_string(&self) -> Option<&String> {
326        match self {
327            Value::String(s) => Some(s),
328            _ => None,
329        }
330    }
331
332    /// Cast the value to [`str`].
333    ///
334    /// If the value is a Lua [`String`], try to convert it to [`str`] or return `None` otherwise.
335    #[inline]
336    pub fn as_str(&self) -> Option<&str> {
337        self.as_string().and_then(|s| s.to_str().ok())
338    }
339
340    /// Cast the value to [`Cow<str>`].
341    ///
342    /// If the value is a Lua [`String`], converts it to [`Cow<str>`] or returns `None` otherwise.
343    #[inline]
344    pub fn as_string_lossy(&self) -> Option<Cow<str>> {
345        self.as_string().map(|s| s.to_string_lossy())
346    }
347
348    /// Returns `true` if the value is a Lua [`Table`].
349    #[inline]
350    pub fn is_table(&self) -> bool {
351        self.as_table().is_some()
352    }
353
354    /// Cast the value to [`Table`].
355    ///
356    /// If the value is a Lua [`Table`], returns it or `None` otherwise.
357    #[inline]
358    pub fn as_table(&self) -> Option<&Table> {
359        match self {
360            Value::Table(t) => Some(t),
361            _ => None,
362        }
363    }
364
365    /// Returns `true` if the value is a Lua [`Thread`].
366    #[inline]
367    pub fn is_thread(&self) -> bool {
368        self.as_thread().is_some()
369    }
370
371    /// Cast the value to [`Thread`].
372    ///
373    /// If the value is a Lua [`Thread`], returns it or `None` otherwise.
374    #[inline]
375    pub fn as_thread(&self) -> Option<&Thread> {
376        match self {
377            Value::Thread(t) => Some(t),
378            _ => None,
379        }
380    }
381
382    /// Returns `true` if the value is a Lua [`Function`].
383    #[inline]
384    pub fn is_function(&self) -> bool {
385        self.as_function().is_some()
386    }
387
388    /// Cast the value to [`Function`].
389    ///
390    /// If the value is a Lua [`Function`], returns it or `None` otherwise.
391    #[inline]
392    pub fn as_function(&self) -> Option<&Function> {
393        match self {
394            Value::Function(f) => Some(f),
395            _ => None,
396        }
397    }
398
399    /// Returns `true` if the value is an [`AnyUserData`].
400    #[inline]
401    pub fn is_userdata(&self) -> bool {
402        self.as_userdata().is_some()
403    }
404
405    /// Cast the value to [`AnyUserData`].
406    ///
407    /// If the value is an [`AnyUserData`], returns it or `None` otherwise.
408    #[inline]
409    pub fn as_userdata(&self) -> Option<&AnyUserData> {
410        match self {
411            Value::UserData(ud) => Some(ud),
412            _ => None,
413        }
414    }
415
416    /// Returns `true` if the value is a Buffer wrapped in [`AnyUserData`].
417    #[cfg(any(feature = "luau", doc))]
418    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
419    #[doc(hidden)]
420    #[inline]
421    pub fn is_buffer(&self) -> bool {
422        self.as_userdata()
423            .map(|ud| ud.1 == SubtypeId::Buffer)
424            .unwrap_or_default()
425    }
426
427    /// Returns `true` if the value is a CData wrapped in [`AnyUserData`].
428    #[cfg(any(feature = "luajit", doc))]
429    #[cfg_attr(docsrs, doc(cfg(feature = "luajit")))]
430    #[doc(hidden)]
431    #[inline]
432    pub fn is_cdata(&self) -> bool {
433        self.as_userdata()
434            .map(|ud| ud.1 == SubtypeId::CData)
435            .unwrap_or_default()
436    }
437
438    /// Wrap reference to this Value into [`SerializableValue`].
439    ///
440    /// This allows customizing serialization behavior using serde.
441    #[cfg(feature = "serialize")]
442    #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
443    #[doc(hidden)]
444    pub fn to_serializable(&self) -> SerializableValue<'_, 'lua> {
445        SerializableValue::new(self, Default::default(), None)
446    }
447
448    // Compares two values.
449    // Used to sort values for Debug printing.
450    pub(crate) fn cmp(&self, other: &Self) -> Ordering {
451        fn cmp_num(a: Number, b: Number) -> Ordering {
452            match (a, b) {
453                _ if a < b => Ordering::Less,
454                _ if a > b => Ordering::Greater,
455                _ => Ordering::Equal,
456            }
457        }
458
459        match (self, other) {
460            // Nil
461            (Value::Nil, Value::Nil) => Ordering::Equal,
462            (Value::Nil, _) => Ordering::Less,
463            (_, Value::Nil) => Ordering::Greater,
464            // Null (a special case)
465            (Value::LightUserData(ud1), Value::LightUserData(ud2)) if ud1 == ud2 => Ordering::Equal,
466            (Value::LightUserData(ud1), _) if ud1.0.is_null() => Ordering::Less,
467            (_, Value::LightUserData(ud2)) if ud2.0.is_null() => Ordering::Greater,
468            // Boolean
469            (Value::Boolean(a), Value::Boolean(b)) => a.cmp(b),
470            (Value::Boolean(_), _) => Ordering::Less,
471            (_, Value::Boolean(_)) => Ordering::Greater,
472            // Integer && Number
473            (Value::Integer(a), Value::Integer(b)) => a.cmp(b),
474            (&Value::Integer(a), &Value::Number(b)) => cmp_num(a as Number, b),
475            (&Value::Number(a), &Value::Integer(b)) => cmp_num(a, b as Number),
476            (&Value::Number(a), &Value::Number(b)) => cmp_num(a, b),
477            (Value::Integer(_) | Value::Number(_), _) => Ordering::Less,
478            (_, Value::Integer(_) | Value::Number(_)) => Ordering::Greater,
479            // String
480            (Value::String(a), Value::String(b)) => a.as_bytes().cmp(b.as_bytes()),
481            (Value::String(_), _) => Ordering::Less,
482            (_, Value::String(_)) => Ordering::Greater,
483            // Other variants can be randomly ordered
484            (a, b) => a.to_pointer().cmp(&b.to_pointer()),
485        }
486    }
487
488    pub(crate) fn fmt_pretty(
489        &self,
490        fmt: &mut fmt::Formatter,
491        recursive: bool,
492        ident: usize,
493        visited: &mut HashSet<*const c_void>,
494    ) -> fmt::Result {
495        match self {
496            Value::Nil => write!(fmt, "nil"),
497            Value::Boolean(b) => write!(fmt, "{b}"),
498            Value::LightUserData(ud) if ud.0.is_null() => write!(fmt, "null"),
499            Value::LightUserData(ud) => write!(fmt, "lightuserdata: {:?}", ud.0),
500            Value::Integer(i) => write!(fmt, "{i}"),
501            Value::Number(n) => write!(fmt, "{n}"),
502            #[cfg(feature = "luau")]
503            Value::Vector(v) => write!(fmt, "{v}"),
504            Value::String(s) => write!(fmt, "{s:?}"),
505            Value::Table(t) if recursive && !visited.contains(&t.to_pointer()) => {
506                t.fmt_pretty(fmt, ident, visited)
507            }
508            t @ Value::Table(_) => write!(fmt, "table: {:?}", t.to_pointer()),
509            f @ Value::Function(_) => write!(fmt, "function: {:?}", f.to_pointer()),
510            t @ Value::Thread(_) => write!(fmt, "thread: {:?}", t.to_pointer()),
511            u @ Value::UserData(ud) => {
512                // Try `__name/__type` first then `__tostring`
513                let name = ud.type_name().ok().flatten();
514                let s = name
515                    .map(|name| format!("{name}: {:?}", u.to_pointer()))
516                    .or_else(|| u.to_string().ok())
517                    .unwrap_or_else(|| format!("userdata: {:?}", u.to_pointer()));
518                write!(fmt, "{s}")
519            }
520            Value::Error(e) if recursive => write!(fmt, "{e:?}"),
521            Value::Error(_) => write!(fmt, "error"),
522        }
523    }
524}
525
526impl fmt::Debug for Value<'_> {
527    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
528        if fmt.alternate() {
529            return self.fmt_pretty(fmt, true, 0, &mut HashSet::new());
530        }
531        match self {
532            Value::Nil => write!(fmt, "Nil"),
533            Value::Boolean(b) => write!(fmt, "Boolean({b})"),
534            Value::LightUserData(ud) => write!(fmt, "{ud:?}"),
535            Value::Integer(i) => write!(fmt, "Integer({i})"),
536            Value::Number(n) => write!(fmt, "Number({n})"),
537            #[cfg(feature = "luau")]
538            Value::Vector(v) => write!(fmt, "{v:?}"),
539            Value::String(s) => write!(fmt, "String({s:?})"),
540            Value::Table(t) => write!(fmt, "{t:?}"),
541            Value::Function(f) => write!(fmt, "{f:?}"),
542            Value::Thread(t) => write!(fmt, "{t:?}"),
543            Value::UserData(ud) => write!(fmt, "{ud:?}"),
544            Value::Error(e) => write!(fmt, "Error({e:?})"),
545        }
546    }
547}
548
549impl<'lua> PartialEq for Value<'lua> {
550    fn eq(&self, other: &Self) -> bool {
551        match (self, other) {
552            (Value::Nil, Value::Nil) => true,
553            (Value::Boolean(a), Value::Boolean(b)) => a == b,
554            (Value::LightUserData(a), Value::LightUserData(b)) => a == b,
555            (Value::Integer(a), Value::Integer(b)) => *a == *b,
556            (Value::Integer(a), Value::Number(b)) => *a as Number == *b,
557            (Value::Number(a), Value::Integer(b)) => *a == *b as Number,
558            (Value::Number(a), Value::Number(b)) => *a == *b,
559            #[cfg(feature = "luau")]
560            (Value::Vector(v1), Value::Vector(v2)) => v1 == v2,
561            (Value::String(a), Value::String(b)) => a == b,
562            (Value::Table(a), Value::Table(b)) => a == b,
563            (Value::Function(a), Value::Function(b)) => a == b,
564            (Value::Thread(a), Value::Thread(b)) => a == b,
565            (Value::UserData(a), Value::UserData(b)) => a == b,
566            _ => false,
567        }
568    }
569}
570
571impl<'lua> AsRef<Value<'lua>> for Value<'lua> {
572    #[inline]
573    fn as_ref(&self) -> &Self {
574        self
575    }
576}
577
578/// A wrapped [`Value`] with customized serialization behavior.
579#[cfg(feature = "serialize")]
580#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
581pub struct SerializableValue<'a, 'lua> {
582    value: &'a Value<'lua>,
583    options: crate::serde::de::Options,
584    // In many cases we don't need `visited` map, so don't allocate memory by default
585    visited: Option<Rc<RefCell<FxHashSet<*const c_void>>>>,
586}
587
588#[cfg(feature = "serialize")]
589impl<'lua> Serialize for Value<'lua> {
590    #[inline]
591    fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
592        SerializableValue::new(self, Default::default(), None).serialize(serializer)
593    }
594}
595
596#[cfg(feature = "serialize")]
597impl<'a, 'lua> SerializableValue<'a, 'lua> {
598    #[inline]
599    pub(crate) fn new(
600        value: &'a Value<'lua>,
601        options: crate::serde::de::Options,
602        visited: Option<&Rc<RefCell<FxHashSet<*const c_void>>>>,
603    ) -> Self {
604        if let Value::Table(_) = value {
605            return Self {
606                value,
607                options,
608                // We need to always initialize the `visited` map for Tables
609                visited: visited.cloned().or_else(|| Some(Default::default())),
610            };
611        }
612        Self {
613            value,
614            options,
615            visited: None,
616        }
617    }
618
619    /// If true, an attempt to serialize types such as [`Function`], [`Thread`], [`LightUserData`]
620    /// and [`Error`] will cause an error.
621    /// Otherwise these types skipped when iterating or serialized as unit type.
622    ///
623    /// Default: **true**
624    #[must_use]
625    pub const fn deny_unsupported_types(mut self, enabled: bool) -> Self {
626        self.options.deny_unsupported_types = enabled;
627        self
628    }
629
630    /// If true, an attempt to serialize a recursive table (table that refers to itself)
631    /// will cause an error.
632    /// Otherwise subsequent attempts to serialize the same table will be ignored.
633    ///
634    /// Default: **true**
635    #[must_use]
636    pub const fn deny_recursive_tables(mut self, enabled: bool) -> Self {
637        self.options.deny_recursive_tables = enabled;
638        self
639    }
640
641    /// If true, keys in tables will be iterated (and serialized) in sorted order.
642    ///
643    /// Default: **false**
644    #[must_use]
645    pub const fn sort_keys(mut self, enabled: bool) -> Self {
646        self.options.sort_keys = enabled;
647        self
648    }
649}
650
651#[cfg(feature = "serialize")]
652impl<'a, 'lua> Serialize for SerializableValue<'a, 'lua> {
653    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
654    where
655        S: Serializer,
656    {
657        match self.value {
658            Value::Nil => serializer.serialize_unit(),
659            Value::Boolean(b) => serializer.serialize_bool(*b),
660            #[allow(clippy::useless_conversion)]
661            Value::Integer(i) => serializer.serialize_i64((*i).into()),
662            Value::Number(n) => serializer.serialize_f64(*n),
663            #[cfg(feature = "luau")]
664            Value::Vector(v) => v.serialize(serializer),
665            Value::String(s) => s.serialize(serializer),
666            Value::Table(t) => {
667                let visited = self.visited.as_ref().unwrap().clone();
668                SerializableTable::new(t, self.options, visited).serialize(serializer)
669            }
670            Value::LightUserData(ud) if ud.0.is_null() => serializer.serialize_none(),
671            Value::UserData(ud) if ud.is_serializable() || self.options.deny_unsupported_types => {
672                ud.serialize(serializer)
673            }
674            Value::Function(_)
675            | Value::Thread(_)
676            | Value::UserData(_)
677            | Value::LightUserData(_)
678            | Value::Error(_) => {
679                if self.options.deny_unsupported_types {
680                    let msg = format!("cannot serialize <{}>", self.value.type_name());
681                    Err(ser::Error::custom(msg))
682                } else {
683                    serializer.serialize_unit()
684                }
685            }
686        }
687    }
688}
689
690/// Trait for types convertible to `Value`.
691pub trait IntoLua<'lua>: Sized {
692    /// Performs the conversion.
693    fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>>;
694
695    /// Pushes the value into the Lua stack.
696    ///
697    /// # Safety
698    /// This method does not check Lua stack space.
699    #[doc(hidden)]
700    #[inline]
701    unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
702        lua.push_value(self.into_lua(lua)?)
703    }
704}
705
706/// Trait for types convertible from `Value`.
707pub trait FromLua<'lua>: Sized {
708    /// Performs the conversion.
709    fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self>;
710
711    /// Performs the conversion for an argument (eg. function argument).
712    ///
713    /// `i` is the argument index (position),
714    /// `to` is a function name that received the argument.
715    #[doc(hidden)]
716    #[inline]
717    fn from_lua_arg(arg: Value<'lua>, i: usize, to: Option<&str>, lua: &'lua Lua) -> Result<Self> {
718        Self::from_lua(arg, lua).map_err(|err| Error::BadArgument {
719            to: to.map(|s| s.to_string()),
720            pos: i,
721            name: None,
722            cause: Arc::new(err),
723        })
724    }
725
726    /// Performs the conversion for a value in the Lua stack at index `idx`.
727    #[doc(hidden)]
728    #[inline]
729    unsafe fn from_stack(idx: c_int, lua: &'lua Lua) -> Result<Self> {
730        Self::from_lua(lua.stack_value(idx), lua)
731    }
732
733    /// Same as `from_lua_arg` but for a value in the Lua stack at index `idx`.
734    #[doc(hidden)]
735    #[inline]
736    unsafe fn from_stack_arg(
737        idx: c_int,
738        i: usize,
739        to: Option<&str>,
740        lua: &'lua Lua,
741    ) -> Result<Self> {
742        Self::from_stack(idx, lua).map_err(|err| Error::BadArgument {
743            to: to.map(|s| s.to_string()),
744            pos: i,
745            name: None,
746            cause: Arc::new(err),
747        })
748    }
749}
750
751/// Multiple Lua values used for both argument passing and also for multiple return values.
752#[derive(Debug, Clone)]
753pub struct MultiValue<'lua> {
754    vec: Vec<Value<'lua>>,
755    lua: Option<&'lua Lua>,
756}
757
758impl Drop for MultiValue<'_> {
759    fn drop(&mut self) {
760        if let Some(lua) = self.lua {
761            let vec = mem::take(&mut self.vec);
762            lua.push_multivalue_to_pool(vec);
763        }
764    }
765}
766
767impl<'lua> MultiValue<'lua> {
768    /// Creates an empty `MultiValue` containing no values.
769    pub const fn new() -> MultiValue<'lua> {
770        MultiValue {
771            vec: Vec::new(),
772            lua: None,
773        }
774    }
775
776    /// Similar to `new` but can reuse previously used container with allocated capacity.
777    #[inline]
778    pub(crate) fn with_lua_and_capacity(lua: &'lua Lua, capacity: usize) -> MultiValue<'lua> {
779        let vec = lua
780            .pop_multivalue_from_pool()
781            .map(|mut vec| {
782                vec.reserve(capacity);
783                vec
784            })
785            .unwrap_or_else(|| Vec::with_capacity(capacity));
786        MultiValue {
787            vec,
788            lua: Some(lua),
789        }
790    }
791}
792
793impl<'lua> Default for MultiValue<'lua> {
794    #[inline]
795    fn default() -> MultiValue<'lua> {
796        MultiValue::new()
797    }
798}
799
800impl<'lua> FromIterator<Value<'lua>> for MultiValue<'lua> {
801    #[inline]
802    fn from_iter<I: IntoIterator<Item = Value<'lua>>>(iter: I) -> Self {
803        MultiValue::from_vec(Vec::from_iter(iter))
804    }
805}
806
807impl<'lua> IntoIterator for MultiValue<'lua> {
808    type Item = Value<'lua>;
809    type IntoIter = iter::Rev<vec::IntoIter<Value<'lua>>>;
810
811    #[inline]
812    fn into_iter(mut self) -> Self::IntoIter {
813        let vec = mem::take(&mut self.vec);
814        mem::forget(self);
815        vec.into_iter().rev()
816    }
817}
818
819impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
820    type Item = &'a Value<'lua>;
821    type IntoIter = iter::Rev<slice::Iter<'a, Value<'lua>>>;
822
823    #[inline]
824    fn into_iter(self) -> Self::IntoIter {
825        self.vec.iter().rev()
826    }
827}
828
829impl<'lua> Index<usize> for MultiValue<'lua> {
830    type Output = Value<'lua>;
831
832    #[inline]
833    fn index(&self, index: usize) -> &Self::Output {
834        if let Some(result) = self.get(index) {
835            result
836        } else {
837            panic!(
838                "index out of bounds: the len is {} but the index is {}",
839                self.len(),
840                index
841            )
842        }
843    }
844}
845
846impl<'lua> MultiValue<'lua> {
847    #[inline]
848    pub fn from_vec(mut vec: Vec<Value<'lua>>) -> MultiValue<'lua> {
849        vec.reverse();
850        MultiValue { vec, lua: None }
851    }
852
853    #[inline]
854    pub fn into_vec(mut self) -> Vec<Value<'lua>> {
855        let mut vec = mem::take(&mut self.vec);
856        mem::forget(self);
857        vec.reverse();
858        vec
859    }
860
861    #[inline]
862    pub fn get(&self, index: usize) -> Option<&Value<'lua>> {
863        if index < self.vec.len() {
864            return self.vec.get(self.vec.len() - index - 1);
865        }
866        None
867    }
868
869    #[inline]
870    pub fn pop_front(&mut self) -> Option<Value<'lua>> {
871        self.vec.pop()
872    }
873
874    #[inline]
875    pub fn push_front(&mut self, value: Value<'lua>) {
876        self.vec.push(value);
877    }
878
879    #[inline]
880    pub fn clear(&mut self) {
881        self.vec.clear();
882    }
883
884    #[inline]
885    pub fn len(&self) -> usize {
886        self.vec.len()
887    }
888
889    #[inline]
890    pub fn is_empty(&self) -> bool {
891        self.vec.is_empty()
892    }
893
894    #[inline]
895    pub fn iter(&self) -> iter::Rev<slice::Iter<Value<'lua>>> {
896        self.vec.iter().rev()
897    }
898
899    #[inline]
900    pub(crate) fn drain_all(&mut self) -> iter::Rev<vec::Drain<Value<'lua>>> {
901        self.vec.drain(..).rev()
902    }
903
904    #[inline]
905    pub(crate) fn refill(
906        &mut self,
907        iter: impl IntoIterator<Item = Result<Value<'lua>>>,
908    ) -> Result<()> {
909        self.vec.clear();
910        for value in iter {
911            self.vec.push(value?);
912        }
913        self.vec.reverse();
914        Ok(())
915    }
916}
917
918/// Trait for types convertible to any number of Lua values.
919///
920/// This is a generalization of `IntoLua`, allowing any number of resulting Lua values instead of just
921/// one. Any type that implements `IntoLua` will automatically implement this trait.
922pub trait IntoLuaMulti<'lua>: Sized {
923    /// Performs the conversion.
924    fn into_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>>;
925
926    /// Pushes the values into the Lua stack.
927    ///
928    /// Returns number of pushed values.
929    #[doc(hidden)]
930    #[inline]
931    unsafe fn push_into_stack_multi(self, lua: &'lua Lua) -> Result<c_int> {
932        let mut values = self.into_lua_multi(lua)?;
933        let len: c_int = values.len().try_into().unwrap();
934        unsafe {
935            check_stack(lua.state(), len + 1)?;
936            for v in values.drain_all() {
937                lua.push_value(v)?;
938            }
939        }
940        Ok(len)
941    }
942}
943
944/// Trait for types that can be created from an arbitrary number of Lua values.
945///
946/// This is a generalization of `FromLua`, allowing an arbitrary number of Lua values to participate
947/// in the conversion. Any type that implements `FromLua` will automatically implement this trait.
948pub trait FromLuaMulti<'lua>: Sized {
949    /// Performs the conversion.
950    ///
951    /// In case `values` contains more values than needed to perform the conversion, the excess
952    /// values should be ignored. This reflects the semantics of Lua when calling a function or
953    /// assigning values. Similarly, if not enough values are given, conversions should assume that
954    /// any missing values are nil.
955    fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self>;
956
957    /// Performs the conversion for a list of arguments.
958    ///
959    /// `i` is an index (position) of the first argument,
960    /// `to` is a function name that received the arguments.
961    #[doc(hidden)]
962    #[inline]
963    fn from_lua_args(
964        args: MultiValue<'lua>,
965        i: usize,
966        to: Option<&str>,
967        lua: &'lua Lua,
968    ) -> Result<Self> {
969        let _ = (i, to);
970        Self::from_lua_multi(args, lua)
971    }
972
973    /// Performs the conversion for a number of values in the Lua stack.
974    #[doc(hidden)]
975    #[inline]
976    unsafe fn from_stack_multi(nvals: c_int, lua: &'lua Lua) -> Result<Self> {
977        let mut values = MultiValue::with_lua_and_capacity(lua, nvals as usize);
978        for idx in 1..=nvals {
979            values.push_front(lua.stack_value(-idx));
980        }
981        if nvals > 0 {
982            // It's safe to clear the stack as all references moved to ref thread
983            ffi::lua_pop(lua.state(), nvals);
984        }
985        Self::from_lua_multi(values, lua)
986    }
987
988    /// Same as `from_lua_args` but for a number of values in the Lua stack.
989    #[doc(hidden)]
990    #[inline]
991    unsafe fn from_stack_args(
992        nargs: c_int,
993        i: usize,
994        to: Option<&str>,
995        lua: &'lua Lua,
996    ) -> Result<Self> {
997        let _ = (i, to);
998        Self::from_stack_multi(nargs, lua)
999    }
1000}
1001
1002#[cfg(test)]
1003mod assertions {
1004    use super::*;
1005
1006    static_assertions::assert_not_impl_any!(Value: Send);
1007    static_assertions::assert_not_impl_any!(MultiValue: Send);
1008}