mlua_codemp_patch/state.rs
1use std::any::TypeId;
2use std::cell::RefCell;
3use std::marker::PhantomData;
4use std::ops::Deref;
5use std::os::raw::{c_int, c_void};
6use std::panic::Location;
7use std::result::Result as StdResult;
8use std::{fmt, mem, ptr};
9
10use crate::chunk::{AsChunk, Chunk};
11use crate::error::{Error, Result};
12use crate::function::Function;
13use crate::hook::Debug;
14use crate::memory::MemoryState;
15// use crate::scope::Scope;
16use crate::stdlib::StdLib;
17use crate::string::String;
18use crate::table::Table;
19use crate::thread::Thread;
20use crate::types::{
21 AppDataRef, AppDataRefMut, ArcReentrantMutexGuard, Integer, LightUserData, MaybeSend, Number,
22 ReentrantMutex, ReentrantMutexGuard, RegistryKey, XRc, XWeak,
23};
24use crate::userdata::{AnyUserData, UserData, UserDataProxy, UserDataRegistry, UserDataVariant};
25use crate::util::{assert_stack, check_stack, push_string, push_table, rawset_field, StackGuard};
26use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil, Value};
27
28#[cfg(not(feature = "luau"))]
29use crate::hook::HookTriggers;
30
31#[cfg(any(feature = "luau", doc))]
32use crate::{chunk::Compiler, types::VmState};
33
34#[cfg(feature = "async")]
35use std::future::{self, Future};
36
37#[cfg(feature = "serialize")]
38use serde::Serialize;
39
40pub(crate) use extra::ExtraData;
41pub use raw::RawLua;
42use util::{callback_error_ext, StateGuard};
43
44/// Top level Lua struct which represents an instance of Lua VM.
45#[derive(Clone)]
46pub struct Lua {
47 pub(self) raw: XRc<ReentrantMutex<RawLua>>,
48 // Controls whether garbage collection should be run on drop
49 pub(self) collect_garbage: bool,
50}
51
52#[derive(Clone)]
53pub(crate) struct WeakLua(XWeak<ReentrantMutex<RawLua>>);
54
55pub(crate) struct LuaGuard(ArcReentrantMutexGuard<RawLua>);
56
57/// Mode of the Lua garbage collector (GC).
58///
59/// In Lua 5.4 GC can work in two modes: incremental and generational.
60/// Previous Lua versions support only incremental GC.
61///
62/// More information can be found in the Lua [documentation].
63///
64/// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
65#[derive(Clone, Copy, Debug, PartialEq, Eq)]
66pub enum GCMode {
67 Incremental,
68 /// Requires `feature = "lua54"`
69 #[cfg(feature = "lua54")]
70 #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
71 Generational,
72}
73
74/// Controls Lua interpreter behavior such as Rust panics handling.
75#[derive(Clone, Debug)]
76#[non_exhaustive]
77pub struct LuaOptions {
78 /// Catch Rust panics when using [`pcall`]/[`xpcall`].
79 ///
80 /// If disabled, wraps these functions and automatically resumes panic if found.
81 /// Also in Lua 5.1 adds ability to provide arguments to [`xpcall`] similar to Lua >= 5.2.
82 ///
83 /// If enabled, keeps [`pcall`]/[`xpcall`] unmodified.
84 /// Panics are still automatically resumed if returned to the Rust side.
85 ///
86 /// Default: **true**
87 ///
88 /// [`pcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-pcall
89 /// [`xpcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-xpcall
90 pub catch_rust_panics: bool,
91
92 /// Max size of thread (coroutine) object pool used to execute asynchronous functions.
93 ///
94 /// It works on Lua 5.4 and Luau, where [`lua_resetthread`] function
95 /// is available and allows to reuse old coroutines after resetting their state.
96 ///
97 /// Default: **0** (disabled)
98 ///
99 /// [`lua_resetthread`]: https://www.lua.org/manual/5.4/manual.html#lua_resetthread
100 #[cfg(feature = "async")]
101 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
102 pub thread_pool_size: usize,
103}
104
105impl Default for LuaOptions {
106 fn default() -> Self {
107 const { LuaOptions::new() }
108 }
109}
110
111impl LuaOptions {
112 /// Returns a new instance of `LuaOptions` with default parameters.
113 pub const fn new() -> Self {
114 LuaOptions {
115 catch_rust_panics: true,
116 #[cfg(feature = "async")]
117 thread_pool_size: 0,
118 }
119 }
120
121 /// Sets [`catch_rust_panics`] option.
122 ///
123 /// [`catch_rust_panics`]: #structfield.catch_rust_panics
124 #[must_use]
125 pub const fn catch_rust_panics(mut self, enabled: bool) -> Self {
126 self.catch_rust_panics = enabled;
127 self
128 }
129
130 /// Sets [`thread_pool_size`] option.
131 ///
132 /// [`thread_pool_size`]: #structfield.thread_pool_size
133 #[cfg(feature = "async")]
134 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
135 #[must_use]
136 pub const fn thread_pool_size(mut self, size: usize) -> Self {
137 self.thread_pool_size = size;
138 self
139 }
140}
141
142impl Drop for Lua {
143 fn drop(&mut self) {
144 if self.collect_garbage {
145 let _ = self.gc_collect();
146 }
147 }
148}
149
150impl fmt::Debug for Lua {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 write!(f, "Lua({:p})", self.lock().state())
153 }
154}
155
156impl Default for Lua {
157 #[inline]
158 fn default() -> Self {
159 Lua::new()
160 }
161}
162
163impl Lua {
164 /// Creates a new Lua state and loads the **safe** subset of the standard libraries.
165 ///
166 /// # Safety
167 /// The created Lua state would have _some_ safety guarantees and would not allow to load unsafe
168 /// standard libraries or C modules.
169 ///
170 /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
171 ///
172 /// [`StdLib`]: crate::StdLib
173 pub fn new() -> Lua {
174 mlua_expect!(
175 Self::new_with(StdLib::ALL_SAFE, LuaOptions::default()),
176 "Cannot create a Lua state"
177 )
178 }
179
180 /// Creates a new Lua state and loads all the standard libraries.
181 ///
182 /// # Safety
183 /// The created Lua state would not have safety guarantees and would allow to load C modules.
184 pub unsafe fn unsafe_new() -> Lua {
185 Self::unsafe_new_with(StdLib::ALL, LuaOptions::default())
186 }
187
188 /// Creates a new Lua state and loads the specified safe subset of the standard libraries.
189 ///
190 /// Use the [`StdLib`] flags to specify the libraries you want to load.
191 ///
192 /// # Safety
193 /// The created Lua state would have _some_ safety guarantees and would not allow to load unsafe
194 /// standard libraries or C modules.
195 ///
196 /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
197 ///
198 /// [`StdLib`]: crate::StdLib
199 pub fn new_with(libs: StdLib, options: LuaOptions) -> Result<Lua> {
200 #[cfg(not(feature = "luau"))]
201 if libs.contains(StdLib::DEBUG) {
202 return Err(Error::SafetyError(
203 "The unsafe `debug` module can't be loaded using safe `new_with`".to_string(),
204 ));
205 }
206 #[cfg(feature = "luajit")]
207 if libs.contains(StdLib::FFI) {
208 return Err(Error::SafetyError(
209 "The unsafe `ffi` module can't be loaded using safe `new_with`".to_string(),
210 ));
211 }
212
213 let lua = unsafe { Self::inner_new(libs, options) };
214
215 if libs.contains(StdLib::PACKAGE) {
216 mlua_expect!(lua.disable_c_modules(), "Error disabling C modules");
217 }
218 unsafe { lua.lock().set_safe() };
219
220 Ok(lua)
221 }
222
223 /// Creates a new Lua state and loads the specified subset of the standard libraries.
224 ///
225 /// Use the [`StdLib`] flags to specify the libraries you want to load.
226 ///
227 /// # Safety
228 /// The created Lua state will not have safety guarantees and allow to load C modules.
229 ///
230 /// [`StdLib`]: crate::StdLib
231 pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
232 // Workaround to avoid stripping a few unused Lua symbols that could be imported
233 // by C modules in unsafe mode
234 let mut _symbols: Vec<*const extern "C-unwind" fn()> =
235 vec![ffi::lua_isuserdata as _, ffi::lua_tocfunction as _];
236
237 #[cfg(not(feature = "luau"))]
238 _symbols.extend_from_slice(&[
239 ffi::lua_atpanic as _,
240 ffi::luaL_loadstring as _,
241 ffi::luaL_openlibs as _,
242 ]);
243 #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
244 {
245 _symbols.push(ffi::lua_getglobal as _);
246 _symbols.push(ffi::lua_setglobal as _);
247 _symbols.push(ffi::luaL_setfuncs as _);
248 }
249
250 Self::inner_new(libs, options)
251 }
252
253 /// Creates a new Lua state with required `libs` and `options`
254 unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
255 let lua = Lua {
256 raw: RawLua::new(libs, options),
257 collect_garbage: true,
258 };
259
260 #[cfg(feature = "luau")]
261 mlua_expect!(lua.configure_luau(), "Error configuring Luau");
262
263 lua
264 }
265
266 /// Constructs a new Lua instance from an existing raw state.
267 ///
268 /// Once called, a returned Lua state is cached in the registry and can be retrieved
269 /// by calling this function again.
270 #[allow(clippy::missing_safety_doc)]
271 #[inline]
272 pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua {
273 Lua {
274 raw: RawLua::init_from_ptr(state, false),
275 collect_garbage: true,
276 }
277 }
278
279 /// FIXME: Deprecated load_from_std_lib
280
281 /// Loads the specified subset of the standard libraries into an existing Lua state.
282 ///
283 /// Use the [`StdLib`] flags to specify the libraries you want to load.
284 pub fn load_std_libs(&self, libs: StdLib) -> Result<()> {
285 unsafe { self.lock().load_std_libs(libs) }
286 }
287
288 /// Loads module `modname` into an existing Lua state using the specified entrypoint
289 /// function.
290 ///
291 /// Internally calls the Lua function `func` with the string `modname` as an argument,
292 /// sets the call result to `package.loaded[modname]` and returns copy of the result.
293 ///
294 /// If `package.loaded[modname]` value is not nil, returns copy of the value without
295 /// calling the function.
296 ///
297 /// If the function does not return a non-nil value then this method assigns true to
298 /// `package.loaded[modname]`.
299 ///
300 /// Behavior is similar to Lua's [`require`] function.
301 ///
302 /// [`require`]: https://www.lua.org/manual/5.4/manual.html#pdf-require
303 pub fn load_from_function<T>(&self, modname: &str, func: Function) -> Result<T>
304 where
305 T: FromLua,
306 {
307 let lua = self.lock();
308 let state = lua.state();
309 let loaded = unsafe {
310 let _sg = StackGuard::new(state);
311 check_stack(state, 2)?;
312 protect_lua!(state, 0, 1, fn(state) {
313 ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
314 })?;
315 Table(lua.pop_ref())
316 };
317
318 let modname = unsafe { lua.create_string(modname)? };
319 let value = match loaded.raw_get(&modname)? {
320 Value::Nil => {
321 let result = match func.call(&modname)? {
322 Value::Nil => Value::Boolean(true),
323 res => res,
324 };
325 loaded.raw_set(modname, &result)?;
326 result
327 }
328 res => res,
329 };
330 T::from_lua(value, self)
331 }
332
333 /// Unloads module `modname`.
334 ///
335 /// Removes module from the [`package.loaded`] table which allows to load it again.
336 /// It does not support unloading binary Lua modules since they are internally cached and can be
337 /// unloaded only by closing Lua state.
338 ///
339 /// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
340 pub fn unload(&self, modname: &str) -> Result<()> {
341 let lua = self.lock();
342 let state = lua.state();
343 let loaded = unsafe {
344 let _sg = StackGuard::new(state);
345 check_stack(state, 2)?;
346 protect_lua!(state, 0, 1, fn(state) {
347 ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
348 })?;
349 Table(lua.pop_ref())
350 };
351
352 loaded.raw_set(modname, Nil)
353 }
354
355 // Executes module entrypoint function, which returns only one Value.
356 // The returned value then pushed onto the stack.
357 #[doc(hidden)]
358 #[cfg(not(tarpaulin_include))]
359 pub unsafe fn entrypoint<F, A, R>(state: *mut ffi::lua_State, func: F) -> c_int
360 where
361 F: FnOnce(&Lua, A) -> Result<R>,
362 A: FromLuaMulti,
363 R: IntoLua,
364 {
365 // Make sure that Lua is initialized
366 let mut lua = Self::init_from_ptr(state);
367 lua.collect_garbage = false;
368 // `Lua` is no longer needed and must be dropped at this point to avoid possible memory leak
369 // in case of possible longjmp (lua_error) below
370 drop(lua);
371
372 callback_error_ext(state, ptr::null_mut(), move |extra, nargs| {
373 let rawlua = (*extra).raw_lua();
374 let _guard = StateGuard::new(rawlua, state);
375 let args = A::from_stack_args(nargs, 1, None, rawlua)?;
376 func(rawlua.lua(), args)?.push_into_stack(rawlua)?;
377 Ok(1)
378 })
379 }
380
381 // A simple module entrypoint without arguments
382 #[doc(hidden)]
383 #[cfg(not(tarpaulin_include))]
384 pub unsafe fn entrypoint1<F, R>(state: *mut ffi::lua_State, func: F) -> c_int
385 where
386 F: FnOnce(&Lua) -> Result<R>,
387 R: IntoLua,
388 {
389 Self::entrypoint(state, move |lua, _: ()| func(lua))
390 }
391
392 /// Skips memory checks for some operations.
393 #[doc(hidden)]
394 #[cfg(feature = "module")]
395 pub fn skip_memory_check(&self, skip: bool) {
396 let lua = self.lock();
397 unsafe { (*lua.extra.get()).skip_memory_check = skip };
398 }
399
400 /// Enables (or disables) sandbox mode on this Lua instance.
401 ///
402 /// This method, in particular:
403 /// - Set all libraries to read-only
404 /// - Set all builtin metatables to read-only
405 /// - Set globals to read-only (and activates safeenv)
406 /// - Setup local environment table that performs writes locally and proxies reads to the global
407 /// environment.
408 ///
409 /// # Examples
410 ///
411 /// ```
412 /// # use mlua::{Lua, Result};
413 /// # fn main() -> Result<()> {
414 /// let lua = Lua::new();
415 ///
416 /// lua.sandbox(true)?;
417 /// lua.load("var = 123").exec()?;
418 /// assert_eq!(lua.globals().get::<u32>("var")?, 123);
419 ///
420 /// // Restore the global environment (clear changes made in sandbox)
421 /// lua.sandbox(false)?;
422 /// assert_eq!(lua.globals().get::<Option<u32>>("var")?, None);
423 /// # Ok(())
424 /// # }
425 /// ```
426 ///
427 /// Requires `feature = "luau"`
428 #[cfg(any(feature = "luau", docsrs))]
429 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
430 pub fn sandbox(&self, enabled: bool) -> Result<()> {
431 let lua = self.lock();
432 unsafe {
433 if (*lua.extra.get()).sandboxed != enabled {
434 let state = lua.main_state;
435 check_stack(state, 3)?;
436 protect_lua!(state, 0, 0, |state| {
437 if enabled {
438 ffi::luaL_sandbox(state, 1);
439 ffi::luaL_sandboxthread(state);
440 } else {
441 // Restore original `LUA_GLOBALSINDEX`
442 ffi::lua_xpush(lua.ref_thread(), state, ffi::LUA_GLOBALSINDEX);
443 ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
444 ffi::luaL_sandbox(state, 0);
445 }
446 })?;
447 (*lua.extra.get()).sandboxed = enabled;
448 }
449 Ok(())
450 }
451 }
452
453 /// Sets a 'hook' function that will periodically be called as Lua code executes.
454 ///
455 /// When exactly the hook function is called depends on the contents of the `triggers`
456 /// parameter, see [`HookTriggers`] for more details.
457 ///
458 /// The provided hook function can error, and this error will be propagated through the Lua code
459 /// that was executing at the time the hook was triggered. This can be used to implement a
460 /// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and
461 /// erroring once an instruction limit has been reached.
462 ///
463 /// This method sets a hook function for the current thread of this Lua instance.
464 /// If you want to set a hook function for another thread (coroutine), use
465 /// [`Thread::set_hook()`] instead.
466 ///
467 /// Please note you cannot have more than one hook function set at a time for this Lua instance.
468 ///
469 /// # Example
470 ///
471 /// Shows each line number of code being executed by the Lua interpreter.
472 ///
473 /// ```
474 /// # use mlua::{Lua, HookTriggers, Result};
475 /// # fn main() -> Result<()> {
476 /// let lua = Lua::new();
477 /// lua.set_hook(HookTriggers::EVERY_LINE, |_lua, debug| {
478 /// println!("line {}", debug.curr_line());
479 /// Ok(())
480 /// });
481 ///
482 /// lua.load(r#"
483 /// local x = 2 + 3
484 /// local y = x * 63
485 /// local z = string.len(x..", "..y)
486 /// "#).exec()
487 /// # }
488 /// ```
489 ///
490 /// [`HookTriggers`]: crate::HookTriggers
491 /// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
492 #[cfg(not(feature = "luau"))]
493 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
494 pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F)
495 where
496 F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
497 {
498 let lua = self.lock();
499 unsafe { lua.set_thread_hook(lua.state(), triggers, callback) };
500 }
501
502 /// Removes any hook previously set by [`Lua::set_hook()`] or [`Thread::set_hook()`].
503 ///
504 /// This function has no effect if a hook was not previously set.
505 #[cfg(not(feature = "luau"))]
506 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
507 pub fn remove_hook(&self) {
508 let lua = self.lock();
509 unsafe {
510 let state = lua.state();
511 ffi::lua_sethook(state, None, 0, 0);
512 match crate::util::get_main_state(lua.main_state) {
513 Some(main_state) if !ptr::eq(state, main_state) => {
514 // If main_state is different from state, remove hook from it too
515 ffi::lua_sethook(main_state, None, 0, 0);
516 }
517 _ => {}
518 };
519 (*lua.extra.get()).hook_callback = None;
520 (*lua.extra.get()).hook_thread = ptr::null_mut();
521 }
522 }
523
524 /// Sets an 'interrupt' function that will periodically be called by Luau VM.
525 ///
526 /// Any Luau code is guaranteed to call this handler "eventually"
527 /// (in practice this can happen at any function call or at any loop iteration).
528 ///
529 /// The provided interrupt function can error, and this error will be propagated through
530 /// the Luau code that was executing at the time the interrupt was triggered.
531 /// Also this can be used to implement continuous execution limits by instructing Luau VM to
532 /// yield by returning [`VmState::Yield`].
533 ///
534 /// This is similar to [`Lua::set_hook`] but in more simplified form.
535 ///
536 /// # Example
537 ///
538 /// Periodically yield Luau VM to suspend execution.
539 ///
540 /// ```
541 /// # use std::sync::{Arc, atomic::{AtomicU64, Ordering}};
542 /// # use mlua::{Lua, Result, ThreadStatus, VmState};
543 /// # fn main() -> Result<()> {
544 /// let lua = Lua::new();
545 /// let count = Arc::new(AtomicU64::new(0));
546 /// lua.set_interrupt(move |_| {
547 /// if count.fetch_add(1, Ordering::Relaxed) % 2 == 0 {
548 /// return Ok(VmState::Yield);
549 /// }
550 /// Ok(VmState::Continue)
551 /// });
552 ///
553 /// let co = lua.create_thread(
554 /// lua.load(r#"
555 /// local b = 0
556 /// for _, x in ipairs({1, 2, 3}) do b += x end
557 /// "#)
558 /// .into_function()?,
559 /// )?;
560 /// while co.status() == ThreadStatus::Resumable {
561 /// co.resume(())?;
562 /// }
563 /// # Ok(())
564 /// # }
565 /// ```
566 #[cfg(any(feature = "luau", docsrs))]
567 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
568 pub fn set_interrupt<F>(&self, callback: F)
569 where
570 F: Fn(&Lua) -> Result<VmState> + MaybeSend + 'static,
571 {
572 use std::rc::Rc;
573
574 unsafe extern "C-unwind" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) {
575 if gc >= 0 {
576 // We don't support GC interrupts since they cannot survive Lua exceptions
577 return;
578 }
579 let result = callback_error_ext(state, ptr::null_mut(), move |extra, _| {
580 let interrupt_cb = (*extra).interrupt_callback.clone();
581 let interrupt_cb = mlua_expect!(interrupt_cb, "no interrupt callback set in interrupt_proc");
582 if Rc::strong_count(&interrupt_cb) > 2 {
583 return Ok(VmState::Continue); // Don't allow recursion
584 }
585 let _guard = StateGuard::new((*extra).raw_lua(), state);
586 interrupt_cb((*extra).lua())
587 });
588 match result {
589 VmState::Continue => {}
590 VmState::Yield => {
591 ffi::lua_yield(state, 0);
592 }
593 }
594 }
595
596 // Set interrupt callback
597 let lua = self.lock();
598 unsafe {
599 (*lua.extra.get()).interrupt_callback = Some(Rc::new(callback));
600 (*ffi::lua_callbacks(lua.main_state)).interrupt = Some(interrupt_proc);
601 }
602 }
603
604 /// Removes any 'interrupt' previously set by `set_interrupt`.
605 ///
606 /// This function has no effect if an 'interrupt' was not previously set.
607 #[cfg(any(feature = "luau", docsrs))]
608 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
609 pub fn remove_interrupt(&self) {
610 let lua = self.lock();
611 unsafe {
612 (*lua.extra.get()).interrupt_callback = None;
613 (*ffi::lua_callbacks(lua.main_state)).interrupt = None;
614 }
615 }
616
617 /// Sets the warning function to be used by Lua to emit warnings.
618 ///
619 /// Requires `feature = "lua54"`
620 #[cfg(feature = "lua54")]
621 #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
622 pub fn set_warning_function<F>(&self, callback: F)
623 where
624 F: Fn(&Lua, &str, bool) -> Result<()> + MaybeSend + 'static,
625 {
626 use std::ffi::CStr;
627 use std::os::raw::c_char;
628 use std::string::String as StdString;
629
630 unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
631 let extra = ud as *mut ExtraData;
632 callback_error_ext((*extra).raw_lua().state(), extra, |extra, _| {
633 let cb = mlua_expect!(
634 (*extra).warn_callback.as_ref(),
635 "no warning callback set in warn_proc"
636 );
637 let msg = StdString::from_utf8_lossy(CStr::from_ptr(msg).to_bytes());
638 cb((*extra).lua(), &msg, tocont != 0)
639 });
640 }
641
642 let lua = self.lock();
643 let state = lua.main_state;
644 unsafe {
645 (*lua.extra.get()).warn_callback = Some(Box::new(callback));
646 ffi::lua_setwarnf(state, Some(warn_proc), lua.extra.get() as *mut c_void);
647 }
648 }
649
650 /// Removes warning function previously set by `set_warning_function`.
651 ///
652 /// This function has no effect if a warning function was not previously set.
653 ///
654 /// Requires `feature = "lua54"`
655 #[cfg(feature = "lua54")]
656 #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
657 pub fn remove_warning_function(&self) {
658 let lua = self.lock();
659 unsafe {
660 (*lua.extra.get()).warn_callback = None;
661 ffi::lua_setwarnf(lua.main_state, None, ptr::null_mut());
662 }
663 }
664
665 /// Emits a warning with the given message.
666 ///
667 /// A message in a call with `incomplete` set to `true` should be continued in
668 /// another call to this function.
669 ///
670 /// Requires `feature = "lua54"`
671 #[cfg(feature = "lua54")]
672 #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
673 pub fn warning(&self, msg: impl AsRef<str>, incomplete: bool) {
674 let msg = msg.as_ref();
675 let mut bytes = vec![0; msg.len() + 1];
676 bytes[..msg.len()].copy_from_slice(msg.as_bytes());
677 let real_len = bytes.iter().position(|&c| c == 0).unwrap();
678 bytes.truncate(real_len);
679 let lua = self.lock();
680 unsafe {
681 ffi::lua_warning(lua.state(), bytes.as_ptr() as *const _, incomplete as c_int);
682 }
683 }
684
685 /// Gets information about the interpreter runtime stack.
686 ///
687 /// This function returns [`Debug`] structure that can be used to get information about the
688 /// function executing at a given level. Level `0` is the current running function, whereas
689 /// level `n+1` is the function that has called level `n` (except for tail calls, which do
690 /// not count in the stack).
691 ///
692 /// [`Debug`]: crate::hook::Debug
693 pub fn inspect_stack(&self, level: usize) -> Option<Debug> {
694 let lua = self.lock();
695 unsafe {
696 let mut ar: ffi::lua_Debug = mem::zeroed();
697 let level = level as c_int;
698 #[cfg(not(feature = "luau"))]
699 if ffi::lua_getstack(lua.state(), level, &mut ar) == 0 {
700 return None;
701 }
702 #[cfg(feature = "luau")]
703 if ffi::lua_getinfo(lua.state(), level, cstr!(""), &mut ar) == 0 {
704 return None;
705 }
706 Some(Debug::new_owned(lua, level, ar))
707 }
708 }
709
710 /// Returns the amount of memory (in bytes) currently used inside this Lua state.
711 pub fn used_memory(&self) -> usize {
712 let lua = self.lock();
713 unsafe {
714 match MemoryState::get(lua.main_state) {
715 mem_state if !mem_state.is_null() => (*mem_state).used_memory(),
716 _ => {
717 // Get data from the Lua GC
718 let used_kbytes = ffi::lua_gc(lua.main_state, ffi::LUA_GCCOUNT, 0);
719 let used_kbytes_rem = ffi::lua_gc(lua.main_state, ffi::LUA_GCCOUNTB, 0);
720 (used_kbytes as usize) * 1024 + (used_kbytes_rem as usize)
721 }
722 }
723 }
724 }
725
726 /// Sets a memory limit (in bytes) on this Lua state.
727 ///
728 /// Once an allocation occurs that would pass this memory limit,
729 /// a `Error::MemoryError` is generated instead.
730 /// Returns previous limit (zero means no limit).
731 ///
732 /// Does not work in module mode where Lua state is managed externally.
733 pub fn set_memory_limit(&self, limit: usize) -> Result<usize> {
734 let lua = self.lock();
735 unsafe {
736 match MemoryState::get(lua.main_state) {
737 mem_state if !mem_state.is_null() => Ok((*mem_state).set_memory_limit(limit)),
738 _ => Err(Error::MemoryLimitNotAvailable),
739 }
740 }
741 }
742
743 /// Returns true if the garbage collector is currently running automatically.
744 ///
745 /// Requires `feature = "lua54/lua53/lua52/luau"`
746 #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52", feature = "luau"))]
747 pub fn gc_is_running(&self) -> bool {
748 let lua = self.lock();
749 unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCISRUNNING, 0) != 0 }
750 }
751
752 /// Stop the Lua GC from running
753 pub fn gc_stop(&self) {
754 let lua = self.lock();
755 unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCSTOP, 0) };
756 }
757
758 /// Restarts the Lua GC if it is not running
759 pub fn gc_restart(&self) {
760 let lua = self.lock();
761 unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCRESTART, 0) };
762 }
763
764 /// Perform a full garbage-collection cycle.
765 ///
766 /// It may be necessary to call this function twice to collect all currently unreachable
767 /// objects. Once to finish the current gc cycle, and once to start and finish the next cycle.
768 pub fn gc_collect(&self) -> Result<()> {
769 let lua = self.lock();
770 unsafe {
771 check_stack(lua.main_state, 2)?;
772 protect_lua!(lua.main_state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
773 }
774 }
775
776 /// Steps the garbage collector one indivisible step.
777 ///
778 /// Returns true if this has finished a collection cycle.
779 pub fn gc_step(&self) -> Result<bool> {
780 self.gc_step_kbytes(0)
781 }
782
783 /// Steps the garbage collector as though memory had been allocated.
784 ///
785 /// if `kbytes` is 0, then this is the same as calling `gc_step`. Returns true if this step has
786 /// finished a collection cycle.
787 pub fn gc_step_kbytes(&self, kbytes: c_int) -> Result<bool> {
788 let lua = self.lock();
789 unsafe {
790 check_stack(lua.main_state, 3)?;
791 protect_lua!(lua.main_state, 0, 0, |state| {
792 ffi::lua_gc(state, ffi::LUA_GCSTEP, kbytes) != 0
793 })
794 }
795 }
796
797 /// Sets the 'pause' value of the collector.
798 ///
799 /// Returns the previous value of 'pause'. More information can be found in the Lua
800 /// [documentation].
801 ///
802 /// For Luau this parameter sets GC goal
803 ///
804 /// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
805 pub fn gc_set_pause(&self, pause: c_int) -> c_int {
806 let lua = self.lock();
807 unsafe {
808 #[cfg(not(feature = "luau"))]
809 return ffi::lua_gc(lua.main_state, ffi::LUA_GCSETPAUSE, pause);
810 #[cfg(feature = "luau")]
811 return ffi::lua_gc(lua.main_state, ffi::LUA_GCSETGOAL, pause);
812 }
813 }
814
815 /// Sets the 'step multiplier' value of the collector.
816 ///
817 /// Returns the previous value of the 'step multiplier'. More information can be found in the
818 /// Lua [documentation].
819 ///
820 /// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
821 pub fn gc_set_step_multiplier(&self, step_multiplier: c_int) -> c_int {
822 let lua = self.lock();
823 unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCSETSTEPMUL, step_multiplier) }
824 }
825
826 /// Changes the collector to incremental mode with the given parameters.
827 ///
828 /// Returns the previous mode (always `GCMode::Incremental` in Lua < 5.4).
829 /// More information can be found in the Lua [documentation].
830 ///
831 /// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5.1
832 pub fn gc_inc(&self, pause: c_int, step_multiplier: c_int, step_size: c_int) -> GCMode {
833 let lua = self.lock();
834 let state = lua.main_state;
835
836 #[cfg(any(
837 feature = "lua53",
838 feature = "lua52",
839 feature = "lua51",
840 feature = "luajit",
841 feature = "luau"
842 ))]
843 unsafe {
844 if pause > 0 {
845 #[cfg(not(feature = "luau"))]
846 ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, pause);
847 #[cfg(feature = "luau")]
848 ffi::lua_gc(state, ffi::LUA_GCSETGOAL, pause);
849 }
850
851 if step_multiplier > 0 {
852 ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, step_multiplier);
853 }
854
855 #[cfg(feature = "luau")]
856 if step_size > 0 {
857 ffi::lua_gc(state, ffi::LUA_GCSETSTEPSIZE, step_size);
858 }
859 #[cfg(not(feature = "luau"))]
860 let _ = step_size; // Ignored
861
862 GCMode::Incremental
863 }
864
865 #[cfg(feature = "lua54")]
866 let prev_mode = unsafe { ffi::lua_gc(state, ffi::LUA_GCINC, pause, step_multiplier, step_size) };
867 #[cfg(feature = "lua54")]
868 match prev_mode {
869 ffi::LUA_GCINC => GCMode::Incremental,
870 ffi::LUA_GCGEN => GCMode::Generational,
871 _ => unreachable!(),
872 }
873 }
874
875 /// Changes the collector to generational mode with the given parameters.
876 ///
877 /// Returns the previous mode. More information about the generational GC
878 /// can be found in the Lua 5.4 [documentation][lua_doc].
879 ///
880 /// Requires `feature = "lua54"`
881 ///
882 /// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5.2
883 #[cfg(feature = "lua54")]
884 #[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
885 pub fn gc_gen(&self, minor_multiplier: c_int, major_multiplier: c_int) -> GCMode {
886 let lua = self.lock();
887 let state = lua.main_state;
888 let prev_mode = unsafe { ffi::lua_gc(state, ffi::LUA_GCGEN, minor_multiplier, major_multiplier) };
889 match prev_mode {
890 ffi::LUA_GCGEN => GCMode::Generational,
891 ffi::LUA_GCINC => GCMode::Incremental,
892 _ => unreachable!(),
893 }
894 }
895
896 /// Sets a default Luau compiler (with custom options).
897 ///
898 /// This compiler will be used by default to load all Lua chunks
899 /// including via `require` function.
900 ///
901 /// See [`Compiler`] for details and possible options.
902 ///
903 /// Requires `feature = "luau"`
904 #[cfg(any(feature = "luau", doc))]
905 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
906 pub fn set_compiler(&self, compiler: Compiler) {
907 let lua = self.lock();
908 unsafe { (*lua.extra.get()).compiler = Some(compiler) };
909 }
910
911 /// Toggles JIT compilation mode for new chunks of code.
912 ///
913 /// By default JIT is enabled. Changing this option does not have any effect on
914 /// already loaded functions.
915 #[cfg(any(feature = "luau-jit", doc))]
916 #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
917 pub fn enable_jit(&self, enable: bool) {
918 let lua = self.lock();
919 unsafe { (*lua.extra.get()).enable_jit = enable };
920 }
921
922 /// Sets Luau feature flag (global setting).
923 ///
924 /// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
925 #[cfg(feature = "luau")]
926 #[doc(hidden)]
927 #[allow(clippy::result_unit_err)]
928 pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
929 if let Ok(name) = std::ffi::CString::new(name) {
930 if unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 } {
931 return Ok(());
932 }
933 }
934 Err(())
935 }
936
937 /// Returns Lua source code as a `Chunk` builder type.
938 ///
939 /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or
940 /// similar on the returned builder. Code is not even parsed until one of these methods is
941 /// called.
942 ///
943 /// [`Chunk::exec`]: crate::Chunk::exec
944 #[track_caller]
945 pub fn load<'a>(&self, chunk: impl AsChunk<'a>) -> Chunk<'a> {
946 let caller = Location::caller();
947 Chunk {
948 lua: self.weak(),
949 name: chunk.name().unwrap_or_else(|| caller.to_string()),
950 env: chunk.environment(self),
951 mode: chunk.mode(),
952 source: chunk.source(),
953 #[cfg(feature = "luau")]
954 compiler: unsafe { (*self.lock().extra.get()).compiler.clone() },
955 }
956 }
957
958 /// Create and return an interned Lua string. Lua strings can be arbitrary `[u8]` data including
959 /// embedded nulls, so in addition to `&str` and `&String`, you can also pass plain `&[u8]`
960 /// here.
961 #[inline]
962 pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<String> {
963 unsafe { self.lock().create_string(s) }
964 }
965
966 /// Create and return a Luau [buffer] object from a byte slice of data.
967 ///
968 /// Requires `feature = "luau"`
969 ///
970 /// [buffer]: https://luau-lang.org/library#buffer-library
971 #[cfg(feature = "luau")]
972 pub fn create_buffer(&self, buf: impl AsRef<[u8]>) -> Result<AnyUserData> {
973 use crate::types::SubtypeId;
974
975 let lua = self.lock();
976 let state = lua.state();
977 unsafe {
978 if lua.unlikely_memory_error() {
979 crate::util::push_buffer(lua.ref_thread(), buf.as_ref(), false)?;
980 return Ok(AnyUserData(lua.pop_ref_thread(), SubtypeId::Buffer));
981 }
982
983 let _sg = StackGuard::new(state);
984 check_stack(state, 4)?;
985 crate::util::push_buffer(state, buf.as_ref(), true)?;
986 Ok(AnyUserData(lua.pop_ref(), SubtypeId::Buffer))
987 }
988 }
989
990 /// Creates and returns a new empty table.
991 pub fn create_table(&self) -> Result<Table> {
992 self.create_table_with_capacity(0, 0)
993 }
994
995 /// Creates and returns a new empty table, with the specified capacity.
996 /// `narr` is a hint for how many elements the table will have as a sequence;
997 /// `nrec` is a hint for how many other elements the table will have.
998 /// Lua may use these hints to preallocate memory for the new table.
999 pub fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
1000 unsafe { self.lock().create_table_with_capacity(narr, nrec) }
1001 }
1002
1003 /// Creates a table and fills it with values from an iterator.
1004 pub fn create_table_from<K, V, I>(&self, iter: I) -> Result<Table>
1005 where
1006 K: IntoLua,
1007 V: IntoLua,
1008 I: IntoIterator<Item = (K, V)>,
1009 {
1010 let lua = self.lock();
1011 let state = lua.state();
1012 unsafe {
1013 let _sg = StackGuard::new(state);
1014 check_stack(state, 6)?;
1015
1016 let iter = iter.into_iter();
1017 let lower_bound = iter.size_hint().0;
1018 let protect = !lua.unlikely_memory_error();
1019 push_table(state, 0, lower_bound, protect)?;
1020 for (k, v) in iter {
1021 lua.push(k)?;
1022 lua.push(v)?;
1023 if protect {
1024 protect_lua!(state, 3, 1, fn(state) ffi::lua_rawset(state, -3))?;
1025 } else {
1026 ffi::lua_rawset(state, -3);
1027 }
1028 }
1029
1030 Ok(Table(lua.pop_ref()))
1031 }
1032 }
1033
1034 /// Creates a table from an iterator of values, using `1..` as the keys.
1035 pub fn create_sequence_from<T, I>(&self, iter: I) -> Result<Table>
1036 where
1037 T: IntoLua,
1038 I: IntoIterator<Item = T>,
1039 {
1040 unsafe { self.lock().create_sequence_from(iter) }
1041 }
1042
1043 /// Wraps a Rust function or closure, creating a callable Lua function handle to it.
1044 ///
1045 /// The function's return value is always a `Result`: If the function returns `Err`, the error
1046 /// is raised as a Lua error, which can be caught using `(x)pcall` or bubble up to the Rust code
1047 /// that invoked the Lua code. This allows using the `?` operator to propagate errors through
1048 /// intermediate Lua code.
1049 ///
1050 /// If the function returns `Ok`, the contained value will be converted to one or more Lua
1051 /// values. For details on Rust-to-Lua conversions, refer to the [`IntoLua`] and
1052 /// [`IntoLuaMulti`] traits.
1053 ///
1054 /// # Examples
1055 ///
1056 /// Create a function which prints its argument:
1057 ///
1058 /// ```
1059 /// # use mlua::{Lua, Result};
1060 /// # fn main() -> Result<()> {
1061 /// # let lua = Lua::new();
1062 /// let greet = lua.create_function(|_, name: String| {
1063 /// println!("Hello, {}!", name);
1064 /// Ok(())
1065 /// });
1066 /// # let _ = greet; // used
1067 /// # Ok(())
1068 /// # }
1069 /// ```
1070 ///
1071 /// Use tuples to accept multiple arguments:
1072 ///
1073 /// ```
1074 /// # use mlua::{Lua, Result};
1075 /// # fn main() -> Result<()> {
1076 /// # let lua = Lua::new();
1077 /// let print_person = lua.create_function(|_, (name, age): (String, u8)| {
1078 /// println!("{} is {} years old!", name, age);
1079 /// Ok(())
1080 /// });
1081 /// # let _ = print_person; // used
1082 /// # Ok(())
1083 /// # }
1084 /// ```
1085 ///
1086 /// [`IntoLua`]: crate::IntoLua
1087 /// [`IntoLuaMulti`]: crate::IntoLuaMulti
1088 pub fn create_function<F, A, R>(&self, func: F) -> Result<Function>
1089 where
1090 F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
1091 A: FromLuaMulti,
1092 R: IntoLuaMulti,
1093 {
1094 (self.lock()).create_callback(Box::new(move |rawlua, nargs| unsafe {
1095 let args = A::from_stack_args(nargs, 1, None, rawlua)?;
1096 func(rawlua.lua(), args)?.push_into_stack_multi(rawlua)
1097 }))
1098 }
1099
1100 /// Wraps a Rust mutable closure, creating a callable Lua function handle to it.
1101 ///
1102 /// This is a version of [`create_function`] that accepts a FnMut argument. Refer to
1103 /// [`create_function`] for more information about the implementation.
1104 ///
1105 /// [`create_function`]: #method.create_function
1106 pub fn create_function_mut<F, A, R>(&self, func: F) -> Result<Function>
1107 where
1108 F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
1109 A: FromLuaMulti,
1110 R: IntoLuaMulti,
1111 {
1112 let func = RefCell::new(func);
1113 self.create_function(move |lua, args| {
1114 (*func.try_borrow_mut().map_err(|_| Error::RecursiveMutCallback)?)(lua, args)
1115 })
1116 }
1117
1118 /// Wraps a C function, creating a callable Lua function handle to it.
1119 ///
1120 /// # Safety
1121 /// This function is unsafe because provides a way to execute unsafe C function.
1122 pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
1123 let lua = self.lock();
1124 ffi::lua_pushcfunction(lua.ref_thread(), func);
1125 Ok(Function(lua.pop_ref_thread()))
1126 }
1127
1128 /// Wraps a Rust async function or closure, creating a callable Lua function handle to it.
1129 ///
1130 /// While executing the function Rust will poll the Future and if the result is not ready,
1131 /// call `yield()` passing internal representation of a `Poll::Pending` value.
1132 ///
1133 /// The function must be called inside Lua coroutine ([`Thread`]) to be able to suspend its
1134 /// execution. An executor should be used to poll [`AsyncThread`] and mlua will take a
1135 /// provided Waker in that case. Otherwise noop waker will be used if try to call the
1136 /// function outside of Rust executors.
1137 ///
1138 /// The family of `call_async()` functions takes care about creating [`Thread`].
1139 ///
1140 /// Requires `feature = "async"`
1141 ///
1142 /// # Examples
1143 ///
1144 /// Non blocking sleep:
1145 ///
1146 /// ```
1147 /// use std::time::Duration;
1148 /// use mlua::{Lua, Result};
1149 ///
1150 /// async fn sleep(_lua: Lua, n: u64) -> Result<&'static str> {
1151 /// tokio::time::sleep(Duration::from_millis(n)).await;
1152 /// Ok("done")
1153 /// }
1154 ///
1155 /// #[tokio::main]
1156 /// async fn main() -> Result<()> {
1157 /// let lua = Lua::new();
1158 /// lua.globals().set("sleep", lua.create_async_function(sleep)?)?;
1159 /// let res: String = lua.load("return sleep(...)").call_async(100).await?; // Sleep 100ms
1160 /// assert_eq!(res, "done");
1161 /// Ok(())
1162 /// }
1163 /// ```
1164 ///
1165 /// [`Thread`]: crate::Thread
1166 /// [`AsyncThread`]: crate::AsyncThread
1167 #[cfg(feature = "async")]
1168 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1169 pub fn create_async_function<F, A, FR, R>(&self, func: F) -> Result<Function>
1170 where
1171 F: Fn(Lua, A) -> FR + MaybeSend + 'static,
1172 A: FromLuaMulti,
1173 FR: Future<Output = Result<R>> + MaybeSend + 'static,
1174 R: IntoLuaMulti,
1175 {
1176 // In future we should switch to async closures when they are stable to capture `&Lua`
1177 // See https://rust-lang.github.io/rfcs/3668-async-closures.html
1178 (self.lock()).create_async_callback(Box::new(move |rawlua, nargs| unsafe {
1179 let args = match A::from_stack_args(nargs, 1, None, rawlua) {
1180 Ok(args) => args,
1181 Err(e) => return Box::pin(future::ready(Err(e))),
1182 };
1183 let lua = rawlua.lua();
1184 let fut = func(lua.clone(), args);
1185 Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
1186 }))
1187 }
1188
1189 /// Wraps a Lua function into a new thread (or coroutine).
1190 ///
1191 /// Equivalent to `coroutine.create`.
1192 pub fn create_thread(&self, func: Function) -> Result<Thread> {
1193 unsafe { self.lock().create_thread(&func) }
1194 }
1195
1196 /// Creates a Lua userdata object from a custom userdata type.
1197 ///
1198 /// All userdata instances of the same type `T` shares the same metatable.
1199 #[inline]
1200 pub fn create_userdata<T>(&self, data: T) -> Result<AnyUserData>
1201 where
1202 T: UserData + MaybeSend + 'static,
1203 {
1204 unsafe { self.lock().make_userdata(UserDataVariant::new(data)) }
1205 }
1206
1207 /// Creates a Lua userdata object from a custom serializable userdata type.
1208 ///
1209 /// Requires `feature = "serialize"`
1210 #[cfg(feature = "serialize")]
1211 #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
1212 #[inline]
1213 pub fn create_ser_userdata<T>(&self, data: T) -> Result<AnyUserData>
1214 where
1215 T: UserData + Serialize + MaybeSend + 'static,
1216 {
1217 unsafe { self.lock().make_userdata(UserDataVariant::new_ser(data)) }
1218 }
1219
1220 /// Creates a Lua userdata object from a custom Rust type.
1221 ///
1222 /// You can register the type using [`Lua::register_userdata_type()`] to add fields or methods
1223 /// _before_ calling this method.
1224 /// Otherwise, the userdata object will have an empty metatable.
1225 ///
1226 /// All userdata instances of the same type `T` shares the same metatable.
1227 #[inline]
1228 pub fn create_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1229 where
1230 T: MaybeSend + 'static,
1231 {
1232 unsafe { self.lock().make_any_userdata(UserDataVariant::new(data)) }
1233 }
1234
1235 /// Creates a Lua userdata object from a custom serializable Rust type.
1236 ///
1237 /// See [`Lua::create_any_userdata()`] for more details.
1238 ///
1239 /// Requires `feature = "serialize"`
1240 #[cfg(feature = "serialize")]
1241 #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
1242 #[inline]
1243 pub fn create_ser_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1244 where
1245 T: Serialize + MaybeSend + 'static,
1246 {
1247 unsafe { (self.lock()).make_any_userdata(UserDataVariant::new_ser(data)) }
1248 }
1249
1250 /// Registers a custom Rust type in Lua to use in userdata objects.
1251 ///
1252 /// This methods provides a way to add fields or methods to userdata objects of a type `T`.
1253 pub fn register_userdata_type<T: 'static>(&self, f: impl FnOnce(&mut UserDataRegistry<T>)) -> Result<()> {
1254 let mut registry = const { UserDataRegistry::new() };
1255 f(&mut registry);
1256
1257 let lua = self.lock();
1258 unsafe {
1259 // Deregister the type if it already registered
1260 let type_id = TypeId::of::<T>();
1261 if let Some(&table_id) = (*lua.extra.get()).registered_userdata.get(&type_id) {
1262 ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, table_id);
1263 }
1264
1265 // Register the type
1266 lua.register_userdata_metatable(registry)?;
1267 }
1268 Ok(())
1269 }
1270
1271 /// Create a Lua userdata "proxy" object from a custom userdata type.
1272 ///
1273 /// Proxy object is an empty userdata object that has `T` metatable attached.
1274 /// The main purpose of this object is to provide access to static fields and functions
1275 /// without creating an instance of type `T`.
1276 ///
1277 /// You can get or set uservalues on this object but you cannot borrow any Rust type.
1278 ///
1279 /// # Examples
1280 ///
1281 /// ```
1282 /// # use mlua::{Lua, Result, UserData, UserDataFields, UserDataMethods};
1283 /// # fn main() -> Result<()> {
1284 /// # let lua = Lua::new();
1285 /// struct MyUserData(i32);
1286 ///
1287 /// impl UserData for MyUserData {
1288 /// fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
1289 /// fields.add_field_method_get("val", |_, this| Ok(this.0));
1290 /// }
1291 ///
1292 /// fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
1293 /// methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
1294 /// }
1295 /// }
1296 ///
1297 /// lua.globals().set("MyUserData", lua.create_proxy::<MyUserData>()?)?;
1298 ///
1299 /// lua.load("assert(MyUserData.new(321).val == 321)").exec()?;
1300 /// # Ok(())
1301 /// # }
1302 /// ```
1303 #[inline]
1304 pub fn create_proxy<T>(&self) -> Result<AnyUserData>
1305 where
1306 T: UserData + 'static,
1307 {
1308 let ud = UserDataProxy::<T>(PhantomData);
1309 unsafe { self.lock().make_userdata(UserDataVariant::new(ud)) }
1310 }
1311
1312 /// Sets the metatable for a Luau builtin vector type.
1313 #[cfg(any(feature = "luau", doc))]
1314 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1315 pub fn set_vector_metatable(&self, metatable: Option<Table>) {
1316 let lua = self.lock();
1317 let state = lua.state();
1318 unsafe {
1319 let _sg = StackGuard::new(state);
1320 assert_stack(state, 2);
1321
1322 #[cfg(not(feature = "luau-vector4"))]
1323 ffi::lua_pushvector(state, 0., 0., 0.);
1324 #[cfg(feature = "luau-vector4")]
1325 ffi::lua_pushvector(state, 0., 0., 0., 0.);
1326 match metatable {
1327 Some(metatable) => lua.push_ref(&metatable.0),
1328 None => ffi::lua_pushnil(state),
1329 };
1330 ffi::lua_setmetatable(state, -2);
1331 }
1332 }
1333
1334 /// Returns a handle to the global environment.
1335 pub fn globals(&self) -> Table {
1336 let lua = self.lock();
1337 let state = lua.state();
1338 unsafe {
1339 let _sg = StackGuard::new(state);
1340 assert_stack(state, 1);
1341 #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
1342 ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1343 #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1344 ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
1345 Table(lua.pop_ref())
1346 }
1347 }
1348
1349 /// Returns a handle to the active `Thread`. For calls to `Lua` this will be the main Lua
1350 /// thread, for parameters given to a callback, this will be whatever Lua thread called the
1351 /// callback.
1352 pub fn current_thread(&self) -> Thread {
1353 let lua = self.lock();
1354 let state = lua.state();
1355 unsafe {
1356 let _sg = StackGuard::new(state);
1357 assert_stack(state, 1);
1358 ffi::lua_pushthread(state);
1359 Thread(lua.pop_ref(), state)
1360 }
1361 }
1362
1363 /// Calls the given function with a `Scope` parameter, giving the function the ability to create
1364 /// userdata and callbacks from rust types that are !Send or non-'static.
1365 ///
1366 /// The lifetime of any function or userdata created through `Scope` lasts only until the
1367 /// completion of this method call, on completion all such created values are automatically
1368 /// dropped and Lua references to them are invalidated. If a script accesses a value created
1369 /// through `Scope` outside of this method, a Lua error will result. Since we can ensure the
1370 /// lifetime of values created through `Scope`, and we know that `Lua` cannot be sent to another
1371 /// thread while `Scope` is live, it is safe to allow !Send datatypes and whose lifetimes only
1372 /// outlive the scope lifetime.
1373 ///
1374 /// Inside the scope callback, all handles created through Scope will share the same unique 'lua
1375 /// lifetime of the parent `Lua`. This allows scoped and non-scoped values to be mixed in
1376 /// API calls, which is very useful (e.g. passing a scoped userdata to a non-scoped function).
1377 /// However, this also enables handles to scoped values to be trivially leaked from the given
1378 /// callback. This is not dangerous, though! After the callback returns, all scoped values are
1379 /// invalidated, which means that though references may exist, the Rust types backing them have
1380 /// dropped. `Function` types will error when called, and `AnyUserData` will be typeless. It
1381 /// would be impossible to prevent handles to scoped values from escaping anyway, since you
1382 /// would always be able to smuggle them through Lua state.
1383 // pub fn scope<'lua, 'scope, R>(
1384 // &'lua self,
1385 // f: impl FnOnce(&Scope<'lua, 'scope>) -> Result<R>,
1386 // ) -> Result<R>
1387 // where
1388 // 'lua: 'scope,
1389 // {
1390 // f(&Scope::new(self))
1391 // }
1392
1393 /// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
1394 /// behavior.
1395 ///
1396 /// To succeed, the value must be a string (in which case this is a no-op), an integer, or a
1397 /// number.
1398 pub fn coerce_string(&self, v: Value) -> Result<Option<String>> {
1399 Ok(match v {
1400 Value::String(s) => Some(s),
1401 v => unsafe {
1402 let lua = self.lock();
1403 let state = lua.state();
1404 let _sg = StackGuard::new(state);
1405 check_stack(state, 4)?;
1406
1407 lua.push_value(&v)?;
1408 let res = if lua.unlikely_memory_error() {
1409 ffi::lua_tolstring(state, -1, ptr::null_mut())
1410 } else {
1411 protect_lua!(state, 1, 1, |state| {
1412 ffi::lua_tolstring(state, -1, ptr::null_mut())
1413 })?
1414 };
1415 if !res.is_null() {
1416 Some(String(lua.pop_ref()))
1417 } else {
1418 None
1419 }
1420 },
1421 })
1422 }
1423
1424 /// Attempts to coerce a Lua value into an integer in a manner consistent with Lua's internal
1425 /// behavior.
1426 ///
1427 /// To succeed, the value must be an integer, a floating point number that has an exact
1428 /// representation as an integer, or a string that can be converted to an integer. Refer to the
1429 /// Lua manual for details.
1430 pub fn coerce_integer(&self, v: Value) -> Result<Option<Integer>> {
1431 Ok(match v {
1432 Value::Integer(i) => Some(i),
1433 v => unsafe {
1434 let lua = self.lock();
1435 let state = lua.state();
1436 let _sg = StackGuard::new(state);
1437 check_stack(state, 2)?;
1438
1439 lua.push_value(&v)?;
1440 let mut isint = 0;
1441 let i = ffi::lua_tointegerx(state, -1, &mut isint);
1442 if isint == 0 {
1443 None
1444 } else {
1445 Some(i)
1446 }
1447 },
1448 })
1449 }
1450
1451 /// Attempts to coerce a Lua value into a Number in a manner consistent with Lua's internal
1452 /// behavior.
1453 ///
1454 /// To succeed, the value must be a number or a string that can be converted to a number. Refer
1455 /// to the Lua manual for details.
1456 pub fn coerce_number(&self, v: Value) -> Result<Option<Number>> {
1457 Ok(match v {
1458 Value::Number(n) => Some(n),
1459 v => unsafe {
1460 let lua = self.lock();
1461 let state = lua.state();
1462 let _sg = StackGuard::new(state);
1463 check_stack(state, 2)?;
1464
1465 lua.push_value(&v)?;
1466 let mut isnum = 0;
1467 let n = ffi::lua_tonumberx(state, -1, &mut isnum);
1468 if isnum == 0 {
1469 None
1470 } else {
1471 Some(n)
1472 }
1473 },
1474 })
1475 }
1476
1477 /// Converts a value that implements `IntoLua` into a `Value` instance.
1478 #[inline]
1479 pub fn pack(&self, t: impl IntoLua) -> Result<Value> {
1480 t.into_lua(self)
1481 }
1482
1483 /// Converts a `Value` instance into a value that implements `FromLua`.
1484 #[inline]
1485 pub fn unpack<T: FromLua>(&self, value: Value) -> Result<T> {
1486 T::from_lua(value, self)
1487 }
1488
1489 /// Converts a value that implements `IntoLuaMulti` into a `MultiValue` instance.
1490 #[inline]
1491 pub fn pack_multi(&self, t: impl IntoLuaMulti) -> Result<MultiValue> {
1492 t.into_lua_multi(self)
1493 }
1494
1495 /// Converts a `MultiValue` instance into a value that implements `FromLuaMulti`.
1496 #[inline]
1497 pub fn unpack_multi<T: FromLuaMulti>(&self, value: MultiValue) -> Result<T> {
1498 T::from_lua_multi(value, self)
1499 }
1500
1501 /// Set a value in the Lua registry based on a string name.
1502 ///
1503 /// This value will be available to rust from all `Lua` instances which share the same main
1504 /// state.
1505 pub fn set_named_registry_value(&self, name: &str, t: impl IntoLua) -> Result<()> {
1506 let lua = self.lock();
1507 let state = lua.state();
1508 unsafe {
1509 let _sg = StackGuard::new(state);
1510 check_stack(state, 5)?;
1511
1512 lua.push(t)?;
1513 rawset_field(state, ffi::LUA_REGISTRYINDEX, name)
1514 }
1515 }
1516
1517 /// Get a value from the Lua registry based on a string name.
1518 ///
1519 /// Any Lua instance which shares the underlying main state may call this method to
1520 /// get a value previously set by [`Lua::set_named_registry_value`].
1521 pub fn named_registry_value<T>(&self, name: &str) -> Result<T>
1522 where
1523 T: FromLua,
1524 {
1525 let lua = self.lock();
1526 let state = lua.state();
1527 unsafe {
1528 let _sg = StackGuard::new(state);
1529 check_stack(state, 3)?;
1530
1531 let protect = !lua.unlikely_memory_error();
1532 push_string(state, name.as_bytes(), protect)?;
1533 ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
1534
1535 T::from_stack(-1, &lua)
1536 }
1537 }
1538
1539 /// Removes a named value in the Lua registry.
1540 ///
1541 /// Equivalent to calling [`Lua::set_named_registry_value`] with a value of Nil.
1542 pub fn unset_named_registry_value(&self, name: &str) -> Result<()> {
1543 self.set_named_registry_value(name, Nil)
1544 }
1545
1546 /// Place a value in the Lua registry with an auto-generated key.
1547 ///
1548 /// This value will be available to Rust from all `Lua` instances which share the same main
1549 /// state.
1550 ///
1551 /// Be warned, garbage collection of values held inside the registry is not automatic, see
1552 /// [`RegistryKey`] for more details.
1553 /// However, dropped [`RegistryKey`]s automatically reused to store new values.
1554 pub fn create_registry_value(&self, t: impl IntoLua) -> Result<RegistryKey> {
1555 let lua = self.lock();
1556 let state = lua.state();
1557 unsafe {
1558 let _sg = StackGuard::new(state);
1559 check_stack(state, 4)?;
1560
1561 lua.push(t)?;
1562
1563 let unref_list = (*lua.extra.get()).registry_unref_list.clone();
1564
1565 // Check if the value is nil (no need to store it in the registry)
1566 if ffi::lua_isnil(state, -1) != 0 {
1567 return Ok(RegistryKey::new(ffi::LUA_REFNIL, unref_list));
1568 }
1569
1570 // Try to reuse previously allocated slot
1571 let free_registry_id = unref_list.lock().as_mut().and_then(|x| x.pop());
1572 if let Some(registry_id) = free_registry_id {
1573 // It must be safe to replace the value without triggering memory error
1574 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
1575 return Ok(RegistryKey::new(registry_id, unref_list));
1576 }
1577
1578 // Allocate a new RegistryKey slot
1579 let registry_id = if lua.unlikely_memory_error() {
1580 ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
1581 } else {
1582 protect_lua!(state, 1, 0, |state| {
1583 ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
1584 })?
1585 };
1586 Ok(RegistryKey::new(registry_id, unref_list))
1587 }
1588 }
1589
1590 /// Get a value from the Lua registry by its `RegistryKey`
1591 ///
1592 /// Any Lua instance which shares the underlying main state may call this method to get a value
1593 /// previously placed by [`Lua::create_registry_value`].
1594 pub fn registry_value<T: FromLua>(&self, key: &RegistryKey) -> Result<T> {
1595 let lua = self.lock();
1596 if !lua.owns_registry_value(key) {
1597 return Err(Error::MismatchedRegistryKey);
1598 }
1599
1600 let state = lua.state();
1601 match key.id() {
1602 ffi::LUA_REFNIL => T::from_lua(Value::Nil, self),
1603 registry_id => unsafe {
1604 let _sg = StackGuard::new(state);
1605 check_stack(state, 1)?;
1606
1607 ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
1608 T::from_stack(-1, &lua)
1609 },
1610 }
1611 }
1612
1613 /// Removes a value from the Lua registry.
1614 ///
1615 /// You may call this function to manually remove a value placed in the registry with
1616 /// [`Lua::create_registry_value`]. In addition to manual [`RegistryKey`] removal, you can also
1617 /// call [`Lua::expire_registry_values`] to automatically remove values from the registry
1618 /// whose [`RegistryKey`]s have been dropped.
1619 pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
1620 let lua = self.lock();
1621 if !lua.owns_registry_value(&key) {
1622 return Err(Error::MismatchedRegistryKey);
1623 }
1624
1625 unsafe {
1626 ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, key.take());
1627 }
1628 Ok(())
1629 }
1630
1631 /// Replaces a value in the Lua registry by its [`RegistryKey`].
1632 ///
1633 /// An identifier used in [`RegistryKey`] may possibly be changed to a new value.
1634 ///
1635 /// See [`Lua::create_registry_value`] for more details.
1636 pub fn replace_registry_value(&self, key: &mut RegistryKey, t: impl IntoLua) -> Result<()> {
1637 let lua = self.lock();
1638 if !lua.owns_registry_value(key) {
1639 return Err(Error::MismatchedRegistryKey);
1640 }
1641
1642 let t = t.into_lua(self)?;
1643
1644 let state = lua.state();
1645 unsafe {
1646 let _sg = StackGuard::new(state);
1647 check_stack(state, 2)?;
1648
1649 match (t, key.id()) {
1650 (Value::Nil, ffi::LUA_REFNIL) => {
1651 // Do nothing, no need to replace nil with nil
1652 }
1653 (Value::Nil, registry_id) => {
1654 // Remove the value
1655 ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, registry_id);
1656 key.set_id(ffi::LUA_REFNIL);
1657 }
1658 (value, ffi::LUA_REFNIL) => {
1659 // Allocate a new `RegistryKey`
1660 let new_key = self.create_registry_value(value)?;
1661 key.set_id(new_key.take());
1662 }
1663 (value, registry_id) => {
1664 // It must be safe to replace the value without triggering memory error
1665 lua.push_value(&value)?;
1666 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
1667 }
1668 }
1669 }
1670 Ok(())
1671 }
1672
1673 /// Returns true if the given [`RegistryKey`] was created by a [`Lua`] which shares the
1674 /// underlying main state with this [`Lua`] instance.
1675 ///
1676 /// Other than this, methods that accept a [`RegistryKey`] will return
1677 /// [`Error::MismatchedRegistryKey`] if passed a [`RegistryKey`] that was not created with a
1678 /// matching [`Lua`] state.
1679 #[inline]
1680 pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
1681 self.lock().owns_registry_value(key)
1682 }
1683
1684 /// Remove any registry values whose [`RegistryKey`]s have all been dropped.
1685 ///
1686 /// Unlike normal handle values, [`RegistryKey`]s do not automatically remove themselves on
1687 /// Drop, but you can call this method to remove any unreachable registry values not
1688 /// manually removed by [`Lua::remove_registry_value`].
1689 pub fn expire_registry_values(&self) {
1690 let lua = self.lock();
1691 let state = lua.state();
1692 unsafe {
1693 let mut unref_list = (*lua.extra.get()).registry_unref_list.lock();
1694 let unref_list = mem::replace(&mut *unref_list, Some(Vec::new()));
1695 for id in mlua_expect!(unref_list, "unref list not set") {
1696 ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
1697 }
1698 }
1699 }
1700
1701 /// Sets or replaces an application data object of type `T`.
1702 ///
1703 /// Application data could be accessed at any time by using [`Lua::app_data_ref`] or
1704 /// [`Lua::app_data_mut`] methods where `T` is the data type.
1705 ///
1706 /// # Panics
1707 ///
1708 /// Panics if the app data container is currently borrowed.
1709 ///
1710 /// # Examples
1711 ///
1712 /// ```
1713 /// use mlua::{Lua, Result};
1714 ///
1715 /// fn hello(lua: &Lua, _: ()) -> Result<()> {
1716 /// let mut s = lua.app_data_mut::<&str>().unwrap();
1717 /// assert_eq!(*s, "hello");
1718 /// *s = "world";
1719 /// Ok(())
1720 /// }
1721 ///
1722 /// fn main() -> Result<()> {
1723 /// let lua = Lua::new();
1724 /// lua.set_app_data("hello");
1725 /// lua.create_function(hello)?.call(())?;
1726 /// let s = lua.app_data_ref::<&str>().unwrap();
1727 /// assert_eq!(*s, "world");
1728 /// Ok(())
1729 /// }
1730 /// ```
1731 #[track_caller]
1732 pub fn set_app_data<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
1733 let lua = self.lock();
1734 let extra = unsafe { &*lua.extra.get() };
1735 extra.app_data.insert(data)
1736 }
1737
1738 /// Tries to set or replace an application data object of type `T`.
1739 ///
1740 /// Returns:
1741 /// - `Ok(Some(old_data))` if the data object of type `T` was successfully replaced.
1742 /// - `Ok(None)` if the data object of type `T` was successfully inserted.
1743 /// - `Err(data)` if the data object of type `T` was not inserted because the container is
1744 /// currently borrowed.
1745 ///
1746 /// See [`Lua::set_app_data()`] for examples.
1747 pub fn try_set_app_data<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
1748 let lua = self.lock();
1749 let extra = unsafe { &*lua.extra.get() };
1750 extra.app_data.try_insert(data)
1751 }
1752
1753 /// Gets a reference to an application data object stored by [`Lua::set_app_data()`] of type
1754 /// `T`.
1755 ///
1756 /// # Panics
1757 ///
1758 /// Panics if the data object of type `T` is currently mutably borrowed. Multiple immutable
1759 /// reads can be taken out at the same time.
1760 #[track_caller]
1761 pub fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<T>> {
1762 let guard = self.lock_arc();
1763 let extra = unsafe { &*guard.extra.get() };
1764 extra.app_data.borrow(Some(guard))
1765 }
1766
1767 /// Gets a mutable reference to an application data object stored by [`Lua::set_app_data()`] of
1768 /// type `T`.
1769 ///
1770 /// # Panics
1771 ///
1772 /// Panics if the data object of type `T` is currently borrowed.
1773 #[track_caller]
1774 pub fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<T>> {
1775 let guard = self.lock_arc();
1776 let extra = unsafe { &*guard.extra.get() };
1777 extra.app_data.borrow_mut(Some(guard))
1778 }
1779
1780 /// Removes an application data of type `T`.
1781 ///
1782 /// # Panics
1783 ///
1784 /// Panics if the app data container is currently borrowed.
1785 #[track_caller]
1786 pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
1787 let lua = self.lock();
1788 let extra = unsafe { &*lua.extra.get() };
1789 extra.app_data.remove()
1790 }
1791
1792 /// Pushes a value that implements `IntoLua` onto the Lua stack.
1793 ///
1794 /// Uses 2 stack spaces, does not call checkstack.
1795 #[doc(hidden)]
1796 #[inline(always)]
1797 pub unsafe fn push(&self, value: impl IntoLua) -> Result<()> {
1798 self.lock().push(value)
1799 }
1800
1801 /// Returns an internal `Poll::Pending` constant used for executing async callbacks.
1802 #[cfg(feature = "async")]
1803 #[doc(hidden)]
1804 #[inline(always)]
1805 pub fn poll_pending() -> LightUserData {
1806 static ASYNC_POLL_PENDING: u8 = 0;
1807 LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut c_void)
1808 }
1809
1810 // Luau version located in `luau/mod.rs`
1811 #[cfg(not(feature = "luau"))]
1812 fn disable_c_modules(&self) -> Result<()> {
1813 let package: Table = self.globals().get("package")?;
1814
1815 package.set(
1816 "loadlib",
1817 self.create_function(|_, ()| -> Result<()> {
1818 Err(Error::SafetyError(
1819 "package.loadlib is disabled in safe mode".to_string(),
1820 ))
1821 })?,
1822 )?;
1823
1824 #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
1825 let searchers: Table = package.get("searchers")?;
1826 #[cfg(any(feature = "lua51", feature = "luajit"))]
1827 let searchers: Table = package.get("loaders")?;
1828
1829 let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
1830
1831 // The third and fourth searchers looks for a loader as a C library
1832 searchers.raw_set(3, loader)?;
1833 searchers.raw_remove(4)?;
1834
1835 Ok(())
1836 }
1837
1838 #[inline(always)]
1839 pub(crate) fn lock(&self) -> ReentrantMutexGuard<RawLua> {
1840 self.raw.lock()
1841 }
1842
1843 #[inline(always)]
1844 pub(crate) fn lock_arc(&self) -> LuaGuard {
1845 LuaGuard(self.raw.lock_arc())
1846 }
1847
1848 #[inline(always)]
1849 pub(crate) fn weak(&self) -> WeakLua {
1850 WeakLua(XRc::downgrade(&self.raw))
1851 }
1852
1853 /// Returns a handle to the unprotected Lua state without any synchronization.
1854 ///
1855 /// This is useful where we know that the lock is already held by the caller.
1856 #[inline(always)]
1857 pub(crate) unsafe fn raw_lua(&self) -> &RawLua {
1858 &*self.raw.data_ptr()
1859 }
1860}
1861
1862impl WeakLua {
1863 #[track_caller]
1864 #[inline(always)]
1865 pub(crate) fn lock(&self) -> LuaGuard {
1866 LuaGuard::new(self.0.upgrade().expect("Lua instance is destroyed"))
1867 }
1868
1869 #[inline(always)]
1870 pub(crate) fn try_lock(&self) -> Option<LuaGuard> {
1871 Some(LuaGuard::new(self.0.upgrade()?))
1872 }
1873
1874 #[track_caller]
1875 #[inline(always)]
1876 pub(crate) fn upgrade(&self) -> Lua {
1877 Lua {
1878 raw: self.0.upgrade().expect("Lua instance is destroyed"),
1879 collect_garbage: false,
1880 }
1881 }
1882}
1883
1884impl PartialEq for WeakLua {
1885 fn eq(&self, other: &Self) -> bool {
1886 XWeak::ptr_eq(&self.0, &other.0)
1887 }
1888}
1889
1890impl Eq for WeakLua {}
1891
1892impl LuaGuard {
1893 #[cfg(feature = "send")]
1894 pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
1895 LuaGuard(handle.lock_arc())
1896 }
1897
1898 #[cfg(not(feature = "send"))]
1899 pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
1900 LuaGuard(handle.into_lock_arc())
1901 }
1902}
1903
1904impl Deref for LuaGuard {
1905 type Target = RawLua;
1906
1907 fn deref(&self) -> &Self::Target {
1908 &self.0
1909 }
1910}
1911
1912pub(crate) mod extra;
1913mod raw;
1914pub(crate) mod util;
1915
1916#[cfg(test)]
1917mod assertions {
1918 use super::*;
1919
1920 // Lua has lots of interior mutability, should not be RefUnwindSafe
1921 static_assertions::assert_not_impl_any!(Lua: std::panic::RefUnwindSafe);
1922
1923 #[cfg(not(feature = "send"))]
1924 static_assertions::assert_not_impl_any!(Lua: Send);
1925 #[cfg(feature = "send")]
1926 static_assertions::assert_impl_all!(Lua: Send, Sync);
1927}