lua_stdlib/init.rs
1//! Initialization of standard libraries for Lua.
2//!
3//! Opens all standard libraries via `require`-style loading and registers
4//! them into the global table.
5//!
6//! C source: `reference/lua-5.4.7/src/linit.c`.
7
8use crate::state_stub::{LuaState, LuaStateStubExt as _};
9use lua_types::error::LuaError;
10
11type LuaCFunction = fn(&mut LuaState) -> Result<usize, LuaError>;
12
13/// Opener function names are inconsistent across stdlib modules: `base`
14/// exports the canonical `open`, while `string_lib`/`table_lib`/`math_lib`/
15/// `io_lib`/`os_lib` still export their original `luaopen_*`/`open_*` names
16/// (as do `utf8_lib`/`debug_lib`/`coro_lib`/`loadlib`). Unifying every
17/// opener to `pub fn open` would let this table be written more uniformly.
18static LOADED_LIBS: &[(&[u8], LuaCFunction)] = &[
19 (b"_G", crate::base::open),
20 #[cfg(feature = "package")]
21 (b"package", crate::loadlib::luaopen_package),
22 #[cfg(feature = "coroutine")]
23 (b"coroutine", crate::coro_lib::open_coroutine),
24 (b"table", crate::table_lib::open_table),
25 #[cfg(feature = "io")]
26 (b"io", crate::io_lib::luaopen_io),
27 #[cfg(feature = "os")]
28 (b"os", crate::os_lib::open_os),
29 (b"string", crate::string_lib::luaopen_string),
30 (b"math", crate::math_lib::luaopen_math),
31 #[cfg(feature = "utf8")]
32 (b"utf8", crate::utf8_lib::open_utf8),
33 #[cfg(feature = "debug")]
34 (b"debug", crate::debug_lib::open_debug),
35];
36
37/// Open all standard Lua libraries into `state`, registering each into the
38/// global table.
39///
40/// Corresponds to `luaL_openlibs` in `linit.c`. The `true` argument to
41/// `require_lib` means "set global": the loaded module value is assigned to
42/// the global table under `name`, and the value left on the stack is then
43/// discarded.
44pub fn open_libs(state: &mut LuaState) -> Result<(), LuaError> {
45 // Whether this version ships `utf8` (a 5.3 addition) is the #234 capability
46 // matrix — the reference-backed single source — not a second inline version
47 // check. The `#[cfg(feature = "utf8")]`-gated registration entries in
48 // LOADED_LIBS still control compile-time availability.
49 let has_utf8 = state
50 .global()
51 .lua_version
52 .supports(lua_types::Feature::Utf8Lib);
53 for &(name, func) in LOADED_LIBS {
54 if name == b"utf8".as_slice() && !has_utf8 {
55 continue;
56 }
57 state.require_lib(name, func, true)?;
58 state.pop_n(1);
59 }
60 // `bit32` is present on 5.2 and 5.3 and removed in 5.4; the version dimension
61 // comes from the #234 matrix, the compile-time dimension from the feature
62 // gate (registration = `cfg(feature) && version.supports(Bit32Lib)`).
63 #[cfg(feature = "bit32")]
64 if state
65 .global()
66 .lua_version
67 .supports(lua_types::Feature::Bit32Lib)
68 {
69 state.require_lib(b"bit32", crate::bit32_lib::open_bit32, true)?;
70 state.pop_n(1);
71 }
72 Ok(())
73}