1use std::os::raw::c_int;
2use std::string::String as StdString;
3use std::sync::Arc;
4
5use crate::error::{Error, Result};
6use crate::multi::MultiValue;
7use crate::private::Sealed;
8use crate::state::{Lua, RawLua};
9use crate::types::MaybeSend;
10use crate::util::{check_stack, short_type_name};
11use crate::value::Value;
12
13#[cfg(feature = "async")]
14use std::future::Future;
15
16pub trait IntoLua: Sized {
18 fn into_lua(self, lua: &Lua) -> Result<Value>;
20
21 #[doc(hidden)]
26 #[inline]
27 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
28 lua.push_value(&self.into_lua(lua.lua())?)
29 }
30}
31
32pub trait FromLua: Sized {
34 fn from_lua(value: Value, lua: &Lua) -> Result<Self>;
36
37 #[doc(hidden)]
42 #[inline]
43 fn from_lua_arg(arg: Value, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
44 Self::from_lua(arg, lua).map_err(|err| Error::BadArgument {
45 to: to.map(|s| s.to_string()),
46 pos: i,
47 name: None,
48 cause: Arc::new(err),
49 })
50 }
51
52 #[doc(hidden)]
54 #[inline]
55 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
56 Self::from_lua(lua.stack_value(idx, None), lua.lua())
57 }
58
59 #[doc(hidden)]
61 #[inline]
62 unsafe fn from_stack_arg(idx: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
63 Self::from_stack(idx, lua).map_err(|err| Error::BadArgument {
64 to: to.map(|s| s.to_string()),
65 pos: i,
66 name: None,
67 cause: Arc::new(err),
68 })
69 }
70}
71
72pub trait IntoLuaMulti: Sized {
77 fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue>;
79
80 #[doc(hidden)]
84 #[inline]
85 unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
86 let values = self.into_lua_multi(lua.lua())?;
87 let len: c_int = values.len().try_into().unwrap();
88 unsafe {
89 check_stack(lua.state(), len + 1)?;
90 for val in &values {
91 lua.push_value(val)?;
92 }
93 }
94 Ok(len)
95 }
96}
97
98pub trait FromLuaMulti: Sized {
104 fn from_lua_multi(values: MultiValue, lua: &Lua) -> Result<Self>;
111
112 #[doc(hidden)]
117 #[inline]
118 fn from_lua_args(args: MultiValue, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
119 let _ = (i, to);
120 Self::from_lua_multi(args, lua)
121 }
122
123 #[doc(hidden)]
125 #[inline]
126 unsafe fn from_stack_multi(nvals: c_int, lua: &RawLua) -> Result<Self> {
127 let mut values = MultiValue::with_capacity(nvals as usize);
128 for idx in 0..nvals {
129 values.push_back(lua.stack_value(-nvals + idx, None));
130 }
131 Self::from_lua_multi(values, lua.lua())
132 }
133
134 #[doc(hidden)]
136 #[inline]
137 unsafe fn from_stack_args(nargs: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
138 let _ = (i, to);
139 Self::from_stack_multi(nargs, lua)
140 }
141}
142
143pub trait ObjectLike: Sealed {
145 fn get<V: FromLua>(&self, key: impl IntoLua) -> Result<V>;
147
148 fn set(&self, key: impl IntoLua, value: impl IntoLua) -> Result<()>;
150
151 fn call<R>(&self, args: impl IntoLuaMulti) -> Result<R>
156 where
157 R: FromLuaMulti;
158
159 #[cfg(feature = "async")]
164 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
165 fn call_async<R>(&self, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
166 where
167 R: FromLuaMulti;
168
169 fn call_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
172 where
173 R: FromLuaMulti;
174
175 #[cfg(feature = "async")]
182 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
183 fn call_async_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
184 where
185 R: FromLuaMulti;
186
187 fn call_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
192 where
193 R: FromLuaMulti;
194
195 #[cfg(feature = "async")]
202 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
203 fn call_async_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
204 where
205 R: FromLuaMulti;
206
207 fn to_string(&self) -> Result<StdString>;
211}
212
213pub trait LuaNativeFn<A: FromLuaMulti> {
215 type Output: IntoLuaMulti;
216
217 fn call(&self, args: A) -> Self::Output;
218}
219
220pub trait LuaNativeFnMut<A: FromLuaMulti> {
222 type Output: IntoLuaMulti;
223
224 fn call(&mut self, args: A) -> Self::Output;
225}
226
227#[cfg(feature = "async")]
229pub trait LuaNativeAsyncFn<A: FromLuaMulti> {
230 type Output: IntoLuaMulti;
231
232 fn call(&self, args: A) -> impl Future<Output = Self::Output> + MaybeSend + 'static;
233}
234
235macro_rules! impl_lua_native_fn {
236 ($($A:ident),*) => {
237 impl<FN, $($A,)* R> LuaNativeFn<($($A,)*)> for FN
238 where
239 FN: Fn($($A,)*) -> R + MaybeSend + 'static,
240 ($($A,)*): FromLuaMulti,
241 R: IntoLuaMulti,
242 {
243 type Output = R;
244
245 #[allow(non_snake_case)]
246 fn call(&self, args: ($($A,)*)) -> Self::Output {
247 let ($($A,)*) = args;
248 self($($A,)*)
249 }
250 }
251
252 impl<FN, $($A,)* R> LuaNativeFnMut<($($A,)*)> for FN
253 where
254 FN: FnMut($($A,)*) -> R + MaybeSend + 'static,
255 ($($A,)*): FromLuaMulti,
256 R: IntoLuaMulti,
257 {
258 type Output = R;
259
260 #[allow(non_snake_case)]
261 fn call(&mut self, args: ($($A,)*)) -> Self::Output {
262 let ($($A,)*) = args;
263 self($($A,)*)
264 }
265 }
266
267 #[cfg(feature = "async")]
268 impl<FN, $($A,)* Fut, R> LuaNativeAsyncFn<($($A,)*)> for FN
269 where
270 FN: Fn($($A,)*) -> Fut + MaybeSend + 'static,
271 ($($A,)*): FromLuaMulti,
272 Fut: Future<Output = R> + MaybeSend + 'static,
273 R: IntoLuaMulti,
274 {
275 type Output = R;
276
277 #[allow(non_snake_case)]
278 fn call(&self, args: ($($A,)*)) -> impl Future<Output = Self::Output> + MaybeSend + 'static {
279 let ($($A,)*) = args;
280 self($($A,)*)
281 }
282 }
283 };
284}
285
286impl_lua_native_fn!();
287impl_lua_native_fn!(A);
288impl_lua_native_fn!(A, B);
289impl_lua_native_fn!(A, B, C);
290impl_lua_native_fn!(A, B, C, D);
291impl_lua_native_fn!(A, B, C, D, E);
292impl_lua_native_fn!(A, B, C, D, E, F);
293impl_lua_native_fn!(A, B, C, D, E, F, G);
294impl_lua_native_fn!(A, B, C, D, E, F, G, H);
295impl_lua_native_fn!(A, B, C, D, E, F, G, H, I);
296impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J);
297impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K);
298impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L);
299impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M);
300impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
301impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
302impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
303
304pub(crate) trait ShortTypeName {
305 #[inline(always)]
306 fn type_name() -> StdString {
307 short_type_name::<Self>()
308 }
309}
310
311impl<T> ShortTypeName for T {}