1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]

use std::ffi::{c_char, c_double, c_int, c_void};
use std::marker::{PhantomData, PhantomPinned};

#[repr(C)]
#[doc(hidden)]
pub struct lua_State {
    _data: [u8; 0],

    /// This marker ensures the struct is not `Send`, `Sync` and `Unpin` (the
    /// raw pointer is neither `Send` nor `Sync`, `PhantomPinned` is not
    /// `Unpin`).
    _marker: PhantomData<(*mut u8, PhantomPinned)>,
}

// Pseudo-indices.
pub const LUA_REGISTRYINDEX: c_int = -10000;
pub const LUA_ENVIRONINDEX: c_int = -10001;
pub const LUA_GLOBALSINDEX: c_int = -10002;

pub const fn lua_upvalueindex(i: c_int) -> c_int {
    LUA_GLOBALSINDEX - i
}

// Thread status.
pub const LUA_OK: c_int = 0;
pub const LUA_ERRRUN: c_int = 2;
pub const LUA_ERRMEM: c_int = 4;
pub const LUA_ERRERR: c_int = 5;

// Type codes.
pub const LUA_TNONE: c_int = -1;
pub const LUA_TNIL: c_int = 0;
pub const LUA_TBOOLEAN: c_int = 1;
pub const LUA_TLIGHTUSERDATA: c_int = 2;
pub const LUA_TNUMBER: c_int = 3;
pub const LUA_TSTRING: c_int = 4;
pub const LUA_TTABLE: c_int = 5;
pub const LUA_TFUNCTION: c_int = 6;
pub const LUA_TUSERDATA: c_int = 7;
pub const LUA_TTHREAD: c_int = 8;

// https://www.lua.org/manual/5.1/manual.html#lua_CFunction
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;

// https://www.lua.org/manual/5.1/manual.html#lua_Integer
pub type lua_Integer = isize;

// https://www.lua.org/manual/5.1/manual.html#lua_Number
pub type lua_Number = c_double;

extern "C" {
    // https://www.lua.org/manual/5.1/manual.html#lua_call
    pub fn lua_call(L: *mut lua_State, nargs: c_int, nresults: c_int);

    /// Binding to [`lua_createtable()`] (-0, +1).
    ///
    /// Creates a new empty table and pushes it onto the stack. The new table
    /// has space pre-allocated for `narr` array elements and `nrec` non-array
    /// elements.
    ///
    /// This pre-allocation is useful when you know exactly how many
    /// elements the table will have. Otherwise you can use the function
    /// `lua_newtable`.
    ///
    /// [`lua_createtable`]: https://www.lua.org/manual/5.1/manual.html#lua_createtable
    pub fn lua_createtable(L: *mut lua_State, narr: c_int, nrec: c_int);

    // https://www.lua.org/manual/5.1/manual.html#lua_error
    pub fn lua_error(L: *mut lua_State) -> !;

    // https://www.lua.org/manual/5.1/manual.html#lua_call
    pub fn lua_getfield(L: *mut lua_State, index: c_int, k: *const c_char);

    // https://www.lua.org/manual/5.1/manual.html#lua_getmetatable
    pub fn lua_getmetatable(L: *mut lua_State, index: c_int) -> c_int;

    // https://www.lua.org/manual/5.1/manual.html#lua_gettop
    pub fn lua_gettop(L: *mut lua_State) -> c_int;

    // https://www.lua.org/manual/5.1/manual.html#lua_newuserdata
    pub fn lua_newuserdata(L: *mut lua_State, size: usize) -> *mut c_void;

    // https://www.lua.org/manual/5.1/manual.html#lua_next
    pub fn lua_next(L: *mut lua_State, index: c_int) -> c_int;

    // https://www.lua.org/manual/5.1/manual.html#lua_objlen
    pub fn lua_objlen(L: *mut lua_State, index: c_int) -> usize;

    // https://www.lua.org/manual/5.1/manual.html#lua_pcall
    pub fn lua_pcall(
        L: *mut lua_State,
        nargs: c_int,
        nresults: c_int,
        errorfunc: c_int,
    ) -> c_int;

    // https://www.lua.org/manual/5.1/manual.html#lua_pushinteger
    pub fn lua_pushboolean(L: *mut lua_State, n: lua_Integer);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushcclosure
    pub fn lua_pushcclosure(L: *mut lua_State, r#fn: lua_CFunction, n: c_int);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushinteger
    pub fn lua_pushinteger(L: *mut lua_State, n: lua_Integer);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushlightuserdata
    pub fn lua_pushlightuserdata(L: *mut lua_State, p: *mut c_void);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushlstring
    pub fn lua_pushlstring(L: *mut lua_State, s: *const c_char, len: usize);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushnil
    pub fn lua_pushnil(L: *mut lua_State);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushnumber
    pub fn lua_pushnumber(L: *mut lua_State, n: lua_Number);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushstring
    pub fn lua_pushstring(L: *mut lua_State, s: *const c_char);

    // https://www.lua.org/manual/5.1/manual.html#lua_pushvalue
    pub fn lua_pushvalue(L: *mut lua_State, index: c_int);

    // https://www.lua.org/manual/5.1/manual.html#lua_rawgeti
    pub fn lua_rawgeti(L: *mut lua_State, index: c_int, n: c_int);

    // https://www.lua.org/manual/5.1/manual.html#lua_rawset
    pub fn lua_rawset(L: *mut lua_State, index: c_int);

    // https://www.lua.org/manual/5.1/manual.html#lua_rawseti
    pub fn lua_rawseti(L: *mut lua_State, index: c_int, n: c_int);

    // https://www.lua.org/manual/5.1/manual.html#lua_settop
    pub fn lua_settop(L: *mut lua_State, index: c_int);

    // https://www.lua.org/manual/5.1/manual.html#lua_toboolean
    pub fn lua_toboolean(L: *mut lua_State, index: c_int) -> c_int;

    // https://www.lua.org/manual/5.1/manual.html#lua_tointeger
    pub fn lua_tointeger(L: *mut lua_State, index: c_int) -> lua_Integer;

    // https://www.lua.org/manual/5.1/manual.html#lua_tolstring
    pub fn lua_tolstring(
        L: *mut lua_State,
        index: c_int,
        len: *mut usize,
    ) -> *const c_char;

    // https://www.lua.org/manual/5.1/manual.html#lua_tonumber
    pub fn lua_tonumber(L: *mut lua_State, index: c_int) -> lua_Number;

    // https://www.lua.org/manual/5.1/manual.html#lua_touserdata
    pub fn lua_touserdata(L: *mut lua_State, index: c_int) -> *mut c_void;

    // https://www.lua.org/manual/5.1/manual.html#lua_type
    pub fn lua_type(L: *mut lua_State, index: c_int) -> c_int;

    // https://www.lua.org/manual/5.1/manual.html#lua_typename
    pub fn lua_typename(L: *mut lua_State, tp: c_int) -> *const c_char;

    // Lua auxiliary library.

    // https://www.lua.org/manual/5.1/manual.html#luaL_error
    pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;

    // https://www.lua.org/manual/5.1/manual.html#luaL_ref
    pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;

    // https://www.lua.org/manual/5.1/manual.html#luaL_unref
    pub fn luaL_unref(L: *mut lua_State, t: c_int, r#ref: c_int);
}

// https://www.lua.org/manual/5.1/manual.html#lua_getglobal
pub unsafe fn lua_getglobal(L: *mut lua_State, name: *const c_char) {
    lua_getfield(L, LUA_GLOBALSINDEX, name)
}

// https://www.lua.org/manual/5.1/manual.html#lua_pop
pub unsafe fn lua_pop(L: *mut lua_State, n: c_int) {
    lua_settop(L, -n - 1)
}

// https://www.lua.org/manual/5.1/manual.html#lua_pushcfunction
pub unsafe fn lua_pushcfunction(L: *mut lua_State, r#fn: lua_CFunction) {
    lua_pushcclosure(L, r#fn, 0)
}

// https://www.lua.org/manual/5.1/manual.html#lua_tostring
pub unsafe fn lua_tostring(L: *mut lua_State, index: c_int) -> *const c_char {
    lua_tolstring(L, index, std::ptr::null_mut())
}

// https://www.lua.org/manual/5.1/manual.html#luaL_typename
pub unsafe fn luaL_typename(L: *mut lua_State, index: c_int) -> *const c_char {
    lua_typename(L, lua_type(L, index))
}