pub unsafe fn protect_lua<F, R>(
    state: *mut ffi::lua_State,
    nargs: c_int,
    nresults: c_int,
    f: F,
) -> Result<R>
where
    F: Fn(*mut ffi::lua_State) -> R,
    R: Copy,
{
    union URes<R: Copy> {
        uninit: (),
        init: R,
    }

    struct Params<F, R: Copy> {
        function: F,
        result: URes<R>,
        nresults: c_int,
    }

    unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
    where
        R: Copy,
        F: Fn(*mut ffi::lua_State) -> R,
    {
        let params = ffi::lua_touserdata(state, -1) as *mut Params<F, R>;
        ffi::lua_pop(state, 1);

        (*params).result.init = ((*params).function)(state);

        if (*params).nresults == ffi::LUA_MULTRET {
            ffi::lua_gettop(state)
        } else {
            (*params).nresults
        }
    }

    let stack_start = ffi::lua_gettop(state) - nargs;

    ffi::lua_pushcfunction(state, error_traceback);
    ffi::lua_pushcfunction(state, do_call::<F, R>);
    if nargs > 0 {
        ffi::lua_rotate(state, stack_start + 1, 2);
    }

    let mut params = Params {
        function: f,
        result: URes { uninit: () },
        nresults,
    };

    ffi::lua_pushlightuserdata(state, &mut params as *mut Params<F, R> as *mut c_void);
    let ret = ffi::lua_pcall(state, nargs + 1, nresults, stack_start + 1);
    ffi::lua_remove(state, stack_start + 1);

    if ret == ffi::LUA_OK {
        // `LUA_OK` is only returned when the `do_call` function has completed successfully, so
        // `params.result` is definitely initialized.
        Ok(params.result.init)
    } else {
        Err(pop_error(state, ret))
    }
}
// Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way.
// Wraps the inner function in a call to `lua_pcall`, so the inner function only has access to a
// limited lua stack. `nargs` and `nresults` are similar to the parameters of `lua_pcall`, but the
// given function return type is not the return value count, instead the inner function return
// values are assumed to match the `nresults` param. Provided function must *not* panic, and since it
// will generally be lonjmping, should not contain any values that implements Drop.
// Internally uses 3 extra stack spaces, and does not call checkstack.
Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way.
Wraps the inner function in a call to `lua_pcall`, so the inner function only has access to a
limited lua stack.
Call a function that calls into the Lua API and may trigger a Lua error ( longjmp ) in a safe way . Wraps the inner function in a call to ` lua_pcall ` so the inner function only has access to a limited lua stack .
pub unsafe fn protect_lua<F, R>(
    state: *mut ffi::lua_State,
    nargs: c_int,
    nresults: c_int,
    f: F,
) -> Result<R>
where
    F: Fn(*mut ffi::lua_State) -> R,
    R: Copy,
{
    union URes<R: Copy> {
        uninit: (),
        init: R,
    }
    struct Params<F, R: Copy> {
        function: F,
        result: URes<R>,
        nresults: c_int,
    }
    unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
    where
        R: Copy,
        F: Fn(*mut ffi::lua_State) -> R,
    {
        let params = ffi::lua_touserdata(state, -1) as *mut Params<F, R>;
        ffi::lua_pop(state, 1);
        (*params).result.init = ((*params).function)(state);
        if (*params).nresults == ffi::LUA_MULTRET {
            ffi::lua_gettop(state)
        } else {
            (*params).nresults
        }
    }
    let stack_start = ffi::lua_gettop(state) - nargs;
    ffi::lua_pushcfunction(state, error_traceback);
    ffi::lua_pushcfunction(state, do_call::<F, R>);
    if nargs > 0 {
        ffi::lua_rotate(state, stack_start + 1, 2);
    }
    let mut params = Params {
        function: f,
        result: URes { uninit: () },
        nresults,
    };
    ffi::lua_pushlightuserdata(state, &mut params as *mut Params<F, R> as *mut c_void);
    let ret = ffi::lua_pcall(state, nargs + 1, nresults, stack_start + 1);
    ffi::lua_remove(state, stack_start + 1);
    if ret == ffi::LUA_OK {
        // `LUA_OK` is only returned when the `do_call` function has completed successfully, so
        // `params.result` is definitely initialized.
        Ok(params.result.init)
    } else {
        Err(pop_error(state, ret))
    }
}
pub unsafe fn protect_lua < F , R > ( state : * mut ffi :: lua_State , nargs : c_int , nresults : c_int , f : F , ) -> Result < R > where F : Fn ( * mut ffi :: lua_State ) -> R , R : Copy , { union URes < R : Copy > { uninit : ( ) , init : R , } struct Params < F , R : Copy > { function : F , result : URes < R > , nresults : c_int , } unsafe extern " " fn do_call < F , R > ( state : * mut ffi :: lua_State ) -> c_int where R : Copy , F : Fn ( * mut ffi :: lua_State ) -> R , { let params = ffi :: lua_touserdata ( state , - 1 ) as * mut Params < F , R > ; ffi :: lua_pop ( state , 1 ) ; ( * params ) . result . init = ( ( * params ) . function ) ( state ) ; if ( * params ) . nresults == ffi :: LUA_MULTRET { ffi :: lua_gettop ( state ) } else { ( * params ) . nresults } } let stack_start = ffi :: lua_gettop ( state ) - nargs ; ffi :: lua_pushcfunction ( state , error_traceback ) ; ffi :: lua_pushcfunction ( state , do_call :: < F , R > ) ; if nargs > 0 { ffi :: lua_rotate ( state , stack_start + 1 , 2 ) ; } let mut params = Params { function : f , result : URes { uninit : ( ) } , nresults , } ; ffi :: lua_pushlightuserdata ( state , & mut params as * mut Params < F , R > as * mut c_void ) ; let ret = ffi :: lua_pcall ( state , nargs + 1 , nresults , stack_start + 1 ) ; ffi :: lua_remove ( state , stack_start + 1 ) ; if ret == ffi :: LUA_OK { // `LUA_OK` is only returned when the `do_call` function has completed successfully, so // `params.result` is definitely initialized. Ok ( params . result . init ) } else { Err ( pop_error ( state , ret ) ) } }
Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way.
Call a function that calls into the Lua API and may trigger a Lua error ( longjmp ) in a safe way .
state
*mut ffi::lua_State
nargs
c_int
nresults
c_int
f
F
state
*mut ffi::lua_State
nargs
c_int
nresults
c_int
f
F