use core::ptr::{self, NonNull};
use crate::ffi::{self, lua_State};
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq)]
pub struct LuaState(NonNull<lua_State>);
impl LuaState {
#[must_use]
pub const unsafe fn from_ptr(ptr: *mut lua_State) -> Self {
unsafe { Self::from_non_null(NonNull::new_unchecked(ptr) ) }
}
#[must_use]
pub const unsafe fn from_non_null(ptr: NonNull<lua_State>) -> Self {
Self(ptr)
}
#[must_use]
pub const fn as_ptr(&self) -> *mut lua_State {
self.as_non_null().as_ptr()
}
#[must_use]
pub const fn as_non_null(&self) -> NonNull<lua_State> {
self.0
}
pub unsafe fn access_mut<T>(&self, f: impl FnOnce(&mut Self) -> T) -> T {
#[cfg(debug_assertions)]
let top = self.get_top();
let mut lua = unsafe { Self::from_ptr(self.as_ptr()) };
let result = f(&mut lua);
#[cfg(debug_assertions)]
debug_assert!(top == self.get_top(), "mutably accessed the Lua state as the stack held {top} elements, but left it with {} elements instead", self.get_top());
result
}
#[inline]
pub unsafe fn close(self) {
unsafe { ffi::lua_close(self.as_ptr()); }
}
#[inline]
#[must_use]
pub fn version() -> &'static f64 {
unsafe { &*ffi::lua_version(ptr::null_mut()) }
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __test {
($($lib:ident),*) => {{
#[cfg(not(windows))]
#[link(name = "luajit-5.1")]
unsafe extern "C" {}
let ptr = $crate::ffi::luaL_newstate();
$($crate::ffi::$lib(ptr);)*
$crate::LuaState::from_ptr(ptr)
}};
}