low-luajit 0.4.0

Low level but safe bindings to the LuaJIT C API with no dependencies and no-std support to create Lua modules using Rust.
Documentation
use core::{ffi::CStr, fmt::{self, Display}, mem, ptr};
use crate::{LuaState, ffi};

mod nil;
mod boolean;
mod number;
mod string;
mod table;
mod function;
mod userdata;
mod thread;

pub use table::*;
pub use function::*;

/// Possible types for Lua values.
///
/// Can be obtained from [`LuaState::type_of`].
#[repr(i32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LuaType {
	/// *(Returned for non-existing elements.)*
	None = ffi::LUA_TNONE,
	Nil = ffi::LUA_TNIL,
	Boolean = ffi::LUA_TBOOLEAN,
	LightUserdata = ffi::LUA_TLIGHTUSERDATA,
	Number = ffi::LUA_TNUMBER,
	String = ffi::LUA_TSTRING,
	Table = ffi::LUA_TTABLE,
	Function = ffi::LUA_TFUNCTION,
	Userdata = ffi::LUA_TUSERDATA,
	Thread = ffi::LUA_TTHREAD,
}

impl Display for LuaType {
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		// SAFETY: self.name() always returns simple ASCII strings.
		f.write_str(unsafe { str::from_utf8_unchecked(self.name().to_bytes()) })
	}
}

impl LuaType {
	/// Returns the name of this type as a string.
	#[inline]
	#[must_use]
	pub fn name(self) -> &'static CStr {
		// SAFETY: lua_typename does not use the lua_State pointer and always returns a valid nul-terminated string for all LuaType values.
		unsafe { CStr::from_ptr(ffi::lua_typename(ptr::null_mut(), self as i32)) }
	}
}

/// Type related functions.
///
/// *[See also the `LuaType` enum](enum.LuaType.html)*.
impl LuaState {
	/// Returns the type of the value at the given `index`.
	///
	/// Invalid indices will return [`LuaType::None`].
	#[inline]
	#[must_use]
	pub fn type_of(&self, index: i32) -> LuaType {
		// SAFETY: self.0 is always valid and lua_type always returns a value that can be transmuted to a LuaType.
		unsafe { mem::transmute(ffi::lua_type(self.0, index)) }
	}

	/// Checks if there's an element of the given type at the given index `arg_n` and returns it.
	///
	/// If the check fails, [`LuaState::type_error`] is called using `arg_n`.
	///
	/// # Lua Errors
	///
	/// Intentionally errors if the check fails.
	pub fn check_type(&self, arg_n: i32, r#type: LuaType) {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::luaL_checktype(self.0, arg_n, r#type as i32); }
	}
}