1use std::os::raw::c_int;
2use std::sync::Arc;
3
4use crate::error::{Error, Result};
5use crate::multi::MultiValue;
6use crate::private::Sealed;
7use crate::state::{Lua, RawLua, WeakLua};
8use crate::types::MaybeSend;
9use crate::util::{check_stack, parse_lookup_path, short_type_name};
10use crate::value::Value;
11
12#[cfg(feature = "async")]
13use {crate::function::AsyncCallFuture, std::future::Future};
14
15pub trait IntoLua: Sized {
17 fn into_lua(self, lua: &Lua) -> Result<Value>;
19
20 #[doc(hidden)]
25 #[inline]
26 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
27 lua.push_value(&self.into_lua(lua.lua())?)
28 }
29}
30
31pub trait FromLua: Sized {
33 fn from_lua(value: Value, lua: &Lua) -> Result<Self>;
35
36 #[doc(hidden)]
41 #[inline]
42 fn from_lua_arg(arg: Value, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
43 Self::from_lua(arg, lua).map_err(|err| Error::BadArgument {
44 to: to.map(|s| s.to_string()),
45 pos: i,
46 name: None,
47 cause: Arc::new(err),
48 })
49 }
50
51 #[doc(hidden)]
53 #[inline]
54 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
55 Self::from_lua(lua.stack_value(idx, None), lua.lua())
56 }
57
58 #[doc(hidden)]
60 #[inline]
61 unsafe fn from_stack_arg(idx: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
62 Self::from_stack(idx, lua).map_err(|err| Error::BadArgument {
63 to: to.map(|s| s.to_string()),
64 pos: i,
65 name: None,
66 cause: Arc::new(err),
67 })
68 }
69}
70
71pub trait IntoLuaMulti: Sized {
76 fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue>;
78
79 #[doc(hidden)]
83 #[inline]
84 unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> {
85 let values = self.into_lua_multi(lua.lua())?;
86 let len: c_int = values.len().try_into().unwrap();
87 unsafe {
88 check_stack(lua.state(), len + 1)?;
89 for val in &values {
90 lua.push_value(val)?;
91 }
92 }
93 Ok(len)
94 }
95}
96
97pub trait FromLuaMulti: Sized {
103 fn from_lua_multi(values: MultiValue, lua: &Lua) -> Result<Self>;
110
111 #[doc(hidden)]
116 #[inline]
117 fn from_lua_args(args: MultiValue, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
118 let _ = (i, to);
119 Self::from_lua_multi(args, lua)
120 }
121
122 #[doc(hidden)]
124 #[inline]
125 unsafe fn from_stack_multi(nvals: c_int, lua: &RawLua) -> Result<Self> {
126 let mut values = MultiValue::with_capacity(nvals as usize);
127 for idx in 0..nvals {
128 values.push_back(lua.stack_value(-nvals + idx, None));
129 }
130 Self::from_lua_multi(values, lua.lua())
131 }
132
133 #[doc(hidden)]
135 #[inline]
136 unsafe fn from_stack_args(nargs: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> {
137 let _ = (i, to);
138 Self::from_stack_multi(nargs, lua)
139 }
140}
141
142pub trait ObjectLike: Sealed {
144 fn get<V: FromLua>(&self, key: impl IntoLua) -> Result<V>;
146
147 fn set(&self, key: impl IntoLua, value: impl IntoLua) -> Result<()>;
149
150 fn call<R>(&self, args: impl IntoLuaMulti) -> Result<R>
155 where
156 R: FromLuaMulti;
157
158 #[cfg(feature = "async")]
163 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
164 fn call_async<R>(&self, args: impl IntoLuaMulti) -> AsyncCallFuture<R>
165 where
166 R: FromLuaMulti;
167
168 fn call_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
171 where
172 R: FromLuaMulti;
173
174 #[cfg(feature = "async")]
179 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
180 fn call_async_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> AsyncCallFuture<R>
181 where
182 R: FromLuaMulti;
183
184 fn call_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
189 where
190 R: FromLuaMulti;
191
192 #[cfg(feature = "async")]
197 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
198 fn call_async_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> AsyncCallFuture<R>
199 where
200 R: FromLuaMulti;
201
202 fn get_path<V: FromLua>(&self, path: &str) -> Result<V> {
215 let mut current = self.to_value();
216 for (key, safe_nil) in parse_lookup_path(path)? {
217 current = match current {
218 Value::Table(table) => table.get::<Value>(key),
219 Value::UserData(ud) => ud.get::<Value>(key),
220 _ => {
221 let type_name = current.type_name();
222 let err = format!("attempt to index a {type_name} value with key '{key}'");
223 Err(Error::runtime(err))
224 }
225 }?;
226 if safe_nil && (current == Value::Nil || current == Value::NULL) {
227 break;
228 }
229 }
230
231 let lua = self.weak_lua().lock();
232 V::from_lua(current, lua.lua())
233 }
234
235 fn to_string(&self) -> Result<String>;
239
240 fn to_value(&self) -> Value;
242
243 #[doc(hidden)]
245 fn weak_lua(&self) -> &WeakLua;
246}
247
248pub trait LuaNativeFn<A: FromLuaMulti> {
250 type Output: IntoLuaMulti;
251
252 fn call(&self, args: A) -> Self::Output;
253}
254
255pub trait LuaNativeFnMut<A: FromLuaMulti> {
257 type Output: IntoLuaMulti;
258
259 fn call(&mut self, args: A) -> Self::Output;
260}
261
262#[cfg(feature = "async")]
264pub trait LuaNativeAsyncFn<A: FromLuaMulti> {
265 type Output: IntoLuaMulti;
266
267 fn call(&self, args: A) -> impl Future<Output = Self::Output> + MaybeSend + 'static;
268}
269
270macro_rules! impl_lua_native_fn {
271 ($($A:ident),*) => {
272 impl<FN, $($A,)* R> LuaNativeFn<($($A,)*)> for FN
273 where
274 FN: Fn($($A,)*) -> R + MaybeSend + 'static,
275 ($($A,)*): FromLuaMulti,
276 R: IntoLuaMulti,
277 {
278 type Output = R;
279
280 #[allow(non_snake_case)]
281 fn call(&self, args: ($($A,)*)) -> Self::Output {
282 let ($($A,)*) = args;
283 self($($A,)*)
284 }
285 }
286
287 impl<FN, $($A,)* R> LuaNativeFnMut<($($A,)*)> for FN
288 where
289 FN: FnMut($($A,)*) -> R + MaybeSend + 'static,
290 ($($A,)*): FromLuaMulti,
291 R: IntoLuaMulti,
292 {
293 type Output = R;
294
295 #[allow(non_snake_case)]
296 fn call(&mut self, args: ($($A,)*)) -> Self::Output {
297 let ($($A,)*) = args;
298 self($($A,)*)
299 }
300 }
301
302 #[cfg(feature = "async")]
303 impl<FN, $($A,)* Fut, R> LuaNativeAsyncFn<($($A,)*)> for FN
304 where
305 FN: Fn($($A,)*) -> Fut + MaybeSend + 'static,
306 ($($A,)*): FromLuaMulti,
307 Fut: Future<Output = R> + MaybeSend + 'static,
308 R: IntoLuaMulti,
309 {
310 type Output = R;
311
312 #[allow(non_snake_case)]
313 fn call(&self, args: ($($A,)*)) -> impl Future<Output = Self::Output> + MaybeSend + 'static {
314 let ($($A,)*) = args;
315 self($($A,)*)
316 }
317 }
318 };
319}
320
321impl_lua_native_fn!();
322impl_lua_native_fn!(A);
323impl_lua_native_fn!(A, B);
324impl_lua_native_fn!(A, B, C);
325impl_lua_native_fn!(A, B, C, D);
326impl_lua_native_fn!(A, B, C, D, E);
327impl_lua_native_fn!(A, B, C, D, E, F);
328impl_lua_native_fn!(A, B, C, D, E, F, G);
329impl_lua_native_fn!(A, B, C, D, E, F, G, H);
330impl_lua_native_fn!(A, B, C, D, E, F, G, H, I);
331impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J);
332impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K);
333impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L);
334impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M);
335impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
336impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
337impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
338
339pub(crate) trait ShortTypeName {
340 #[inline(always)]
341 fn type_name() -> String {
342 short_type_name::<Self>()
343 }
344}
345
346impl<T> ShortTypeName for T {}