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, WeakLua};
9use crate::types::MaybeSend;
10use crate::util::{check_stack, parse_lookup_path, short_type_name};
11use crate::value::Value;
12
13#[cfg(feature = "async")]
14use {crate::function::AsyncCallFuture, 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) -> AsyncCallFuture<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")]
180 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
181 fn call_async_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> AsyncCallFuture<R>
182 where
183 R: FromLuaMulti;
184
185 fn call_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
190 where
191 R: FromLuaMulti;
192
193 #[cfg(feature = "async")]
198 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
199 fn call_async_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> AsyncCallFuture<R>
200 where
201 R: FromLuaMulti;
202
203 fn get_path<V: FromLua>(&self, path: &str) -> Result<V> {
216 let mut current = self.to_value();
217 for (key, safe_nil) in parse_lookup_path(path)? {
218 current = match current {
219 Value::Table(table) => table.get::<Value>(key),
220 Value::UserData(ud) => ud.get::<Value>(key),
221 _ => {
222 let type_name = current.type_name();
223 let err = format!("attempt to index a {type_name} value with key '{key}'");
224 Err(Error::runtime(err))
225 }
226 }?;
227 if safe_nil && (current == Value::Nil || current == Value::NULL) {
228 break;
229 }
230 }
231
232 let lua = self.weak_lua().lock();
233 V::from_lua(current, lua.lua())
234 }
235
236 fn to_string(&self) -> Result<StdString>;
240
241 fn to_value(&self) -> Value;
243
244 #[doc(hidden)]
246 fn weak_lua(&self) -> &WeakLua;
247}
248
249pub trait LuaNativeFn<A: FromLuaMulti> {
251 type Output: IntoLuaMulti;
252
253 fn call(&self, args: A) -> Self::Output;
254}
255
256pub trait LuaNativeFnMut<A: FromLuaMulti> {
258 type Output: IntoLuaMulti;
259
260 fn call(&mut self, args: A) -> Self::Output;
261}
262
263#[cfg(feature = "async")]
265pub trait LuaNativeAsyncFn<A: FromLuaMulti> {
266 type Output: IntoLuaMulti;
267
268 fn call(&self, args: A) -> impl Future<Output = Self::Output> + MaybeSend + 'static;
269}
270
271macro_rules! impl_lua_native_fn {
272 ($($A:ident),*) => {
273 impl<FN, $($A,)* R> LuaNativeFn<($($A,)*)> for FN
274 where
275 FN: Fn($($A,)*) -> R + MaybeSend + 'static,
276 ($($A,)*): FromLuaMulti,
277 R: IntoLuaMulti,
278 {
279 type Output = R;
280
281 #[allow(non_snake_case)]
282 fn call(&self, args: ($($A,)*)) -> Self::Output {
283 let ($($A,)*) = args;
284 self($($A,)*)
285 }
286 }
287
288 impl<FN, $($A,)* R> LuaNativeFnMut<($($A,)*)> for FN
289 where
290 FN: FnMut($($A,)*) -> R + MaybeSend + 'static,
291 ($($A,)*): FromLuaMulti,
292 R: IntoLuaMulti,
293 {
294 type Output = R;
295
296 #[allow(non_snake_case)]
297 fn call(&mut self, args: ($($A,)*)) -> Self::Output {
298 let ($($A,)*) = args;
299 self($($A,)*)
300 }
301 }
302
303 #[cfg(feature = "async")]
304 impl<FN, $($A,)* Fut, R> LuaNativeAsyncFn<($($A,)*)> for FN
305 where
306 FN: Fn($($A,)*) -> Fut + MaybeSend + 'static,
307 ($($A,)*): FromLuaMulti,
308 Fut: Future<Output = R> + MaybeSend + 'static,
309 R: IntoLuaMulti,
310 {
311 type Output = R;
312
313 #[allow(non_snake_case)]
314 fn call(&self, args: ($($A,)*)) -> impl Future<Output = Self::Output> + MaybeSend + 'static {
315 let ($($A,)*) = args;
316 self($($A,)*)
317 }
318 }
319 };
320}
321
322impl_lua_native_fn!();
323impl_lua_native_fn!(A);
324impl_lua_native_fn!(A, B);
325impl_lua_native_fn!(A, B, C);
326impl_lua_native_fn!(A, B, C, D);
327impl_lua_native_fn!(A, B, C, D, E);
328impl_lua_native_fn!(A, B, C, D, E, F);
329impl_lua_native_fn!(A, B, C, D, E, F, G);
330impl_lua_native_fn!(A, B, C, D, E, F, G, H);
331impl_lua_native_fn!(A, B, C, D, E, F, G, H, I);
332impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J);
333impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K);
334impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L);
335impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M);
336impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
337impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
338impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
339
340pub(crate) trait ShortTypeName {
341 #[inline(always)]
342 fn type_name() -> StdString {
343 short_type_name::<Self>()
344 }
345}
346
347impl<T> ShortTypeName for T {}