Skip to main content

tsuki/
lib.rs

1//! Lua 5.4 ported to Rust.
2//!
3//! # Quickstart
4//!
5//! ```
6//! use tsuki::builtin::{BaseLib, CoroLib, MathLib, StrLib, TableLib, Utf8Lib};
7//! use tsuki::context::{Args, Context, Ret};
8//! use tsuki::{Lua, Value, fp};
9//!
10//! fn main() {
11//!     // Set up.
12//!     let lua = Lua::new(());
13//!
14//!     lua.use_module(None, true, BaseLib).unwrap();
15//!     lua.use_module(None, true, CoroLib).unwrap();
16//!     lua.use_module(None, true, MathLib).unwrap();
17//!     lua.use_module(None, true, StrLib).unwrap();
18//!     lua.use_module(None, true, TableLib).unwrap();
19//!     lua.use_module(None, true, Utf8Lib).unwrap();
20//!
21//!     lua.global().set_str_key("myfunc", fp!(myfunc));
22//!
23//!     // Create Lua thread to run Lua code.
24//!     let chunk = lua.load("abc.lua", "return myfunc()").unwrap();
25//!     let td = lua.create_thread();
26//!     let result = td.call(chunk, ()).unwrap();
27//!
28//!     match result {
29//!         Value::Str(v) => assert_eq!(v.as_utf8(), Some("Hello world!")),
30//!         _ => todo!(),
31//!     }
32//! }
33//!
34//! fn myfunc(cx: Context<(), Args>) -> Result<Context<(), Ret>, Box<dyn core::error::Error>> {
35//!     cx.push_str("Hello world!")?;
36//!
37//!     Ok(cx.into())
38//! }
39//! ```
40//!
41//! # Types that can be converted to UnsafeValue
42//!
43//! You can pass the value of the following types for `impl Into<UnsafeValue>`:
44//!
45//! - [Nil]
46//! - [bool]
47//! - [Fp]
48//! - [YieldFp]
49//! - [AsyncFp]
50//! - [i8]
51//! - [i16]
52//! - [i32]
53//! - [i64]
54//! - [u8]
55//! - [u16]
56//! - [u32]
57//! - [f32]
58//! - [f64]
59//! - [Float]
60//! - [Number]
61//! - Reference to [Str]
62//! - Reference to [Table]
63//! - Reference to [LuaFn]
64//! - Reference to [UserData]
65//! - Reference to [Thread]
66//! - [Ref]
67//! - [Value] or a reference to it
68//! - [Arg] or a reference to it
69//!
70//! The value will be converted to corresponding Lua value. Tsuki does not expose [UnsafeValue] by
71//! design so you cannot construct its value. Tsuki also never handout the value of [UnsafeValue].
72//!
73//! # Get function argument
74//!
75//! Use [Context::arg()] to get an argument passed to Rust function:
76//!
77//! ```
78//! # use tsuki::context::{Args, Context, Ret};
79//! fn myfunc(cx: Context<(), Args>) -> Result<Context<(), Ret>, Box<dyn core::error::Error>> {
80//!     let arg = cx.arg(1); // One-based the same as Lua so this is first argument.
81//!     let val = arg.to_int()?;
82//!
83//!     if val < 0 {
84//!         return Err(arg.error("expect positive integer"));
85//!     }
86//!
87//!     // This will return nil since to any values pushed to cx.
88//!     Ok(cx.into())
89//! }
90//! ```
91//!
92//! # Parsing Lua option
93//!
94//! Tsuki provides a derive macro [FromStr] to handle this.
95//!
96//! # Store value in registry
97//!
98//! You need to create a type per key in registry:
99//!
100//! ```
101//! use tsuki::{RegKey, Table};
102//!
103//! struct MyKey;
104//!
105//! impl<A> RegKey<A> for MyKey {
106//!     type Value<'a>
107//!         = Table<A>
108//!     where
109//!         A: 'a;
110//! }
111//! ```
112//!
113//! Type itself is a key, not its value. Then you can use [Lua::set_registry()] or
114//! [Context::set_registry()] to set the value and [Lua::registry()] or [Context::registry()] to
115//! retrieve the value.
116//!
117//! # Store value in Rust collection
118//!
119//! Tsuki also provides Rust collection that can store Lua values. The following code demonstrate a
120//! registry value of [BTreeMap] to map Rust [String] to any Lua value:
121//!
122//! ```
123//! use tsuki::collections::BTreeMap;
124//! use tsuki::context::{Args, Context, Ret};
125//! use tsuki::{Dynamic, RegKey};
126//!
127//! fn myfunc(cx: Context<(), Args>) -> Result<Context<(), Ret>, Box<dyn core::error::Error>> {
128//!     let v = cx.arg(1);
129//!     let r = cx.registry::<MyKey>().unwrap();
130//!
131//!     r.insert(String::from("abc"), v);
132//!
133//!     Ok(cx.into())
134//! }
135//!
136//! struct MyKey;
137//!
138//! impl<A> RegKey<A> for MyKey {
139//!     type Value<'a>
140//!         = BTreeMap<A, String, Dynamic>
141//!     where
142//!         A: 'a;
143//! }
144//! ```
145//!
146//! See [collections] module for available collections.
147#![no_std]
148#![cfg_attr(docsrs, feature(doc_cfg))]
149
150pub use self::function::*;
151pub use self::gc::Ref;
152pub use self::module::*;
153pub use self::number::*;
154pub use self::parser::*;
155pub use self::registry::*;
156pub use self::string::*;
157pub use self::table::*;
158pub use self::thread::*;
159pub use self::ty::*;
160pub use self::userdata::*;
161
162use self::collections::{BTreeMap, CollectionValue};
163use self::context::{Arg, Args, Context, Ret};
164use self::gc::{Gc, Object};
165use self::ldebug::{funcinfo, luaG_getfuncline};
166use self::ldo::luaD_protectedparser;
167use self::llex::{TK_WHILE, luaX_tokens};
168use self::lstate::lua_Debug;
169use self::ltm::{
170    TM_ADD, TM_BAND, TM_BNOT, TM_BOR, TM_BXOR, TM_CALL, TM_CLOSE, TM_CONCAT, TM_DIV, TM_EQ, TM_GC,
171    TM_IDIV, TM_INDEX, TM_LE, TM_LEN, TM_LT, TM_MOD, TM_MODE, TM_MUL, TM_NEWINDEX, TM_POW, TM_SHL,
172    TM_SHR, TM_SUB, TM_UNM, luaT_gettm,
173};
174use self::lzio::Zio;
175use self::value::{UnsafeValue, UntaggedValue};
176use alloc::boxed::Box;
177use alloc::rc::Rc;
178use alloc::string::String;
179use alloc::vec::Vec;
180use core::any::{Any, TypeId, type_name};
181use core::cell::{Cell, UnsafeCell};
182use core::convert::identity;
183use core::error::Error;
184use core::fmt::{Display, Formatter};
185use core::marker::PhantomPinned;
186use core::mem::MaybeUninit;
187use core::ops::{Deref, DerefMut};
188use core::pin::Pin;
189use core::ptr::null;
190use core::task::RawWakerVTable;
191use thiserror::Error;
192
193pub mod builtin;
194pub mod collections;
195pub mod context;
196
197mod function;
198mod gc;
199mod hasher;
200mod lapi;
201mod lauxlib;
202mod lcode;
203mod lctype;
204mod ldebug;
205mod ldo;
206mod lfunc;
207mod llex;
208mod lmem;
209mod lobject;
210mod lparser;
211mod lstate;
212mod lstring;
213mod ltm;
214mod lzio;
215mod module;
216mod number;
217mod parser;
218mod registry;
219mod string;
220mod table;
221mod thread;
222mod ty;
223mod userdata;
224mod value;
225mod vm;
226
227extern crate alloc;
228#[cfg(feature = "std")]
229extern crate std;
230
231/// Helper macro to construct [Fp] or [AsyncFp].
232#[macro_export]
233macro_rules! fp {
234    ($f:path) => {
235        $crate::Fp::new($f)
236    };
237    ($f:path as yield) => {
238        $crate::YieldFp::new($f)
239    };
240    ($f:path as async) => {
241        $crate::async_fp!($f)
242    };
243}
244
245#[cfg(feature = "std")]
246#[doc(hidden)]
247#[macro_export]
248macro_rules! async_fp {
249    ($f:path) => {
250        $crate::AsyncFp::new(|cx| ::std::boxed::Box::pin($f(cx)))
251    };
252}
253
254#[cfg(not(feature = "std"))]
255#[doc(hidden)]
256#[macro_export]
257macro_rules! async_fp {
258    ($f:path) => {
259        $crate::AsyncFp::new(|cx| ::alloc::boxed::Box::pin($f(cx)))
260    };
261}
262
263/// Generate [core::str::FromStr] implementation for enum to parse Lua
264/// [option](https://www.lua.org/manual/5.4/manual.html#luaL_checkoption).
265///
266/// Only enum with unit variants is supported. The name to map will be the same as Lua convention,
267/// which is lower-cased without separators:
268///
269/// ```
270/// use tsuki::FromStr;
271///
272/// #[derive(FromStr)]
273/// enum MyOption {
274///     Foo,
275///     FooBar,
276/// }
277/// ```
278///
279/// Will map `foo` to `MyOption::Foo` and `foobar` to `MyOption::FooBar`.
280pub use tsuki_macros::FromStr;
281
282/// Generate [Class] implementation from `impl` block.
283///
284/// This attribute macro inspect all associated functions and methods within the `impl` block and
285/// generate a metatable:
286///
287/// ```
288/// use tsuki::context::{Args, Context, Ret};
289/// use tsuki::class;
290///
291/// struct MyUserData;
292///
293/// #[class(associated_data = ())]
294/// impl MyUserData {
295///     fn index1(&self, cx: &Context<(), Args>) -> Result<(), Box<dyn core::error::Error>> {
296///         Ok(())
297///     }
298///
299///     fn index2(cx: Context<(), Args>) -> Result<Context<(), Ret>, Box<dyn core::error::Error>> {
300///         Ok(cx.into())
301///     }
302///
303///     async fn index3(&self, cx: &Context<'_, (), Args>) -> Result<(), Box<dyn core::error::Error>> {
304///         Ok(())
305///     }
306///
307///     #[close]
308///     fn close(&self, cx: &Context<(), Args>) -> Result<(), Box<dyn core::error::Error>> {
309///         Ok(())
310///     }
311/// }
312/// ```
313///
314/// Will set `index1`, `index2`, `index3` and `close` to the metatable with the same name. The
315/// `__index` will be set to the table itself and `__close` will be set to `close`. Use
316/// `#[close(hidden)]` to set to `__close` only.
317///
318/// The `associated_data` is a type of the value passed as `associated_data` to [Lua::new()]. You
319/// can specify a type parameter if `MyUserData` can works with multiple types.
320pub use tsuki_macros::class;
321
322/// Global states shared with all Lua threads.
323#[repr(C)] // Force gc field to be the first field.
324pub struct Lua<A> {
325    gc: Gc<A>,
326    strt: StringTable<A>,
327    l_registry: UnsafeCell<UnsafeValue<A>>,
328    nilvalue: UnsafeCell<UnsafeValue<A>>,
329    dummy_node: Node<A>,
330    seed: u32,
331    modules_locked: Cell<bool>,
332    associated_data: A,
333    phantom: PhantomPinned,
334}
335
336impl<A> Lua<A> {
337    /// Create a new [Lua] with a random seed to hash Lua string.
338    ///
339    /// You can retrieve `associated_data` later with [Self::associated_data()] or
340    /// [Context::associated_data()].
341    ///
342    /// Note that all built-in functions (e.g. `print`) are not enabled by default.
343    #[cfg(feature = "rand")]
344    #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
345    pub fn new(associated_data: A) -> Pin<Rc<Self>> {
346        Self::with_seed(associated_data, rand::random())
347    }
348
349    /// Create a new [Lua] with a seed to hash Lua string.
350    ///
351    /// You can use [Self::new()] instead if `rand` feature is enabled (which is default) or you
352    /// can pass `0` as a seed if
353    /// [HashDoS](https://en.wikipedia.org/wiki/Collision_attack#Hash_flooding) attack is not
354    /// possible for your application.
355    ///
356    /// You can retrieve `associated_data` later with [Self::associated_data()] or
357    /// [Context::associated_data()].
358    ///
359    /// Note that all built-in functions (e.g. `print`) are not enabled by default.
360    pub fn with_seed(associated_data: A, seed: u32) -> Pin<Rc<Self>> {
361        let g = Rc::pin(Lua {
362            gc: unsafe { Gc::new() }, // SAFETY: gc in the first field on Lua.
363            strt: StringTable::new(),
364            l_registry: UnsafeCell::new(Nil.into()),
365            nilvalue: UnsafeCell::new(Nil.into()),
366            dummy_node: Node {
367                tt_: 0 | 1 << 4,
368                key_tt: 0 | 0 << 4,
369                value_: UntaggedValue { i: 0 },
370                next: 0,
371                key_val: UntaggedValue { i: 0 },
372            },
373            seed,
374            modules_locked: Cell::new(false),
375            associated_data,
376            phantom: PhantomPinned,
377        });
378
379        // Setup registry.
380        let reg = unsafe { Table::new(g.deref()) };
381
382        unsafe { g.gc.set_root(reg.cast()) };
383        unsafe { g.l_registry.get().write(UnsafeValue::from_obj(reg.cast())) };
384        unsafe { luaH_resize(reg, 6, 0) };
385
386        // Create LUA_RIDX_GLOBALS.
387        let reg = unsafe { (*reg).array.get() };
388        let glb = unsafe { Table::new(g.deref()) };
389
390        unsafe { reg.add(0).write(false.into()) };
391        unsafe { reg.add(1).write(UnsafeValue::from_obj(glb.cast())) };
392
393        // Create table for metatables.
394        let mts = unsafe { Table::new(g.deref()) };
395
396        unsafe { luaH_resize(mts, 9, 0) };
397
398        for i in 0..9 {
399            let e = unsafe { (*mts).array.get().add(i) };
400
401            unsafe { (*e).tt_ = 1 | 0 << 4 };
402            unsafe { (*e).value_.gc = null() };
403        }
404
405        unsafe { reg.add(2).write(UnsafeValue::from_obj(mts.cast())) };
406
407        // Create table for event names.
408        let events = unsafe { Table::new(g.deref()) };
409        let entries = &[
410            (TM_INDEX, "__index"),
411            (TM_NEWINDEX, "__newindex"),
412            (TM_GC, "__gc"),
413            (TM_MODE, "__mode"),
414            (TM_LEN, "__len"),
415            (TM_EQ, "__eq"),
416            (TM_ADD, "__add"),
417            (TM_SUB, "__sub"),
418            (TM_MUL, "__mul"),
419            (TM_MOD, "__mod"),
420            (TM_POW, "__pow"),
421            (TM_DIV, "__div"),
422            (TM_IDIV, "__idiv"),
423            (TM_BAND, "__band"),
424            (TM_BOR, "__bor"),
425            (TM_BXOR, "__bxor"),
426            (TM_SHL, "__shl"),
427            (TM_SHR, "__shr"),
428            (TM_UNM, "__unm"),
429            (TM_BNOT, "__bnot"),
430            (TM_LT, "__lt"),
431            (TM_LE, "__le"),
432            (TM_CONCAT, "__concat"),
433            (TM_CALL, "__call"),
434            (TM_CLOSE, "__close"),
435        ];
436
437        unsafe { luaH_resize(events, entries.len().try_into().unwrap(), 0) };
438
439        for &(k, v) in entries {
440            let v = unsafe { Str::from_str(g.deref(), v).unwrap_or_else(identity) };
441            let v = unsafe { UnsafeValue::from_obj(v.cast()) };
442
443            unsafe { (*events).set_unchecked(k, v).unwrap_unchecked() };
444        }
445
446        unsafe { reg.add(3).write(UnsafeValue::from_obj(events.cast())) };
447
448        // Create table for Lua tokens.
449        let tokens = unsafe { Table::new(g.deref()) };
450        let n = TK_WHILE - (255 + 1) + 1;
451
452        unsafe { luaH_resize(tokens, 0, n.try_into().unwrap()) };
453
454        for i in 0..n {
455            let k = unsafe { Str::from_str(g.deref(), luaX_tokens[i as usize]) }
456                .unwrap_or_else(identity);
457            let k = unsafe { UnsafeValue::from_obj(k.cast()) };
458
459            unsafe { (*tokens).set_unchecked(k, i + 1).unwrap_unchecked() };
460        }
461
462        unsafe { reg.add(4).write(UnsafeValue::from_obj(tokens.cast())) };
463
464        // Create table for modules.
465        let mods = unsafe { Table::new(g.deref()) };
466
467        unsafe { reg.add(5).write(UnsafeValue::from_obj(mods.cast())) };
468
469        g
470    }
471
472    /// Returns associated data that passed to [Self::new()] or [Self::with_seed()].
473    #[inline(always)]
474    pub fn associated_data(&self) -> &A {
475        &self.associated_data
476    }
477
478    /// Load a Lua module that implemented in Rust.
479    ///
480    /// Supply `name` if you want to use different name than [Module::NAME].
481    ///
482    /// If `global` is `true` this will **overwrite** the global variable with the same name as the
483    /// module.
484    ///
485    /// The error can be either [ModuleExists], [RecursiveCall] or the one that returned from
486    /// [Module::open()].
487    ///
488    /// # Panics
489    /// If [Module::open()] returns a value created from different Lua instance.
490    pub fn use_module<'a, M>(
491        &'a self,
492        name: Option<&str>,
493        global: bool,
494        module: M,
495    ) -> Result<(), Box<dyn Error>>
496    where
497        M: Module<A>,
498        M::Inst<'a>: Into<UnsafeValue<A>>,
499    {
500        // Prevent recursive call.
501        let lock = match ModulesLock::new(&self.modules_locked) {
502            Some(v) => v,
503            None => return Err(Box::new(RecursiveCall::new(Self::use_module::<M>))),
504        };
505
506        // Check if exists.
507        let name = name.unwrap_or(M::NAME);
508        let n = unsafe { Str::from_str(self, name).unwrap_or_else(identity) };
509        let n = unsafe { UnsafeValue::from_obj(n.cast()) };
510        let t = self.modules();
511        let s = unsafe { t.get_raw_unchecked(n) };
512
513        if unsafe { ((*s).tt_ & 0xf) != 0 } {
514            return Err(Box::new(ModuleExists));
515        }
516
517        // Open the module. We need a strong reference to name here since the module can trigger GC.
518        let n = unsafe { Ref::new(n.value_.gc.cast::<Str<A>>()) };
519        let m = module.open(self)?.into();
520
521        if (m.tt_ & 0xf) == 0 {
522            return Ok(());
523        } else if unsafe { (m.tt_ & 1 << 6) != 0 && (*m.value_.gc).global != self } {
524            panic!("the module instance was created from different Lua instance");
525        }
526
527        // SAFETY: n is not nil or NaN.
528        unsafe { t.set_slot_unchecked(s, n.deref(), m).unwrap_unchecked() };
529
530        if global {
531            unsafe { self.global().set_unchecked(n, m).unwrap_unchecked() };
532        }
533
534        drop(lock);
535
536        Ok(())
537    }
538
539    /// Set metatable for Lua string.
540    ///
541    /// # Panics
542    /// - If `mt` was created from different [Lua](crate::Lua) instance.
543    /// - If `mt` contains `__gc`.
544    pub fn set_str_metatable(&self, mt: &Table<A>) {
545        if mt.hdr.global != self {
546            panic!("attempt to set string metatable created from a different Lua");
547        }
548
549        // Prevent __gc metamethod.
550        if unsafe { mt.flags.get() & 1 << TM_GC == 0 && !luaT_gettm(mt, TM_GC).is_null() } {
551            panic!("__gc metamethod is not supported");
552        }
553
554        unsafe { self.metatables().set_unchecked(4, mt).unwrap_unchecked() };
555    }
556
557    /// Register a metatable for userdata `T`. If the metatable for `T` already exists it will be
558    /// **replaced**.
559    ///
560    /// See [Class] if you want to automate the metatable creation for your userdata.
561    ///
562    /// This does not change the metatable for any userdata that already created.
563    ///
564    /// # Panics
565    /// - If `mt` was created from different [Lua](crate::Lua) instance.
566    /// - If `mt` contains `__gc`.
567    pub fn register_metatable<T: Any>(&self, mt: &Table<A>) {
568        if mt.hdr.global != self {
569            panic!("attempt to register a metatable created from a different Lua");
570        }
571
572        // Prevent __gc metamethod.
573        if unsafe { mt.flags.get() & 1 << TM_GC == 0 && !luaT_gettm(mt, TM_GC).is_null() } {
574            panic!("__gc metamethod is not supported");
575        }
576
577        // Add to list.
578        let k = unsafe { RustId::new(self, TypeId::of::<T>()) };
579        let k = unsafe { UnsafeValue::from_obj(k.cast()) };
580
581        unsafe { self.metatables().set_unchecked(k, mt).unwrap_unchecked() };
582
583        self.gc.step();
584    }
585
586    /// Register a metatable for userdata `T`. If the metatable for `T` already exists it will be
587    /// **replaced**.
588    ///
589    /// This does not change the metatable for any userdata that already created.
590    ///
591    /// # Panics
592    /// - If [Class::create_metatable()] returns a table that was created from different
593    ///   [Lua](crate::Lua) instance.
594    /// - If [Class::create_metatable()] returns a table that contains `__gc`.
595    pub fn register_class<T: Class<A>>(&self) {
596        // Create metatable.
597        let mt = T::create_metatable(self);
598        let mt = mt.deref();
599
600        if mt.hdr.global != self {
601            panic!(
602                "{} returns a table that was created from a different Lua",
603                type_name::<T>()
604            );
605        } else if unsafe { mt.flags.get() & 1 << TM_GC == 0 && !luaT_gettm(mt, TM_GC).is_null() } {
606            panic!("{} returns a table that contains __gc", type_name::<T>());
607        }
608
609        // Add to list.
610        let k = unsafe { RustId::new(self, TypeId::of::<T>()) };
611        let k = unsafe { UnsafeValue::from_obj(k.cast()) };
612
613        unsafe { self.metatables().set_unchecked(k, mt).unwrap_unchecked() };
614
615        self.gc.step();
616    }
617
618    /// Sets a value to registry.
619    ///
620    /// # Panics
621    /// If `v` was created from different [Lua](crate::Lua) instance.
622    pub fn set_registry<'a, K>(&self, v: <K::Value<'a> as RegValue<A>>::In<'a>)
623    where
624        K: RegKey<A>,
625        K::Value<'a>: RegValue<A>,
626    {
627        let v = K::Value::into_unsafe(v);
628
629        if unsafe { (v.tt_ & 1 << 6) != 0 && (*v.value_.gc).global != self } {
630            panic!("attempt to set registry value created from different Lua instance");
631        }
632
633        // Set.
634        let r = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
635        let k = unsafe { RustId::new(self, TypeId::of::<K>()) };
636        let k = unsafe { UnsafeValue::from_obj(k.cast()) };
637
638        // SAFETY: k is not nil or NaN.
639        unsafe { (*r).set_unchecked(k, v).unwrap_unchecked() };
640    }
641
642    /// Returns value on registry that was set with [Self::set_registry()] or
643    /// [Context::set_registry()].
644    pub fn registry<'a, K>(&'a self) -> Option<<K::Value<'a> as RegValue<A>>::Out<'a>>
645    where
646        K: RegKey<A>,
647        K::Value<'a>: RegValue<A>,
648    {
649        let id = TypeId::of::<K>();
650        let reg = unsafe { &*(*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
651        let s = unsafe { luaH_getid(reg, &id) };
652
653        match unsafe { (*s).tt_ & 0xf } {
654            0 => None,
655            _ => Some(unsafe { K::Value::from_unsafe(s) }),
656        }
657    }
658
659    /// Returns a global table.
660    #[inline(always)]
661    pub fn global(&self) -> &Table<A> {
662        let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
663        let tab = unsafe { (*reg).array.get().add(1) };
664        let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
665
666        unsafe { &*tab }
667    }
668
669    /// Create a Lua string with UTF-8 content.
670    #[inline(always)]
671    pub fn create_str<T>(&self, v: T) -> Ref<'_, Str<A>>
672    where
673        T: AsRef<str> + AsRef<[u8]> + Into<Vec<u8>>,
674    {
675        let s = unsafe { Str::from_str(self, v) };
676        let v = unsafe { Ref::new(s.unwrap_or_else(identity)) };
677
678        if s.is_ok() {
679            self.gc.step();
680        }
681
682        v
683    }
684
685    /// Create a Lua string with binary content.
686    #[inline(always)]
687    pub fn create_bytes<T>(&self, v: T) -> Ref<'_, Str<A>>
688    where
689        T: AsRef<[u8]> + Into<Vec<u8>>,
690    {
691        let s = unsafe { Str::from_bytes(self, v) };
692        let v = unsafe { Ref::new(s.unwrap_or_else(identity)) };
693
694        if s.is_ok() {
695            self.gc.step();
696        }
697
698        v
699    }
700
701    /// Create a Lua table.
702    #[inline(always)]
703    pub fn create_table(&self) -> Ref<'_, Table<A>> {
704        let v = unsafe { Ref::new(Table::new(self)) };
705
706        self.gc.step();
707
708        v
709    }
710
711    /// Create a full userdata.
712    ///
713    /// The metatable for the userdata that was registered with [Self::register_metatable()] will be
714    /// loaded during creation. A call to [Self::register_metatable()] has no effect for any
715    /// userdata that already created.
716    #[inline(always)]
717    pub fn create_ud<T: Any>(&self, v: T) -> Ref<'_, UserData<A, T>> {
718        let v = unsafe { Ref::new(UserData::new(self, v).cast()) };
719
720        self.gc.step();
721
722        v
723    }
724
725    /// Create a new Lua thread (AKA coroutine).
726    pub fn create_thread(&self) -> Ref<'_, Thread<A>> {
727        let v = unsafe { Ref::new(Thread::new(self)) };
728
729        self.gc.step();
730
731        v
732    }
733
734    /// Create a new [BTreeMap] to map Rust value to Lua value.
735    ///
736    /// `K` can be any Rust type that implement [Ord]. See [collections] module for a list of
737    /// possible type for `V`.
738    pub fn create_btree_map<K, V>(&self) -> Ref<'_, BTreeMap<A, K, V>>
739    where
740        K: Ord + 'static,
741        V: CollectionValue<A> + 'static,
742    {
743        let v = unsafe { Ref::new(BTreeMap::new(self)) };
744
745        self.gc.step();
746
747        v
748    }
749
750    /// Deserialize [Value] from Serde deserializer.
751    ///
752    /// This method can only deserialize a value from self-describing formats.
753    #[cfg(feature = "serde")]
754    #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
755    pub fn deserialize_value<'de, D: serde::Deserializer<'de>>(
756        &self,
757        deserializer: D,
758    ) -> Result<Value<'_, A>, D::Error> {
759        deserializer.deserialize_any(self::value::serde::ValueVisitor::new(self))
760    }
761
762    /// Load a Lua chunk.
763    pub fn load(
764        &self,
765        name: impl Into<String>,
766        chunk: impl AsRef<[u8]>,
767    ) -> Result<Ref<'_, LuaFn<A>>, ParseError> {
768        let chunk = chunk.as_ref();
769        let z = Zio {
770            n: chunk.len(),
771            p: chunk.as_ptr().cast(),
772        };
773
774        // Load.
775        let f = unsafe { luaD_protectedparser(self, z, name.into().into())? };
776
777        if !(*f).upvals.is_empty() {
778            let gt = unsafe {
779                (*((*self.l_registry.get()).value_.gc.cast::<Table<A>>()))
780                    .array
781                    .get()
782                    .offset(2 - 1)
783            };
784
785            let io1 = unsafe { (*(*f).upvals[0].get()).v.get() };
786
787            unsafe { (*io1).value_ = (*gt).value_ };
788            unsafe { (*io1).tt_ = (*gt).tt_ };
789
790            if unsafe { (*gt).tt_ & 1 << 6 != 0 } {
791                if unsafe {
792                    (*(*f).upvals[0].get()).hdr.marked.get() & 1 << 5 != 0
793                        && (*(*gt).value_.gc).marked.get() & (1 << 3 | 1 << 4) != 0
794                } {
795                    unsafe {
796                        self.gc
797                            .barrier((*f).upvals[0].get().cast(), (*gt).value_.gc)
798                    };
799                }
800            }
801        }
802
803        Ok(f)
804    }
805
806    unsafe fn metatable(&self, o: *const UnsafeValue<A>) -> *const Table<A> {
807        match unsafe { (*o).tt_ & 0xf } {
808            5 => unsafe { (*(*o).value_.gc.cast::<Table<A>>()).metatable.get() },
809            7 => unsafe { (*(*o).value_.gc.cast::<UserData<A, ()>>()).mt },
810            v => unsafe { self.metatables().get_raw_int_key(v.into()).value_.gc.cast() },
811        }
812    }
813
814    #[inline(always)]
815    fn metatables(&self) -> &Table<A> {
816        let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
817        let tab = unsafe { (*reg).array.get().add(2) };
818        let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
819
820        unsafe { &*tab }
821    }
822
823    #[inline(always)]
824    fn events(&self) -> &Table<A> {
825        let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
826        let tab = unsafe { (*reg).array.get().add(3) };
827        let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
828
829        unsafe { &*tab }
830    }
831
832    #[inline(always)]
833    fn tokens(&self) -> &Table<A> {
834        let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
835        let tab = unsafe { (*reg).array.get().add(4) };
836        let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
837
838        unsafe { &*tab }
839    }
840
841    #[inline(always)]
842    fn modules(&self) -> &Table<A> {
843        let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
844        let tab = unsafe { (*reg).array.get().add(5) };
845        let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
846
847        unsafe { &*tab }
848    }
849}
850
851/// RAII struct to toggle [Lua::modules_locked].
852struct ModulesLock<'a>(&'a Cell<bool>);
853
854impl<'a> ModulesLock<'a> {
855    #[inline(always)]
856    fn new(locked: &'a Cell<bool>) -> Option<Self> {
857        if locked.get() {
858            return None;
859        }
860
861        locked.set(true);
862
863        Some(Self(locked))
864    }
865}
866
867impl<'a> Drop for ModulesLock<'a> {
868    #[inline(always)]
869    fn drop(&mut self) {
870        self.0.set(false);
871    }
872}
873
874/// Encapsulates a Lua value.
875#[repr(u64, align(8))] // Force field to be at offset 8.
876pub enum Value<'a, A> {
877    /// The value is `nil`.
878    Nil = 0 | 0 << 4,
879    /// The value is `false`.
880    False = 1 | 0 << 4,
881    /// The value is `true`.
882    True = 1 | 1 << 4,
883    /// The value is `function` implemented in Rust.
884    Fp(Fp<A>) = 2 | 0 << 4,
885    /// The value is `function` implemented in Rust to yield coroutine.
886    YieldFp(YieldFp<A>) = 2 | 1 << 4,
887    /// The value is `function` implemented in Rust as async function.
888    AsyncFp(AsyncFp<A>) = 2 | 2 << 4,
889    /// The value is `integer`.
890    Int(i64) = 3 | 0 << 4,
891    /// The value is `float`.
892    Float(Float) = 3 | 1 << 4,
893    /// The value is `string`.
894    Str(Ref<'a, Str<A>>) = 4 | 0 << 4 | 1 << 6,
895    /// The value is `table`.
896    Table(Ref<'a, Table<A>>) = 5 | 0 << 4 | 1 << 6,
897    /// The value is `function` implemented in Lua.
898    LuaFn(Ref<'a, LuaFn<A>>) = 6 | 0 << 4 | 1 << 6,
899    /// The value is `full userdata`.
900    UserData(Ref<'a, UserData<A, dyn Any>>) = 7 | 0 << 4 | 1 << 6,
901    /// The value is `thread`.
902    Thread(Ref<'a, Thread<A>>) = 8 | 0 << 4 | 1 << 6,
903}
904
905// Make sure all fields live at offset 8.
906const _: () = assert!(align_of::<Fp<()>>() <= 8);
907const _: () = assert!(align_of::<YieldFp<()>>() <= 8);
908const _: () = assert!(align_of::<AsyncFp<()>>() <= 8);
909const _: () = assert!(align_of::<i64>() <= 8);
910const _: () = assert!(align_of::<Float>() <= 8);
911const _: () = assert!(align_of::<Ref<Str<()>>>() <= 8);
912
913impl<'a, A> Value<'a, A> {
914    /// Constructs [Value] from [Arg].
915    ///
916    /// Returns [None] if argument `v` does not exists.
917    #[inline]
918    pub fn from_arg(v: &Arg<'_, 'a, A>) -> Option<Self> {
919        let v = v.get_raw_or_null();
920
921        match v.is_null() {
922            true => None,
923            false => Some(unsafe { Self::from_unsafe(v) }),
924        }
925    }
926
927    /// Returns `true` if this value is [Value::Nil].
928    #[inline(always)]
929    pub const fn is_nil(&self) -> bool {
930        matches!(self, Self::Nil)
931    }
932
933    /// Returns [Type] for this value.
934    #[inline(always)]
935    pub fn ty(&self) -> Type {
936        // SAFETY: Value has #[repr(u64)].
937        let t = unsafe { (self as *const Self as *const u64).read() };
938
939        // SAFETY: Low-order byte has the same value as Type.
940        unsafe { core::mem::transmute((t & 0xf) as u8) }
941    }
942
943    /// Returns `false` if this value is either [Value::Nil] or [Value::False] otherwise `true`.
944    ///
945    /// This has the same semantic as `lua_toboolean`.
946    #[inline(always)]
947    pub const fn to_bool(&self) -> bool {
948        !matches!(self, Self::Nil | Self::False)
949    }
950
951    #[inline(never)]
952    unsafe fn from_unsafe(v: *const UnsafeValue<A>) -> Self {
953        let mut r = MaybeUninit::<Self>::uninit();
954        let p = r.as_mut_ptr().cast::<u64>();
955        let t = unsafe { (*v).tt_ };
956
957        match t & 0xf {
958            0 => unsafe { p.write(0 | 0 << 4) },
959            1 | 2 | 3 => unsafe {
960                p.write(t.into());
961                p.add(1).cast::<UntaggedValue<A>>().write((*v).value_);
962            },
963            4 | 5 | 6 | 7 | 8 => unsafe {
964                let v = (*v).value_.gc;
965
966                p.write(t.into());
967                p.add(1).cast::<*const Object<A>>().write(v);
968
969                core::mem::forget(Ref::new_inline(v));
970            },
971            _ => unreachable!(),
972        }
973
974        unsafe { r.assume_init() }
975    }
976}
977
978impl<'a, A> Clone for Value<'a, A> {
979    #[inline(always)]
980    fn clone(&self) -> Self {
981        // SAFETY: Value has #[repr(u64)].
982        let v = self as *const Self as *const u64;
983        let t = unsafe { v.read() as u8 };
984        let v = unsafe { v.add(1).cast::<UntaggedValue<A>>() };
985
986        if t & 1 << 6 != 0 {
987            unsafe { Ref::increment_strong_count((*v).gc) };
988        }
989
990        // Construct new value.
991        let mut r = MaybeUninit::<Self>::uninit();
992        let p = r.as_mut_ptr().cast::<u64>();
993
994        unsafe { p.write(t.into()) };
995        unsafe { p.add(1).cast::<UntaggedValue<A>>().write(*v) };
996
997        unsafe { r.assume_init() }
998    }
999}
1000
1001/// Unit struct to create `nil` value.
1002pub struct Nil;
1003
1004/// Non-Yieldable Rust function.
1005#[repr(transparent)]
1006pub struct Fp<A>(fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>);
1007
1008impl<A> Fp<A> {
1009    /// Construct a new [Fp] from a function pointer.
1010    ///
1011    /// [fp] macro is more convenience than this function.
1012    #[inline(always)]
1013    pub const fn new(v: fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>) -> Self {
1014        Self(v)
1015    }
1016}
1017
1018impl<A> Clone for Fp<A> {
1019    #[inline(always)]
1020    fn clone(&self) -> Self {
1021        *self
1022    }
1023}
1024
1025impl<A> Copy for Fp<A> {}
1026
1027/// Rust function to yield Lua values.
1028#[repr(transparent)]
1029pub struct YieldFp<A>(fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>);
1030
1031impl<A> YieldFp<A> {
1032    /// Construct a new [YieldFp] from a function pointer.
1033    ///
1034    /// [fp] macro is more convenience than this function.
1035    #[inline(always)]
1036    pub const fn new(v: fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>) -> Self {
1037        Self(v)
1038    }
1039}
1040
1041impl<A> Clone for YieldFp<A> {
1042    fn clone(&self) -> Self {
1043        *self
1044    }
1045}
1046
1047impl<A> Copy for YieldFp<A> {}
1048
1049/// Asynchronous Rust function.
1050///
1051/// Note that this function can only be called from Lua. In other words, it cannot be called from
1052/// [Fp] or this function either directly or indirectly.
1053///
1054/// Each call into async function from Lua always incur one heap allocation so create async function
1055/// only when necessary.
1056///
1057/// You need to use [Thread::async_call()] to be able to call this function from Lua.
1058#[repr(transparent)]
1059pub struct AsyncFp<A>(
1060    fn(
1061        Context<A, Args>,
1062    ) -> Pin<Box<dyn Future<Output = Result<Context<A, Ret>, Box<dyn Error>>> + '_>>,
1063);
1064
1065impl<A> AsyncFp<A> {
1066    /// Construct a new [AsyncFp] from a function pointer.
1067    ///
1068    /// [fp] macro is more convenience than this function.
1069    #[inline(always)]
1070    pub const fn new(
1071        v: fn(
1072            Context<A, Args>,
1073        )
1074            -> Pin<Box<dyn Future<Output = Result<Context<A, Ret>, Box<dyn Error>>> + '_>>,
1075    ) -> Self {
1076        Self(v)
1077    }
1078}
1079
1080impl<A> Clone for AsyncFp<A> {
1081    #[inline(always)]
1082    fn clone(&self) -> Self {
1083        *self
1084    }
1085}
1086
1087impl<A> Copy for AsyncFp<A> {}
1088
1089/// Unit struct to store any value in registry or collection.
1090pub struct Dynamic;
1091
1092/// Type of operator.
1093#[repr(u8)]
1094#[derive(Clone, Copy, PartialEq, Eq)]
1095enum Ops {
1096    Add,
1097    Sub,
1098    Mul,
1099    Mod,
1100    Pow,
1101    NumDiv,
1102    IntDiv,
1103    And,
1104    Or,
1105    Xor,
1106    Shl,
1107    Shr,
1108    Neg,
1109    Not,
1110}
1111
1112impl Ops {
1113    const fn from_u8(v: u8) -> Option<Self> {
1114        match v {
1115            v if v == Self::Add as u8 => Some(Self::Add),
1116            v if v == Self::Sub as u8 => Some(Self::Sub),
1117            v if v == Self::Mul as u8 => Some(Self::Mul),
1118            v if v == Self::Mod as u8 => Some(Self::Mod),
1119            v if v == Self::Pow as u8 => Some(Self::Pow),
1120            v if v == Self::NumDiv as u8 => Some(Self::NumDiv),
1121            v if v == Self::IntDiv as u8 => Some(Self::IntDiv),
1122            v if v == Self::And as u8 => Some(Self::And),
1123            v if v == Self::Or as u8 => Some(Self::Or),
1124            v if v == Self::Xor as u8 => Some(Self::Xor),
1125            v if v == Self::Shl as u8 => Some(Self::Shl),
1126            v if v == Self::Shr as u8 => Some(Self::Shr),
1127            v if v == Self::Neg as u8 => Some(Self::Neg),
1128            v if v == Self::Not as u8 => Some(Self::Not),
1129            _ => None,
1130        }
1131    }
1132}
1133
1134/// A wrapper of [Vec] to provide [core::fmt::Write].
1135#[derive(Default)]
1136struct Buffer(Vec<u8>);
1137
1138impl Deref for Buffer {
1139    type Target = Vec<u8>;
1140
1141    #[inline(always)]
1142    fn deref(&self) -> &Self::Target {
1143        &self.0
1144    }
1145}
1146
1147impl DerefMut for Buffer {
1148    #[inline(always)]
1149    fn deref_mut(&mut self) -> &mut Self::Target {
1150        &mut self.0
1151    }
1152}
1153
1154impl AsRef<[u8]> for Buffer {
1155    #[inline(always)]
1156    fn as_ref(&self) -> &[u8] {
1157        &self.0
1158    }
1159}
1160
1161impl core::fmt::Write for Buffer {
1162    #[inline]
1163    fn write_str(&mut self, s: &str) -> core::fmt::Result {
1164        self.0.extend_from_slice(s.as_bytes());
1165        Ok(())
1166    }
1167}
1168
1169impl From<Buffer> for Vec<u8> {
1170    #[inline(always)]
1171    fn from(value: Buffer) -> Self {
1172        value.0
1173    }
1174}
1175
1176/// Contains information how [Fp], [AsyncFp] or [YieldFp] fails.
1177#[derive(Debug)]
1178pub struct CallError {
1179    chunk: Option<(Rc<String>, u32)>,
1180    reason: Box<dyn Error>,
1181}
1182
1183impl CallError {
1184    unsafe fn new<A>(th: *const Thread<A>, mut reason: Box<dyn Error>) -> Box<Self> {
1185        // Forward ourself.
1186        reason = match reason.downcast() {
1187            Ok(v) => return v,
1188            Err(e) => e,
1189        };
1190
1191        // Traverse up until reaching a Lua function.
1192        let mut ci = unsafe { (*th).ci.get() };
1193        let mut chunk = None;
1194
1195        while unsafe { ci != (*th).base_ci.get() } {
1196            let mut ar = lua_Debug::default();
1197
1198            let func = unsafe { (*th).stack.get().add((*ci).func) };
1199            let cl = if unsafe {
1200                (*func).tt_ == 6 | 0 << 4 | 1 << 6 || (*func).tt_ == 6 | 2 << 4 | 1 << 6
1201            } {
1202                unsafe { (*func).value_.gc }
1203            } else {
1204                null()
1205            };
1206
1207            unsafe { funcinfo(&mut ar, cl) };
1208
1209            ar.currentline = if unsafe { !ci.is_null() && (*ci).callstatus & 1 << 1 == 0 } {
1210                unsafe {
1211                    luaG_getfuncline(
1212                        (*(*func).value_.gc.cast::<LuaFn<A>>()).p.get(),
1213                        ((*ci).pc - 1) as _,
1214                    )
1215                }
1216            } else {
1217                -1
1218            };
1219
1220            if let Some(v) = ar.chunk {
1221                chunk = Some((v, u32::try_from(ar.currentline).unwrap()));
1222                break;
1223            }
1224
1225            ci = unsafe { (*ci).previous };
1226        }
1227
1228        Box::new(Self { chunk, reason })
1229    }
1230
1231    /// Returns chunk name and line number if this error triggered from Lua.
1232    pub fn location(&self) -> Option<(&str, u32)> {
1233        self.chunk.as_ref().map(|(n, l)| (n.as_str(), *l))
1234    }
1235
1236    /// Returns error that was originate from [Fp], [AsyncFp] or [YieldFp].
1237    pub fn reason(&self) -> &(dyn Error + 'static) {
1238        self.reason.deref()
1239    }
1240}
1241
1242impl Error for CallError {
1243    fn source(&self) -> Option<&(dyn Error + 'static)> {
1244        self.reason.source()
1245    }
1246}
1247
1248impl Display for CallError {
1249    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1250        self.reason.fmt(f)
1251    }
1252}
1253
1254/// Represents an error when arithmetic operation fails.
1255#[derive(Debug, Error)]
1256pub enum ArithError {
1257    /// Lua code attempt to modulo by zero.
1258    #[error("attempt to perform 'n%0'")]
1259    ModZero,
1260
1261    /// Lua code attempt to divide by zero.
1262    #[error("attempt to divide by zero")]
1263    DivZero,
1264}
1265
1266/// Represents an error when Lua stack is overflow.
1267#[derive(Debug, Error)]
1268#[error("stack overflow")]
1269pub struct StackOverflow;
1270
1271/// Represents an error when [Lua::use_module()] fails due to the module already exists.
1272#[derive(Debug, Error)]
1273#[error("module with the same name already exists")]
1274pub struct ModuleExists;
1275
1276/// Represents an error when a function that cannot be recursive call itself either directly or
1277/// indirectly.
1278#[derive(Debug, Error)]
1279#[error("a call to '{0}' cannot be recursive")]
1280pub struct RecursiveCall(&'static str);
1281
1282impl RecursiveCall {
1283    fn new<F>(_: F) -> Self {
1284        Self(core::any::type_name::<F>())
1285    }
1286}
1287
1288static NON_YIELDABLE_WAKER: RawWakerVTable = RawWakerVTable::new(
1289    |_| unimplemented!(),
1290    |_| unimplemented!(),
1291    |_| unimplemented!(),
1292    |_| {},
1293);
1294
1295static YIELDABLE_WAKER: RawWakerVTable = RawWakerVTable::new(
1296    |_| unimplemented!(),
1297    |_| unimplemented!(),
1298    |_| unimplemented!(),
1299    |_| {},
1300);