use crate::ffi::{
collections::NonNullConst,
sys::api::{GetFunctionFn as GetFunctionFnFFI, SysBinding},
Bool, CBase as CBaseFFI,
};
use crate::init::CBaseAPILoader;
use crate::{CBase, CBaseInterfaceInfo, CBaseRef};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
pub mod library;
pub mod module;
pub mod sys;
pub mod version;
#[cfg(feature = "extensions")]
pub mod extensions;
static mut INTERFACE: MaybeUninit<CBaseRef<'static>> = MaybeUninit::uninit();
#[derive(Debug)]
pub struct Unlock {}
#[derive(Debug)]
pub struct ForgetUnlock {}
impl Drop for Unlock {
fn drop(&mut self) {
unsafe { SysBinding::unlock(get_interface()) }
}
}
#[derive(Debug)]
pub struct LockToken<T> {
_phantom: T,
}
impl LockToken<Unlock> {
pub unsafe fn relinquish_locking(self) -> LockToken<ForgetUnlock> {
std::mem::forget(self);
LockToken {
_phantom: ForgetUnlock {},
}
}
}
impl LockToken<ForgetUnlock> {
pub unsafe fn take_ownership(self) -> LockToken<Unlock> {
std::mem::forget(self);
LockToken {
_phantom: Unlock {},
}
}
}
impl<T> LockToken<T> {
#[inline]
#[must_use]
pub fn lock() -> LockToken<Unlock> {
unsafe {
SysBinding::lock(get_interface());
LockToken {
_phantom: Unlock {},
}
}
}
#[inline]
#[must_use]
pub fn try_lock() -> Option<LockToken<Unlock>> {
unsafe {
match SysBinding::try_lock(get_interface()) {
Bool::False => None,
Bool::True => Some(LockToken {
_phantom: Unlock {},
}),
}
}
}
#[inline]
pub unsafe fn assume_locked() -> LockToken<ForgetUnlock> {
LockToken {
_phantom: ForgetUnlock {},
}
}
}
#[inline]
pub fn initialize(base_module: Option<NonNull<CBaseFFI>>, get_function_fn: GetFunctionFnFFI) {
unsafe {
INTERFACE = MaybeUninit::new(CBaseRef::new(NonNullConst::from(
CBase::fetch_interface(base_module, get_function_fn).internal_interface(),
)));
}
#[cfg(feature = "unwind_internal")]
extensions::unwind_internal::initialize();
}
#[inline]
pub fn get_interface<'a>() -> &'a CBaseRef<'static> {
unsafe { &*INTERFACE.as_ptr() }
}
#[inline]
pub fn get_mut_interface<'a>() -> &'a mut CBaseRef<'static> {
unsafe { &mut *INTERFACE.as_mut_ptr() }
}