Skip to main content

luaur_require/functions/
register_module_impl.rs

1use alloc::ffi::CString;
2use core::ffi::c_char;
3use luaur_vm::functions::lua_gettop::lua_gettop;
4use luaur_vm::functions::lua_insert::lua_insert;
5use luaur_vm::functions::lua_l_argerror_l::luaL_argerrorL;
6use luaur_vm::functions::lua_l_checklstring::lua_l_checklstring;
7use luaur_vm::functions::lua_l_findtable::luaL_findtable;
8use luaur_vm::functions::lua_pushstring::lua_pushstring;
9use luaur_vm::functions::lua_replace::lua_replace;
10use luaur_vm::functions::lua_settable::lua_settable;
11use luaur_vm::macros::lua_l_error::luaL_error;
12use luaur_vm::macros::lua_pop::lua_pop;
13use luaur_vm::macros::lua_registryindex::LUA_REGISTRYINDEX;
14use luaur_vm::records::lua_state::lua_State;
15
16const REGISTERED_CACHE_TABLE_KEY: *const c_char = c"_REGISTEREDMODULES".as_ptr();
17
18pub fn register_module_impl(l: *mut lua_State) -> i32 {
19    unsafe {
20        if lua_gettop(l) != 2 {
21            luaL_error!(
22                l,
23                "expected 2 arguments: aliased require path and desired result"
24            );
25            return 0;
26        }
27
28        let mut len = 0usize;
29        let path = lua_l_checklstring(l, 1, &mut len);
30        if len == 0 || *path != b'@' as c_char {
31            luaL_argerrorL(l, 1, "path must begin with '@'");
32        }
33
34        let mut path_lower = core::slice::from_raw_parts(path as *const u8, len).to_vec();
35        for byte in &mut path_lower {
36            if *byte >= b'A' && *byte <= b'Z' {
37                *byte += b'a' - b'A';
38            }
39        }
40
41        let path_lower = CString::new(path_lower).unwrap();
42        lua_pushstring(l, path_lower.as_ptr());
43        lua_replace(l, 1);
44
45        luaL_findtable(l, LUA_REGISTRYINDEX, REGISTERED_CACHE_TABLE_KEY, 1);
46        lua_insert(l, 1);
47        lua_settable(l, 1);
48        lua_pop(l, 1);
49
50        0
51    }
52}