tlua/
lib.rs

1#![allow(clippy::let_and_return)]
2#![allow(clippy::approx_constant)]
3#![allow(clippy::needless_return)]
4#![allow(clippy::redundant_closure_call)]
5#![allow(clippy::len_without_is_empty)]
6#![allow(clippy::unnecessary_cast)]
7//! High-level zero-cost bindings for Lua (fork of
8//! [hlua](https://crates.io/crates/hlua))
9//!
10//! Lua is an interpreted programming language. This crate allows you to execute Lua code.
11//!
12//! # General usage
13//!
14//! In order to execute Lua code you first need a *Lua context*, which is represented in this
15//! library with [the `Lua` struct](struct.Lua.html). You can then call the
16//! the [`eval`](struct.Lua.html#method.eval) or
17//! [`exec`](struct.Lua.html#method.exec) method on this object.
18//!
19//! For example:
20//!
21//! ```no_run
22//! use tlua::Lua;
23//!
24//! let mut lua = Lua::new();
25//! lua.exec("a = 12 * 5").unwrap();
26//! let a: u32 = lua.eval("return a + 1").unwrap();
27//! ```
28//!
29//! This example puts the value `60` in the global variable `a`. The values of all global variables
30//! are stored within the `Lua` struct. If you execute multiple Lua scripts on the same context,
31//! each script will have access to the same global variables that were modified by the previous
32//! scripts.
33//!
34//! In order to do something actually useful with Lua, we will need to make Lua and Rust
35//! communicate with each other. This can be done in four ways:
36//!
37//! - You can use methods on the `Lua` struct to read or write the values of global variables with
38//!   the [`get`](struct.Lua.html#method.get) and [`set`](struct.Lua.html#method.set) methods. For
39//!   example you can write to a global variable with a Lua script then read it from Rust, or you
40//!   can write to a global variable from Rust then read it from a Lua script.
41//!
42//! - The Lua script that you evaluate with the [`eval`](struct.Lua.html#method.eval) method
43//!   can return a value.
44//!
45//! - You can set the value of a global variable to a Rust functions or closures, which can then be
46//!   invoked with a Lua script. See [the `Function` struct](struct.Function.html) for more
47//!   information. For example if you set the value of the global variable `foo` to a Rust
48//!   function, you can then call it from Lua with `foo()`.
49//!
50//! - Similarly you can set the value of a global variable to a Lua function, then call it from
51//!   Rust. The function call can return a value.
52//!
53//! Which method(s) you use depends on which API you wish to expose to your Lua scripts.
54//!
55//! # Pushing and loading values
56//!
57//! The interface between Rust and Lua involves two things:
58//!
59//! - Sending values from Rust to Lua, which is known as *pushing* the value.
60//! - Sending values from Lua to Rust, which is known as *loading* the value.
61//!
62//! Pushing (ie. sending from Rust to Lua) can be done with
63//! [the `set` method](struct.Lua.html#method.set):
64//!
65//! ```no_run
66//! let lua = tlua::Lua::new();
67//! lua.set("a", 50);
68//! ```
69//!
70//! You can push values that implement [the `Push` trait](trait.Push.html) or
71//! [the `PushOne` trait](trait.PushOne.html) depending on the situation:
72//!
73//! - Integers, floating point numbers and booleans.
74//! - `String` and `&str`.
75//! - Any Rust function or closure whose parameters and loadable and whose return type is pushable.
76//!   See the documentation of [the `Function` struct](struct.Function.html) for more information.
77//! - [The `AnyLuaValue` struct](struct.AnyLuaValue.html). This enumeration represents any possible
78//!   value in Lua.
79//! - The [`LuaCode`](struct.LuaCode.html) and
80//!   [`LuaCodeFromReader`](struct.LuaCodeFromReader.html) structs. Since pushing these structs can
81//!   result in an error, you need to use [`checked_set`](struct.Lua.html#method.checked_set)
82//!   instead of `set`.
83//! - `Vec`s and `HashMap`s whose content is pushable.
84//! - As a special case, `Result` can be pushed only as the return type of a Rust function or
85//!   closure. If they contain an error, the Rust function call is considered to have failed.
86//! - As a special case, tuples can be pushed when they are the return type of a Rust function or
87//!   closure. They implement `Push` but not `PushOne`.
88//! - TODO: userdata
89//!
90//! Loading (ie. sending from Lua to Rust) can be done with
91//! [the `get` method](struct.Lua.html#method.get):
92//!
93//! ```no_run
94//! # use tlua::Lua;
95//! # let lua = Lua::new();
96//! let a: i32 = lua.get("a").unwrap();
97//! ```
98//!
99//! You can load values that implement [the `LuaRead` trait](trait.LuaRead.html):
100//!
101//! - Integers, floating point numbers and booleans.
102//! - `String` and [`StringInLua`](struct.StringInLua.html) (ie. the equivalent of `&str`). Loading
103//!   the latter has no cost while loading a `String` performs an allocation.
104//! - Any function (Lua or Rust), with [the `LuaFunction` struct](struct.LuaFunction.html). This
105//!   can then be used to execute the function.
106//! - [The `AnyLuaValue` struct](struct.AnyLuaValue.html). This enumeration represents any possible
107//!   value in Lua.
108//! - [The `LuaTable` struct](struct.LuaTable.html). This struct represents a table in Lua, where
109//!   keys and values can be of different types. The table can then be iterated and individual
110//!   elements can be loaded or modified.
111//! - As a special case, tuples can be loaded when they are the return type of a Lua function or as
112//!   the return type of [`eval`](struct.Lua.html#method.eval).
113//! - TODO: userdata
114//!
115use std::borrow::{Borrow, Cow};
116use std::collections::LinkedList;
117use std::ffi::{CStr, CString};
118use std::fmt;
119use std::io::Read;
120use std::io::{self, Write};
121use std::num::NonZeroI32;
122
123pub use ::tlua_derive::*;
124
125/// The recommended way to describe tests in `tlua` crate
126///
127/// # Example
128/// ```skip
129/// #[tlua::test]
130/// fn my_test() {
131///     assert!(true);
132/// }
133/// ```
134pub use ::tlua_derive::test;
135
136pub use any::{AnyHashableLuaValue, AnyLuaString, AnyLuaValue};
137pub use cdata::{AsCData, CData, CDataOnStack};
138pub use functions_write::{
139    function0, function1, function10, function2, function3, function4, function5, function6,
140    function7, function8, function9, protected_call, CFunction, Function, InsideCallback, Throw,
141};
142pub use lua_functions::LuaFunction;
143pub use lua_functions::{LuaCode, LuaCodeFromReader};
144pub use lua_tables::{LuaTable, LuaTableIterator};
145pub use object::{
146    Call, CallError, Callable, Index, Indexable, IndexableRW, MethodCallError, NewIndex, Object,
147};
148pub use rust_tables::{PushIterError, PushIterErrorOf, TableFromIter};
149pub use tuples::{AsTable, TuplePushError};
150pub use userdata::UserdataOnStack;
151pub use userdata::{push_some_userdata, push_userdata, read_userdata};
152pub use values::BytesInLua;
153pub use values::{False, Nil, Null, Strict, StringInLua, ToString, True, Typename};
154
155#[deprecated = "Use `CallError` instead"]
156pub type LuaFunctionCallError<E> = CallError<E>;
157pub type LuaTableMap = std::collections::HashMap<AnyHashableLuaValue, AnyLuaValue>;
158pub type LuaSequence = Vec<AnyLuaValue>;
159
160mod any;
161mod cdata;
162pub mod debug;
163pub mod ffi;
164mod functions_write;
165mod lua_functions;
166mod lua_tables;
167mod macros;
168mod object;
169mod rust_tables;
170#[cfg(feature = "extra_impls")]
171mod smol_str;
172#[cfg(feature = "internal_test")]
173pub mod test;
174mod tuples;
175mod userdata;
176pub mod util;
177mod values;
178
179pub type LuaState = *mut ffi::lua_State;
180
181/// A static lua context that must be created from an existing lua state pointer
182/// and that will **not** be closed when dropped.
183pub type StaticLua = Lua<on_drop::Ignore>;
184
185/// A temporary lua context that will be closed when dropped.
186pub type TempLua = Lua<on_drop::Close>;
187
188/// A lua context corresponding to a lua thread (see [`ffi::lua_newthread`])
189/// stored in the global [REGISTRY](ffi::LUA_REGISTRYINDEX) and will be removed
190/// from there when dropped.
191///
192/// `LuaThread` currently can only be created from an instance of [`StaticLua`]
193/// because closing a state from which a thread has been created is forbidden.
194pub type LuaThread = Lua<on_drop::Unref>;
195
196/// Main object of the library.
197///
198/// The type parameter `OnDrop` specifies what happens with the underlying lua
199/// state when the instance gets dropped. There are currently 3 supported cases:
200/// - `on_drop::Ignore`: nothing happens
201/// - `on_drop::Close`: [`ffi::lua_close`] is called
202/// - `on_drop::Unref`: [`ffi::luaL_unref`] is called with the associated value
203///
204/// # About panic safety
205///
206/// This type isn't panic safe. This means that if a panic happens while you were using the `Lua`,
207/// then it will probably stay in a corrupt state. Trying to use the `Lua` again will most likely
208/// result in another panic but shouldn't result in unsafety.
209#[derive(Debug)]
210pub struct Lua<OnDrop>
211where
212    OnDrop: on_drop::OnDrop,
213{
214    lua: LuaState,
215    on_drop: OnDrop,
216}
217
218mod on_drop {
219    use crate::{ffi, LuaState};
220
221    pub trait OnDrop {
222        fn on_drop(&mut self, l: LuaState);
223    }
224
225    /// See [`StaticLua`].
226    #[derive(Debug)]
227    pub struct Ignore;
228
229    impl OnDrop for Ignore {
230        fn on_drop(&mut self, _: LuaState) {}
231    }
232
233    /// See [`TempLua`].
234    #[derive(Debug)]
235    pub struct Close;
236
237    impl OnDrop for Close {
238        fn on_drop(&mut self, l: LuaState) {
239            unsafe { ffi::lua_close(l) }
240        }
241    }
242
243    /// See [`LuaThread`].
244    #[derive(Debug)]
245    pub struct Unref(pub i32);
246
247    impl OnDrop for Unref {
248        fn on_drop(&mut self, l: LuaState) {
249            unsafe { ffi::luaL_unref(l, ffi::LUA_REGISTRYINDEX, self.0) }
250        }
251    }
252}
253
254/// RAII guard for a value pushed on the stack.
255///
256/// You shouldn't have to manipulate this type directly unless you are fiddling with the
257/// library's internals.
258pub struct PushGuard<L>
259where
260    L: AsLua,
261{
262    lua: L,
263    top: i32,
264    size: i32,
265}
266
267impl<L> std::fmt::Debug for PushGuard<L>
268where
269    L: AsLua,
270    L: std::fmt::Debug,
271{
272    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
273        let start = unsafe {
274            AbsoluteIndex::new_unchecked(NonZeroI32::new(self.top - self.size + 1).unwrap())
275        };
276        f.debug_struct("PushGuard")
277            .field("lua", &self.lua)
278            .field("size", &self.size)
279            .field(
280                "lua_type",
281                &typenames(self.lua.as_lua(), start, self.size as _),
282            )
283            .finish()
284    }
285}
286
287impl<L: AsLua> PushGuard<L> {
288    /// Creates a new `PushGuard` from this Lua context representing `size` items on the stack.
289    /// When this `PushGuard` is destroyed, `size` items will be popped.
290    ///
291    /// # Safety
292    /// There must be at least `size` elements on the `lua` stack and it must be
293    /// safe to drop them at the same time with this `PushGuard`.
294    #[inline]
295    pub unsafe fn new(lua: L, size: i32) -> Self {
296        PushGuard {
297            top: ffi::lua_gettop(lua.as_lua()),
298            lua,
299            size: size as _,
300        }
301    }
302
303    #[inline]
304    pub fn assert_one_and_forget(self) -> i32 {
305        assert_eq!(self.size, 1);
306        self.forget_internal()
307    }
308
309    /// Returns the number of elements managed by this `PushGuard`.
310    #[inline]
311    pub fn size(&self) -> i32 {
312        self.size
313    }
314
315    /// Prevents the value from being popped when the `PushGuard` is destroyed, and returns the
316    /// number of elements on the Lua stack.
317    ///
318    /// # Safety
319    /// The values on the stack will not be popped automatically, so the caller
320    /// must ensure nothing is leaked.
321    #[inline]
322    pub unsafe fn forget(self) -> i32 {
323        self.forget_internal()
324    }
325
326    /// Internal crate-only version of `forget`. It is generally assumed that code within this
327    /// crate that calls this method knows what it is doing.
328    #[inline]
329    fn forget_internal(mut self) -> i32 {
330        let size = self.size;
331        self.size = 0;
332        size
333    }
334
335    /// Destroys the guard, popping the value. Returns the inner part,
336    /// which returns access when using by-value capture.
337    #[inline]
338    pub fn into_inner(self) -> L {
339        use std::{
340            mem::{self, MaybeUninit},
341            ptr,
342        };
343
344        let mut res = MaybeUninit::uninit();
345        unsafe {
346            ptr::copy_nonoverlapping(&self.lua, res.as_mut_ptr(), 1);
347            if self.size != 0 {
348                ffi::lua_pop(self.lua.as_lua(), self.size as _);
349            }
350        };
351        mem::forget(self);
352
353        unsafe { res.assume_init() }
354    }
355}
356
357/// Trait for objects that have access to a Lua context.
358pub trait AsLua {
359    fn as_lua(&self) -> *mut ffi::lua_State;
360
361    /// Try to push `v` onto the lua stack.
362    ///
363    /// In case of success returns a `PushGuard` which captures `self` by value
364    /// and stores the amount of values pushed onto the stack.
365    ///
366    /// In case of failure returns a tuple with 2 elements:
367    /// - an error, which occured during the attempt to push
368    /// - `self`
369    #[inline(always)]
370    fn try_push<T>(self, v: T) -> Result<PushGuard<Self>, (<T as PushInto<Self>>::Err, Self)>
371    where
372        Self: Sized,
373        T: PushInto<Self>,
374    {
375        v.push_into_lua(self)
376    }
377
378    /// Push `v` onto the lua stack.
379    ///
380    /// This method is only available if `T::Err` implements `Into<Void>`, which
381    /// means that no error can happen during the attempt to push.
382    ///
383    /// Returns a `PushGuard` which captures `self` by value and stores the
384    /// amount of values pushed onto the stack.
385    #[inline(always)]
386    fn push<T>(self, v: T) -> PushGuard<Self>
387    where
388        Self: Sized,
389        T: PushInto<Self>,
390        <T as PushInto<Self>>::Err: Into<Void>,
391    {
392        v.push_into_no_err(self)
393    }
394
395    /// Try to push `v` onto the lua stack.
396    ///
397    /// This method is only available if `T` implements `PushOneInto`, which
398    /// means that it pushes a single value onto the stack.
399    ///
400    /// Returns a `PushGuard` which captures `self` by value and stores the
401    /// amount of values pushed onto the stack (ideally this will be 1, but it
402    /// is the responsibility of the impelemntor to make sure it is so).
403    #[inline(always)]
404    fn try_push_one<T>(self, v: T) -> Result<PushGuard<Self>, (<T as PushInto<Self>>::Err, Self)>
405    where
406        Self: Sized,
407        T: PushOneInto<Self>,
408    {
409        v.push_into_lua(self)
410    }
411
412    /// Push `v` onto the lua stack.
413    ///
414    /// This method is only available if
415    /// - `T` implements `PushOneInto`, which means that it pushes a single value onto the stack
416    /// - `T::Err` implements `Into<Void>`, which means that no error can happen during the attempt to push
417    ///
418    /// Returns a `PushGuard` which captures `self` by value and stores the
419    /// amount of values pushed onto the stack (ideally this will be 1, but it
420    /// is the responsibility of the impelemntor to make sure it is so).
421    #[inline(always)]
422    fn push_one<T>(self, v: T) -> PushGuard<Self>
423    where
424        Self: Sized,
425        T: PushOneInto<Self>,
426        <T as PushInto<Self>>::Err: Into<Void>,
427    {
428        v.push_into_no_err(self)
429    }
430
431    /// Push `iterator` onto the lua stack as a lua table.
432    ///
433    /// This method is only available if
434    /// - `I::Item` implements `PushInto<LuaState>`, which means that it can be
435    ///   pushed onto the lua stack by value
436    /// - `I::Item::Err` implements `Into<Void>`, which means that no error can
437    ///   happen during the attempt to push
438    ///
439    /// If `I::Item` pushes a single value onto the stack, the resulting lua
440    /// table is a lua sequence (a table with 1-based integer keys).
441    ///
442    /// If `I::Item` pushes 2 values onto the stack, the resulting lua table is
443    /// a regular lua table with the provided keys.
444    ///
445    /// If `I::Item` pushes more than 2 values, the function returns `Err(self)`.
446    ///
447    /// Returns a `PushGuard` which captures `self` by value and stores the
448    /// amount of values pushed onto the stack (exactly 1 -- lua table).
449    #[inline(always)]
450    fn push_iter<I>(self, iterator: I) -> Result<PushGuard<Self>, Self>
451    where
452        Self: Sized,
453        I: Iterator,
454        <I as Iterator>::Item: PushInto<LuaState>,
455        <<I as Iterator>::Item as PushInto<LuaState>>::Err: Into<Void>,
456    {
457        rust_tables::push_iter(self, iterator).map_err(|(_, lua)| lua)
458    }
459
460    /// Push `iterator` onto the lua stack as a lua table.
461    ///
462    /// This method is only available if `I::Item` implements
463    /// `PushInto<LuaState>`, which means that it can be pushed onto the lua
464    /// stack by value.
465    ///
466    /// If `I::Item` pushes a single value onto the stack, the resulting lua
467    /// table is a lua sequence (a table with 1-based integer keys).
468    ///
469    /// If `I::Item` pushes 2 values onto the stack, the resulting lua table is
470    /// a regular lua table with the provided keys.
471    ///
472    /// If `I::Item` pushes more than 2 values or an error happens during an
473    /// attempt to push, the function returns `Err((e, self))` where `e` is a
474    /// `PushIterErrorOf`.
475    ///
476    /// Returns a `PushGuard` which captures `self` by value and stores the
477    /// amount of values pushed onto the stack (exactly 1 -- lua table).
478    #[inline(always)]
479    fn try_push_iter<I>(self, iterator: I) -> Result<PushGuard<Self>, (PushIterErrorOf<I>, Self)>
480    where
481        Self: Sized,
482        I: Iterator,
483        <I as Iterator>::Item: PushInto<LuaState>,
484    {
485        rust_tables::push_iter(self, iterator)
486    }
487
488    #[inline(always)]
489    fn read<T>(self) -> ReadResult<T, Self>
490    where
491        Self: Sized,
492        T: LuaRead<Self>,
493    {
494        T::lua_read(self)
495    }
496
497    #[inline(always)]
498    fn read_at<T>(self, index: i32) -> ReadResult<T, Self>
499    where
500        Self: Sized,
501        T: LuaRead<Self>,
502    {
503        T::lua_read_at_maybe_zero_position(self, index)
504    }
505
506    #[inline(always)]
507    fn read_at_nz<T>(self, index: NonZeroI32) -> ReadResult<T, Self>
508    where
509        Self: Sized,
510        T: LuaRead<Self>,
511    {
512        T::lua_read_at_position(self, index)
513    }
514
515    /// Call a rust function in protected mode. If a lua error is thrown during
516    /// execution of `f` the function will return a `LuaError`.
517    ///
518    /// This can also be sometimes used to catch other C++ exceptions although
519    /// be careful with that.
520    #[track_caller]
521    #[inline(always)]
522    fn pcall<F, R>(&self, f: F) -> Result<R, LuaError>
523    where
524        F: FnOnce(StaticLua) -> R,
525    {
526        protected_call(self, f)
527    }
528}
529
530impl<T> AsLua for &'_ T
531where
532    T: ?Sized + AsLua,
533{
534    fn as_lua(&self) -> *mut ffi::lua_State {
535        T::as_lua(self)
536    }
537}
538
539impl<D> AsLua for Lua<D>
540where
541    D: on_drop::OnDrop,
542{
543    #[inline]
544    fn as_lua(&self) -> *mut ffi::lua_State {
545        self.lua
546    }
547}
548
549impl AsLua for *mut ffi::lua_State {
550    fn as_lua(&self) -> *mut ffi::lua_State {
551        *self
552    }
553}
554
555impl<L> AsLua for PushGuard<L>
556where
557    L: AsLua,
558{
559    #[inline]
560    fn as_lua(&self) -> *mut ffi::lua_State {
561        self.lua.as_lua()
562    }
563}
564
565/// Type returned from [`Push::push_to_lua`] function.
566pub type PushResult<L, P> = Result<PushGuard<L>, (<P as Push<L>>::Err, L)>;
567
568/// Types implementing this trait can be pushed onto the Lua stack by reference.
569pub trait Push<L: AsLua> {
570    /// Error that can happen when pushing a value.
571    type Err;
572
573    /// Pushes the value on the top of the stack.
574    ///
575    /// Must return a guard representing the elements that have been pushed.
576    ///
577    /// You can implement this for any type you want by redirecting to call to
578    /// another implementation (for example `5.push_to_lua`) or by calling
579    /// `userdata::push_userdata`.
580    fn push_to_lua(&self, lua: L) -> Result<PushGuard<L>, (Self::Err, L)>;
581
582    /// Same as `push_to_lua` but can only succeed and is only available if
583    /// `Err` implements `Into<Void>`.
584    #[inline]
585    fn push_no_err(&self, lua: L) -> PushGuard<L>
586    where
587        <Self as Push<L>>::Err: Into<Void>,
588    {
589        match self.push_to_lua(lua) {
590            Ok(p) => p,
591            Err(_) => unreachable!("no way to instantiate Void"),
592        }
593    }
594}
595
596impl<T, L> Push<L> for &'_ T
597where
598    L: AsLua,
599    T: ?Sized,
600    T: Push<L>,
601{
602    type Err = T::Err;
603
604    fn push_to_lua(&self, lua: L) -> Result<PushGuard<L>, (Self::Err, L)> {
605        T::push_to_lua(*self, lua)
606    }
607}
608
609/// Extension trait for `Push`. Guarantees that only one element will be pushed.
610///
611/// This should be implemented on most types that implement `Push`, except for tuples.
612///
613/// > **Note**: Implementing this trait on a type that pushes multiple elements will most likely
614/// > result in panics.
615// Note for the implementation: since this trait is not unsafe, it is mostly a hint. Functions can
616// require this trait if they only accept one pushed element, but they must also add a runtime
617// assertion to make sure that only one element was actually pushed.
618pub trait PushOne<L: AsLua>: Push<L> {}
619
620impl<T, L> PushOne<L> for &'_ T
621where
622    L: AsLua,
623    T: ?Sized,
624    T: PushOne<L>,
625{
626}
627
628/// Type returned from [`PushInto::push_into_lua`] function.
629pub type PushIntoResult<L, P> = Result<PushGuard<L>, (<P as PushInto<L>>::Err, L)>;
630
631/// Types implementing this trait can be pushed onto the Lua stack by value.
632pub trait PushInto<L>
633where
634    L: AsLua,
635{
636    type Err;
637
638    /// Push the value into lua by value
639    fn push_into_lua(self, lua: L) -> Result<PushGuard<L>, (Self::Err, L)>;
640
641    /// Same as `push_into_lua` but can only succeed and is only available if
642    /// `Err` implements `Into<Void>`.
643    #[inline]
644    fn push_into_no_err(self, lua: L) -> PushGuard<L>
645    where
646        Self: Sized,
647        <Self as PushInto<L>>::Err: Into<Void>,
648    {
649        match self.push_into_lua(lua) {
650            Ok(p) => p,
651            Err(_) => unreachable!("no way to instantiate Void"),
652        }
653    }
654}
655
656impl<T, L> PushInto<L> for &'_ T
657where
658    L: AsLua,
659    T: ?Sized,
660    T: Push<L>,
661{
662    type Err = T::Err;
663
664    fn push_into_lua(self, lua: L) -> Result<PushGuard<L>, (Self::Err, L)> {
665        self.push_to_lua(lua)
666    }
667}
668
669/// Extension trait for `PushInto`. Guarantees that only one element will be
670/// pushed.
671///
672/// This should be implemented on most types that implement `PushInto`, except
673/// for tuples.
674///
675/// > **Note**: Implementing this trait on a type that pushes multiple elements
676/// > will most likely result in panics.
677///
678// Note for the implementation: since this trait is not unsafe, it is mostly a
679// hint. Functions can require this trait if they only accept one pushed
680// element, but they must also add a runtime assertion to make sure that only
681// one element was actually pushed.
682pub trait PushOneInto<L: AsLua>: PushInto<L> {}
683
684impl<T, L> PushOneInto<L> for &'_ T
685where
686    L: AsLua,
687    T: ?Sized,
688    T: PushOne<L>,
689{
690}
691
692/// Type that cannot be instantiated.
693///
694/// Will be replaced with `!` eventually (<https://github.com/rust-lang/rust/issues/35121>).
695#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
696pub enum Void {}
697
698impl fmt::Display for Void {
699    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
700        unreachable!("Void cannot be instantiated")
701    }
702}
703
704pub const NEGATIVE_ONE: NonZeroI32 = NonZeroI32::new(-1).unwrap();
705pub const NEGATIVE_TWO: NonZeroI32 = NonZeroI32::new(-2).unwrap();
706
707////////////////////////////////////////////////////////////////////////////////
708// LuaRead
709////////////////////////////////////////////////////////////////////////////////
710
711/// Types that can be obtained from a Lua context.
712///
713/// Most types that implement `Push` also implement `LuaRead`, but this is not always the case
714/// (for example `&'static str` implements `Push` but not `LuaRead`).
715pub trait LuaRead<L>: Sized {
716    #[inline(always)]
717    fn n_values_expected() -> i32 {
718        1
719    }
720
721    /// Reads the data from Lua.
722    #[inline]
723    fn lua_read(lua: L) -> ReadResult<Self, L> {
724        let index = NonZeroI32::new(-Self::n_values_expected()).expect("Invalid n_values_expected");
725        Self::lua_read_at_position(lua, index)
726    }
727
728    fn lua_read_at_maybe_zero_position(lua: L, index: i32) -> ReadResult<Self, L>
729    where
730        L: AsLua,
731    {
732        if let Some(index) = NonZeroI32::new(index) {
733            Self::lua_read_at_position(lua, index)
734        } else {
735            let e = WrongType::default()
736                .expected_type::<Self>()
737                .actual("no value");
738            Err((lua, e))
739        }
740    }
741
742    /// Reads the data from Lua at a given position.
743    fn lua_read_at_position(lua: L, index: NonZeroI32) -> ReadResult<Self, L>;
744}
745
746pub type ReadResult<T, L> = Result<T, (L, WrongType)>;
747
748impl<L: AsLua> LuaRead<L> for LuaState {
749    fn lua_read_at_maybe_zero_position(lua: L, _: i32) -> ReadResult<Self, L> {
750        Ok(lua.as_lua())
751    }
752
753    fn lua_read_at_position(lua: L, _: NonZeroI32) -> ReadResult<Self, L> {
754        Ok(lua.as_lua())
755    }
756}
757
758////////////////////////////////////////////////////////////////////////////////
759// LuaError
760////////////////////////////////////////////////////////////////////////////////
761
762/// Error that can happen when executing Lua code.
763#[derive(Debug, thiserror::Error)]
764pub enum LuaError {
765    /// There was a syntax error when parsing the Lua code.
766    #[error("syntax error: {0}")]
767    SyntaxError(String),
768
769    /// There was an error during execution of the Lua code
770    /// (for example not enough parameters for a function call).
771    #[error("{0}")]
772    ExecutionError(Cow<'static, str>),
773
774    /// There was an IoError while reading the source code to execute.
775    #[error("{0}")]
776    ReadError(#[from] io::Error),
777
778    /// The call to `eval` has requested the wrong type of data.
779    #[error("{0}")]
780    WrongType(#[from] WrongType),
781}
782
783////////////////////////////////////////////////////////////////////////////////
784// WrongType
785////////////////////////////////////////////////////////////////////////////////
786
787#[derive(Debug, thiserror::Error)]
788pub struct WrongType {
789    when: &'static str,
790    rust_expected: String,
791    lua_actual: String,
792    subtypes: LinkedList<WrongType>,
793}
794
795impl<E> From<WrongType> for CallError<E> {
796    fn from(e: WrongType) -> Self {
797        Self::LuaError(e.into())
798    }
799}
800
801impl Default for WrongType {
802    fn default() -> Self {
803        Self {
804            when: "reading Lua value",
805            rust_expected: Default::default(),
806            lua_actual: Default::default(),
807            subtypes: Default::default(),
808        }
809    }
810}
811
812impl fmt::Display for WrongType {
813    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
814        let subtype = crate::unwrap_or! { self.subtypes.front(),
815            write!(f, "failed ")?;
816            return display_leaf(self, f);
817        };
818
819        if subtype.subtypes.is_empty()
820            && subtype.rust_expected == self.rust_expected
821            && subtype.lua_actual == self.lua_actual
822        {
823            write!(f, "failed ")?;
824            return display_leaf(self, f);
825        }
826
827        if self.subtypes.len() == 1 {
828            write!(f, "{subtype}")?;
829        } else {
830            write!(f, "variant #1: {subtype}")?;
831            for (subtype, i) in self.subtypes.iter().skip(1).zip(2..) {
832                write!(f, "\nvariant #{i}: {subtype}")?;
833            }
834        }
835
836        write!(f, "\n    while ")?;
837        display_leaf(self, f)?;
838
839        return Ok(());
840
841        fn display_leaf(wt: &WrongType, f: &mut fmt::Formatter) -> fmt::Result {
842            return write!(
843                f,
844                "{}: {} expected, got {}",
845                wt.when, wt.rust_expected, wt.lua_actual
846            );
847        }
848    }
849}
850
851impl WrongType {
852    #[inline(always)]
853    pub fn info(when: &'static str) -> Self {
854        Self {
855            when,
856            ..Self::default()
857        }
858    }
859
860    #[inline(always)]
861    pub fn when(mut self, when: &'static str) -> Self {
862        self.when = when;
863        self
864    }
865
866    #[inline(always)]
867    pub fn expected_type<T>(mut self) -> Self {
868        self.rust_expected = std::any::type_name::<T>().into();
869        self
870    }
871
872    #[inline(always)]
873    pub fn expected(mut self, expected: impl Into<String>) -> Self {
874        self.rust_expected = expected.into();
875        self
876    }
877
878    /// Set the actual Lua type from a value at `index`.
879    #[inline(always)]
880    pub fn actual_single_lua<L: AsLua>(mut self, lua: L, index: NonZeroI32) -> Self {
881        let index = AbsoluteIndex::new(index, lua.as_lua());
882        self.lua_actual = typenames(lua, index, 1);
883        self
884    }
885
886    /// Set the actual Lua type from a range of lowest `n_values` on the stack.
887    #[inline(always)]
888    #[track_caller]
889    pub fn actual_multiple_lua<L: AsLua>(self, lua: L, n_values: i32) -> Self {
890        self.actual_multiple_lua_at(lua, -n_values, n_values)
891    }
892
893    /// Set the actual Lua type from a range of `n_values` values starting at index `start`.
894    #[inline(always)]
895    #[track_caller]
896    pub fn actual_multiple_lua_at<L: AsLua>(
897        mut self,
898        lua: L,
899        start: impl Into<i32>,
900        n_values: i32,
901    ) -> Self {
902        if let Some(start) = AbsoluteIndex::try_new(start, lua.as_lua()) {
903            self.lua_actual = typenames(lua, start, n_values as _);
904        } else {
905            self.lua_actual = "no values".into()
906        }
907        self
908    }
909
910    #[inline(always)]
911    pub fn actual(mut self, actual: impl Into<String>) -> Self {
912        self.lua_actual = actual.into();
913        self
914    }
915
916    #[inline(always)]
917    pub fn subtype(mut self, subtype: Self) -> Self {
918        self.subtypes.push_back(subtype);
919        self
920    }
921
922    #[inline(always)]
923    pub fn subtypes(mut self, subtypes: LinkedList<Self>) -> Self {
924        self.subtypes = subtypes;
925        self
926    }
927}
928
929pub fn typename(lua: impl AsLua, index: i32) -> &'static CStr {
930    unsafe {
931        let lua_type = ffi::lua_type(lua.as_lua(), index);
932        let typename = ffi::lua_typename(lua.as_lua(), lua_type);
933        CStr::from_ptr(typename)
934    }
935}
936
937#[track_caller]
938pub fn typenames(lua: impl AsLua, start: AbsoluteIndex, count: u32) -> String {
939    let l_ptr = lua.as_lua();
940    let single_typename = |i| typename(l_ptr, i as _).to_string_lossy();
941
942    let start = start.get();
943    match count {
944        0 => return "()".into(),
945        1 => return single_typename(start).into_owned(),
946        _ => {}
947    }
948
949    let mut res = Vec::with_capacity(32);
950    write!(res, "(").expect("writing to vec cannot fail");
951    let end = start + count - 1;
952    for i in start..end {
953        write!(res, "{}, ", single_typename(i)).expect("writing to vec cannot fail");
954    }
955    write!(res, "{})", single_typename(end)).expect("writing to vec cannot fail");
956    // concatenation of utf8 is utf8
957    unsafe { String::from_utf8_unchecked(res) }
958}
959
960////////////////////////////////////////////////////////////////////////////////
961// impl TempLua
962////////////////////////////////////////////////////////////////////////////////
963
964impl TempLua {
965    /// Builds a new empty TempLua context.
966    ///
967    /// There are no global variables and the registry is totally empty. Even the functions from
968    /// the standard library can't be used.
969    ///
970    /// If you want to use the Lua standard library in the scripts of this context, see
971    /// [the openlibs method](#method.openlibs)
972    ///
973    /// # Example
974    ///
975    /// ```no_run
976    /// use tlua::Lua;
977    /// let lua = Lua::new();
978    /// ```
979    ///
980    /// # Panic
981    ///
982    /// The function panics if the underlying call to `lua_newstate` fails
983    /// (which indicates lack of memory).
984    #[track_caller]
985    #[inline]
986    pub fn new() -> Self {
987        let lua = unsafe { ffi::luaL_newstate() };
988        if lua.is_null() {
989            panic!("lua_newstate failed");
990        }
991
992        // called whenever lua encounters an unexpected error.
993        extern "C-unwind" fn panic(lua: *mut ffi::lua_State) -> libc::c_int {
994            let err = unsafe { ffi::lua_tostring(lua, -1) };
995            let err = unsafe { CStr::from_ptr(err) };
996            let err = String::from_utf8(err.to_bytes().to_vec()).unwrap();
997            panic!("PANIC: unprotected error in call to Lua API ({})\n", err);
998        }
999
1000        unsafe { ffi::lua_atpanic(lua, panic) };
1001
1002        unsafe { Self::from_existing(lua) }
1003    }
1004
1005    /// Takes an existing `lua_State` and build a TemplLua object from it.
1006    ///
1007    /// `lua_close` will be called on the `lua_State` in drop.
1008    ///
1009    /// # Safety
1010    /// A pointer to a valid `lua` context must be provided which is ok to be
1011    /// closed.
1012    #[inline]
1013    pub unsafe fn from_existing<T>(lua: *mut T) -> Self {
1014        Self {
1015            lua: lua as _,
1016            on_drop: on_drop::Close,
1017        }
1018    }
1019}
1020
1021impl StaticLua {
1022    /// Takes an existing `lua_State` and build a StaticLua object from it.
1023    ///
1024    /// `lua_close` is **NOT** called in `drop`.
1025    ///
1026    /// # Safety
1027    /// A pointer to a valid `lua` context must be provided.
1028    #[inline]
1029    pub unsafe fn from_static<T>(lua: *mut T) -> Self {
1030        Self {
1031            lua: lua as _,
1032            on_drop: on_drop::Ignore,
1033        }
1034    }
1035
1036    /// Creates a new Lua thread with an independent stack and runs the provided
1037    /// function within it. The new state has access to all the global objects
1038    /// available to `self`.
1039    pub fn new_thread(&self) -> LuaThread {
1040        unsafe {
1041            let lua = ffi::lua_newthread(self.as_lua());
1042            let r = ffi::luaL_ref(self.as_lua(), ffi::LUA_REGISTRYINDEX);
1043            LuaThread {
1044                lua,
1045                on_drop: on_drop::Unref(r),
1046            }
1047        }
1048    }
1049}
1050
1051impl<L: AsLua> LuaRead<L> for StaticLua {
1052    fn lua_read_at_maybe_zero_position(lua: L, _: i32) -> ReadResult<Self, L> {
1053        Ok(Self {
1054            lua: lua.as_lua(),
1055            on_drop: on_drop::Ignore,
1056        })
1057    }
1058
1059    fn lua_read_at_position(lua: L, _: NonZeroI32) -> ReadResult<Self, L> {
1060        Ok(Self {
1061            lua: lua.as_lua(),
1062            on_drop: on_drop::Ignore,
1063        })
1064    }
1065}
1066
1067impl<OnDrop> Lua<OnDrop>
1068where
1069    OnDrop: on_drop::OnDrop,
1070{
1071    /// Opens all standard Lua libraries.
1072    ///
1073    /// See the reference for the standard library here:
1074    /// <https://www.lua.org/manual/5.2/manual.html#6>
1075    ///
1076    /// This is done by calling `luaL_openlibs`.
1077    ///
1078    /// # Example
1079    ///
1080    /// ```no_run
1081    /// use tlua::Lua;
1082    /// let lua = Lua::new();
1083    /// lua.openlibs();
1084    /// ```
1085    #[inline]
1086    // TODO(gmoshkin): this method should be part of AsLua
1087    pub fn openlibs(&self) {
1088        unsafe { ffi::luaL_openlibs(self.lua) }
1089    }
1090
1091    /// Opens base library.
1092    ///
1093    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_base>
1094    #[inline]
1095    // TODO(gmoshkin): this method should be part of AsLua
1096    pub fn open_base(&self) {
1097        unsafe { ffi::luaopen_base(self.lua) }
1098    }
1099
1100    /// Opens bit32 library.
1101    ///
1102    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_bit32>
1103    #[inline]
1104    // TODO(gmoshkin): this method should be part of AsLua
1105    pub fn open_bit(&self) {
1106        unsafe { ffi::luaopen_bit(self.lua) }
1107    }
1108
1109    /// Opens debug library.
1110    ///
1111    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_debug>
1112    #[inline]
1113    // TODO(gmoshkin): this method should be part of AsLua
1114    pub fn open_debug(&self) {
1115        unsafe { ffi::luaopen_debug(self.lua) }
1116    }
1117
1118    /// Opens io library.
1119    ///
1120    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_io>
1121    #[inline]
1122    // TODO(gmoshkin): this method should be part of AsLua
1123    pub fn open_io(&self) {
1124        unsafe { ffi::luaopen_io(self.lua) }
1125    }
1126
1127    /// Opens math library.
1128    ///
1129    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_math>
1130    #[inline]
1131    // TODO(gmoshkin): this method should be part of AsLua
1132    pub fn open_math(&self) {
1133        unsafe { ffi::luaopen_math(self.lua) }
1134    }
1135
1136    /// Opens os library.
1137    ///
1138    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_os>
1139    #[inline]
1140    // TODO(gmoshkin): this method should be part of AsLua
1141    pub fn open_os(&self) {
1142        unsafe { ffi::luaopen_os(self.lua) }
1143    }
1144
1145    /// Opens package library.
1146    ///
1147    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_package>
1148    #[inline]
1149    // TODO(gmoshkin): this method should be part of AsLua
1150    pub fn open_package(&self) {
1151        unsafe { ffi::luaopen_package(self.lua) }
1152    }
1153
1154    /// Opens string library.
1155    ///
1156    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_string>
1157    #[inline]
1158    // TODO(gmoshkin): this method should be part of AsLua
1159    pub fn open_string(&self) {
1160        unsafe { ffi::luaopen_string(self.lua) }
1161    }
1162
1163    /// Opens table library.
1164    ///
1165    /// <https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_table>
1166    #[inline]
1167    // TODO(gmoshkin): this method should be part of AsLua
1168    pub fn open_table(&self) {
1169        unsafe { ffi::luaopen_table(self.lua) }
1170    }
1171
1172    /// Executes some Lua code in the context.
1173    ///
1174    /// The code will have access to all the global variables you set with methods such as `set`.
1175    /// Every time you execute some code in the context, the code can modify these global variables.
1176    ///
1177    /// The template parameter of this function is the return type of the expression that is being
1178    /// evaluated.
1179    /// In order to avoid compilation error, you should call this function either by doing
1180    /// `lua.eval::<T>(...)` or `let result: T = lua.eval(...);` where `T` is the type of
1181    /// the expression.
1182    /// The function will return an error if the actual return type of the expression doesn't
1183    /// match the template parameter.
1184    ///
1185    /// The return type must implement the `LuaRead` trait. See
1186    /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
1187    /// information.
1188    ///
1189    /// # Examples
1190    ///
1191    /// ```no_run
1192    /// use tlua::Lua;
1193    /// let lua = Lua::new();
1194    ///
1195    /// let twelve: i32 = lua.eval("return 3 * 4;").unwrap();
1196    /// let sixty = lua.eval::<i32>("return 6 * 10;").unwrap();
1197    /// ```
1198    #[track_caller]
1199    #[inline(always)]
1200    // TODO(gmoshkin): this method should be part of AsLua
1201    pub fn eval<'lua, T>(&'lua self, code: &str) -> Result<T, LuaError>
1202    where
1203        T: LuaRead<PushGuard<LuaFunction<PushGuard<&'lua Self>>>>,
1204    {
1205        LuaFunction::load(self, code)?.into_call()
1206    }
1207
1208    /// Executes some Lua code in the context
1209    /// passing the arguments in place of `...`.
1210    ///
1211    /// ```no_run
1212    /// use tlua::Lua;
1213    /// let lua = Lua::new();
1214    /// let two: i32 = lua.eval_with("return 1 + ...", 1).unwrap();
1215    /// assert_eq!(two, 2);
1216    /// ```
1217    /// See also [`Lua::eval`]
1218    #[track_caller]
1219    #[inline(always)]
1220    // TODO(gmoshkin): this method should be part of AsLua
1221    pub fn eval_with<'lua, A, T>(&'lua self, code: &str, args: A) -> Result<T, CallError<A::Err>>
1222    where
1223        A: PushInto<LuaState>,
1224        T: LuaRead<PushGuard<LuaFunction<PushGuard<&'lua Self>>>>,
1225    {
1226        LuaFunction::load(self, code)?.into_call_with_args(args)
1227    }
1228
1229    /// Executes some Lua code in the context.
1230    ///
1231    /// The code will have access to all the global variables you set with
1232    /// methods such as `set`.  Every time you execute some code in the context,
1233    /// the code can modify these global variables.
1234    ///
1235    /// # Examples
1236    ///
1237    /// ```no_run
1238    /// use tlua::Lua;
1239    /// let lua = Lua::new();
1240    /// lua.exec("function multiply_by_two(a) return a * 2 end").unwrap();
1241    /// lua.exec("twelve = multiply_by_two(6)").unwrap();
1242    /// ```
1243    #[track_caller]
1244    #[inline(always)]
1245    // TODO(gmoshkin): this method should be part of AsLua
1246    pub fn exec(&self, code: &str) -> Result<(), LuaError> {
1247        LuaFunction::load(self, code)?.into_call()
1248    }
1249
1250    /// Executes some Lua code in the context
1251    /// passing the arguments in place of `...`.
1252    ///
1253    /// # Examples
1254    ///
1255    /// ```no_run
1256    /// use tlua::Lua;
1257    /// let lua = Lua::new();
1258    /// lua.exec_with("a, b = ...; c = a * b", (3, 4)).unwrap();
1259    /// let c: i32 = lua.get("c").unwrap();
1260    /// assert_eq!(c, 12);
1261    /// ```
1262    /// See also [`Lua::exec`]
1263    #[track_caller]
1264    #[inline(always)]
1265    // TODO(gmoshkin): this method should be part of AsLua
1266    pub fn exec_with<A>(&self, code: &str, args: A) -> Result<(), CallError<A::Err>>
1267    where
1268        A: PushInto<LuaState>,
1269    {
1270        LuaFunction::load(self, code)?.into_call_with_args(args)
1271    }
1272
1273    /// Executes some Lua code on the context.
1274    ///
1275    /// This does the same thing as [the `eval` method](#method.eval), but the
1276    /// code to evaluate is loaded from an object that implements `Read`.
1277    ///
1278    /// Use this method when you potentially have a large amount of code (for example if you read
1279    /// the code from a file) in order to avoid having to put everything in memory first before
1280    /// passing it to the Lua interpreter.
1281    ///
1282    /// # Example
1283    ///
1284    /// ```no_run
1285    /// use std::fs::File;
1286    /// use tlua::Lua;
1287    ///
1288    /// let mut lua = Lua::new();
1289    /// let script = File::open("script.lua").unwrap();
1290    /// let res: u32 = lua.eval_from(script).unwrap();
1291    /// ```
1292    #[track_caller]
1293    #[inline(always)]
1294    // TODO(gmoshkin): this method should be part of AsLua
1295    pub fn eval_from<'lua, T>(&'lua self, code: impl Read) -> Result<T, LuaError>
1296    where
1297        T: LuaRead<PushGuard<LuaFunction<PushGuard<&'lua Self>>>>,
1298    {
1299        LuaFunction::load_from_reader(self, code)?.into_call()
1300    }
1301
1302    /// Executes some Lua code on the context.
1303    ///
1304    /// This does the same thing as [the `exec` method](#method.exec), but the
1305    /// code to execute is loaded from an object that implements `Read`.
1306    ///
1307    /// Use this method when you potentially have a large amount of code (for
1308    /// example if you read the code from a file) in order to avoid having to
1309    /// put everything in memory first before passing it to the Lua interpreter.
1310    ///
1311    /// # Example
1312    ///
1313    /// ```no_run
1314    /// use std::fs::File;
1315    /// use tlua::Lua;
1316    ///
1317    /// let mut lua = Lua::new();
1318    /// let script = File::open("script.lua").unwrap();
1319    /// lua.exec_from(script).unwrap();
1320    /// ```
1321    #[track_caller]
1322    #[inline(always)]
1323    // TODO(gmoshkin): this method should be part of AsLua
1324    pub fn exec_from(&self, code: impl Read) -> Result<(), LuaError> {
1325        LuaFunction::load_from_reader(self, code)?.into_call()
1326    }
1327
1328    /// Reads the value of a global variable.
1329    ///
1330    /// Returns `None` if the variable doesn't exist or has the wrong type.
1331    ///
1332    /// The type must implement the `LuaRead` trait. See
1333    /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
1334    /// information.
1335    ///
1336    /// # Example
1337    ///
1338    /// ```no_run
1339    /// use tlua::Lua;
1340    /// let lua = Lua::new();
1341    /// lua.exec("a = 5").unwrap();
1342    /// let a: i32 = lua.get("a").unwrap();
1343    /// assert_eq!(a, 5);
1344    /// ```
1345    #[inline]
1346    // TODO(gmoshkin): this method should be part of AsLua
1347    pub fn get<'lua, V, I>(&'lua self, index: I) -> Option<V>
1348    where
1349        I: Borrow<str>,
1350        V: LuaRead<PushGuard<&'lua Self>>,
1351    {
1352        let index = CString::new(index.borrow()).unwrap();
1353        unsafe {
1354            ffi::lua_getglobal(self.lua, index.as_ptr());
1355            V::lua_read(PushGuard::new(self, 1)).ok()
1356        }
1357    }
1358
1359    /// Reads the value of a global, capturing the context by value.
1360    #[inline]
1361    // TODO(gmoshkin): this method should be part of AsLua
1362    pub fn into_get<V, I>(self, index: I) -> Result<V, PushGuard<Self>>
1363    where
1364        I: Borrow<str>,
1365        V: LuaRead<PushGuard<Self>>,
1366    {
1367        let index = CString::new(index.borrow()).unwrap();
1368        unsafe {
1369            ffi::lua_getglobal(self.lua, index.as_ptr());
1370            V::lua_read(PushGuard::new(self, 1)).map_err(|(l, _)| l)
1371        }
1372    }
1373
1374    /// Modifies the value of a global variable.
1375    ///
1376    /// If you want to write an array, you are encouraged to use
1377    /// [the `empty_array` method](#method.empty_array) instead.
1378    ///
1379    /// The type must implement the `PushOne` trait. See
1380    /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
1381    /// information.
1382    ///
1383    /// # Example
1384    ///
1385    /// ```no_run
1386    /// use tlua::Lua;
1387    /// let lua = Lua::new();
1388    ///
1389    /// lua.set("a", 12);
1390    /// let six: i32 = lua.eval("return a / 2;").unwrap();
1391    /// assert_eq!(six, 6);
1392    /// ```
1393    #[inline]
1394    // TODO(gmoshkin): this method should be part of AsLua
1395    pub fn set<'lua, I, V>(&'lua self, index: I, value: V)
1396    where
1397        I: Borrow<str>,
1398        V: PushOneInto<&'lua Self>,
1399        <V as PushInto<&'lua Self>>::Err: Into<Void>,
1400    {
1401        match self.checked_set(index, value) {
1402            Ok(_) => (),
1403            Err(_) => unreachable!(),
1404        }
1405    }
1406
1407    /// Modifies the value of a global variable.
1408    // TODO: docs
1409    #[inline]
1410    // TODO(gmoshkin): this method should be part of AsLua
1411    pub fn checked_set<'lua, I, V>(
1412        &'lua self,
1413        index: I,
1414        value: V,
1415    ) -> Result<(), <V as PushInto<&'lua Self>>::Err>
1416    where
1417        I: Borrow<str>,
1418        V: PushOneInto<&'lua Self>,
1419    {
1420        unsafe {
1421            ffi::lua_pushglobaltable(self.lua);
1422            self.as_lua().push(index.borrow()).assert_one_and_forget();
1423            match self.try_push(value) {
1424                Ok(pushed) => {
1425                    assert_eq!(pushed.size, 1);
1426                    pushed.forget()
1427                }
1428                Err((err, lua)) => {
1429                    ffi::lua_pop(lua.as_lua(), 2);
1430                    return Err(err);
1431                }
1432            };
1433            ffi::lua_settable(self.lua, -3);
1434            ffi::lua_pop(self.lua, 1);
1435            Ok(())
1436        }
1437    }
1438
1439    /// Sets the value of a global variable to an empty array, then loads it.
1440    ///
1441    /// This is the function you should use if you want to set the value of a global variable to
1442    /// an array. After calling it, you will obtain a `LuaTable` object which you can then fill
1443    /// with the elements of the array.
1444    ///
1445    /// # Example
1446    ///
1447    /// ```no_run
1448    /// use tlua::Lua;
1449    /// let lua = Lua::new();
1450    /// lua.openlibs();     // Necessary for `ipairs`.
1451    ///
1452    /// {
1453    ///     let mut array = lua.empty_array("my_values");
1454    ///     array.set(1, 10);       // Don't forget that Lua arrays are indexed from 1.
1455    ///     array.set(2, 15);
1456    ///     array.set(3, 20);
1457    /// }
1458    ///
1459    /// let sum: i32 = lua.eval(r#"
1460    ///     local sum = 0
1461    ///     for i, val in ipairs(my_values) do
1462    ///         sum = sum + val
1463    ///     end
1464    ///     return sum
1465    /// "#).unwrap();
1466    ///
1467    /// assert_eq!(sum, 45);
1468    /// ```
1469    #[inline]
1470    // TODO(gmoshkin): this method should be part of AsLua
1471    pub fn empty_array<I>(&self, index: I) -> LuaTable<PushGuard<&Self>>
1472    where
1473        I: Borrow<str>,
1474    {
1475        unsafe {
1476            ffi::lua_pushglobaltable(self.as_lua());
1477            match index.borrow().push_to_lua(self.as_lua()) {
1478                Ok(pushed) => pushed.forget(),
1479                Err(_) => unreachable!(),
1480            };
1481            ffi::lua_newtable(self.as_lua());
1482            ffi::lua_settable(self.as_lua(), -3);
1483            ffi::lua_pop(self.as_lua(), 1);
1484
1485            // TODO: cleaner implementation
1486            self.get(index).unwrap()
1487        }
1488    }
1489
1490    /// Loads the array containing the global variables.
1491    ///
1492    /// In lua, the global variables accessible from the lua code are all part of a table which
1493    /// you can load here.
1494    ///
1495    /// # Examples
1496    ///
1497    /// The function can be used to write global variables, just like `set`.
1498    ///
1499    /// ```no_run
1500    /// use tlua::Lua;
1501    /// let lua = Lua::new();
1502    /// lua.globals_table().set("a", 5);
1503    /// assert_eq!(lua.get::<i32, _>("a"), Some(5));
1504    /// ```
1505    ///
1506    /// A more useful feature for this function is that it allows you to set the metatable of the
1507    /// global variables. See TODO for more info.
1508    ///
1509    /// ```no_run
1510    /// use tlua::Lua;
1511    /// use tlua::AnyLuaValue;
1512    ///
1513    /// let lua = Lua::new();
1514    /// {
1515    ///     let globals = lua.globals_table();
1516    ///     let metatable = globals.get_or_create_metatable();
1517    ///     metatable.set("__index", tlua::function2(|_: AnyLuaValue, var: String| -> AnyLuaValue {
1518    ///         println!("The user tried to access the variable {:?}", var);
1519    ///         AnyLuaValue::LuaNumber(48.0)
1520    ///     }));
1521    /// }
1522    ///
1523    /// let b: i32 = lua.eval("return b * 2;").unwrap();
1524    /// // -> The user tried to access the variable "b"
1525    ///
1526    /// assert_eq!(b, 96);
1527    /// ```
1528    #[inline]
1529    // TODO(gmoshkin): this method should be part of AsLua
1530    pub fn globals_table(&self) -> LuaTable<PushGuard<&Self>> {
1531        unsafe {
1532            ffi::lua_pushglobaltable(self.lua);
1533            let guard = PushGuard::new(self, 1);
1534            LuaRead::lua_read(guard).ok().unwrap()
1535        }
1536    }
1537}
1538
1539impl Default for TempLua {
1540    fn default() -> Self {
1541        Self::new()
1542    }
1543}
1544
1545impl<T> Drop for Lua<T>
1546where
1547    T: on_drop::OnDrop,
1548{
1549    #[inline]
1550    fn drop(&mut self) {
1551        self.on_drop.on_drop(self.lua)
1552    }
1553}
1554
1555impl<L: AsLua> Drop for PushGuard<L> {
1556    #[inline]
1557    fn drop(&mut self) {
1558        if self.size != 0 {
1559            unsafe {
1560                ffi::lua_pop(self.lua.as_lua(), self.size as _);
1561            }
1562        }
1563    }
1564}
1565
1566#[derive(Debug, Clone, Copy)]
1567pub struct AbsoluteIndex(NonZeroI32);
1568
1569impl AbsoluteIndex {
1570    /// Convert the non-zero index into an absolute index.
1571    ///
1572    /// # Panicking
1573    /// Will panic if `index` equals to `-1 - lua_gettop(lua)`.
1574    #[inline]
1575    #[track_caller]
1576    pub fn new<L>(index: NonZeroI32, lua: L) -> Self
1577    where
1578        L: AsLua,
1579    {
1580        Self::try_new(index, lua).expect("Invalid relative index")
1581    }
1582
1583    /// Convert the non-zero `index` into an absolute index or return `None` if
1584    /// the result would not be non-zero.
1585    #[inline]
1586    pub fn try_new<L>(index: impl Into<i32>, lua: L) -> Option<Self>
1587    where
1588        L: AsLua,
1589    {
1590        let top = unsafe { ffi::lua_gettop(lua.as_lua()) };
1591        let index = index.into();
1592        if ffi::is_relative_index(index) {
1593            NonZeroI32::new(top + index + 1).map(Self)
1594        } else {
1595            NonZeroI32::new(index).map(Self)
1596        }
1597    }
1598
1599    /// # Safety
1600    /// `index` must be a valid absolute or relative index into the lua stack
1601    /// with which it's going to be used
1602    pub unsafe fn new_unchecked(index: NonZeroI32) -> Self {
1603        Self(index)
1604    }
1605
1606    pub fn get(&self) -> u32 {
1607        self.0.get() as _
1608    }
1609}
1610
1611impl From<AbsoluteIndex> for i32 {
1612    fn from(index: AbsoluteIndex) -> i32 {
1613        index.0.get()
1614    }
1615}