low-luajit 0.2.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 crate::{AmountReturned, LuaState, ffi};

/// Number related functions.
impl LuaState {
	/// Returns `true` if the value at the given acceptable `index` is a number, `false` otherwise.
	#[inline]
	#[must_use]
	pub fn is_number(&self, index: i32) -> bool {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::lua_isnumber(self.0, index) != 0 }
	}

	/// Converts the value at the given acceptable `index` to a number and returns it.
	///
	/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `0.0`.
	///
	/// This conversion *does not* affect the element in the stack itself (it stays as is).
	#[inline]
	#[must_use]
	pub fn to_number(&self, index: i32) -> f64 {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::lua_tonumber(self.0, index) }
	}

	/// Converts the value at the given acceptable `index` to a number and returns it.
	///
	/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `None`.
	///
	/// This conversion *does not* affect the element in the stack itself (it stays as is).
	#[inline]
	#[must_use]
	pub fn to_number_x(&self, index: i32) -> Option<f64> {
		// SAFETY: self.0 is always valid and is_num is initialized right before passing its pointer.
		let mut is_num = 0;
		let number = unsafe { ffi::lua_tonumberx(self.0, index, &raw mut is_num) };
		(is_num != 0).then_some(number)
	}

	/// Converts the value at the given acceptable `index` to an integer and returns it.
	///
	/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `0`.
	///
	/// If the number is not an integer, it will be truncated in an unspecified way.
	///
	/// This conversion *does not* affect the element in the stack itself (it stays as is).
	#[inline]
	#[must_use]
	pub fn to_integer(&self, index: i32) -> isize {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::lua_tointeger(self.0, index) }
	}

	/// Converts the value at the given acceptable `index` to an integer and returns it.
	///
	/// Only numbers or strings that can be converted into numbers are accepted. Anything else will return `0`.
	///
	/// If the number is not an integer, it will be truncated in an unspecified way.
	///
	/// This conversion *does not* affect the element in the stack itself (it stays as is).
	#[inline]
	#[must_use]
	pub fn to_integer_x(&self, index: i32) -> Option<isize> {
		// SAFETY: self.0 is always valid.
		let mut is_num = 0;
		let integer = unsafe { ffi::lua_tointegerx(self.0, index, &raw mut is_num) };
		(is_num != 0).then_some(integer)
	}

	/// Pushes the given `number` onto the stack.
	#[inline]
	pub fn push_number(&mut self, number: f64) {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::lua_pushnumber(self.0, number); }
	}

	/// Pushes the given `integer` onto the stack.
	#[inline]
	pub fn push_integer(&mut self, integer: isize) {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::lua_pushinteger(self.0, integer); }
	}

	/// Checks if there's a number 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.
	#[inline]
	pub fn check_number(&self, arg_n: i32) -> f64 {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::luaL_checknumber(self.0, arg_n) }
	}

	/// Checks if there's a number at the given index `arg_n` and returns it as an integer.
	///
	/// If the check fails, `LuaState::type_error` is called using `arg_n`.
	///
	/// # Lua Errors
	///
	/// Intentionally errors if the check fails.
	#[inline]
	pub fn check_integer(&self, arg_n: i32) -> isize {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::luaL_checkinteger(self.0, arg_n) }
	}

	/// Behaves exactly as [`LuaState::check_number`],
	/// but returns `default` instead of erroring when the element at the given index `arg_n` is `nil` (or non-existing).
	#[inline]
	pub fn opt_number(&self, arg_n: i32, default: f64) -> f64 {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::luaL_optnumber(self.0, arg_n, default) }
	}

	/// Behaves exactly as [`LuaState::check_integer`],
	/// but returns `default` instead of erroring when the element at the given index `arg_n` is `nil` (or non-existing).
	#[inline]
	pub fn opt_integer(&self, arg_n: i32, default: isize) -> isize {
		// SAFETY: self.0 is always valid.
		unsafe { ffi::luaL_optinteger(self.0, arg_n, default) }
	}

	/// Finishes the currently called [`CFunction`], returning the given `number` to the caller.
	///
	/// The `LuaState` wrapper is consumed to prevent invalidating the `AmountReturned` (the Lua state itself is left intact).
	///
	/// [`CFunction`]: ./type.CFunction.html
	#[inline]
	pub fn return_number(mut self, number: f64) -> AmountReturned {
		self.push_number(number);

		// SAFETY: There should always be at least one element in the stack.
		unsafe { AmountReturned::unchecked(1) }
	}

	/// Finishes the currently called [`CFunction`], returning the given `integer` to the caller.
	///
	/// The `LuaState` wrapper is consumed to prevent invalidating the `AmountReturned` (the Lua state itself is left intact).
	///
	/// [`CFunction`]: ./type.CFunction.html
	#[inline]
	pub fn return_integer(mut self, integer: isize) -> AmountReturned {
		self.push_integer(integer);

		// SAFETY: There should always be at least one element in the stack.
		unsafe { AmountReturned::unchecked(1) }
	}
}