Skip to main content

mlua/
multi.rs

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