Skip to main content

luaur_code_gen/functions/
userdata_remapper_wrap.rs

1use crate::functions::get_code_gen_context::get_code_gen_context;
2use crate::type_aliases::lua_state::lua_State;
3use luaur_common::enums::luau_bytecode_type::LuauBytecodeType;
4
5/// C trampoline installed into `global_State::ecb.gettypemapping` so the VM's
6/// bytecode loader can map userdata type names through the registered remapper.
7///
8/// Mirrors `userdataRemapperWrap` (CodeGen/src/CodeGenContext.cpp):
9/// ```cpp
10/// static uint8_t userdataRemapperWrap(lua_State* L, const char* str, size_t len) {
11///     if (BaseCodeGenContext* codegenCtx = getCodeGenContext(L)) {
12///         uint8_t index = codegenCtx->userdataRemapper(codegenCtx->userdataRemappingContext, str, len);
13///         if (index < (LBC_TYPE_TAGGED_USERDATA_END - LBC_TYPE_TAGGED_USERDATA_BASE))
14///             return LBC_TYPE_TAGGED_USERDATA_BASE + index;
15///     }
16///     return LBC_TYPE_USERDATA;
17/// }
18/// ```
19///
20/// # Safety
21/// `l` must be a valid `lua_State` pointer (or null, which is handled). This is
22/// invoked by the VM through a function pointer, hence `extern "C"`.
23pub unsafe extern "C" fn userdata_remapper_wrap(
24    l: *mut lua_State,
25    str: *const core::ffi::c_char,
26    len: usize,
27) -> u8 {
28    let codegen_ctx = get_code_gen_context(l);
29    if !codegen_ctx.is_null() {
30        let ctx = &*codegen_ctx;
31
32        // The wrapper is only installed as `gettypemapping` when a remapper is
33        // present, so `userdata_remapper` is `Some` here; this mirrors the C++
34        // direct call and falls through to LBC_TYPE_USERDATA otherwise.
35        if let Some(remapper) = ctx.userdata_remapper {
36            let index = remapper(ctx.userdata_remapping_context, str, len);
37
38            let base = LuauBytecodeType::LBC_TYPE_TAGGED_USERDATA_BASE.0 as u8;
39            let end = LuauBytecodeType::LBC_TYPE_TAGGED_USERDATA_END.0 as u8;
40
41            if (index as u16) < (end as u16 - base as u16) {
42                return base.wrapping_add(index as u8);
43            }
44        }
45    }
46
47    LuauBytecodeType::LBC_TYPE_USERDATA.0 as u8
48}