Skip to main content

luaur_code_gen/functions/
set_userdata_remapper.rs

1use crate::functions::get_code_gen_context::get_code_gen_context;
2use crate::functions::userdata_remapper_wrap::userdata_remapper_wrap;
3use crate::type_aliases::lua_state::lua_State;
4use crate::type_aliases::userdata_remapper_callback::UserdataRemapperCallback;
5use core::ffi::c_void;
6
7/// Sets the userdata remapper callback and context on the code generation context.
8///
9/// Mirrors `setUserdataRemapper` (CodeGen/src/CodeGenContext.cpp):
10/// ```cpp
11/// void setUserdataRemapper(lua_State* L, void* context, UserdataRemapperCallback cb) {
12///     if (BaseCodeGenContext* codegenCtx = getCodeGenContext(L)) {
13///         codegenCtx->userdataRemappingContext = context;
14///         codegenCtx->userdataRemapper = cb;
15///         L->global->ecb.gettypemapping = cb ? userdataRemapperWrap : nullptr;
16///     }
17/// }
18/// ```
19///
20/// # Safety
21///
22/// - `L` must be a valid, non-null pointer to a `lua_State`.
23/// - The global state (`L->global`) must be valid and initialized.
24/// - The code generation context must be valid and properly initialized.
25/// - The callback `cb` must be a valid function pointer.
26#[inline]
27pub fn set_userdata_remapper(
28    L: *mut lua_State,
29    context: *mut c_void,
30    cb: UserdataRemapperCallback,
31) {
32    // get_code_gen_context handles the null checks (L / global / context) internally.
33    let codegen_ctx = get_code_gen_context(L);
34    if codegen_ctx.is_null() {
35        return;
36    }
37
38    // SAFETY: codegen_ctx is non-null and points to a valid BaseCodeGenContext;
39    // the caller guarantees L (and L->global) are valid per the contract above.
40    unsafe {
41        (*codegen_ctx).userdata_remapping_context = context;
42        // C++ stores the function pointer directly (`userdataRemapper = cb`).
43        // The Rust field is `Option<UserdataRemapperCallback>`, so wrap the value
44        // itself rather than taking the address of the local `cb`.
45        (*codegen_ctx).userdata_remapper = Some(cb);
46
47        // C++: L->global->ecb.gettypemapping = cb ? userdataRemapperWrap : nullptr;
48        // The translated `cb` parameter is a non-nullable function pointer, so a
49        // remapper is always present here and the wrapper trampoline is installed.
50        let global = (*L).global;
51        if !global.is_null() {
52            (*global).ecb.gettypemapping = Some(userdata_remapper_wrap);
53        }
54    }
55}