Skip to main content

luaur_rt/
traits.rs

1//! The conversion traits. Mirror `mlua::{IntoLua, FromLua, IntoLuaMulti,
2//! FromLuaMulti}`.
3//!
4//! These are simplified relative to mlua: mlua's traits carry extra
5//! stack-oriented methods (`push_into_stack`, `from_stack`, ...) for its FFI
6//! fast paths. Since luaur is a pure-Rust engine we route everything through
7//! the safe [`Value`] / [`MultiValue`] representation, so our traits only need
8//! the value-level methods. The public method *names and shapes*
9//! (`into_lua(self, &Lua)`, `from_lua(value, &Lua)`,
10//! `into_lua_multi`, `from_lua_multi`) match mlua exactly.
11
12use crate::error::Result;
13use crate::multi::MultiValue;
14use crate::state::Lua;
15use crate::value::Value;
16
17/// Convert a Rust value into a single Lua [`Value`].
18///
19/// Mirrors `mlua::IntoLua`.
20pub trait IntoLua: Sized {
21    /// Perform the conversion.
22    fn into_lua(self, lua: &Lua) -> Result<Value>;
23}
24
25/// Convert a single Lua [`Value`] into a Rust value.
26///
27/// Mirrors `mlua::FromLua`.
28pub trait FromLua: Sized {
29    /// Perform the conversion.
30    fn from_lua(value: Value, lua: &Lua) -> Result<Self>;
31
32    /// Convert an argument at 1-based position `i`. The default forwards to
33    /// [`FromLua::from_lua`]; specific impls can produce nicer messages.
34    /// Mirrors `mlua::FromLua::from_lua_arg`.
35    fn from_lua_arg(arg: Value, _i: usize, _to: Option<&str>, lua: &Lua) -> Result<Self> {
36        Self::from_lua(arg, lua)
37    }
38}
39
40/// Convert a Rust value into a sequence of Lua values (multiple returns / args).
41///
42/// Mirrors `mlua::IntoLuaMulti`.
43pub trait IntoLuaMulti: Sized {
44    /// Perform the conversion.
45    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue>;
46}
47
48/// Convert a sequence of Lua values into a Rust value.
49///
50/// Mirrors `mlua::FromLuaMulti`.
51pub trait FromLuaMulti: Sized {
52    /// Perform the conversion.
53    fn from_lua_multi(values: MultiValue, lua: &Lua) -> Result<Self>;
54}
55
56// Any single-value type is trivially a multi-value of length one.
57impl<T: IntoLua> IntoLuaMulti for T {
58    fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
59        let mut m = MultiValue::with_capacity(1);
60        m.push_back(self.into_lua(lua)?);
61        Ok(m)
62    }
63}
64
65// And any single-value type can be parsed from the first of a multi-value
66// (extra values are ignored, matching Lua's "take what you need" calling
67// convention).
68impl<T: FromLua> FromLuaMulti for T {
69    fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
70        let v = values.pop_front().unwrap_or(Value::Nil);
71        T::from_lua(v, lua)
72    }
73}