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