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