mlua_codemp_patch/
value.rs

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