mlua_codemp_patch/
multi.rs

1use std::iter::FromIterator;
2use std::ops::{Deref, DerefMut};
3use std::os::raw::c_int;
4use std::result::Result as StdResult;
5
6use crate::error::Result;
7use crate::state::{Lua, RawLua};
8use crate::util::check_stack;
9use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil};
10
11/// Result is convertible to `MultiValue` following the common Lua idiom of returning the result
12/// on success, or in the case of an error, returning `nil` and an error message.
13impl<T: IntoLua, E: IntoLua> IntoLuaMulti for StdResult<T, E> {
14    #[inline]
15    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
16        match self {
17            Ok(val) => (val,).into_lua_multi(lua),
18            Err(err) => (Nil, err).into_lua_multi(lua),
19        }
20    }
21
22    #[inline]
23    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
24        match self {
25            Ok(val) => (val,).push_into_stack_multi(lua),
26            Err(err) => (Nil, err).push_into_stack_multi(lua),
27        }
28    }
29}
30
31impl<E: IntoLua> IntoLuaMulti for StdResult<(), E> {
32    #[inline]
33    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
34        match self {
35            Ok(_) => const { Ok(MultiValue::new()) },
36            Err(err) => (Nil, err).into_lua_multi(lua),
37        }
38    }
39
40    #[inline]
41    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
42        match self {
43            Ok(_) => Ok(0),
44            Err(err) => (Nil, err).push_into_stack_multi(lua),
45        }
46    }
47}
48
49impl<T: IntoLua> IntoLuaMulti for T {
50    #[inline]
51    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
52        let mut v = MultiValue::with_capacity(1);
53        v.push_back(self.into_lua(lua)?);
54        Ok(v)
55    }
56
57    #[inline]
58    unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
59        self.push_into_stack(lua)?;
60        Ok(1)
61    }
62}
63
64impl<T: FromLua> FromLuaMulti for T {
65    #[inline]
66    fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
67        T::from_lua(values.pop_front().unwrap_or(Nil), lua)
68    }
69
70    #[inline]
71    fn from_lua_args(mut args: MultiValue, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
72        T::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua)
73    }
74
75    #[inline]
76    unsafe fn from_stack_multi(nvals: c_int, lua: &RawLua) -> Result<Self> {
77        if nvals == 0 {
78            return T::from_lua(Nil, lua.lua());
79        }
80        T::from_stack(-nvals, lua)
81    }
82
83    #[inline]
84    unsafe fn from_stack_args(nargs: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
85        if nargs == 0 {
86            return T::from_lua_arg(Nil, i, to, lua.lua());
87        }
88        T::from_stack_arg(-nargs, i, to, lua)
89    }
90}
91
92impl IntoLuaMulti for MultiValue {
93    #[inline]
94    fn into_lua_multi(self, _: &Lua) -> Result<MultiValue> {
95        Ok(self)
96    }
97}
98
99impl FromLuaMulti for MultiValue {
100    #[inline]
101    fn from_lua_multi(values: MultiValue, _: &Lua) -> Result<Self> {
102        Ok(values)
103    }
104}
105
106/// Wraps a variable number of `T`s.
107///
108/// Can be used to work with variadic functions more easily. Using this type as the last argument of
109/// a Rust callback will accept any number of arguments from Lua and convert them to the type `T`
110/// using [`FromLua`]. `Variadic<T>` can also be returned from a callback, returning a variable
111/// number of values to Lua.
112///
113/// The [`MultiValue`] type is equivalent to `Variadic<Value>`.
114///
115/// # Examples
116///
117/// ```
118/// # use mlua::{Lua, Result, Variadic};
119/// # fn main() -> Result<()> {
120/// # let lua = Lua::new();
121/// let add = lua.create_function(|_, vals: Variadic<f64>| -> Result<f64> {
122///     Ok(vals.iter().sum())
123/// })?;
124/// lua.globals().set("add", add)?;
125/// assert_eq!(lua.load("add(3, 2, 5)").eval::<f32>()?, 10.0);
126/// # Ok(())
127/// # }
128/// ```
129///
130/// [`FromLua`]: crate::FromLua
131/// [`MultiValue`]: crate::MultiValue
132#[derive(Debug, Clone)]
133pub struct Variadic<T>(Vec<T>);
134
135impl<T> Variadic<T> {
136    /// Creates an empty `Variadic` wrapper containing no values.
137    pub const fn new() -> Variadic<T> {
138        Variadic(Vec::new())
139    }
140}
141
142impl<T> Default for Variadic<T> {
143    fn default() -> Variadic<T> {
144        const { Variadic::new() }
145    }
146}
147
148impl<T> FromIterator<T> for Variadic<T> {
149    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
150        Variadic(Vec::from_iter(iter))
151    }
152}
153
154impl<T> IntoIterator for Variadic<T> {
155    type Item = T;
156    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
157
158    fn into_iter(self) -> Self::IntoIter {
159        self.0.into_iter()
160    }
161}
162
163impl<T> Deref for Variadic<T> {
164    type Target = Vec<T>;
165
166    fn deref(&self) -> &Self::Target {
167        &self.0
168    }
169}
170
171impl<T> DerefMut for Variadic<T> {
172    fn deref_mut(&mut self) -> &mut Self::Target {
173        &mut self.0
174    }
175}
176
177impl<T: IntoLua> IntoLuaMulti for Variadic<T> {
178    #[inline]
179    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
180        MultiValue::from_lua_iter(lua, self)
181    }
182}
183
184impl<T: FromLua> FromLuaMulti for Variadic<T> {
185    #[inline]
186    fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
187        values
188            .drain(..)
189            .map(|val| T::from_lua(val, lua))
190            .collect::<Result<Vec<T>>>()
191            .map(Variadic)
192    }
193}
194
195macro_rules! impl_tuple {
196    () => (
197        impl IntoLuaMulti for () {
198            #[inline]
199            fn into_lua_multi(self, _: &Lua) -> Result<MultiValue> {
200                const { Ok(MultiValue::new()) }
201            }
202
203            #[inline]
204            unsafe fn push_into_stack_multi(self, _lua: &RawLua) -> Result<c_int> {
205                Ok(0)
206            }
207        }
208
209        impl FromLuaMulti for () {
210            #[inline]
211            fn from_lua_multi(_values: MultiValue, _lua: &Lua) -> Result<Self> {
212                Ok(())
213            }
214
215            #[inline]
216            unsafe fn from_stack_multi(nvals: c_int, lua: &RawLua) -> Result<Self> {
217                if nvals > 0 {
218                    ffi::lua_pop(lua.state(), nvals);
219                }
220                Ok(())
221            }
222        }
223    );
224
225    ($last:ident $($name:ident)*) => (
226        impl<$($name,)* $last> IntoLuaMulti for ($($name,)* $last,)
227            where $($name: IntoLua,)*
228                  $last: IntoLuaMulti
229        {
230            #[allow(unused_mut, non_snake_case)]
231            #[inline]
232            fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
233                let ($($name,)* $last,) = self;
234
235                let mut results = $last.into_lua_multi(lua)?;
236                push_reverse!(results, $($name.into_lua(lua)?,)*);
237                Ok(results)
238            }
239
240            #[allow(non_snake_case)]
241            #[inline]
242            unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
243                let ($($name,)* $last,) = self;
244                let mut nresults = 0;
245                $(
246                    _ = $name;
247                    nresults += 1;
248                )*
249                check_stack(lua.state(), nresults + 1)?;
250                $(
251                    $name.push_into_stack(lua)?;
252                )*
253                nresults += $last.push_into_stack_multi(lua)?;
254                Ok(nresults)
255            }
256        }
257
258        impl<$($name,)* $last> FromLuaMulti for ($($name,)* $last,)
259            where $($name: FromLua,)*
260                  $last: FromLuaMulti
261        {
262            #[allow(unused_mut, non_snake_case)]
263            #[inline]
264            fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
265                $(let $name = FromLua::from_lua(values.pop_front().unwrap_or(Nil), lua)?;)*
266                let $last = FromLuaMulti::from_lua_multi(values, lua)?;
267                Ok(($($name,)* $last,))
268            }
269
270            #[allow(unused_mut, non_snake_case)]
271            #[inline]
272            fn from_lua_args(mut args: MultiValue, mut i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
273                $(
274                    let $name = FromLua::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua)?;
275                    i += 1;
276                )*
277                let $last = FromLuaMulti::from_lua_args(args, i, to, lua)?;
278                Ok(($($name,)* $last,))
279            }
280
281            #[allow(unused_mut, non_snake_case)]
282            #[inline]
283            unsafe fn from_stack_multi(mut nvals: c_int, lua: &RawLua) -> Result<Self> {
284                $(
285                    let $name = if nvals > 0 {
286                        nvals -= 1;
287                        FromLua::from_stack(-(nvals + 1), lua)
288                    } else {
289                        FromLua::from_lua(Nil, lua.lua())
290                    }?;
291                )*
292                let $last = FromLuaMulti::from_stack_multi(nvals, lua)?;
293                Ok(($($name,)* $last,))
294            }
295
296            #[allow(unused_mut, non_snake_case)]
297            #[inline]
298            unsafe fn from_stack_args(mut nargs: c_int, mut i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
299                $(
300                    let $name = if nargs > 0 {
301                        nargs -= 1;
302                        FromLua::from_stack_arg(-(nargs + 1), i, to, lua)
303                    } else {
304                        FromLua::from_lua_arg(Nil, i, to, lua.lua())
305                    }?;
306                    i += 1;
307                )*
308                let $last = FromLuaMulti::from_stack_args(nargs, i, to, lua)?;
309                Ok(($($name,)* $last,))
310            }
311        }
312    );
313}
314
315macro_rules! push_reverse {
316    ($multi_value:expr, $first:expr, $($rest:expr,)*) => (
317        push_reverse!($multi_value, $($rest,)*);
318        $multi_value.push_front($first);
319    );
320
321    ($multi_value:expr, $first:expr) => (
322        $multi_value.push_front($first);
323    );
324
325    ($multi_value:expr,) => ();
326}
327
328impl_tuple!();
329impl_tuple!(A);
330impl_tuple!(A B);
331impl_tuple!(A B C);
332impl_tuple!(A B C D);
333impl_tuple!(A B C D E);
334impl_tuple!(A B C D E F);
335impl_tuple!(A B C D E F G);
336impl_tuple!(A B C D E F G H);
337impl_tuple!(A B C D E F G H I);
338impl_tuple!(A B C D E F G H I J);
339impl_tuple!(A B C D E F G H I J K);
340impl_tuple!(A B C D E F G H I J K L);
341impl_tuple!(A B C D E F G H I J K L M);
342impl_tuple!(A B C D E F G H I J K L M N);
343impl_tuple!(A B C D E F G H I J K L M N O);
344impl_tuple!(A B C D E F G H I J K L M N O P);