ezlua/
macros.rs

1/// Helper macro to create lua module
2#[cfg(not(feature = "vendored"))]
3#[macro_export]
4macro_rules! lua_module {
5    ($name:ident, $init:expr) => {
6        #[no_mangle]
7        pub unsafe extern "C-unwind" fn $name(l: *mut $crate::ffi::lua_State) -> i32 {
8            $crate::convert::module_function_wrapper($init)(l)
9        }
10    };
11}
12
13/// Helper macro to create lua module
14#[cfg(feature = "vendored")]
15#[macro_export]
16macro_rules! lua_module {
17    ($name:ident, $init:expr) => {
18        compile_error!("Feature `vendored` should be not enabled when crate build as a lua module");
19    };
20}
21
22/// Helper macro to `impl ToLua` for serializable types easily
23///
24/// ```rust
25/// use elua::prelude::*;
26/// use serde::{Deserialize, Serialize};
27///
28/// #[derive(Debug, Default, Deserialize, Serialize)]
29/// struct Config {
30///     name: String,
31///     path: String,
32///     timeout: u64,
33///     // ...
34/// }
35///
36/// ezlua::impl_tolua_as_serde!(Config);
37///
38/// let lua = Lua::with_open_libs();
39/// lua.global().set("config", Config::default())?;
40/// // config in lua is `{name = '', path = '', timeout = 0}`
41/// ```
42#[cfg(feature = "serde")]
43#[macro_export]
44macro_rules! impl_tolua_as_serde {
45    ($t:ty) => {
46        impl $crate::prelude::ToLua for $t {
47            fn to_lua<'a>(
48                self,
49                lua: &'a $crate::prelude::LuaState,
50            ) -> $crate::prelude::LuaResult<$crate::prelude::ValRef<'a>> {
51                $crate::prelude::ToLua::to_lua($crate::serde::SerdeValue(self), lua)
52            }
53        }
54    };
55}
56
57/// Helper macro to `impl FromLua` for serializable types easily
58///
59/// ```rust
60/// use serde::{Deserialize, Serialize};
61///
62/// #[derive(Debug, Default, Deserialize, Serialize)]
63/// struct Config {
64///     name: String,
65///     path: String,
66///     timeout: u64,
67///     // ...
68/// }
69///
70/// ezlua::impl_fromlua_as_serde!(Config);
71///
72/// let lua = Lua::with_open_libs();
73/// lua.global().set_closure("set_config", |config: Config| {
74///     println!("{config:?}");
75/// })?;
76/// lua.do_string("set_config({name = 'test', path = '/', timeout = 0})", None)?;
77/// // will print `Config { name: "test", path: "/", timeout: 0 }`
78/// ```
79#[cfg(feature = "serde")]
80#[macro_export]
81macro_rules! impl_fromlua_as_serde {
82    ($t:ty) => {
83        impl $crate::prelude::FromLua<'_> for $t {
84            fn from_lua(
85                lua: &$crate::prelude::LuaState,
86                val: $crate::prelude::ValRef,
87            ) -> $crate::prelude::LuaResult<Self> {
88                <$crate::serde::SerdeValue<Self> as $crate::prelude::FromLua>::from_lua(lua, val)
89                    .map(|s| s.0)
90            }
91        }
92    };
93
94    (owned $t:ty) => {
95        impl $crate::prelude::FromLua<'_> for $t {
96            fn from_lua(
97                lua: &$crate::prelude::LuaState,
98                val: $crate::prelude::ValRef,
99            ) -> $crate::prelude::LuaResult<Self> {
100                <$crate::serde::SerdeOwnedValue<Self> as $crate::prelude::FromLua>::from_lua(
101                    lua, val,
102                )
103                .map(|s| s.0)
104            }
105        }
106    };
107}
108
109/// Helper macro to `impl ToLuaMulti` for types which can convert to another type implemented ToLuaMulti easily
110///
111/// ```rust
112/// use std::process::{Command, ExitStatus};
113///
114/// struct CmdExitStatus(ExitStatus);
115///
116/// ezlua::impl_toluamulti! {
117///     CmdExitStatus as (bool, Option<i32>): |self| (self.0.success(), self.0.code())
118/// }
119///
120/// lua.global()
121///     .set_closure("execute", |cmd: &str, args: MultiRet<&str>| {
122///         Command::new(cmd).args(args.0).status().map(CmdExitStatus)
123///     })?;
124/// lua.do_string("print(execute('ls', '-l'))", None)?; // true 0
125/// ```
126#[macro_export]
127macro_rules! impl_toluamulti {
128    ($t:ty as $as:ty: |$self:ident| $map:expr) => {
129        impl $crate::prelude::ToLuaMulti for $t {
130            const VALUE_COUNT: Option<usize> = <$as as $crate::prelude::ToLuaMulti>::VALUE_COUNT;
131
132            fn push_multi(
133                $self,
134                lua: &$crate::prelude::LuaState,
135            ) -> $crate::prelude::LuaResult<usize> {
136                $crate::prelude::ToLuaMulti::push_multi($map, lua)
137            }
138        }
139    };
140}
141
142#[macro_export]
143macro_rules! impl_fromlua_as_bitflags {
144    ($t:ty) => {
145        impl $crate::prelude::FromLua<'_> for $t {
146            fn from_lua(
147                lua: &$crate::prelude::LuaState,
148                val: $crate::prelude::ValRef,
149            ) -> $crate::prelude::LuaResult<Self> {
150                <$crate::marker::BitFlags<Self> as $crate::prelude::FromLua>::from_lua(lua, val)
151                    .map(|s| s.0)
152            }
153        }
154    };
155}
156
157#[macro_export]
158macro_rules! impl_tolua_as_bitflags {
159    ($t:ty) => {
160        impl $crate::prelude::ToLua for $t {
161            fn to_lua<'a>(
162                self,
163                lua: &'a $crate::prelude::LuaState,
164            ) -> $crate::prelude::LuaResult<$crate::prelude::ValRef<'a>> {
165                $crate::prelude::ToLua::to_lua($crate::marker::BitFlags(self), lua)
166            }
167        }
168    };
169}
170
171#[macro_export]
172macro_rules! bitflags_table {
173    ($fn:ident => $t:ty) => {
174        fn $fn(
175            lua: &$crate::prelude::LuaState,
176        ) -> $crate::prelude::LuaResult<$crate::prelude::LuaTable> {
177            use ::bitflags::Flag;
178
179            let t = lua.new_table()?;
180            for flag in <$t as ::bitflags::Flags>::FLAGS {
181                t.set(flag.name(), flag.value().bits())?;
182                t.set(flag.value().bits(), flag.name())?;
183            }
184            $crate::prelude::LuaResult::Ok(t)
185        }
186    };
187}
188
189#[macro_export]
190macro_rules! enum_table {
191    ($fn:ident => $(($t:expr, $v:expr),)+) => {
192        fn $fn(
193            lua: &$crate::prelude::LuaState,
194        ) -> $crate::prelude::LuaResult<$crate::prelude::LuaTable> {
195            let t = lua.new_table()?;
196            $(t.set($t, $v)?;)+
197            $(t.set($v, $t)?;)+
198            $crate::prelude::LuaResult::Ok(t)
199        }
200    };
201}