New apis and clippy fixes

This commit is contained in:
William Venner 2022-07-07 19:00:34 +01:00
parent 64ade67496
commit 85c1d6a82a
10 changed files with 126 additions and 39 deletions

2
Cargo.lock generated
View File

@ -109,7 +109,7 @@ dependencies = [
[[package]]
name = "gmod"
version = "15.0.2"
version = "16.0.0"
dependencies = [
"cfg_table",
"cstr",

View File

@ -1,6 +1,6 @@
[package]
name = "gmod"
version = "15.0.2"
version = "16.0.0"
authors = ["William Venner <william@venner.io>"]
edition = "2021"
license = "MIT"

View File

@ -1,5 +1,8 @@
//! [Available Lua Functions](https://docs.rs/gmod/latest/gmod/lua/struct.State.html)
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::result_unit_err)]
#![feature(c_unwind)]
#![feature(thread_id_value)]
@ -255,11 +258,11 @@ pub struct OpenGmodLibraryErrs(pub std::collections::HashMap<&'static str, liblo
impl std::error::Error for OpenGmodLibraryErrs {}
impl std::fmt::Display for OpenGmodLibraryErrs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "")?;
writeln!(f)?;
for (path, err) in &self.0 {
writeln!(f, "{} = {}", path, err)?;
}
writeln!(f, "")?;
writeln!(f)?;
Ok(())
}
}

View File

@ -114,6 +114,7 @@ impl std::ops::DerefMut for LuaSharedInterface {
pub static mut LUA_SHARED: LuaSharedInterface = LuaSharedInterface(UnsafeCell::new(std::ptr::null_mut()), #[cfg(debug_assertions)] AtomicI64::new(-1));
pub struct LuaShared {
pub(crate) library: &'static libloading::Library,
pub lual_newstate: Symbol<'static, unsafe extern "C-unwind" fn() -> LuaState>,
pub lual_openlibs: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState)>,
pub lual_loadfile: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, path: LuaString) -> i32>,
@ -180,7 +181,7 @@ impl LuaShared {
fn import() -> Self {
unsafe {
let (library, path) = Self::find_lua_shared();
let library = Box::leak(Box::new(library)); // Keep this library referenced forever
let library = Box::leak(Box::new(library));
macro_rules! find_symbol {
( $symbol:literal ) => {
@ -249,6 +250,7 @@ impl LuaShared {
lua_status: find_symbol!("lua_status"),
lua_xmove: find_symbol!("lua_xmove"),
lua_equal: find_symbol!("lua_equal"),
library,
}
}
}

View File

@ -1,8 +1,5 @@
use std::{mem::MaybeUninit, borrow::Cow, ffi::c_void};
use crate::lua::*;
use crate::userdata::TaggedUserData;
use crate::{userdata::TaggedUserData, lua::*};
unsafe fn handle_pcall_ignore(lua: State) {
crate::lua_stack_guard!(lua => {
@ -219,7 +216,7 @@ impl LuaState {
handle_pcall_ignore(*self);
false
}
err @ _ => {
err => {
#[cfg(debug_assertions)]
eprintln!("[gmod-rs] pcall_ignore unknown error: {}", err);
false
@ -316,11 +313,52 @@ impl LuaState {
}
#[inline(always)]
/// Creates a closure, which can be used as a function with stored data (upvalues)
///
/// ## Example
///
/// ```ignore
/// #[lua_function]
/// unsafe fn foo(lua: gmod::lua::State) {
/// lua.get_closure_arg(1);
/// let hello = lua.get_string(-1);
/// println!("{}", hello);
/// }
///
/// lua.push_string("Hello, world!");
/// lua.push_closure(foo, 1);
/// ```
pub unsafe fn push_closure(&self, func: LuaFunction, n: i32) {
debug_assert!(n <= 255, "Can't push more than 255 arguments into a closure");
(LUA_SHARED.lua_pushcclosure)(*self, func, n)
}
#[inline(always)]
/// Pushes the `n`th closure argument onto the stack
///
/// ## Example
///
/// ```ignore
/// #[lua_function]
/// unsafe fn foo(lua: gmod::lua::State) {
/// lua.push_closure_arg(1);
/// let hello = lua.get_string(-1);
/// println!("{}", hello);
/// }
///
/// lua.push_string("Hello, world!");
/// lua.push_closure(foo, 1);
/// ```
pub unsafe fn push_closure_arg(&self, n: i32) {
self.push_value(self.upvalue_index(n));
}
#[inline(always)]
/// Equivalent to C `lua_upvalueindex` macro
pub const fn upvalue_index(&self, idx: i32) -> i32 {
LUA_GLOBALSINDEX - idx
}
#[inline(always)]
pub unsafe fn set_table(&self, index: i32) {
(LUA_SHARED.lua_settable)(*self, index)
@ -393,8 +431,7 @@ impl LuaState {
}
pub unsafe fn test_userdata(&self, index: i32, name: LuaString) -> bool {
if !(LUA_SHARED.lua_touserdata)(*self, index).is_null() {
if self.get_metatable(index) != 0 {
if !(LUA_SHARED.lua_touserdata)(*self, index).is_null() && self.get_metatable(index) != 0 {
self.get_field(LUA_REGISTRYINDEX, name);
let result = self.raw_equal(-1, -2);
self.pop_n(2);
@ -402,7 +439,6 @@ impl LuaState {
return true;
}
}
}
false
}
@ -463,6 +499,7 @@ impl LuaState {
}
#[inline(always)]
#[allow(clippy::len_without_is_empty)]
pub unsafe fn len(&self, index: i32) -> i32 {
(LUA_SHARED.lua_objlen)(*self, index)
}
@ -527,7 +564,7 @@ impl LuaState {
pub unsafe fn coroutine_resume_call(&self, narg: i32) {
match (LUA_SHARED.lua_resume)(*self, narg) {
LUA_OK => {},
LUA_ERRRUN => self.error(self.get_string(-2).unwrap_or_else(|| Cow::Borrowed("Unknown error")).as_ref()),
LUA_ERRRUN => self.error(self.get_string(-2).unwrap_or(Cow::Borrowed("Unknown error")).as_ref()),
LUA_ERRMEM => self.error("Out of memory"),
_ => self.error("Unknown internal Lua error")
}
@ -542,7 +579,7 @@ impl LuaState {
handle_pcall_ignore(*self);
Err(())
},
err @ _ => {
err => {
#[cfg(debug_assertions)]
eprintln!("[gmod-rs] coroutine_resume_pcall_ignore unknown error: {}", err);
Err(())
@ -631,11 +668,9 @@ impl LuaState {
pub unsafe fn debug_getinfo_at(&self, level: i32, what: LuaString) -> Option<LuaDebug> {
let mut ar = MaybeUninit::uninit();
if (LUA_SHARED.lua_getstack)(*self, level, ar.as_mut_ptr()) != 0 {
if (LUA_SHARED.lua_getinfo)(*self, what, ar.as_mut_ptr()) != 0 {
if (LUA_SHARED.lua_getstack)(*self, level, ar.as_mut_ptr()) != 0 && (LUA_SHARED.lua_getinfo)(*self, what, ar.as_mut_ptr()) != 0 {
return Some(ar.assume_init());
}
}
None
}

View File

@ -14,6 +14,8 @@ pub use push::*;
mod returns;
pub use returns::ValuesReturned;
mod raw_bind;
#[derive(Debug, Clone)]
pub enum LuaError {
/// Out of memory
@ -78,7 +80,7 @@ macro_rules! lua_stack_guard {
( $lua:ident => $code:block ) => {{
#[cfg(debug_assertions)] {
let top = $lua.get_top();
let ret = (|| $code)();
let ret = $code;
if top != $lua.get_top() {
$lua.dump_stack();
panic!("Stack is dirty! Expected the stack to have {} elements, but it has {}!", top, $lua.get_top());

View File

@ -98,7 +98,7 @@ impl PushToLua for Vec<u8> {
impl PushToLua for &[u8] {
#[inline]
unsafe fn push_to_lua(self, lua: crate::lua::State) {
lua.push_binary_string(&self);
lua.push_binary_string(self);
}
}
impl PushToLua for Duration {

45
gmod/src/lua/raw_bind.rs Normal file
View File

@ -0,0 +1,45 @@
use crate::lua::*;
pub trait CLuaFunction: Copy {}
macro_rules! impl_c_lua_function {
($($($arg:ident) *;)*) => {
$(
impl<$($arg, )* R> CLuaFunction for extern "C-unwind" fn($($arg),*) -> R {}
impl<$($arg, )* R> CLuaFunction for unsafe extern "C-unwind" fn($($arg),*) -> R {}
impl<$($arg, )* R> CLuaFunction for extern "C" fn($($arg),*) -> R {}
impl<$($arg, )* R> CLuaFunction for unsafe extern "C" fn($($arg),*) -> R {}
)*
};
}
impl_c_lua_function!(
;
T1;
T1 T2;
T1 T2 T3;
T1 T2 T3 T4;
T1 T2 T3 T4 T5;
T1 T2 T3 T4 T5 T6;
T1 T2 T3 T4 T5 T6 T7;
T1 T2 T3 T4 T5 T6 T7 T8;
T1 T2 T3 T4 T5 T6 T7 T8 T9;
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10;
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11;
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12;
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13;
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14;
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15;
T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16;
);
impl State {
#[inline(always)]
/// Binds to a raw Lua C function.
///
/// If anything is missing from this library, you can use this function to bind it yourself.
///
/// Note, this may be a somewhat expensive operation, so storing its result in some way is recommended.
pub unsafe fn raw_bind<F: CLuaFunction>(&self, symbol: &[u8]) -> Result<F, libloading::Error> {
LUA_SHARED.library.get::<F>(symbol).map(|f| *f)
}
}

View File

@ -3,10 +3,10 @@ use std::{num::NonZeroI32, borrow::Cow};
#[repr(transparent)]
pub struct ValuesReturned(pub i32);
impl Into<i32> for ValuesReturned {
impl From<ValuesReturned> for i32 {
#[inline(always)]
fn into(self) -> i32 {
self.0
fn from(v: ValuesReturned) -> Self {
v.0
}
}
@ -45,11 +45,11 @@ impl From<Option<NonZeroI32>> for ValuesReturned {
}
pub trait DisplayLuaError {
fn display_lua_error<'a>(&'a self) -> Cow<'a, str>;
fn display_lua_error(&self) -> Cow<'_, str>;
}
impl<E: std::fmt::Debug> DisplayLuaError for E {
#[inline(always)]
fn display_lua_error<'a>(&'a self) -> Cow<'a, str> {
fn display_lua_error(&self) -> Cow<'_, str> {
Cow::Owned(format!("{:?}", self))
}
}

View File

@ -100,7 +100,7 @@ macro_rules! userdata {
/// This will NOT perform a type check to ensure that the tagged userdata matches the user data you are coercing to.
///
/// Coercing to the wrong type is undefined behaviour and is likely to crash your program.
pub unsafe fn coerce_unchecked<T: CoercibleUserData>(&self) -> &mut T {
pub unsafe fn coerce_unchecked<'a, 'b, T: CoercibleUserData>(&'a self) -> &'b mut T {
&mut *(self.data as *mut T)
}
}