use crate::{JmpBuf, JmpBufFields};
use crate::{SigJmpBuf, SigJmpBufFields};
use libc::{c_int, c_void};
#[link(name = "interop_via_c", kind="static")]
extern "C" {
fn call_closure_with_setjmp(closure_env_ptr: *mut c_void, closure_code: extern "C" fn(jbuf: *const JmpBufFields, env_ptr: *mut c_void) -> c_int) -> c_int;
fn call_closure_with_sigsetjmp(savemask: c_int, closure_env_ptr: *mut c_void, closure_code: extern "C" fn(jbuf: *const SigJmpBufFields, env_ptr: *mut c_void) -> c_int) -> c_int;
}
pub fn call_with_setjmp<F>(mut callback: F) -> c_int
where
F: for<'a> FnOnce(&'a JmpBufFields) -> c_int,
{
extern "C" fn call_from_c_to_rust<F>(jbuf: JmpBuf, closure_env_ptr: *mut c_void) -> c_int
where
F: for<'a> FnOnce(&'a JmpBufFields) -> c_int,
{
let closure_env_ptr: *mut F = closure_env_ptr as *mut F;
unsafe { (closure_env_ptr.read())(&*jbuf) }
}
unsafe {
let closure_env_ptr = std::ptr::addr_of_mut!(callback);
std::mem::forget(callback);
call_closure_with_setjmp(closure_env_ptr as *mut c_void, call_from_c_to_rust::<F>)
}
}
pub fn call_with_sigsetjmp<F>(savemask: bool, mut callback: F) -> c_int
where
F: for<'a> FnOnce(&'a SigJmpBufFields) -> c_int,
{
extern "C" fn call_from_c_to_rust<F>(jbuf: SigJmpBuf, closure_env_ptr: *mut c_void) -> c_int
where
F: for<'a> FnOnce(&'a SigJmpBufFields) -> c_int,
{
let closure_env_ptr: *mut F = closure_env_ptr as *mut F;
unsafe { (closure_env_ptr.read())(&*jbuf) }
}
let savemask: c_int = if savemask { 1 } else { 0 };
unsafe {
let closure_env_ptr = std::ptr::addr_of_mut!(callback);
std::mem::forget(callback);
call_closure_with_sigsetjmp(savemask, closure_env_ptr as *mut c_void, call_from_c_to_rust::<F>)
}
}