use std::{cell::UnsafeCell, ffi::c_void, mem::transmute_copy, ptr::null_mut};
#[allow(non_camel_case_types, non_snake_case)]
pub mod ffi {
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
pub use detours_macros::detour;
pub struct Transaction {
_private: (),
}
impl Transaction {
pub unsafe fn attach<F: Copy>(&mut self, detour: &Detour<F>, target: *mut c_void) {
unsafe {
*detour.target.get() = target;
ffi::DetourAttach(
detour.target.get(),
core::mem::transmute_copy(&detour.detour),
);
}
}
pub unsafe fn detach<F: Copy>(&mut self, detour: &Detour<F>) {
unsafe {
ffi::DetourDetach(
detour.target.get(),
core::mem::transmute_copy(&detour.detour),
)
};
}
}
pub fn transaction<R>(f: impl FnOnce(&mut Transaction) -> R) -> R {
unsafe { ffi::DetourTransactionBegin() };
let mut tx = Transaction { _private: () };
let result = f(&mut tx);
unsafe { ffi::DetourTransactionCommit() };
result
}
pub struct Detour<F> {
target: UnsafeCell<*mut c_void>,
detour: F,
}
unsafe impl<F> Sync for Detour<F> {}
impl<F: Copy> Detour<F> {
pub const fn new(detour: F) -> Self {
Self {
target: UnsafeCell::new(null_mut()),
detour,
}
}
pub unsafe fn target(&self) -> F {
unsafe { transmute_copy(&*self.target.get()) }
}
}