Skip to main content

mlua/
multi.rs

1use std::collections::{VecDeque, vec_deque};
2use std::iter::FromIterator;
3use std::mem;
4use std::ops::{Deref, DerefMut};
5use std::os::raw::c_int;
6use std::result::Result as StdResult;
7
8use crate::error::Result;
9use crate::state::{Lua, RawLua};
10use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
11use crate::util::check_stack;
12use crate::value::{Nil, Value};
13
14/// Result is convertible to [`MultiValue`] following the common Lua idiom of returning the result
15/// on success, or in the case of an error, returning `nil` and an error message.
16impl<T: IntoLua, E: IntoLua> IntoLuaMulti for StdResult<T, E> {
17    #[inline]
18    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
19        match self {
20            Ok(val) => (val,).into_lua_multi(lua),
21            Err(err) => (Nil, err).into_lua_multi(lua),
22        }
23    }
24
25    #[inline]
26    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
27        match self {
28            Ok(val) => (val,).push_into_stack_multi(lua),
29            Err(err) => (Nil, err).push_into_stack_multi(lua),
30        }
31    }
32}
33
34impl<E: IntoLua> IntoLuaMulti for StdResult<(), E> {
35    #[inline]
36    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
37        match self {
38            Ok(_) => const { Ok(MultiValue::new()) },
39            Err(err) => (Nil, err).into_lua_multi(lua),
40        }
41    }
42
43    #[inline]
44    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
45        match self {
46            Ok(_) => Ok(0),
47            Err(err) => (Nil, err).push_into_stack_multi(lua),
48        }
49    }
50}
51
52impl<T: IntoLua> IntoLuaMulti for T {
53    #[inline]
54    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
55        let mut v = MultiValue::with_capacity(1);
56        v.push_back(self.into_lua(lua)?);
57        Ok(v)
58    }
59
60    #[inline]
61    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
62        self.push_into_stack(lua)?;
63        Ok(1)
64    }
65}
66
67impl<T: FromLua> FromLuaMulti for T {
68    #[inline]
69    fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
70        T::from_lua(values.pop_front().unwrap_or(Nil), lua)
71    }
72
73    #[inline]
74    fn from_lua_args(mut args: MultiValue, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
75        T::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua)
76    }
77
78    #[inline]
79    unsafe fn from_stack_multi(nvals: c_int, lua: &RawLua) -> Result<Self> {
80        if nvals == 0 {
81            return T::from_lua(Nil, lua.lua());
82        }
83        T::from_stack(-nvals, lua)
84    }
85
86    #[inline]
87    unsafe fn from_stack_args(nargs: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
88        if nargs == 0 {
89            return T::from_lua_arg(Nil, i, to, lua.lua());
90        }
91        T::from_stack_arg(-nargs, i, to, lua)
92    }
93}
94
95/// Multiple Lua values used for both argument passing and also for multiple return values.
96#[derive(Default, Debug, Clone)]
97pub struct MultiValue(VecDeque<Value>);
98
99impl Deref for MultiValue {
100    type Target = VecDeque<Value>;
101
102    #[inline]
103    fn deref(&self) -> &Self::Target {
104        &self.0
105    }
106}
107
108impl DerefMut for MultiValue {
109    #[inline]
110    fn deref_mut(&mut self) -> &mut Self::Target {
111        &mut self.0
112    }
113}
114
115impl MultiValue {
116    /// Creates an empty `MultiValue` containing no values.
117    #[inline]
118    pub const fn new() -> MultiValue {
119        MultiValue(VecDeque::new())
120    }
121
122    /// Creates an empty `MultiValue` container with space for at least `capacity` elements.
123    pub fn with_capacity(capacity: usize) -> MultiValue {
124        MultiValue(VecDeque::with_capacity(capacity))
125    }
126
127    /// Creates a `MultiValue` container from vector of values.
128    ///
129    /// This method works in *O*(1) time and does not allocate any additional memory.
130    #[inline]
131    pub fn from_vec(vec: Vec<Value>) -> MultiValue {
132        vec.into()
133    }
134
135    /// Consumes the `MultiValue` and returns a vector of values.
136    ///
137    /// This method needs *O*(*n*) data movement if the circular buffer doesn't happen to be at the
138    /// beginning of the allocation.
139    #[inline]
140    pub fn into_vec(self) -> Vec<Value> {
141        self.into()
142    }
143
144    #[inline]
145    pub(crate) fn from_lua_iter<T: IntoLua>(lua: &Lua, iter: impl IntoIterator<Item = T>) -> Result<Self> {
146        let iter = iter.into_iter();
147        let mut multi_value = MultiValue::with_capacity(iter.size_hint().0);
148        for value in iter {
149            multi_value.push_back(value.into_lua(lua)?);
150        }
151        Ok(multi_value)
152    }
153}
154
155impl From<Vec<Value>> for MultiValue {
156    #[inline]
157    fn from(value: Vec<Value>) -> Self {
158        MultiValue(value.into())
159    }
160}
161
162impl From<MultiValue> for Vec<Value> {
163    #[inline]
164    fn from(value: MultiValue) -> Self {
165        value.0.into()
166    }
167}
168
169impl FromIterator<Value> for MultiValue {
170    #[inline]
171    fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
172        let mut multi_value = MultiValue::new();
173        multi_value.extend(iter);
174        multi_value
175    }
176}
177
178impl IntoIterator for MultiValue {
179    type Item = Value;
180    type IntoIter = vec_deque::IntoIter<Value>;
181
182    #[inline]
183    fn into_iter(mut self) -> Self::IntoIter {
184        let deque = mem::take(&mut self.0);
185        mem::forget(self);
186        deque.into_iter()
187    }
188}
189
190impl<'a> IntoIterator for &'a MultiValue {
191    type Item = &'a Value;
192    type IntoIter = vec_deque::Iter<'a, Value>;
193
194    #[inline]
195    fn into_iter(self) -> Self::IntoIter {
196        self.0.iter()
197    }
198}
199
200impl IntoLuaMulti for MultiValue {
201    #[inline]
202    fn into_lua_multi(self, _: &Lua) -> Result<MultiValue> {
203        Ok(self)
204    }
205}
206
207impl IntoLuaMulti for &MultiValue {
208    #[inline]
209    fn into_lua_multi(self, _: &Lua) -> Result<MultiValue> {
210        Ok(self.clone())
211    }
212
213    #[inline]
214    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
215        let nresults = self.len() as i32;
216        check_stack(lua.state(), nresults + 1)?;
217        for value in &self.0 {
218            lua.push_value(value)?;
219        }
220        Ok(nresults)
221    }
222}
223
224impl FromLuaMulti for MultiValue {
225    #[inline]
226    fn from_lua_multi(values: MultiValue, _: &Lua) -> Result<Self> {
227        Ok(values)
228    }
229}
230
231/// Wraps a variable number of `T`s.
232///
233/// Can be used to work with variadic functions more easily. Using this type as the last argument of
234/// a Rust callback will accept any number of arguments from Lua and convert them to the type `T`
235/// using [`FromLua`]. `Variadic<T>` can also be returned from a callback, returning a variable
236/// number of values to Lua.
237///
238/// The [`MultiValue`] type is equivalent to `Variadic<Value>`.
239///
240/// # Examples
241///
242/// ```
243/// # use mlua::{Lua, Result, Variadic};
244/// # fn main() -> Result<()> {
245/// # let lua = Lua::new();
246/// let add = lua.create_function(|_, vals: Variadic<f64>| -> Result<f64> {
247///     Ok(vals.iter().sum())
248/// })?;
249/// lua.globals().set("add", add)?;
250/// assert_eq!(lua.load("add(3, 2, 5)").eval::<f32>()?, 10.0);
251/// # Ok(())
252/// # }
253/// ```
254#[derive(Default, Debug, Clone)]
255pub struct Variadic<T>(Vec<T>);
256
257impl<T> Variadic<T> {
258    /// Creates an empty `Variadic` wrapper containing no values.
259    pub const fn new() -> Variadic<T> {
260        Variadic(Vec::new())
261    }
262
263    /// Creates an empty `Variadic` container with space for at least `capacity` elements.
264    pub fn with_capacity(capacity: usize) -> Variadic<T> {
265        Variadic(Vec::with_capacity(capacity))
266    }
267}
268
269impl<T> Deref for Variadic<T> {
270    type Target = Vec<T>;
271
272    fn deref(&self) -> &Self::Target {
273        &self.0
274    }
275}
276
277impl<T> DerefMut for Variadic<T> {
278    fn deref_mut(&mut self) -> &mut Self::Target {
279        &mut self.0
280    }
281}
282
283impl<T> From<Vec<T>> for Variadic<T> {
284    #[inline]
285    fn from(vec: Vec<T>) -> Self {
286        Variadic(vec)
287    }
288}
289
290impl<T> From<Variadic<T>> for Vec<T> {
291    #[inline]
292    fn from(value: Variadic<T>) -> Self {
293        value.0
294    }
295}
296
297impl<T> FromIterator<T> for Variadic<T> {
298    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
299        Variadic(Vec::from_iter(iter))
300    }
301}
302
303impl<T> IntoIterator for Variadic<T> {
304    type Item = T;
305    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
306
307    fn into_iter(self) -> Self::IntoIter {
308        self.0.into_iter()
309    }
310}
311
312impl<T: IntoLua> IntoLuaMulti for Variadic<T> {
313    #[inline]
314    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
315        MultiValue::from_lua_iter(lua, self)
316    }
317
318    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
319        let nresults = self.len() as i32;
320        check_stack(lua.state(), nresults + 1)?;
321        for value in self.0 {
322            value.push_into_stack(lua)?;
323        }
324        Ok(nresults)
325    }
326}
327
328impl<T: FromLua> FromLuaMulti for Variadic<T> {
329    #[inline]
330    fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
331        values
332            .drain(..)
333            .map(|val| T::from_lua(val, lua))
334            .collect::<Result<Vec<T>>>()
335            .map(Variadic)
336    }
337}
338
339macro_rules! impl_tuple {
340    () => (
341        impl IntoLuaMulti for () {
342            #[inline]
343            fn into_lua_multi(self, _: &Lua) -> Result<MultiValue> {
344                const { Ok(MultiValue::new()) }
345            }
346
347            #[inline]
348            unsafe fn push_into_stack_multi(self, _lua: &RawLua) -> Result<c_int> {
349                Ok(0)
350            }
351        }
352
353        impl FromLuaMulti for () {
354            #[inline]
355            fn from_lua_multi(_values: MultiValue, _lua: &Lua) -> Result<Self> {
356                Ok(())
357            }
358
359            #[inline]
360            unsafe fn from_stack_multi(_nvals: c_int, _lua: &RawLua) -> Result<Self> {
361                Ok(())
362            }
363        }
364    );
365
366    ($last:ident $($name:ident)*) => (
367        impl<$($name,)* $last> IntoLuaMulti for ($($name,)* $last,)
368            where $($name: IntoLua,)*
369                  $last: IntoLuaMulti
370        {
371            #[allow(unused_mut, non_snake_case)]
372            #[inline]
373            fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
374                let ($($name,)* $last,) = self;
375
376                let mut results = $last.into_lua_multi(lua)?;
377                push_reverse!(results, $($name.into_lua(lua)?,)*);
378                Ok(results)
379            }
380
381            #[allow(non_snake_case)]
382            #[inline]
383            unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
384                let ($($name,)* $last,) = self;
385                let mut nresults = 0;
386                $(
387                    _ = $name;
388                    nresults += 1;
389                )*
390                check_stack(lua.state(), nresults + 1)?;
391                $(
392                    $name.push_into_stack(lua)?;
393                )*
394                nresults += $last.push_into_stack_multi(lua)?;
395                Ok(nresults)
396            }
397        }
398
399        impl<$($name,)* $last> FromLuaMulti for ($($name,)* $last,)
400            where $($name: FromLua,)*
401                  $last: FromLuaMulti
402        {
403            #[allow(unused_mut, non_snake_case)]
404            #[inline]
405            fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
406                $(let $name = FromLua::from_lua(values.pop_front().unwrap_or(Nil), lua)?;)*
407                let $last = FromLuaMulti::from_lua_multi(values, lua)?;
408                Ok(($($name,)* $last,))
409            }
410
411            #[allow(unused_mut, non_snake_case)]
412            #[inline]
413            fn from_lua_args(mut args: MultiValue, mut i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
414                $(
415                    let $name = FromLua::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua)?;
416                    i += 1;
417                )*
418                let $last = FromLuaMulti::from_lua_args(args, i, to, lua)?;
419                Ok(($($name,)* $last,))
420            }
421
422            #[allow(unused_mut, non_snake_case)]
423            #[inline]
424            unsafe fn from_stack_multi(mut nvals: c_int, lua: &RawLua) -> Result<Self> {
425                $(
426                    let $name = if nvals > 0 {
427                        nvals -= 1;
428                        FromLua::from_stack(-(nvals + 1), lua)
429                    } else {
430                        FromLua::from_lua(Nil, lua.lua())
431                    }?;
432                )*
433                let $last = FromLuaMulti::from_stack_multi(nvals, lua)?;
434                Ok(($($name,)* $last,))
435            }
436
437            #[allow(unused_mut, non_snake_case)]
438            #[inline]
439            unsafe fn from_stack_args(mut nargs: c_int, mut i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
440                $(
441                    let $name = if nargs > 0 {
442                        nargs -= 1;
443                        FromLua::from_stack_arg(-(nargs + 1), i, to, lua)
444                    } else {
445                        FromLua::from_lua_arg(Nil, i, to, lua.lua())
446                    }?;
447                    i += 1;
448                )*
449                let $last = FromLuaMulti::from_stack_args(nargs, i, to, lua)?;
450                Ok(($($name,)* $last,))
451            }
452        }
453    );
454}
455
456macro_rules! push_reverse {
457    ($multi_value:expr, $first:expr, $($rest:expr,)*) => (
458        push_reverse!($multi_value, $($rest,)*);
459        $multi_value.push_front($first);
460    );
461
462    ($multi_value:expr, $first:expr) => (
463        $multi_value.push_front($first);
464    );
465
466    ($multi_value:expr,) => ();
467}
468
469impl_tuple!();
470impl_tuple!(A);
471impl_tuple!(A B);
472impl_tuple!(A B C);
473impl_tuple!(A B C D);
474impl_tuple!(A B C D E);
475impl_tuple!(A B C D E F);
476impl_tuple!(A B C D E F G);
477impl_tuple!(A B C D E F G H);
478impl_tuple!(A B C D E F G H I);
479impl_tuple!(A B C D E F G H I J);
480impl_tuple!(A B C D E F G H I J K);
481impl_tuple!(A B C D E F G H I J K L);
482impl_tuple!(A B C D E F G H I J K L M);
483impl_tuple!(A B C D E F G H I J K L M N);
484impl_tuple!(A B C D E F G H I J K L M N O);
485impl_tuple!(A B C D E F G H I J K L M N O P);
486
487#[cfg(test)]
488mod assertions {
489    use super::*;
490
491    #[cfg(not(feature = "send"))]
492    static_assertions::assert_not_impl_any!(MultiValue: Send);
493    #[cfg(feature = "send")]
494    static_assertions::assert_impl_all!(MultiValue: Send, Sync);
495}