mlua/state.rs
1//! Lua state management.
2//!
3//! This module provides the main [`Lua`] state handle together with state-specific
4//! configuration and garbage collector controls.
5
6use std::any::TypeId;
7use std::cell::{BorrowError, BorrowMutError, RefCell};
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::os::raw::{c_char, c_int};
11use std::panic::Location;
12use std::result::Result as StdResult;
13use std::{fmt, mem, ptr};
14
15use crate::chunk::{AsChunk, Chunk};
16use crate::debug::Debug;
17use crate::error::{Error, Result};
18use crate::function::Function;
19use crate::memory::MemoryState;
20use crate::multi::MultiValue;
21use crate::scope::Scope;
22use crate::stdlib::StdLib;
23use crate::string::LuaString;
24use crate::table::Table;
25use crate::thread::{Thread, ThreadEvent, ThreadTriggers};
26use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
27use crate::types::{
28 AppDataRef, AppDataRefMut, ArcReentrantMutexGuard, Integer, LuaType, MaybeSend, MaybeSync, Number,
29 ReentrantMutex, ReentrantMutexGuard, RegistryKey, VmState, XRc, XWeak,
30};
31use crate::userdata::{AnyUserData, UserData, UserDataProxy, UserDataRegistry, UserDataStorage};
32use crate::util::{StackGuard, assert_stack, check_stack, protect_lua_closure, push_string, rawset_field};
33use crate::value::{Nil, Value};
34
35#[cfg(not(feature = "luau"))]
36use crate::{debug::HookTriggers, types::HookKind};
37
38#[cfg(any(feature = "luau", doc))]
39use crate::{buffer::Buffer, chunk::Compiler};
40
41#[cfg(feature = "async")]
42use {
43 crate::types::LightUserData,
44 std::future::{self, Future},
45 std::task::Poll,
46};
47
48#[cfg(feature = "serde")]
49use serde::Serialize;
50
51pub(crate) use extra::ExtraData;
52#[doc(hidden)]
53pub use raw::RawLua;
54pub(crate) use util::callback_error_ext;
55
56/// Top level Lua struct which represents an instance of Lua VM.
57pub struct Lua {
58 pub(self) raw: XRc<ReentrantMutex<RawLua>>,
59 // Controls whether garbage collection should be run on drop
60 pub(self) collect_garbage: bool,
61}
62
63/// Weak reference to Lua instance.
64///
65/// This can used to prevent circular references between Lua and Rust objects.
66#[derive(Clone)]
67pub struct WeakLua(XWeak<ReentrantMutex<RawLua>>);
68
69pub(crate) struct LuaGuard(ArcReentrantMutexGuard<RawLua>);
70
71/// Tuning parameters for the incremental GC collector.
72///
73/// Each field is an [`Option`]: `None` leaves the corresponding parameter unchanged, while
74/// `Some(v)` sets it. Units and ranges depend on the Lua version, check the Lua reference manual
75/// for details.
76#[non_exhaustive]
77#[derive(Clone, Copy, Debug, Default)]
78pub struct GcIncParams {
79 /// Pause between successive GC cycles, expressed as a percentage of live memory.
80 #[cfg(not(feature = "luau"))]
81 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
82 pub pause: Option<c_int>,
83
84 /// Target heap size as a percentage of live data, controlling how aggressively
85 /// the GC reclaims memory (`LUA_GCSETGOAL`).
86 #[cfg(any(feature = "luau", doc))]
87 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
88 pub goal: Option<c_int>,
89
90 /// GC work performed per unit of memory allocated.
91 pub step_multiplier: Option<c_int>,
92
93 /// Granularity of each GC step.
94 ///
95 /// The unit is version-dependent, check the Lua reference manual for details.
96 #[cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))]
97 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))))]
98 pub step_size: Option<c_int>,
99}
100
101impl GcIncParams {
102 /// Sets the `pause` parameter.
103 #[cfg(not(feature = "luau"))]
104 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
105 #[must_use]
106 pub fn pause(mut self, v: c_int) -> Self {
107 self.pause = Some(v);
108 self
109 }
110
111 /// Sets the `goal` parameter.
112 #[cfg(any(feature = "luau", doc))]
113 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
114 #[must_use]
115 pub fn goal(mut self, v: c_int) -> Self {
116 self.goal = Some(v);
117 self
118 }
119
120 /// Sets the `step_multiplier` parameter.
121 #[must_use]
122 pub fn step_multiplier(mut self, v: c_int) -> Self {
123 self.step_multiplier = Some(v);
124 self
125 }
126
127 /// Sets the `step_size` parameter.
128 #[cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))]
129 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))))]
130 #[must_use]
131 pub fn step_size(mut self, v: c_int) -> Self {
132 self.step_size = Some(v);
133 self
134 }
135}
136
137/// Tuning parameters for the generational GC collector (Lua 5.4+).
138///
139/// Each field is an [`Option`]: `None` leaves the corresponding parameter unchanged, while
140/// `Some(v)` sets it. Units and ranges depend on the Lua version, check the reference manual
141/// for details.
142#[cfg(any(feature = "lua55", feature = "lua54"))]
143#[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
144#[non_exhaustive]
145#[derive(Clone, Copy, Debug, Default)]
146pub struct GcGenParams {
147 /// Frequency of minor (young-generation) collection steps.
148 pub minor_multiplier: Option<c_int>,
149
150 /// Threshold controlling how large the young generation can grow before triggering
151 /// a shift from minor to major collection.
152 pub minor_to_major: Option<c_int>,
153
154 /// Threshold controlling how much the major collection must shrink the heap before
155 /// switching back to minor (young-generation) collection.
156 #[cfg(feature = "lua55")]
157 #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
158 pub major_to_minor: Option<c_int>,
159}
160
161#[cfg(any(feature = "lua55", feature = "lua54"))]
162impl GcGenParams {
163 /// Sets the `minor_multiplier` parameter.
164 #[must_use]
165 pub fn minor_multiplier(mut self, v: c_int) -> Self {
166 self.minor_multiplier = Some(v);
167 self
168 }
169
170 /// Sets the `minor_to_major` threshold.
171 #[must_use]
172 pub fn minor_to_major(mut self, v: c_int) -> Self {
173 self.minor_to_major = Some(v);
174 self
175 }
176
177 /// Sets the `major_to_minor` parameter.
178 #[cfg(feature = "lua55")]
179 #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
180 #[must_use]
181 pub fn major_to_minor(mut self, v: c_int) -> Self {
182 self.major_to_minor = Some(v);
183 self
184 }
185}
186
187/// Lua garbage collector (GC) operating mode.
188///
189/// Use [`Lua::gc_set_mode`] to switch the collector mode and/or tune its parameters.
190#[non_exhaustive]
191#[derive(Clone, Debug)]
192pub enum GcMode {
193 /// Incremental mark-and-sweep
194 Incremental(GcIncParams),
195
196 /// Generational
197 #[cfg(any(feature = "lua55", feature = "lua54"))]
198 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
199 Generational(GcGenParams),
200}
201
202/// Controls Lua interpreter behavior such as Rust panics handling.
203#[derive(Clone, Debug)]
204#[non_exhaustive]
205pub struct LuaOptions {
206 /// Catch Rust panics when using [`pcall`]/[`xpcall`].
207 ///
208 /// If disabled, wraps these functions and automatically resumes panic if found.
209 /// Also in Lua 5.1 adds ability to provide arguments to [`xpcall`] similar to Lua >= 5.2.
210 ///
211 /// If enabled, keeps [`pcall`]/[`xpcall`] unmodified.
212 /// Panics are still automatically resumed if returned to the Rust side.
213 ///
214 /// Default: **true**
215 ///
216 /// [`pcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-pcall
217 /// [`xpcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-xpcall
218 pub catch_rust_panics: bool,
219
220 /// Max size of thread (coroutine) object pool used to execute asynchronous functions.
221 ///
222 /// Default: **0** (disabled)
223 ///
224 /// [`lua_resetthread`]: https://www.lua.org/manual/5.4/manual.html#lua_resetthread
225 #[cfg(feature = "async")]
226 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
227 pub thread_pool_size: usize,
228}
229
230impl Default for LuaOptions {
231 fn default() -> Self {
232 const { LuaOptions::new() }
233 }
234}
235
236impl LuaOptions {
237 /// Returns a new instance of `LuaOptions` with default parameters.
238 pub const fn new() -> Self {
239 LuaOptions {
240 catch_rust_panics: true,
241 #[cfg(feature = "async")]
242 thread_pool_size: 0,
243 }
244 }
245
246 /// Sets [`catch_rust_panics`] option.
247 ///
248 /// [`catch_rust_panics`]: #structfield.catch_rust_panics
249 #[must_use]
250 pub const fn catch_rust_panics(mut self, enabled: bool) -> Self {
251 self.catch_rust_panics = enabled;
252 self
253 }
254
255 /// Sets [`thread_pool_size`] option.
256 ///
257 /// [`thread_pool_size`]: #structfield.thread_pool_size
258 #[cfg(feature = "async")]
259 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
260 #[must_use]
261 pub const fn thread_pool_size(mut self, size: usize) -> Self {
262 self.thread_pool_size = size;
263 self
264 }
265}
266
267/// Luau JIT options
268#[cfg(any(feature = "luau-jit", doc))]
269#[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
270#[derive(Clone, Copy, Debug, PartialEq, Eq)]
271pub struct JitOptions {
272 inliner: bool,
273}
274
275#[cfg(any(feature = "luau-jit", doc))]
276impl Default for JitOptions {
277 fn default() -> Self {
278 const { Self::new() }
279 }
280}
281
282#[cfg(any(feature = "luau-jit", doc))]
283impl JitOptions {
284 /// Creates default JIT options.
285 pub const fn new() -> Self {
286 JitOptions { inliner: false }
287 }
288
289 /// Toggles the runtime bytecode inliner.
290 ///
291 /// Disabled by default. Changing this option does not affect already loaded functions.
292 #[must_use]
293 pub const fn inliner(mut self, enabled: bool) -> Self {
294 self.inliner = enabled;
295 self
296 }
297}
298
299impl Drop for Lua {
300 fn drop(&mut self) {
301 if self.collect_garbage {
302 let _ = self.gc_collect();
303 }
304 }
305}
306
307impl Clone for Lua {
308 #[inline]
309 fn clone(&self) -> Self {
310 Lua {
311 raw: XRc::clone(&self.raw),
312 collect_garbage: false,
313 }
314 }
315}
316
317impl fmt::Debug for Lua {
318 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319 write!(f, "Lua({:p})", self.lock().state())
320 }
321}
322
323impl Default for Lua {
324 #[inline]
325 fn default() -> Self {
326 Lua::new()
327 }
328}
329
330impl Lua {
331 /// Creates a new Lua state and loads the **safe** subset of the standard libraries.
332 ///
333 /// # Safety
334 /// The created Lua state will have _some_ safety guarantees and will not allow to load unsafe
335 /// standard libraries or C modules.
336 ///
337 /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
338 pub fn new() -> Lua {
339 mlua_expect!(
340 Self::new_with(StdLib::ALL_SAFE, LuaOptions::default()),
341 "Cannot create a Lua state"
342 )
343 }
344
345 /// Creates a new Lua state and loads all the standard libraries.
346 ///
347 /// # Safety
348 /// The created Lua state will not have safety guarantees and will allow to load C modules.
349 pub unsafe fn unsafe_new() -> Lua {
350 Self::unsafe_new_with(StdLib::ALL, LuaOptions::default())
351 }
352
353 /// Creates a new Lua state and loads the specified safe subset of the standard libraries.
354 ///
355 /// Use the [`StdLib`] flags to specify the libraries you want to load.
356 ///
357 /// # Safety
358 /// The created Lua state will have _some_ safety guarantees and will not allow to load unsafe
359 /// standard libraries or C modules.
360 ///
361 /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
362 pub fn new_with(libs: StdLib, options: LuaOptions) -> Result<Lua> {
363 #[cfg(not(feature = "luau"))]
364 if libs.contains(StdLib::DEBUG) {
365 return Err(Error::SafetyError(
366 "The unsafe `debug` module can't be loaded using safe `new_with`".to_string(),
367 ));
368 }
369 #[cfg(feature = "luajit")]
370 if libs.contains(StdLib::FFI) {
371 return Err(Error::SafetyError(
372 "The unsafe `ffi` module can't be loaded using safe `new_with`".to_string(),
373 ));
374 }
375
376 let lua = unsafe { Self::inner_new(libs, options) };
377
378 #[cfg(not(feature = "luau"))]
379 if libs.contains(StdLib::PACKAGE) {
380 mlua_expect!(lua.disable_c_modules(), "Error disabling C modules");
381 }
382 lua.lock().mark_safe();
383
384 Ok(lua)
385 }
386
387 /// Creates a new Lua state and loads the specified subset of the standard libraries.
388 ///
389 /// Use the [`StdLib`] flags to specify the libraries you want to load.
390 ///
391 /// # Safety
392 /// The created Lua state will not have safety guarantees and allow to load C modules.
393 pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
394 // Workaround to avoid stripping a few unused Lua symbols that could be imported
395 // by C modules in unsafe mode
396 let mut _symbols: Vec<*const extern "C-unwind" fn()> =
397 vec![ffi::lua_isuserdata as _, ffi::lua_tocfunction as _];
398
399 #[cfg(not(feature = "luau"))]
400 _symbols.extend_from_slice(&[
401 ffi::lua_atpanic as _,
402 ffi::luaL_loadstring as _,
403 ffi::luaL_openlibs as _,
404 ]);
405 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
406 {
407 _symbols.push(ffi::lua_getglobal as _);
408 _symbols.push(ffi::lua_setglobal as _);
409 _symbols.push(ffi::luaL_setfuncs as _);
410 }
411
412 Self::inner_new(libs, options)
413 }
414
415 /// Creates a new Lua state with required `libs` and `options`
416 unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
417 let lua = Lua {
418 raw: RawLua::new(libs, &options),
419 collect_garbage: true,
420 };
421
422 #[cfg(feature = "luau")]
423 mlua_expect!(lua.configure_luau(), "Error configuring Luau");
424
425 lua
426 }
427
428 /// Returns or constructs Lua instance from a raw state.
429 ///
430 /// Once initialized, the returned Lua instance is cached in the registry and can be retrieved
431 /// by calling this function again.
432 ///
433 /// # Safety
434 /// The `Lua` must outlive the chosen lifetime `'a`.
435 #[inline]
436 pub unsafe fn get_or_init_from_ptr<'a>(state: *mut ffi::lua_State) -> &'a Lua {
437 debug_assert!(!state.is_null(), "Lua state is null");
438 match ExtraData::get(state) {
439 extra if !extra.is_null() => (*extra).lua(),
440 _ => {
441 // The `owned` flag is set to `false` as we don't own the Lua state.
442 RawLua::init_from_ptr(state, false);
443 (*ExtraData::get(state)).lua()
444 }
445 }
446 }
447
448 /// Calls provided function passing a raw lua state.
449 ///
450 /// The arguments will be pushed onto the stack before calling the function.
451 ///
452 /// This method ensures that the Lua instance is locked while the function is called
453 /// and restores Lua stack after the function returns.
454 ///
455 /// # Example
456 /// ```
457 /// # use mlua::{Lua, Result};
458 /// # fn main() -> Result<()> {
459 /// let lua = Lua::new();
460 /// let n: i32 = unsafe {
461 /// let nums = (3, 4, 5);
462 /// lua.exec_raw(nums, |state| {
463 /// let n = ffi::lua_gettop(state);
464 /// let mut sum = 0;
465 /// for i in 1..=n {
466 /// sum += ffi::lua_tointeger(state, i);
467 /// }
468 /// ffi::lua_pop(state, n);
469 /// ffi::lua_pushinteger(state, sum);
470 /// })
471 /// }?;
472 /// assert_eq!(n, 12);
473 /// # Ok(())
474 /// # }
475 /// ```
476 #[allow(clippy::missing_safety_doc)]
477 pub unsafe fn exec_raw<R: FromLuaMulti>(
478 &self,
479 args: impl IntoLuaMulti,
480 f: impl FnOnce(*mut ffi::lua_State),
481 ) -> Result<R> {
482 let lua = self.lock();
483 let state = lua.state();
484 let _sg = StackGuard::new(state);
485 let stack_start = ffi::lua_gettop(state);
486 let nargs = args.push_into_stack_multi(&lua)?;
487 check_stack(state, 3)?;
488 protect_lua_closure::<_, ()>(state, nargs, ffi::LUA_MULTRET, f)?;
489 let nresults = ffi::lua_gettop(state) - stack_start;
490 R::from_stack_multi(nresults, &lua)
491 }
492
493 /// Calls provided function passing a reference to the [`RawLua`] handle.
494 ///
495 /// Provided [`RawLua`] handle can be used to manually pushing/popping values to/from the stack.
496 ///
497 /// # Example
498 /// ```
499 /// # use mlua::{Lua, Result, FromLua, IntoLua, IntoLuaMulti};
500 /// # fn main() -> Result<()> {
501 /// let lua = Lua::new();
502 /// let n: i32 = {
503 /// let nums = (3, 4, 5);
504 /// lua.exec_raw_lua(|rawlua| unsafe {
505 /// nums.push_into_stack_multi(rawlua)?;
506 /// let mut sum = 0;
507 /// for _ in 0..3 {
508 /// sum += rawlua.pop::<i32>()?;
509 /// }
510 /// Result::Ok(sum)
511 /// })
512 /// }?;
513 /// assert_eq!(n, 12);
514 /// # Ok(())
515 /// # }
516 /// ```
517 #[doc(hidden)]
518 pub fn exec_raw_lua<R>(&self, f: impl FnOnce(&RawLua) -> R) -> R {
519 let lua = self.lock();
520 f(&lua)
521 }
522
523 /// Loads the specified subset of the standard libraries into an existing Lua state.
524 ///
525 /// Use the [`StdLib`] flags to specify the libraries you want to load.
526 pub fn load_std_libs(&self, libs: StdLib) -> Result<()> {
527 unsafe { self.lock().load_std_libs(libs) }
528 }
529
530 /// Registers module into an existing Lua state using the specified value.
531 ///
532 /// After registration, the given value will always be immediately returned when the
533 /// given module is [required].
534 ///
535 /// [required]: https://www.lua.org/manual/5.4/manual.html#pdf-require
536 pub fn register_module(&self, modname: &str, value: impl IntoLua) -> Result<()> {
537 #[cfg(not(feature = "luau"))]
538 const LOADED_MODULES_KEY: *const c_char = ffi::LUA_LOADED_TABLE;
539 #[cfg(feature = "luau")]
540 const LOADED_MODULES_KEY: *const c_char = ffi::LUA_REGISTERED_MODULES_TABLE;
541
542 if cfg!(feature = "luau") && !modname.starts_with('@') {
543 return Err(Error::runtime("module name must begin with '@'"));
544 }
545 #[cfg(feature = "luau")]
546 let modname = modname.to_ascii_lowercase();
547 unsafe {
548 self.exec_raw::<()>(value, |state| {
549 ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, LOADED_MODULES_KEY);
550 ffi::lua_pushlstring(state, modname.as_ptr() as *const c_char, modname.len() as _);
551 ffi::lua_pushvalue(state, -3);
552 ffi::lua_rawset(state, -3);
553 })
554 }
555 }
556
557 /// Preloads module into an existing Lua state using the specified loader function.
558 ///
559 /// When the module is required, the loader function will be called with module name as the
560 /// first argument.
561 ///
562 /// This is similar to setting the [`package.preload[modname]`] field.
563 ///
564 /// [`package.preload[modname]`]: <https://www.lua.org/manual/5.4/manual.html#pdf-package.preload>
565 #[cfg(not(feature = "luau"))]
566 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
567 pub fn preload_module(&self, modname: &str, func: Function) -> Result<()> {
568 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
569 let preload = unsafe {
570 self.exec_raw::<Option<Table>>((), |state| {
571 ffi::lua_getfield(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_PRELOAD_TABLE);
572 })?
573 };
574 #[cfg(any(feature = "lua51", feature = "luajit"))]
575 let preload = unsafe {
576 self.exec_raw::<Option<Table>>((), |state| {
577 if ffi::lua_getfield(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_LOADED_TABLE) != ffi::LUA_TNIL {
578 ffi::luaL_getsubtable(state, -1, ffi::LUA_LOADLIBNAME);
579 ffi::luaL_getsubtable(state, -1, cstr!("preload"));
580 ffi::lua_rotate(state, 1, 1);
581 }
582 })?
583 };
584 if let Some(preload) = preload {
585 preload.raw_set(modname, func)?;
586 }
587 Ok(())
588 }
589
590 /// Unloads module `modname`.
591 ///
592 /// This method does not support unloading binary Lua modules since they are internally cached
593 /// and can be unloaded only by closing Lua state.
594 ///
595 /// This is similar to calling [`Lua::register_module`] with `Nil` value.
596 ///
597 /// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
598 pub fn unload_module(&self, modname: &str) -> Result<()> {
599 self.register_module(modname, Nil)
600 }
601
602 // Executes module entrypoint function, which returns only one Value.
603 // The returned value then pushed onto the stack.
604 #[doc(hidden)]
605 #[cfg(not(tarpaulin_include))]
606 pub unsafe fn entrypoint<F, A, R>(state: *mut ffi::lua_State, func: F) -> c_int
607 where
608 F: FnOnce(&Lua, A) -> Result<R>,
609 A: FromLuaMulti,
610 R: IntoLua,
611 {
612 // Make sure that Lua is initialized
613 let _ = Self::get_or_init_from_ptr(state);
614
615 callback_error_ext(state, ptr::null_mut(), true, move |extra, nargs| {
616 let rawlua = (*extra).raw_lua();
617 let args = A::from_stack_args(nargs, 1, None, rawlua)?;
618 func(rawlua.lua(), args)?.push_into_stack(rawlua)?;
619 Ok(1)
620 })
621 }
622
623 // A simple module entrypoint without arguments
624 #[doc(hidden)]
625 #[cfg(not(tarpaulin_include))]
626 pub unsafe fn entrypoint1<F, R>(state: *mut ffi::lua_State, func: F) -> c_int
627 where
628 F: FnOnce(&Lua) -> Result<R>,
629 R: IntoLua,
630 {
631 Self::entrypoint(state, move |lua, _: ()| func(lua))
632 }
633
634 /// Skips memory checks for some operations.
635 #[doc(hidden)]
636 #[cfg(feature = "module")]
637 pub fn skip_memory_check(&self, skip: bool) {
638 let lua = self.lock();
639 unsafe { (*lua.extra.get()).skip_memory_check = skip };
640 }
641
642 /// Enables (or disables) sandbox mode on this Lua instance.
643 ///
644 /// This method, in particular:
645 /// - Set all libraries to read-only
646 /// - Set all builtin metatables to read-only
647 /// - Set globals to read-only (and activates safeenv)
648 /// - Setup local environment table that performs writes locally and proxies reads to the global
649 /// environment.
650 /// - Allow only `count` mode in `collectgarbage` function.
651 ///
652 /// # Examples
653 ///
654 /// ```
655 /// # use mlua::{Lua, Result};
656 /// # #[cfg(feature = "luau")]
657 /// # fn main() -> Result<()> {
658 /// let lua = Lua::new();
659 ///
660 /// lua.sandbox(true)?;
661 /// lua.load("var = 123").exec()?;
662 /// assert_eq!(lua.globals().get::<u32>("var")?, 123);
663 ///
664 /// // Restore the global environment (clear changes made in sandbox)
665 /// lua.sandbox(false)?;
666 /// assert_eq!(lua.globals().get::<Option<u32>>("var")?, None);
667 /// # Ok(())
668 /// # }
669 ///
670 /// # #[cfg(not(feature = "luau"))]
671 /// # fn main() {}
672 /// ```
673 #[cfg(any(feature = "luau", doc))]
674 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
675 pub fn sandbox(&self, enabled: bool) -> Result<()> {
676 let lua = self.lock();
677 unsafe {
678 if (*lua.extra.get()).sandboxed != enabled {
679 let state = lua.main_state();
680 check_stack(state, 3)?;
681 protect_lua!(state, 0, 0, |state| {
682 if enabled {
683 ffi::luaL_sandbox(state, 1);
684 ffi::luaL_sandboxthread(state);
685 } else {
686 // Restore original `LUA_GLOBALSINDEX`
687 ffi::lua_xpush(lua.ref_thread(), state, ffi::LUA_GLOBALSINDEX);
688 ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
689 ffi::luaL_sandbox(state, 0);
690 }
691 })?;
692 (*lua.extra.get()).sandboxed = enabled;
693 }
694 Ok(())
695 }
696 }
697
698 /// Sets or replaces a global hook function that will periodically be called as Lua code
699 /// executes.
700 ///
701 /// All new threads created (by mlua) after this call will use the global hook function.
702 ///
703 /// For more information see [`Lua::set_hook`].
704 #[cfg(not(feature = "luau"))]
705 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
706 pub fn set_global_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
707 where
708 F: Fn(&Lua, &Debug) -> Result<VmState> + MaybeSend + 'static,
709 {
710 let lua = self.lock();
711 unsafe {
712 (*lua.extra.get()).hook_triggers = triggers;
713 (*lua.extra.get()).hook_callback = Some(XRc::new(callback));
714 lua.set_thread_hook(lua.state(), HookKind::Global)
715 }
716 }
717
718 /// Sets a hook function that will periodically be called as Lua code executes.
719 ///
720 /// When exactly the hook function is called depends on the contents of the `triggers`
721 /// parameter, see [`HookTriggers`] for more details.
722 ///
723 /// The provided hook function can error, and this error will be propagated through the Lua code
724 /// that was executing at the time the hook was triggered. This can be used to implement a
725 /// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and
726 /// erroring once an instruction limit has been reached.
727 ///
728 /// This method sets a hook function for the *current* thread of this Lua instance.
729 /// If you want to set a hook function for another thread (coroutine), use
730 /// [`Thread::set_hook`] instead.
731 ///
732 /// # Example
733 ///
734 /// Shows each line number of code being executed by the Lua interpreter.
735 ///
736 /// ```
737 /// # use mlua::{Lua, HookTriggers, Result, VmState};
738 /// # fn main() -> Result<()> {
739 /// let lua = Lua::new();
740 /// lua.set_hook(HookTriggers::EVERY_LINE, |_lua, debug| {
741 /// println!("line {:?}", debug.current_line());
742 /// Ok(VmState::Continue)
743 /// });
744 ///
745 /// lua.load(r#"
746 /// local x = 2 + 3
747 /// local y = x * 63
748 /// local z = string.len(x..", "..y)
749 /// "#).exec()
750 /// # }
751 /// ```
752 ///
753 /// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
754 #[cfg(not(feature = "luau"))]
755 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
756 pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
757 where
758 F: Fn(&Lua, &Debug) -> Result<VmState> + MaybeSend + 'static,
759 {
760 let lua = self.lock();
761 unsafe { lua.set_thread_hook(lua.state(), HookKind::Thread(triggers, XRc::new(callback))) }
762 }
763
764 /// Removes a global hook previously set by [`Lua::set_global_hook`].
765 ///
766 /// This function has no effect if a hook was not previously set.
767 #[cfg(not(feature = "luau"))]
768 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
769 pub fn remove_global_hook(&self) {
770 let lua = self.lock();
771 unsafe {
772 (*lua.extra.get()).hook_callback = None;
773 (*lua.extra.get()).hook_triggers = HookTriggers::default();
774 }
775 }
776
777 /// Removes any hook from the current thread.
778 ///
779 /// This function has no effect if a hook was not previously set.
780 #[cfg(not(feature = "luau"))]
781 #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
782 pub fn remove_hook(&self) {
783 let lua = self.lock();
784 unsafe {
785 ffi::lua_sethook(lua.state(), None, 0, 0);
786 }
787 }
788
789 /// Sets an interrupt function that will periodically be called by Luau VM.
790 ///
791 /// Any Luau code is guaranteed to call this handler "eventually"
792 /// (in practice this can happen at any function call or at any loop iteration).
793 /// This is similar to `Lua::set_hook` but in more simplified form.
794 ///
795 /// The provided interrupt function can error, and this error will be propagated through
796 /// the Luau code that was executing at the time the interrupt was triggered.
797 /// Also this can be used to implement continuous execution limits by instructing Luau VM to
798 /// yield by returning [`VmState::Yield`]. The yield will happen only at yieldable points
799 /// of execution (not across metamethod/C-call boundaries).
800 ///
801 /// # Example
802 ///
803 /// Periodically yield Luau VM to suspend execution.
804 ///
805 /// ```
806 /// # use std::sync::{Arc, atomic::{AtomicU64, Ordering}};
807 /// # use mlua::thread::ThreadStatus;
808 /// # use mlua::{Lua, Result, VmState};
809 /// # #[cfg(feature = "luau")]
810 /// # fn main() -> Result<()> {
811 /// let lua = Lua::new();
812 /// let count = Arc::new(AtomicU64::new(0));
813 /// lua.set_interrupt(move |_| {
814 /// if count.fetch_add(1, Ordering::Relaxed) % 2 == 0 {
815 /// return Ok(VmState::Yield);
816 /// }
817 /// Ok(VmState::Continue)
818 /// });
819 ///
820 /// let co = lua.create_thread(
821 /// lua.load(r#"
822 /// local b = 0
823 /// for _, x in ipairs({1, 2, 3}) do b += x end
824 /// "#)
825 /// .into_function()?,
826 /// )?;
827 /// while co.status() == ThreadStatus::Resumable {
828 /// co.resume::<()>(())?;
829 /// }
830 /// # Ok(())
831 /// # }
832 ///
833 /// # #[cfg(not(feature = "luau"))]
834 /// # fn main() {}
835 /// ```
836 #[cfg(any(feature = "luau", doc))]
837 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
838 pub fn set_interrupt<F>(&self, callback: F)
839 where
840 F: Fn(&Lua) -> Result<VmState> + MaybeSend + 'static,
841 {
842 unsafe extern "C-unwind" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) {
843 if gc >= 0 {
844 // We don't support GC interrupts since they cannot survive Lua exceptions
845 return;
846 }
847 let result = callback_error_ext(state, ptr::null_mut(), false, move |extra, _| {
848 let interrupt_cb = (*extra).interrupt_callback.clone();
849 let interrupt_cb = mlua_expect!(interrupt_cb, "no interrupt callback set in interrupt_proc");
850 if XRc::strong_count(&interrupt_cb) > 2 {
851 return Ok(VmState::Continue); // Don't allow recursion
852 }
853 interrupt_cb((*extra).lua())
854 });
855 match result {
856 VmState::Continue => {}
857 VmState::Yield => {
858 // We can yield only at yieldable points, otherwise ignore and continue
859 if ffi::lua_isyieldable(state) != 0 {
860 ffi::lua_yield(state, 0);
861 }
862 }
863 }
864 }
865
866 // Set interrupt callback
867 let lua = self.lock();
868 unsafe {
869 (*lua.extra.get()).interrupt_callback = Some(XRc::new(callback));
870 (*ffi::lua_callbacks(lua.main_state())).interrupt = Some(interrupt_proc);
871 }
872 }
873
874 /// Removes any interrupt function previously set by `set_interrupt`.
875 ///
876 /// This function has no effect if an 'interrupt' was not previously set.
877 #[cfg(any(feature = "luau", doc))]
878 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
879 pub fn remove_interrupt(&self) {
880 let lua = self.lock();
881 unsafe {
882 (*lua.extra.get()).interrupt_callback = None;
883 (*ffi::lua_callbacks(lua.main_state())).interrupt = None;
884 }
885 }
886
887 /// Sets a callback invoked when thread lifecycle events occur.
888 ///
889 /// `triggers` controls which events trigger the callback, see [`ThreadTriggers`] for more
890 /// details.
891 ///
892 /// Only one callback can be registered at a time. Calling this again replaces the previous
893 /// callback and its triggers.
894 ///
895 /// If the callback returns an error, it's propagated out of the operation that triggered the
896 /// event. For a [`ThreadEvent::Yield`], the yielded values are discarded.
897 ///
898 /// # Example
899 ///
900 /// Subscribe only to yield events:
901 ///
902 /// ```
903 /// # use mlua::thread::{ThreadTriggers, ThreadEvent};
904 /// # use mlua::{Lua, Result};
905 /// # fn main() -> Result<()> {
906 /// let lua = Lua::new();
907 /// lua.set_thread_event_callback(
908 /// ThreadTriggers::ON_YIELD,
909 /// |_lua, event| {
910 /// if let ThreadEvent::Yield(thread) = event {
911 /// println!("thread yielded");
912 /// }
913 /// Ok(())
914 /// },
915 /// );
916 /// # Ok(())
917 /// # }
918 /// ```
919 pub fn set_thread_event_callback<F>(&self, triggers: ThreadTriggers, callback: F)
920 where
921 F: Fn(&Lua, ThreadEvent) -> Result<()> + MaybeSend + 'static,
922 {
923 let lua = self.lock();
924 unsafe {
925 (*lua.extra.get()).thread_triggers = triggers;
926 (*lua.extra.get()).thread_event_callback = Some(XRc::new(callback));
927 #[cfg(feature = "luau")]
928 {
929 let proc = Self::userthread_proc as _;
930 (*ffi::lua_callbacks(lua.main_state())).userthread = triggers.on_create.then_some(proc);
931 }
932 }
933 }
934
935 /// Removes the thread event callback previously set by [`Lua::set_thread_event_callback`].
936 ///
937 /// This function has no effect if a callback was not previously set.
938 pub fn remove_thread_event_callback(&self) {
939 let lua = self.lock();
940 let extra = lua.extra.get();
941 unsafe {
942 (*extra).thread_triggers = ThreadTriggers::new();
943 (*extra).thread_event_callback = None;
944 #[cfg(feature = "luau")]
945 {
946 (*ffi::lua_callbacks(lua.main_state())).userthread = None;
947 }
948 }
949 }
950
951 #[cfg(feature = "luau")]
952 unsafe extern "C-unwind" fn userthread_proc(parent: *mut ffi::lua_State, child: *mut ffi::lua_State) {
953 // Only handle thread creation
954 if parent.is_null() {
955 return;
956 }
957
958 let extra = ExtraData::get(child);
959 if !(*extra).thread_triggers.on_create || !(*extra).thread_event_state.is_null() {
960 return;
961 }
962 let callback = match &(*extra).thread_event_callback {
963 Some(cb) => cb.clone(),
964 _ => return,
965 };
966 ffi::lua_pushthread(child);
967 ffi::lua_xmove(child, (*extra).ref_thread, 1);
968 let thread = Thread((*extra).raw_lua().pop_ref_thread(), child);
969 callback_error_ext(parent, extra, false, move |extra, _| {
970 let _guard = crate::thread::ThreadEventGuard::new((*extra).raw_lua(), child);
971 callback((*extra).lua(), ThreadEvent::Create(thread))
972 })
973 }
974
975 /// Sets the warning function to be used by Lua to emit warnings.
976 #[cfg(any(feature = "lua55", feature = "lua54"))]
977 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
978 pub fn set_warning_function<F>(&self, callback: F)
979 where
980 F: Fn(&Lua, &str, bool) -> Result<()> + MaybeSend + 'static,
981 {
982 use std::ffi::CStr;
983 use std::os::raw::{c_char, c_void};
984
985 unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
986 let extra = ud as *mut ExtraData;
987 callback_error_ext((*extra).raw_lua().state(), extra, false, |extra, _| {
988 let warn_callback = (*extra).warn_callback.clone();
989 let warn_callback = mlua_expect!(warn_callback, "no warning callback set in warn_proc");
990 if XRc::strong_count(&warn_callback) > 2 {
991 return Ok(());
992 }
993 let msg = String::from_utf8_lossy(CStr::from_ptr(msg).to_bytes());
994 warn_callback((*extra).lua(), &msg, tocont != 0)
995 });
996 }
997
998 let lua = self.lock();
999 unsafe {
1000 (*lua.extra.get()).warn_callback = Some(XRc::new(callback));
1001 ffi::lua_setwarnf(lua.state(), Some(warn_proc), lua.extra.get() as *mut c_void);
1002 }
1003 }
1004
1005 /// Removes warning function previously set by `set_warning_function`.
1006 ///
1007 /// This function has no effect if a warning function was not previously set.
1008 #[cfg(any(feature = "lua55", feature = "lua54"))]
1009 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
1010 pub fn remove_warning_function(&self) {
1011 let lua = self.lock();
1012 unsafe {
1013 (*lua.extra.get()).warn_callback = None;
1014 ffi::lua_setwarnf(lua.state(), None, ptr::null_mut());
1015 }
1016 }
1017
1018 /// Emits a warning with the given message.
1019 ///
1020 /// A message in a call with `incomplete` set to `true` should be continued in
1021 /// another call to this function.
1022 #[cfg(any(feature = "lua55", feature = "lua54"))]
1023 #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
1024 pub fn warning(&self, msg: impl AsRef<str>, incomplete: bool) {
1025 let msg = msg.as_ref().as_bytes();
1026 let end = msg.iter().position(|&c| c == 0).unwrap_or(msg.len());
1027 let mut bytes = Vec::with_capacity(end + 1);
1028 bytes.extend_from_slice(&msg[..end]);
1029 bytes.push(0);
1030 let lua = self.lock();
1031 unsafe {
1032 ffi::lua_warning(lua.state(), bytes.as_ptr() as *const _, incomplete as c_int);
1033 }
1034 }
1035
1036 /// Gets information about the interpreter runtime stack at the given level.
1037 ///
1038 /// This function calls callback `f`, passing the [`struct@Debug`] structure that can be used to
1039 /// get information about the function executing at a given level.
1040 /// Level `0` is the current running function, whereas level `n+1` is the function that has
1041 /// called level `n` (except for tail calls, which do not count in the stack).
1042 pub fn inspect_stack<R>(&self, level: usize, f: impl FnOnce(&Debug) -> R) -> Option<R> {
1043 let lua = self.lock();
1044 unsafe {
1045 let mut ar = mem::zeroed::<ffi::lua_Debug>();
1046 let level = level as c_int;
1047 #[cfg(not(feature = "luau"))]
1048 if ffi::lua_getstack(lua.state(), level, &mut ar) == 0 {
1049 return None;
1050 }
1051 #[cfg(feature = "luau")]
1052 if ffi::lua_getinfo(lua.state(), level, cstr!(""), &mut ar) == 0 {
1053 return None;
1054 }
1055
1056 Some(f(&Debug::new(&lua, level, &mut ar)))
1057 }
1058 }
1059
1060 /// Creates a traceback of the call stack at the given level.
1061 ///
1062 /// The `msg` parameter, if provided, is added at the beginning of the traceback.
1063 /// The `level` parameter works the same way as in [`Lua::inspect_stack`].
1064 pub fn traceback(&self, msg: Option<&str>, level: usize) -> Result<LuaString> {
1065 let lua = self.lock();
1066 unsafe {
1067 check_stack(lua.state(), 3)?;
1068 protect_lua!(lua.state(), 0, 1, |state| {
1069 let msg = match msg {
1070 Some(s) => ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len()),
1071 None => ptr::null(),
1072 };
1073 // `protect_lua` adds it's own call frame, so we need to increase level by 1
1074 ffi::luaL_traceback(state, state, msg, (level + 1) as c_int);
1075 })?;
1076 Ok(LuaString(lua.pop_ref()))
1077 }
1078 }
1079
1080 /// Returns the amount of memory (in bytes) currently used inside this Lua state.
1081 pub fn used_memory(&self) -> usize {
1082 let lua = self.lock();
1083 let state = lua.main_state();
1084 unsafe {
1085 match MemoryState::get(state) {
1086 mem_state if !mem_state.is_null() => (*mem_state).used_memory(),
1087 _ => {
1088 // Get data from the Lua GC
1089 let used_kbytes = ffi::lua_gc(state, ffi::LUA_GCCOUNT, 0);
1090 let used_kbytes_rem = ffi::lua_gc(state, ffi::LUA_GCCOUNTB, 0);
1091 (used_kbytes as usize) * 1024 + (used_kbytes_rem as usize)
1092 }
1093 }
1094 }
1095 }
1096
1097 /// Sets a memory limit (in bytes) on this Lua state.
1098 ///
1099 /// Once an allocation occurs that would pass this memory limit, a `Error::MemoryError` is
1100 /// generated instead.
1101 /// Returns previous limit (zero means no limit).
1102 ///
1103 /// Does not work in module mode where Lua state is managed externally.
1104 pub fn set_memory_limit(&self, limit: usize) -> Result<usize> {
1105 let lua = self.lock();
1106 unsafe {
1107 match MemoryState::get(lua.state()) {
1108 mem_state if !mem_state.is_null() => Ok((*mem_state).set_memory_limit(limit)),
1109 _ => Err(Error::MemoryControlNotAvailable),
1110 }
1111 }
1112 }
1113
1114 /// Returns `true` if the garbage collector is currently running automatically.
1115 #[cfg(any(
1116 feature = "lua55",
1117 feature = "lua54",
1118 feature = "lua53",
1119 feature = "lua52",
1120 feature = "luau"
1121 ))]
1122 #[cfg_attr(
1123 docsrs,
1124 doc(cfg(any(
1125 feature = "lua55",
1126 feature = "lua54",
1127 feature = "lua53",
1128 feature = "lua52",
1129 feature = "luau"
1130 )))
1131 )]
1132 pub fn gc_is_running(&self) -> bool {
1133 let lua = self.lock();
1134 unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCISRUNNING, 0) != 0 }
1135 }
1136
1137 /// Stops the Lua GC from running.
1138 pub fn gc_stop(&self) {
1139 let lua = self.lock();
1140 unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCSTOP, 0) };
1141 }
1142
1143 /// Restarts the Lua GC if it is not running.
1144 pub fn gc_restart(&self) {
1145 let lua = self.lock();
1146 unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCRESTART, 0) };
1147 }
1148
1149 /// Performs a full garbage-collection cycle.
1150 ///
1151 /// It may be necessary to call this function twice to collect all currently unreachable
1152 /// objects. Once to finish the current gc cycle, and once to start and finish the next cycle.
1153 pub fn gc_collect(&self) -> Result<()> {
1154 let lua = self.lock();
1155 let state = lua.main_state();
1156 unsafe {
1157 check_stack(state, 2)?;
1158 protect_lua!(state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
1159 }
1160 }
1161
1162 /// Performs a basic step of garbage collection.
1163 ///
1164 /// In incremental mode, a basic step corresponds to the current step size. In generational
1165 /// mode, a basic step performs a full minor collection or an incremental step, if the collector
1166 /// has scheduled one.
1167 ///
1168 /// In incremental mode, returns `true` if this step has finished a collection cycle.
1169 /// In generational mode, returns `true` if the step finished a major collection.
1170 pub fn gc_step(&self) -> Result<bool> {
1171 let lua = self.lock();
1172 let state = lua.main_state();
1173 unsafe {
1174 check_stack(state, 3)?;
1175 protect_lua!(state, 0, 0, |state| {
1176 ffi::lua_gc(state, ffi::LUA_GCSTEP, 0) != 0
1177 })
1178 }
1179 }
1180
1181 /// Switches the GC to the given mode with the provided parameters.
1182 ///
1183 /// Returns the previous [`GcMode`]. Only the collector *mode* is reported, the returned value's
1184 /// parameter fields are always `None`.
1185 ///
1186 /// If the collector is internally stopped, the mode cannot be changed and the requested mode is
1187 /// returned as-is.
1188 ///
1189 /// # Examples
1190 ///
1191 /// Switch to generational mode (Lua 5.4+):
1192 /// ```ignore
1193 /// let prev = lua.gc_set_mode(GcMode::Generational(GcGenParams::default()));
1194 /// ```
1195 ///
1196 /// Switch to incremental mode with custom parameters:
1197 /// ```ignore
1198 /// lua.gc_set_mode(GcMode::Incremental(
1199 /// GcIncParams::default().step_multiplier(100)
1200 /// ));
1201 /// ```
1202 pub fn gc_set_mode(&self, mode: GcMode) -> GcMode {
1203 let lua = self.lock();
1204 let state = lua.main_state();
1205
1206 match mode {
1207 #[cfg(feature = "lua55")]
1208 GcMode::Incremental(params) => unsafe {
1209 if let Some(v) = params.pause {
1210 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPPAUSE, v);
1211 }
1212 if let Some(v) = params.step_multiplier {
1213 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPMUL, v);
1214 }
1215 if let Some(v) = params.step_size {
1216 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPSIZE, v);
1217 }
1218 match ffi::lua_gc(state, ffi::LUA_GCINC) {
1219 ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1220 _ => GcMode::Incremental(GcIncParams::default()),
1221 }
1222 },
1223 #[cfg(feature = "lua54")]
1224 GcMode::Incremental(params) => unsafe {
1225 let pause = params.pause.unwrap_or(0);
1226 let step_mul = params.step_multiplier.unwrap_or(0);
1227 let step_size = params.step_size.unwrap_or(0);
1228 match ffi::lua_gc(state, ffi::LUA_GCINC, pause, step_mul, step_size) {
1229 ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1230 _ => GcMode::Incremental(GcIncParams::default()),
1231 }
1232 },
1233 #[cfg(any(feature = "lua53", feature = "lua52", feature = "lua51", feature = "luajit"))]
1234 GcMode::Incremental(params) => unsafe {
1235 if let Some(v) = params.pause {
1236 ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, v);
1237 }
1238 if let Some(v) = params.step_multiplier {
1239 ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1240 }
1241 GcMode::Incremental(GcIncParams::default())
1242 },
1243 #[cfg(feature = "luau")]
1244 GcMode::Incremental(params) => unsafe {
1245 if let Some(v) = params.goal {
1246 ffi::lua_gc(state, ffi::LUA_GCSETGOAL, v);
1247 }
1248 if let Some(v) = params.step_multiplier {
1249 ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1250 }
1251 if let Some(v) = params.step_size {
1252 ffi::lua_gc(state, ffi::LUA_GCSETSTEPSIZE, v);
1253 }
1254 GcMode::Incremental(GcIncParams::default())
1255 },
1256
1257 #[cfg(feature = "lua55")]
1258 GcMode::Generational(params) => unsafe {
1259 if let Some(v) = params.minor_multiplier {
1260 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMUL, v);
1261 }
1262 if let Some(v) = params.minor_to_major {
1263 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMAJOR, v);
1264 }
1265 if let Some(v) = params.major_to_minor {
1266 ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMAJORMINOR, v);
1267 }
1268 match ffi::lua_gc(state, ffi::LUA_GCGEN) {
1269 ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1270 _ => GcMode::Generational(GcGenParams::default()),
1271 }
1272 },
1273 #[cfg(feature = "lua54")]
1274 GcMode::Generational(params) => unsafe {
1275 let minor = params.minor_multiplier.unwrap_or(0);
1276 let minor_to_major = params.minor_to_major.unwrap_or(0);
1277 match ffi::lua_gc(state, ffi::LUA_GCGEN, minor, minor_to_major) {
1278 ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1279 _ => GcMode::Generational(GcGenParams::default()),
1280 }
1281 },
1282 }
1283 }
1284
1285 /// Sets a default Luau compiler (with custom options).
1286 ///
1287 /// This compiler will be used by default to load all Lua chunks
1288 /// including via `require` function.
1289 ///
1290 /// See [`Compiler`] for details and possible options.
1291 #[cfg(any(feature = "luau", doc))]
1292 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1293 pub fn set_compiler(&self, compiler: Compiler) {
1294 let lua = self.lock();
1295 unsafe { (*lua.extra.get()).compiler = Some(compiler) };
1296 }
1297
1298 /// Toggles JIT compilation mode for new chunks of code.
1299 ///
1300 /// By default JIT is enabled. Changing this option does not have any effect on
1301 /// already loaded functions.
1302 #[cfg(any(feature = "luau-jit", doc))]
1303 #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1304 pub fn enable_jit(&self, enable: bool) {
1305 let lua = self.lock();
1306 unsafe { (*lua.extra.get()).enable_jit = enable };
1307 }
1308
1309 /// Configures JIT options for this Lua VM.
1310 #[cfg(any(feature = "luau-jit", doc))]
1311 #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1312 pub fn set_jit_options(&self, options: JitOptions) {
1313 let lua = self.lock();
1314 unsafe {
1315 let state = lua.main_state();
1316 if options.inliner {
1317 let _ = Self::set_fflag("LuauCallFeedback", true);
1318 let _ = Self::set_fflag("LuauEmitCallFeedback", true);
1319 ffi::luau_enable_jit_inliner(state);
1320 } else {
1321 ffi::luau_disable_jit_inliner(state);
1322 }
1323 }
1324 }
1325
1326 /// Sets Luau feature flag (global setting).
1327 ///
1328 /// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
1329 #[cfg(feature = "luau")]
1330 #[doc(hidden)]
1331 #[allow(clippy::result_unit_err)]
1332 pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
1333 if let Ok(name) = std::ffi::CString::new(name)
1334 && unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 }
1335 {
1336 return Ok(());
1337 }
1338 Err(())
1339 }
1340
1341 /// Returns Lua source code as a `Chunk` builder type.
1342 ///
1343 /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or
1344 /// similar on the returned builder. Code is not even parsed until one of these methods is
1345 /// called.
1346 ///
1347 /// [`Chunk::exec`]: crate::chunk::Chunk::exec
1348 #[track_caller]
1349 pub fn load<'a>(&self, chunk: impl AsChunk + 'a) -> Chunk<'a> {
1350 self.load_with_location(chunk, Location::caller())
1351 }
1352
1353 pub(crate) fn load_with_location<'a>(
1354 &self,
1355 chunk: impl AsChunk + 'a,
1356 location: &'static Location<'static>,
1357 ) -> Chunk<'a> {
1358 Chunk {
1359 lua: self.weak(),
1360 name: chunk
1361 .name()
1362 .unwrap_or_else(|| format!("@{}:{}", location.file(), location.line())),
1363 env: chunk.environment(self),
1364 mode: chunk.mode(),
1365 source: chunk.source(),
1366 #[cfg(feature = "luau")]
1367 compiler: unsafe { (*self.lock().extra.get()).compiler.clone() },
1368 }
1369 }
1370
1371 /// Creates and returns an interned Lua string.
1372 ///
1373 /// Lua strings can be arbitrary `[u8]` data including embedded nulls, so in addition to `&str`
1374 /// and `&String`, you can also pass plain `&[u8]` here.
1375 #[inline]
1376 pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<LuaString> {
1377 unsafe { self.lock().create_string(s.as_ref()) }
1378 }
1379
1380 /// Creates and returns an external Lua string.
1381 ///
1382 /// External string is a string where the memory is managed by Rust code, and Lua only holds a
1383 /// reference to it. This can be used to avoid copying large strings into Lua memory.
1384 #[cfg(feature = "lua55")]
1385 #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
1386 #[inline]
1387 pub fn create_external_string(&self, s: impl Into<Vec<u8>>) -> Result<LuaString> {
1388 unsafe { self.lock().create_external_string(s.into()) }
1389 }
1390
1391 /// Creates and returns a Luau [buffer] object from a byte slice of data.
1392 ///
1393 /// [buffer]: https://luau.org/library#buffer-library
1394 #[cfg(any(feature = "luau", doc))]
1395 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1396 pub fn create_buffer(&self, data: impl AsRef<[u8]>) -> Result<Buffer> {
1397 let lua = self.lock();
1398 let data = data.as_ref();
1399 unsafe {
1400 let (ptr, buffer) = lua.create_buffer_with_capacity(data.len())?;
1401 ptr.copy_from_nonoverlapping(data.as_ptr(), data.len());
1402 Ok(buffer)
1403 }
1404 }
1405
1406 /// Creates and returns a Luau [buffer] object with the specified size.
1407 ///
1408 /// Size limit is 1GB. All bytes will be initialized to zero.
1409 ///
1410 /// [buffer]: https://luau.org/library#buffer-library
1411 #[cfg(any(feature = "luau", doc))]
1412 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1413 pub fn create_buffer_with_capacity(&self, size: usize) -> Result<Buffer> {
1414 unsafe { Ok(self.lock().create_buffer_with_capacity(size)?.1) }
1415 }
1416
1417 /// Creates and returns a new empty table.
1418 #[inline]
1419 pub fn create_table(&self) -> Result<Table> {
1420 self.create_table_with_capacity(0, 0)
1421 }
1422
1423 /// Creates and returns a new empty table, with the specified capacity.
1424 ///
1425 /// - `narr` is a hint for how many elements the table will have as a sequence.
1426 /// - `nrec` is a hint for how many other elements the table will have.
1427 ///
1428 /// Lua may use these hints to preallocate memory for the new table.
1429 pub fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
1430 unsafe { self.lock().create_table_with_capacity(narr, nrec) }
1431 }
1432
1433 /// Creates a table and fills it with values from an iterator.
1434 pub fn create_table_from<K, V>(&self, iter: impl IntoIterator<Item = (K, V)>) -> Result<Table>
1435 where
1436 K: IntoLua,
1437 V: IntoLua,
1438 {
1439 unsafe { self.lock().create_table_from(iter) }
1440 }
1441
1442 /// Creates a table from an iterator of values, using `1..` as the keys.
1443 pub fn create_sequence_from<T>(&self, iter: impl IntoIterator<Item = T>) -> Result<Table>
1444 where
1445 T: IntoLua,
1446 {
1447 unsafe { self.lock().create_sequence_from(iter) }
1448 }
1449
1450 /// Wraps a Rust function or closure, creating a callable Lua function handle to it.
1451 ///
1452 /// The function's return value is always a `Result`: If the function returns `Err`, the error
1453 /// is raised as a Lua error, which can be caught using `(x)pcall` or bubble up to the Rust code
1454 /// that invoked the Lua code. This allows using the `?` operator to propagate errors through
1455 /// intermediate Lua code.
1456 ///
1457 /// If the function returns `Ok`, the contained value will be converted to one or more Lua
1458 /// values. For details on Rust-to-Lua conversions, refer to the [`IntoLua`] and
1459 /// [`IntoLuaMulti`] traits.
1460 ///
1461 /// # Examples
1462 ///
1463 /// Create a function which prints its argument:
1464 ///
1465 /// ```
1466 /// # use mlua::{Lua, Result};
1467 /// # fn main() -> Result<()> {
1468 /// # let lua = Lua::new();
1469 /// let greet = lua.create_function(|_, name: String| {
1470 /// println!("Hello, {}!", name);
1471 /// Ok(())
1472 /// });
1473 /// # let _ = greet; // used
1474 /// # Ok(())
1475 /// # }
1476 /// ```
1477 ///
1478 /// Use tuples to accept multiple arguments:
1479 ///
1480 /// ```
1481 /// # use mlua::{Lua, Result};
1482 /// # fn main() -> Result<()> {
1483 /// # let lua = Lua::new();
1484 /// let print_person = lua.create_function(|_, (name, age): (String, u8)| {
1485 /// println!("{} is {} years old!", name, age);
1486 /// Ok(())
1487 /// });
1488 /// # let _ = print_person; // used
1489 /// # Ok(())
1490 /// # }
1491 /// ```
1492 pub fn create_function<F, A, R>(&self, func: F) -> Result<Function>
1493 where
1494 F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
1495 A: FromLuaMulti,
1496 R: IntoLuaMulti,
1497 {
1498 (self.lock()).create_callback(Box::new(move |rawlua, nargs| unsafe {
1499 let args = A::from_stack_args(nargs, 1, None, rawlua)?;
1500 func(rawlua.lua(), args)?.push_into_stack_multi(rawlua)
1501 }))
1502 }
1503
1504 /// Wraps a Rust mutable closure, creating a callable Lua function handle to it.
1505 ///
1506 /// This is a version of [`Lua::create_function`] that accepts a `FnMut` argument.
1507 pub fn create_function_mut<F, A, R>(&self, func: F) -> Result<Function>
1508 where
1509 F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
1510 A: FromLuaMulti,
1511 R: IntoLuaMulti,
1512 {
1513 let func = RefCell::new(func);
1514 self.create_function(move |lua, args| {
1515 (*func.try_borrow_mut().map_err(|_| Error::RecursiveMutCallback)?)(lua, args)
1516 })
1517 }
1518
1519 /// Wraps a C function, creating a callable Lua function handle to it.
1520 ///
1521 /// # Safety
1522 /// This function is unsafe because provides a way to execute unsafe C function.
1523 pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
1524 let lua = self.lock();
1525 if cfg!(any(
1526 feature = "lua55",
1527 feature = "lua54",
1528 feature = "lua53",
1529 feature = "lua52"
1530 )) {
1531 ffi::lua_pushcfunction(lua.ref_thread(), func);
1532 return Ok(Function(lua.pop_ref_thread()));
1533 }
1534
1535 // Lua <5.2 requires memory allocation to push a C function
1536 let state = lua.state();
1537 {
1538 let _sg = StackGuard::new(state);
1539 check_stack(state, 3)?;
1540
1541 if lua.unlikely_memory_error() {
1542 ffi::lua_pushcfunction(state, func);
1543 } else {
1544 protect_lua!(state, 0, 1, |state| ffi::lua_pushcfunction(state, func))?;
1545 }
1546 Ok(Function(lua.pop_ref()))
1547 }
1548 }
1549
1550 /// Wraps a Rust async function or closure, creating a callable Lua function handle to it.
1551 ///
1552 /// While executing the function Rust will poll the Future and if the result is not ready,
1553 /// call `yield()` passing internal representation of a `Poll::Pending` value.
1554 ///
1555 /// The function must be called inside Lua coroutine ([`Thread`]) to be able to suspend its
1556 /// execution. An executor should be used to poll [`AsyncThread`] and mlua will take a provided
1557 /// Waker in that case. Otherwise noop waker will be used if try to call the function outside of
1558 /// Rust executors.
1559 ///
1560 /// The family of `call_async()` functions takes care about creating [`Thread`].
1561 ///
1562 /// # Examples
1563 ///
1564 /// Non blocking sleep:
1565 ///
1566 /// ```
1567 /// use std::time::Duration;
1568 /// use mlua::{Lua, Result};
1569 ///
1570 /// async fn sleep(_lua: Lua, n: u64) -> Result<&'static str> {
1571 /// tokio::time::sleep(Duration::from_millis(n)).await;
1572 /// Ok("done")
1573 /// }
1574 ///
1575 /// #[tokio::main]
1576 /// async fn main() -> Result<()> {
1577 /// let lua = Lua::new();
1578 /// lua.globals().set("sleep", lua.create_async_function(sleep)?)?;
1579 /// let res: String = lua.load("return sleep(...)").call_async(100).await?; // Sleep 100ms
1580 /// assert_eq!(res, "done");
1581 /// Ok(())
1582 /// }
1583 /// ```
1584 ///
1585 /// [`AsyncThread`]: crate::thread::AsyncThread
1586 #[cfg(feature = "async")]
1587 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1588 pub fn create_async_function<F, A, FR, R>(&self, func: F) -> Result<Function>
1589 where
1590 F: Fn(Lua, A) -> FR + MaybeSend + 'static,
1591 A: FromLuaMulti,
1592 FR: Future<Output = Result<R>> + MaybeSend + 'static,
1593 R: IntoLuaMulti,
1594 {
1595 // In future we should switch to async closures when they are stable to capture `&Lua`
1596 // See https://rust-lang.github.io/rfcs/3668-async-closures.html
1597 (self.lock()).create_async_callback(Box::new(move |rawlua, nargs| unsafe {
1598 let args = match A::from_stack_args(nargs, 1, None, rawlua) {
1599 Ok(args) => args,
1600 Err(e) => return Box::pin(future::ready(Err(e))),
1601 };
1602 let lua = rawlua.lua();
1603 let fut = func(lua.clone(), args);
1604 Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
1605 }))
1606 }
1607
1608 /// Wraps a Lua function into a new thread (or coroutine).
1609 ///
1610 /// Equivalent to `coroutine.create`.
1611 pub fn create_thread(&self, func: Function) -> Result<Thread> {
1612 unsafe { self.lock().create_thread(&func) }
1613 }
1614
1615 /// Creates a Lua userdata object from a custom userdata type.
1616 ///
1617 /// All userdata instances of the same type `T` shares the same metatable.
1618 #[inline]
1619 pub fn create_userdata<T>(&self, data: T) -> Result<AnyUserData>
1620 where
1621 T: UserData + MaybeSend + MaybeSync + 'static,
1622 {
1623 unsafe { self.lock().make_userdata(UserDataStorage::new(data)) }
1624 }
1625
1626 /// Creates a Lua userdata object from a custom serializable userdata type.
1627 #[cfg(feature = "serde")]
1628 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1629 #[inline]
1630 pub fn create_ser_userdata<T>(&self, data: T) -> Result<AnyUserData>
1631 where
1632 T: UserData + Serialize + MaybeSend + MaybeSync + 'static,
1633 {
1634 unsafe { self.lock().make_userdata(UserDataStorage::new_ser(data)) }
1635 }
1636
1637 /// Creates a Lua userdata object from a custom Rust type.
1638 ///
1639 /// You can register the type using [`Lua::register_userdata_type`] to add fields or methods
1640 /// _before_ calling this method.
1641 /// Otherwise, the userdata object will have an empty metatable.
1642 ///
1643 /// All userdata instances of the same type `T` shares the same metatable.
1644 #[inline]
1645 pub fn create_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1646 where
1647 T: MaybeSend + MaybeSync + 'static,
1648 {
1649 unsafe { self.lock().make_any_userdata(UserDataStorage::new(data)) }
1650 }
1651
1652 /// Creates a Lua userdata object from a custom serializable Rust type.
1653 ///
1654 /// See [`Lua::create_any_userdata`] for more details.
1655 #[cfg(feature = "serde")]
1656 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1657 #[inline]
1658 pub fn create_ser_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1659 where
1660 T: Serialize + MaybeSend + MaybeSync + 'static,
1661 {
1662 unsafe { (self.lock()).make_any_userdata(UserDataStorage::new_ser(data)) }
1663 }
1664
1665 /// Registers a custom Rust type in Lua to use in userdata objects.
1666 ///
1667 /// This methods provides a way to add fields or methods to userdata objects of a type `T`.
1668 pub fn register_userdata_type<T: 'static>(&self, f: impl FnOnce(&mut UserDataRegistry<T>)) -> Result<()> {
1669 let type_id = TypeId::of::<T>();
1670 let mut registry = UserDataRegistry::new(self);
1671 f(&mut registry);
1672
1673 let lua = self.lock();
1674 unsafe {
1675 // Deregister the type if it already registered
1676 if let Some(table_id) = (*lua.extra.get()).registered_userdata_t.remove(&type_id) {
1677 ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, table_id);
1678 }
1679
1680 // Add to "pending" registration map
1681 ((*lua.extra.get()).pending_userdata_reg).insert(type_id, registry.into_raw());
1682 }
1683 Ok(())
1684 }
1685
1686 /// Create a Lua userdata "proxy" object from a custom userdata type.
1687 ///
1688 /// Proxy object is an empty userdata object that has `T` metatable attached.
1689 /// The main purpose of this object is to provide access to static fields and functions
1690 /// without creating an instance of type `T`.
1691 ///
1692 /// You can get or set uservalues on this object but you cannot borrow any Rust type.
1693 ///
1694 /// # Examples
1695 ///
1696 /// ```
1697 /// # use mlua::{Lua, Result, UserData, UserDataFields, UserDataMethods};
1698 /// # fn main() -> Result<()> {
1699 /// # let lua = Lua::new();
1700 /// struct MyUserData(i32);
1701 ///
1702 /// impl UserData for MyUserData {
1703 /// fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
1704 /// fields.add_field_method_get("val", |_, this| Ok(this.0));
1705 /// }
1706 ///
1707 /// fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
1708 /// methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
1709 /// }
1710 /// }
1711 ///
1712 /// lua.globals().set("MyUserData", lua.create_proxy::<MyUserData>()?)?;
1713 ///
1714 /// lua.load("assert(MyUserData.new(321).val == 321)").exec()?;
1715 /// # Ok(())
1716 /// # }
1717 /// ```
1718 #[inline]
1719 pub fn create_proxy<T>(&self) -> Result<AnyUserData>
1720 where
1721 T: UserData + 'static,
1722 {
1723 let ud = UserDataProxy::<T>(PhantomData);
1724 unsafe { self.lock().make_userdata(UserDataStorage::new(ud)) }
1725 }
1726
1727 /// Gets the metatable of a Lua built-in (primitive) type.
1728 ///
1729 /// The metatable is shared by all values of the given type.
1730 ///
1731 /// See [`Lua::set_type_metatable`] for examples.
1732 #[allow(private_bounds)]
1733 pub fn type_metatable<T: LuaType>(&self) -> Option<Table> {
1734 let lua = self.lock();
1735 let state = lua.state();
1736 unsafe {
1737 let _sg = StackGuard::new(state);
1738 assert_stack(state, 2);
1739
1740 if lua.push_primitive_type::<T>() && ffi::lua_getmetatable(state, -1) != 0 {
1741 return Some(Table(lua.pop_ref()));
1742 }
1743 }
1744 None
1745 }
1746
1747 /// Sets the metatable for a Lua built-in (primitive) type.
1748 ///
1749 /// The metatable will be shared by all values of the given type.
1750 ///
1751 /// # Examples
1752 ///
1753 /// Change metatable for Lua boolean type:
1754 ///
1755 /// ```
1756 /// # use mlua::{Lua, Result, Function};
1757 /// # fn main() -> Result<()> {
1758 /// # let lua = Lua::new();
1759 /// let mt = lua.create_table()?;
1760 /// mt.set("__tostring", lua.create_function(|_, b: bool| Ok(if b { "2" } else { "0" }))?)?;
1761 /// lua.set_type_metatable::<bool>(Some(mt));
1762 /// lua.load("assert(tostring(true) == '2')").exec()?;
1763 /// # Ok(())
1764 /// # }
1765 /// ```
1766 #[allow(private_bounds)]
1767 pub fn set_type_metatable<T: LuaType>(&self, metatable: Option<Table>) {
1768 let lua = self.lock();
1769 let state = lua.state();
1770 unsafe {
1771 let _sg = StackGuard::new(state);
1772 assert_stack(state, 2);
1773
1774 if lua.push_primitive_type::<T>() {
1775 match metatable {
1776 Some(metatable) => lua.push_ref(&metatable.0),
1777 None => ffi::lua_pushnil(state),
1778 }
1779 ffi::lua_setmetatable(state, -2);
1780 }
1781 }
1782 }
1783
1784 /// Returns a handle to the global environment.
1785 pub fn globals(&self) -> Table {
1786 let lua = self.lock();
1787 let state = lua.state();
1788 unsafe {
1789 let _sg = StackGuard::new(state);
1790 assert_stack(state, 1);
1791 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1792 ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1793 #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1794 ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
1795 Table(lua.pop_ref())
1796 }
1797 }
1798
1799 /// Sets the global environment.
1800 ///
1801 /// This will replace the current global environment with the provided `globals` table.
1802 ///
1803 /// For Lua 5.2+ the globals table is stored in the registry and shared between all threads.
1804 /// For Lua 5.1 and Luau the globals table is stored in each thread.
1805 ///
1806 /// Please note that any existing Lua functions have cached global environment and will not
1807 /// see the changes made by this method.
1808 /// To update the environment for existing Lua functions, use [`Function::set_environment`].
1809 pub fn set_globals(&self, globals: Table) -> Result<()> {
1810 let lua = self.lock();
1811 let state = lua.state();
1812 unsafe {
1813 #[cfg(feature = "luau")]
1814 if (*lua.extra.get()).sandboxed {
1815 return Err(Error::runtime("cannot change globals in a sandboxed Lua state"));
1816 }
1817
1818 let _sg = StackGuard::new(state);
1819 check_stack(state, 1)?;
1820
1821 lua.push_ref(&globals.0);
1822
1823 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1824 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1825 #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1826 ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
1827 }
1828
1829 Ok(())
1830 }
1831
1832 /// Returns a handle to the active `Thread`.
1833 ///
1834 /// For calls to `Lua` this will be the main Lua thread, for parameters given to a callback,
1835 /// this will be whatever Lua thread called the callback.
1836 pub fn current_thread(&self) -> Thread {
1837 let lua = self.lock();
1838 let state = lua.state();
1839 unsafe {
1840 // If this thread is implicit (created by `call_async`), return the root user-owned thread
1841 // instead.
1842 #[cfg(feature = "async")]
1843 if let Some(&owner) = (*lua.extra.get()).thread_ownership_map.get(&state) {
1844 assert_stack(owner, 1);
1845 ffi::lua_pushthread(owner);
1846 ffi::lua_xmove(owner, lua.ref_thread(), 1);
1847 return Thread(lua.pop_ref_thread(), owner);
1848 }
1849
1850 let _sg = StackGuard::new(state);
1851 assert_stack(state, 1);
1852 ffi::lua_pushthread(state);
1853 Thread(lua.pop_ref(), state)
1854 }
1855 }
1856
1857 /// Calls the given function with a [`Scope`] parameter, giving the function the ability to
1858 /// create userdata and callbacks from Rust types that are `!Send` or non-`'static`.
1859 ///
1860 /// The lifetime of any function or userdata created through [`Scope`] lasts only until the
1861 /// completion of this method call, on completion all such created values are automatically
1862 /// dropped and Lua references to them are invalidated. If a script accesses a value created
1863 /// through [`Scope`] outside of this method, a Lua error will result. Since we can ensure the
1864 /// lifetime of values created through [`Scope`], and we know that [`Lua`] cannot be sent to
1865 /// another thread while [`Scope`] is live, it is safe to allow `!Send` data types and whose
1866 /// lifetimes only outlive the scope lifetime.
1867 pub fn scope<'env, R>(
1868 &self,
1869 f: impl for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> Result<R>,
1870 ) -> Result<R> {
1871 f(&Scope::new(self.lock_arc()))
1872 }
1873
1874 /// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
1875 /// behavior.
1876 ///
1877 /// To succeed, the value must be a string (in which case this is a no-op), an integer, or a
1878 /// number.
1879 pub fn coerce_string(&self, v: Value) -> Result<Option<LuaString>> {
1880 Ok(match v {
1881 Value::String(s) => Some(s),
1882 v => unsafe {
1883 let lua = self.lock();
1884 let state = lua.state();
1885 let _sg = StackGuard::new(state);
1886 check_stack(state, 4)?;
1887
1888 lua.push_value(&v)?;
1889 let res = if lua.unlikely_memory_error() {
1890 ffi::lua_tolstring(state, -1, ptr::null_mut())
1891 } else {
1892 protect_lua!(state, 1, 1, |state| {
1893 ffi::lua_tolstring(state, -1, ptr::null_mut())
1894 })?
1895 };
1896 if !res.is_null() {
1897 Some(LuaString(lua.pop_ref()))
1898 } else {
1899 None
1900 }
1901 },
1902 })
1903 }
1904
1905 /// Attempts to coerce a Lua value into an integer in a manner consistent with Lua's internal
1906 /// behavior.
1907 ///
1908 /// To succeed, the value must be an integer, a floating point number that has an exact
1909 /// representation as an integer, or a string that can be converted to an integer. Refer to the
1910 /// Lua manual for details.
1911 pub fn coerce_integer(&self, v: Value) -> Result<Option<Integer>> {
1912 Ok(match v {
1913 Value::Integer(i) => Some(i),
1914 v => unsafe {
1915 let lua = self.lock();
1916 let state = lua.state();
1917 let _sg = StackGuard::new(state);
1918 check_stack(state, 2)?;
1919
1920 lua.push_value(&v)?;
1921 let mut isint = 0;
1922 let i = ffi::lua_tointegerx(state, -1, &mut isint);
1923 (isint != 0).then_some(i)
1924 },
1925 })
1926 }
1927
1928 /// Attempts to coerce a Lua value into a Number in a manner consistent with Lua's internal
1929 /// behavior.
1930 ///
1931 /// To succeed, the value must be a number or a string that can be converted to a number. Refer
1932 /// to the Lua manual for details.
1933 pub fn coerce_number(&self, v: Value) -> Result<Option<Number>> {
1934 Ok(match v {
1935 Value::Number(n) => Some(n),
1936 v => unsafe {
1937 let lua = self.lock();
1938 let state = lua.state();
1939 let _sg = StackGuard::new(state);
1940 check_stack(state, 2)?;
1941
1942 lua.push_value(&v)?;
1943 let mut isnum = 0;
1944 let n = ffi::lua_tonumberx(state, -1, &mut isnum);
1945 (isnum != 0).then_some(n)
1946 },
1947 })
1948 }
1949
1950 /// Converts a value that implements [`IntoLua`] into a [`Value`] instance.
1951 #[inline]
1952 pub fn pack(&self, t: impl IntoLua) -> Result<Value> {
1953 t.into_lua(self)
1954 }
1955
1956 /// Converts a [`Value`] instance into a value that implements [`FromLua`].
1957 #[inline]
1958 pub fn unpack<T: FromLua>(&self, value: Value) -> Result<T> {
1959 T::from_lua(value, self)
1960 }
1961
1962 /// Converts a value that implements [`IntoLua`] into a [`FromLua`] variant.
1963 #[inline]
1964 pub fn convert<U: FromLua>(&self, value: impl IntoLua) -> Result<U> {
1965 U::from_lua(value.into_lua(self)?, self)
1966 }
1967
1968 /// Converts a value that implements [`IntoLuaMulti`] into a [`MultiValue`] instance.
1969 #[inline]
1970 pub fn pack_multi(&self, t: impl IntoLuaMulti) -> Result<MultiValue> {
1971 t.into_lua_multi(self)
1972 }
1973
1974 /// Converts a [`MultiValue`] instance into a value that implements [`FromLuaMulti`].
1975 #[inline]
1976 pub fn unpack_multi<T: FromLuaMulti>(&self, value: MultiValue) -> Result<T> {
1977 T::from_lua_multi(value, self)
1978 }
1979
1980 /// Set a value in the Lua registry based on a string key.
1981 ///
1982 /// This value will be available to Rust from all Lua instances which share the same main
1983 /// state.
1984 pub fn set_named_registry_value(&self, key: &str, t: impl IntoLua) -> Result<()> {
1985 let lua = self.lock();
1986 let state = lua.state();
1987 unsafe {
1988 let _sg = StackGuard::new(state);
1989 check_stack(state, 5)?;
1990
1991 lua.push(t)?;
1992 rawset_field(state, ffi::LUA_REGISTRYINDEX, key)
1993 }
1994 }
1995
1996 /// Get a value from the Lua registry based on a string key.
1997 ///
1998 /// Any Lua instance which shares the underlying main state may call this method to
1999 /// get a value previously set by [`Lua::set_named_registry_value`].
2000 pub fn named_registry_value<T>(&self, key: &str) -> Result<T>
2001 where
2002 T: FromLua,
2003 {
2004 let lua = self.lock();
2005 let state = lua.state();
2006 unsafe {
2007 let _sg = StackGuard::new(state);
2008 check_stack(state, 3)?;
2009
2010 let protect = !lua.unlikely_memory_error();
2011 push_string(state, key.as_bytes(), protect)?;
2012 ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
2013
2014 T::from_stack(-1, &lua)
2015 }
2016 }
2017
2018 /// Removes a named value in the Lua registry.
2019 ///
2020 /// Equivalent to calling [`Lua::set_named_registry_value`] with a value of [`Nil`].
2021 #[inline]
2022 pub fn unset_named_registry_value(&self, key: &str) -> Result<()> {
2023 self.set_named_registry_value(key, Nil)
2024 }
2025
2026 /// Place a value in the Lua registry with an auto-generated key.
2027 ///
2028 /// This value will be available to Rust from all Lua instances which share the same main
2029 /// state.
2030 ///
2031 /// Be warned, garbage collection of values held inside the registry is not automatic, see
2032 /// [`RegistryKey`] for more details.
2033 /// However, dropped [`RegistryKey`]s automatically reused to store new values.
2034 pub fn create_registry_value(&self, t: impl IntoLua) -> Result<RegistryKey> {
2035 let lua = self.lock();
2036 let state = lua.state();
2037 unsafe {
2038 let _sg = StackGuard::new(state);
2039 check_stack(state, 4)?;
2040
2041 lua.push(t)?;
2042
2043 let unref_list = (*lua.extra.get()).registry_unref_list.clone();
2044
2045 // Check if the value is nil (no need to store it in the registry)
2046 if ffi::lua_isnil(state, -1) != 0 {
2047 return Ok(RegistryKey::new(ffi::LUA_REFNIL, unref_list));
2048 }
2049
2050 // Try to reuse previously allocated slot
2051 let free_registry_id = unref_list.lock().as_mut().and_then(|x| x.pop());
2052 if let Some(registry_id) = free_registry_id {
2053 // It must be safe to replace the value without triggering memory error
2054 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2055 return Ok(RegistryKey::new(registry_id, unref_list));
2056 }
2057
2058 // Allocate a new RegistryKey slot
2059 let registry_id = if lua.unlikely_memory_error() {
2060 ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
2061 } else {
2062 protect_lua!(state, 1, 0, |state| {
2063 ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
2064 })?
2065 };
2066 Ok(RegistryKey::new(registry_id, unref_list))
2067 }
2068 }
2069
2070 /// Get a value from the Lua registry by its [`RegistryKey`]
2071 ///
2072 /// Any Lua instance which shares the underlying main state may call this method to get a value
2073 /// previously placed by [`Lua::create_registry_value`].
2074 pub fn registry_value<T: FromLua>(&self, key: &RegistryKey) -> Result<T> {
2075 let lua = self.lock();
2076 if !lua.owns_registry_value(key) {
2077 return Err(Error::MismatchedRegistryKey);
2078 }
2079
2080 let state = lua.state();
2081 match key.id() {
2082 ffi::LUA_REFNIL => T::from_lua(Value::Nil, self),
2083 registry_id => unsafe {
2084 let _sg = StackGuard::new(state);
2085 check_stack(state, 1)?;
2086
2087 ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2088 T::from_stack(-1, &lua)
2089 },
2090 }
2091 }
2092
2093 /// Removes a value from the Lua registry.
2094 ///
2095 /// You may call this function to manually remove a value placed in the registry with
2096 /// [`Lua::create_registry_value`]. In addition to manual [`RegistryKey`] removal, you can also
2097 /// call [`Lua::expire_registry_values`] to automatically remove values from the registry
2098 /// whose [`RegistryKey`]s have been dropped.
2099 pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
2100 let lua = self.lock();
2101 if !lua.owns_registry_value(&key) {
2102 return Err(Error::MismatchedRegistryKey);
2103 }
2104
2105 unsafe { ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, key.take()) };
2106 Ok(())
2107 }
2108
2109 /// Replaces a value in the Lua registry by its [`RegistryKey`].
2110 ///
2111 /// An identifier used in [`RegistryKey`] may possibly be changed to a new value.
2112 ///
2113 /// See [`Lua::create_registry_value`] for more details.
2114 pub fn replace_registry_value(&self, key: &mut RegistryKey, t: impl IntoLua) -> Result<()> {
2115 let lua = self.lock();
2116 if !lua.owns_registry_value(key) {
2117 return Err(Error::MismatchedRegistryKey);
2118 }
2119
2120 let t = t.into_lua(self)?;
2121
2122 let state = lua.state();
2123 unsafe {
2124 let _sg = StackGuard::new(state);
2125 check_stack(state, 2)?;
2126
2127 match (t, key.id()) {
2128 (Value::Nil, ffi::LUA_REFNIL) => {
2129 // Do nothing, no need to replace nil with nil
2130 }
2131 (Value::Nil, registry_id) => {
2132 // Remove the value
2133 ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, registry_id);
2134 key.set_id(ffi::LUA_REFNIL);
2135 }
2136 (value, ffi::LUA_REFNIL) => {
2137 // Allocate a new `RegistryKey`
2138 let new_key = self.create_registry_value(value)?;
2139 key.set_id(new_key.take());
2140 }
2141 (value, registry_id) => {
2142 // It must be safe to replace the value without triggering memory error
2143 lua.push_value(&value)?;
2144 ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2145 }
2146 }
2147 }
2148 Ok(())
2149 }
2150
2151 /// Returns true if the given [`RegistryKey`] was created by a Lua which shares the
2152 /// underlying main state with this Lua instance.
2153 ///
2154 /// Other than this, methods that accept a [`RegistryKey`] will return
2155 /// [`Error::MismatchedRegistryKey`] if passed a [`RegistryKey`] that was not created with a
2156 /// matching [`Lua`] state.
2157 #[inline]
2158 pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
2159 self.lock().owns_registry_value(key)
2160 }
2161
2162 /// Remove any registry values whose [`RegistryKey`]s have all been dropped.
2163 ///
2164 /// Unlike normal handle values, [`RegistryKey`]s do not automatically remove themselves on
2165 /// Drop, but you can call this method to remove any unreachable registry values not
2166 /// manually removed by [`Lua::remove_registry_value`].
2167 pub fn expire_registry_values(&self) {
2168 let lua = self.lock();
2169 let state = lua.state();
2170 unsafe {
2171 let mut unref_list = (*lua.extra.get()).registry_unref_list.lock();
2172 let unref_list = unref_list.replace(Vec::new());
2173 for id in mlua_expect!(unref_list, "unref list is not set") {
2174 ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
2175 }
2176 }
2177 }
2178
2179 /// Sets or replaces an application data object of type `T`.
2180 ///
2181 /// Application data could be accessed at any time by using [`Lua::app_data_ref`] or
2182 /// [`Lua::app_data_mut`] methods where `T` is the data type.
2183 ///
2184 /// # Panics
2185 ///
2186 /// Panics if the app data container is currently borrowed.
2187 ///
2188 /// # Examples
2189 ///
2190 /// ```
2191 /// use mlua::{Lua, Result};
2192 ///
2193 /// fn hello(lua: &Lua, _: ()) -> Result<()> {
2194 /// let mut s = lua.app_data_mut::<&str>().unwrap();
2195 /// assert_eq!(*s, "hello");
2196 /// *s = "world";
2197 /// Ok(())
2198 /// }
2199 ///
2200 /// fn main() -> Result<()> {
2201 /// let lua = Lua::new();
2202 /// lua.set_app_data("hello");
2203 /// lua.create_function(hello)?.call::<()>(())?;
2204 /// let s = lua.app_data_ref::<&str>().unwrap();
2205 /// assert_eq!(*s, "world");
2206 /// Ok(())
2207 /// }
2208 /// ```
2209 #[track_caller]
2210 pub fn set_app_data<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
2211 let lua = self.lock();
2212 let extra = unsafe { &*lua.extra.get() };
2213 extra.app_data.insert(data)
2214 }
2215
2216 /// Tries to set or replace an application data object of type `T`.
2217 ///
2218 /// Returns:
2219 /// - `Ok(Some(old_data))` if the data object of type `T` was successfully replaced.
2220 /// - `Ok(None)` if the data object of type `T` was successfully inserted.
2221 /// - `Err(data)` if the data object of type `T` was not inserted because the container is
2222 /// currently borrowed.
2223 ///
2224 /// See [`Lua::set_app_data`] for examples.
2225 pub fn try_set_app_data<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
2226 let lua = self.lock();
2227 let extra = unsafe { &*lua.extra.get() };
2228 extra.app_data.try_insert(data)
2229 }
2230
2231 /// Gets a reference to an application data object stored by [`Lua::set_app_data`] of type
2232 /// `T`.
2233 ///
2234 /// # Panics
2235 ///
2236 /// Panics if the data object of type `T` is currently mutably borrowed. Multiple immutable
2237 /// reads can be taken out at the same time.
2238 #[track_caller]
2239 pub fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<'_, T>> {
2240 let guard = self.lock_arc();
2241 let extra = unsafe { &*guard.extra.get() };
2242 extra.app_data.borrow(Some(guard))
2243 }
2244
2245 /// Tries to get a reference to an application data object stored by [`Lua::set_app_data`] of
2246 /// type `T`.
2247 pub fn try_app_data_ref<T: 'static>(&self) -> StdResult<Option<AppDataRef<'_, T>>, BorrowError> {
2248 let guard = self.lock_arc();
2249 let extra = unsafe { &*guard.extra.get() };
2250 extra.app_data.try_borrow(Some(guard))
2251 }
2252
2253 /// Gets a mutable reference to an application data object stored by [`Lua::set_app_data`] of
2254 /// type `T`.
2255 ///
2256 /// # Panics
2257 ///
2258 /// Panics if the data object of type `T` is currently borrowed.
2259 #[track_caller]
2260 pub fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<'_, T>> {
2261 let guard = self.lock_arc();
2262 let extra = unsafe { &*guard.extra.get() };
2263 extra.app_data.borrow_mut(Some(guard))
2264 }
2265
2266 /// Tries to get a mutable reference to an application data object stored by
2267 /// [`Lua::set_app_data`] of type `T`.
2268 pub fn try_app_data_mut<T: 'static>(&self) -> StdResult<Option<AppDataRefMut<'_, T>>, BorrowMutError> {
2269 let guard = self.lock_arc();
2270 let extra = unsafe { &*guard.extra.get() };
2271 extra.app_data.try_borrow_mut(Some(guard))
2272 }
2273
2274 /// Removes an application data of type `T`.
2275 ///
2276 /// # Panics
2277 ///
2278 /// Panics if the app data container is currently borrowed.
2279 #[track_caller]
2280 pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
2281 let lua = self.lock();
2282 let extra = unsafe { &*lua.extra.get() };
2283 extra.app_data.remove()
2284 }
2285
2286 /// Returns an internal `Poll::Pending` constant used for executing async callbacks.
2287 ///
2288 /// Every time when [`Future`] is Pending, Lua corotine is suspended with this constant.
2289 #[cfg(feature = "async")]
2290 #[doc(hidden)]
2291 #[inline(always)]
2292 pub fn poll_pending() -> LightUserData {
2293 static ASYNC_POLL_PENDING: u8 = 0;
2294 LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut std::os::raw::c_void)
2295 }
2296
2297 #[cfg(feature = "async")]
2298 #[inline(always)]
2299 pub(crate) fn poll_terminate() -> LightUserData {
2300 static ASYNC_POLL_TERMINATE: u8 = 0;
2301 LightUserData(&ASYNC_POLL_TERMINATE as *const u8 as *mut std::os::raw::c_void)
2302 }
2303
2304 #[cfg(feature = "async")]
2305 #[inline(always)]
2306 pub(crate) fn poll_yield() -> LightUserData {
2307 static ASYNC_POLL_YIELD: u8 = 0;
2308 LightUserData(&ASYNC_POLL_YIELD as *const u8 as *mut std::os::raw::c_void)
2309 }
2310
2311 /// Suspends the current async function, returning the provided arguments to caller.
2312 ///
2313 /// This function is similar to [`coroutine.yield`] but allow yielding Rust functions
2314 /// and passing values to the caller.
2315 /// Please note that you cannot cross [`Thread`] boundaries (e.g. calling `yield_with` on one
2316 /// thread and resuming on another).
2317 ///
2318 /// # Examples
2319 ///
2320 /// Async iterator:
2321 ///
2322 /// ```
2323 /// # use mlua::{Lua, Result};
2324 /// #
2325 /// async fn generator(lua: Lua, _: ()) -> Result<()> {
2326 /// for i in 0..10 {
2327 /// lua.yield_with::<()>(i).await?;
2328 /// }
2329 /// Ok(())
2330 /// }
2331 ///
2332 /// fn main() -> Result<()> {
2333 /// let lua = Lua::new();
2334 /// lua.globals().set("generator", lua.create_async_function(generator)?)?;
2335 ///
2336 /// lua.load(r#"
2337 /// local n = 0
2338 /// for i in coroutine.wrap(generator) do
2339 /// n = n + i
2340 /// end
2341 /// assert(n == 45)
2342 /// "#)
2343 /// .exec()
2344 /// }
2345 /// ```
2346 ///
2347 /// Exchange values on yield:
2348 ///
2349 /// ```
2350 /// # use mlua::{Lua, Result, Value};
2351 /// #
2352 /// async fn pingpong(lua: Lua, mut val: i32) -> Result<()> {
2353 /// loop {
2354 /// val = lua.yield_with::<i32>(val).await? + 1;
2355 /// }
2356 /// Ok(())
2357 /// }
2358 ///
2359 /// # fn main() -> Result<()> {
2360 /// let lua = Lua::new();
2361 ///
2362 /// let co = lua.create_thread(lua.create_async_function(pingpong)?)?;
2363 /// assert_eq!(co.resume::<i32>(1)?, 1);
2364 /// assert_eq!(co.resume::<i32>(2)?, 3);
2365 /// assert_eq!(co.resume::<i32>(3)?, 4);
2366 ///
2367 /// # Ok(())
2368 /// # }
2369 /// ```
2370 ///
2371 /// [`coroutine.yield`]: https://www.lua.org/manual/5.4/manual.html#pdf-coroutine.yield
2372 #[cfg(feature = "async")]
2373 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
2374 pub async fn yield_with<R: FromLuaMulti>(&self, args: impl IntoLuaMulti) -> Result<R> {
2375 let mut args = Some(args.into_lua_multi(self)?);
2376 future::poll_fn(move |_cx| match args.take() {
2377 Some(args) => unsafe {
2378 let lua = self.lock();
2379 lua.push(Self::poll_yield())?; // yield marker
2380 if args.len() <= 1 {
2381 lua.push(args.front())?;
2382 } else {
2383 lua.push(lua.create_sequence_from(&args)?)?;
2384 }
2385 lua.push(args.len())?;
2386 Poll::Pending
2387 },
2388 None => unsafe {
2389 let lua = self.lock();
2390 let state = lua.state();
2391 let top = ffi::lua_gettop(state);
2392 if top == 0 || ffi::lua_type(state, 1) != ffi::LUA_TUSERDATA {
2393 // This must be impossible scenario if used correctly
2394 return Poll::Ready(R::from_stack_multi(0, &lua));
2395 }
2396 let _sg = StackGuard::with_top(state, 1);
2397 Poll::Ready(R::from_stack_multi(top - 1, &lua))
2398 },
2399 })
2400 .await
2401 }
2402
2403 /// Returns a weak reference to the Lua instance.
2404 ///
2405 /// This is useful for creating a reference to the Lua instance that does not prevent it from
2406 /// being deallocated.
2407 #[inline(always)]
2408 pub fn weak(&self) -> WeakLua {
2409 WeakLua(XRc::downgrade(&self.raw))
2410 }
2411
2412 #[cfg(not(feature = "luau"))]
2413 fn disable_c_modules(&self) -> Result<()> {
2414 let package: Table = self.globals().get("package")?;
2415
2416 package.set(
2417 "loadlib",
2418 self.create_function(|_, ()| -> Result<()> {
2419 Err(Error::SafetyError(
2420 "package.loadlib is disabled in safe mode".to_string(),
2421 ))
2422 })?,
2423 )?;
2424
2425 #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
2426 let searchers: Table = package.get("searchers")?;
2427 #[cfg(any(feature = "lua51", feature = "luajit"))]
2428 let searchers: Table = package.get("loaders")?;
2429
2430 let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
2431
2432 // The third and fourth searchers looks for a loader as a C library
2433 searchers.raw_set(3, loader)?;
2434 if searchers.raw_len() >= 4 {
2435 searchers.raw_remove(4)?;
2436 }
2437
2438 Ok(())
2439 }
2440
2441 #[inline(always)]
2442 pub(crate) fn lock(&self) -> ReentrantMutexGuard<'_, RawLua> {
2443 let rawlua = self.raw.lock();
2444 #[cfg(feature = "luau")]
2445 if unsafe { (*rawlua.extra.get()).running_gc } {
2446 panic!("Luau VM is suspended while GC is running");
2447 }
2448 rawlua
2449 }
2450
2451 #[inline(always)]
2452 pub(crate) fn lock_arc(&self) -> LuaGuard {
2453 LuaGuard(self.raw.lock_arc())
2454 }
2455
2456 /// Returns a handle to the unprotected Lua state without any synchronization.
2457 ///
2458 /// This is useful where we know that the lock is already held by the caller.
2459 #[cfg(feature = "async")]
2460 #[inline(always)]
2461 pub(crate) unsafe fn raw_lua(&self) -> &RawLua {
2462 &*self.raw.data_ptr()
2463 }
2464}
2465
2466impl WeakLua {
2467 #[track_caller]
2468 #[inline(always)]
2469 pub(crate) fn lock(&self) -> LuaGuard {
2470 let guard = LuaGuard::new(self.0.upgrade().expect("Lua instance is destroyed"));
2471 #[cfg(feature = "luau")]
2472 if unsafe { (*guard.extra.get()).running_gc } {
2473 panic!("Luau VM is suspended while GC is running");
2474 }
2475 guard
2476 }
2477
2478 #[inline(always)]
2479 pub(crate) fn try_lock(&self) -> Option<LuaGuard> {
2480 Some(LuaGuard::new(self.0.upgrade()?))
2481 }
2482
2483 /// Upgrades the weak Lua reference to a strong reference.
2484 ///
2485 /// # Panics
2486 ///
2487 /// Panics if the Lua instance is destroyed.
2488 #[track_caller]
2489 #[inline(always)]
2490 pub fn upgrade(&self) -> Lua {
2491 Lua {
2492 raw: self.0.upgrade().expect("Lua instance is destroyed"),
2493 collect_garbage: false,
2494 }
2495 }
2496
2497 /// Tries to upgrade the weak Lua reference to a strong reference.
2498 ///
2499 /// Returns `None` if the Lua instance is destroyed.
2500 #[inline(always)]
2501 pub fn try_upgrade(&self) -> Option<Lua> {
2502 Some(Lua {
2503 raw: self.0.upgrade()?,
2504 collect_garbage: false,
2505 })
2506 }
2507}
2508
2509impl PartialEq for WeakLua {
2510 fn eq(&self, other: &Self) -> bool {
2511 XWeak::ptr_eq(&self.0, &other.0)
2512 }
2513}
2514
2515impl Eq for WeakLua {}
2516
2517impl LuaGuard {
2518 #[cfg(feature = "send")]
2519 pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2520 LuaGuard(handle.lock_arc())
2521 }
2522
2523 #[cfg(not(feature = "send"))]
2524 pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2525 LuaGuard(handle.into_lock_arc())
2526 }
2527}
2528
2529impl Deref for LuaGuard {
2530 type Target = RawLua;
2531
2532 fn deref(&self) -> &Self::Target {
2533 &self.0
2534 }
2535}
2536
2537pub(crate) mod extra;
2538mod raw;
2539pub(crate) mod util;
2540
2541#[cfg(test)]
2542mod assertions {
2543 use super::*;
2544
2545 // Lua has lots of interior mutability, should not be RefUnwindSafe
2546 static_assertions::assert_not_impl_any!(Lua: std::panic::RefUnwindSafe);
2547
2548 #[cfg(not(feature = "send"))]
2549 static_assertions::assert_not_impl_any!(Lua: Send);
2550 #[cfg(feature = "send")]
2551 static_assertions::assert_impl_all!(Lua: Send, Sync);
2552}