1use std::cell::UnsafeCell;
2use std::hash::{Hash, Hasher};
3use std::os::raw::{c_int, c_void};
4use std::sync::{Arc, Mutex};
5use std::{fmt, mem, ptr};
6
7#[cfg(feature = "lua54")]
8use std::ffi::CStr;
9
10#[cfg(feature = "async")]
11use futures_core::future::LocalBoxFuture;
12
13use crate::error::Result;
14use crate::ffi;
15#[cfg(not(feature = "luau"))]
16use crate::hook::Debug;
17use crate::lua::{ExtraData, Lua};
18use crate::util::{assert_stack, StackGuard};
19use crate::value::MultiValue;
20
21pub type Integer = ffi::lua_Integer;
23pub type Number = ffi::lua_Number;
25
26#[derive(Debug, Copy, Clone, Eq, PartialEq)]
28pub struct LightUserData(pub *mut c_void);
29
30pub(crate) type Callback<'lua, 'a> =
31 Box<dyn Fn(&'lua Lua, MultiValue<'lua>) -> Result<MultiValue<'lua>> + 'a>;
32
33pub(crate) struct Upvalue<T> {
34 pub(crate) data: T,
35 pub(crate) extra: Arc<UnsafeCell<ExtraData>>,
36}
37
38pub(crate) type CallbackUpvalue = Upvalue<Callback<'static, 'static>>;
39
40#[cfg(feature = "async")]
41pub(crate) type AsyncCallback<'lua, 'a> =
42 Box<dyn Fn(&'lua Lua, MultiValue<'lua>) -> LocalBoxFuture<'lua, Result<MultiValue<'lua>>> + 'a>;
43
44#[cfg(feature = "async")]
45pub(crate) type AsyncCallbackUpvalue = Upvalue<AsyncCallback<'static, 'static>>;
46
47#[cfg(feature = "async")]
48pub(crate) type AsyncPollUpvalue = Upvalue<LocalBoxFuture<'static, Result<MultiValue<'static>>>>;
49
50#[cfg(any(feature = "luau", doc))]
52#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
53pub enum VmState {
54 Continue,
55 Yield,
56}
57
58#[cfg(all(feature = "send", not(feature = "luau")))]
59pub(crate) type HookCallback = Arc<dyn Fn(&Lua, Debug) -> Result<()> + Send>;
60
61#[cfg(all(not(feature = "send"), not(feature = "luau")))]
62pub(crate) type HookCallback = Arc<dyn Fn(&Lua, Debug) -> Result<()>>;
63
64#[cfg(all(feature = "luau", feature = "send"))]
65pub(crate) type InterruptCallback = Arc<dyn Fn() -> Result<VmState> + Send>;
66
67#[cfg(all(feature = "luau", not(feature = "send")))]
68pub(crate) type InterruptCallback = Arc<dyn Fn() -> Result<VmState>>;
69
70#[cfg(all(feature = "send", feature = "lua54"))]
71pub(crate) type WarnCallback = Box<dyn Fn(&Lua, &CStr, bool) -> Result<()> + Send>;
72
73#[cfg(all(not(feature = "send"), feature = "lua54"))]
74pub(crate) type WarnCallback = Box<dyn Fn(&Lua, &CStr, bool) -> Result<()>>;
75
76#[cfg(feature = "send")]
77pub trait MaybeSend: Send {}
78#[cfg(feature = "send")]
79impl<T: Send> MaybeSend for T {}
80
81#[cfg(not(feature = "send"))]
82pub trait MaybeSend {}
83#[cfg(not(feature = "send"))]
84impl<T> MaybeSend for T {}
85
86pub(crate) struct DestructedUserdataMT;
87
88pub struct RegistryKey {
106 pub(crate) registry_id: c_int,
107 pub(crate) unref_list: Arc<Mutex<Option<Vec<c_int>>>>,
108}
109
110impl fmt::Debug for RegistryKey {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 write!(f, "RegistryKey({})", self.registry_id)
113 }
114}
115
116impl Hash for RegistryKey {
117 fn hash<H: Hasher>(&self, state: &mut H) {
118 self.registry_id.hash(state)
119 }
120}
121
122impl PartialEq for RegistryKey {
123 fn eq(&self, other: &RegistryKey) -> bool {
124 self.registry_id == other.registry_id && Arc::ptr_eq(&self.unref_list, &other.unref_list)
125 }
126}
127
128impl Eq for RegistryKey {}
129
130impl Drop for RegistryKey {
131 fn drop(&mut self) {
132 let mut unref_list = mlua_expect!(self.unref_list.lock(), "unref list poisoned");
133 if let Some(list) = unref_list.as_mut() {
134 list.push(self.registry_id);
135 }
136 }
137}
138
139impl RegistryKey {
140 pub(crate) fn take(self) -> c_int {
142 let registry_id = self.registry_id;
143 unsafe {
144 ptr::read(&self.unref_list);
145 mem::forget(self);
146 }
147 registry_id
148 }
149}
150
151pub(crate) struct LuaRef<'lua> {
152 pub(crate) lua: &'lua Lua,
153 pub(crate) index: c_int,
154}
155
156impl<'lua> fmt::Debug for LuaRef<'lua> {
157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158 write!(f, "Ref({})", self.index)
159 }
160}
161
162impl<'lua> Clone for LuaRef<'lua> {
163 fn clone(&self) -> Self {
164 self.lua.clone_ref(self)
165 }
166}
167
168impl<'lua> Drop for LuaRef<'lua> {
169 fn drop(&mut self) {
170 if self.index > 0 {
171 self.lua.drop_ref(self);
172 }
173 }
174}
175
176impl<'lua> PartialEq for LuaRef<'lua> {
177 fn eq(&self, other: &Self) -> bool {
178 let lua = self.lua;
179 unsafe {
180 let _sg = StackGuard::new(lua.state);
181 assert_stack(lua.state, 2);
182 lua.push_ref(self);
183 lua.push_ref(other);
184 ffi::lua_rawequal(lua.state, -1, -2) == 1
185 }
186 }
187}