low-luajit 0.3.1

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::ops::BitOr;
use crate::{LuaState, ffi};

/// Mode flags used to toggle/flush JIT compilation.
///
/// This enum is used by the following functions:
/// - [`LuaState::jit_set_mode`].
/// - [`LuaState::jit_set_engine`].
/// - [`LuaState::jit_set_function`].
///
/// Functions using `JITMode` directly usually allow passing `true`/`false` as an alternative to [`JITMode::On`]/[`JITMode::Off`].
#[repr(i32)]
#[derive(Debug, PartialEq, Eq)]
pub enum JITMode {
	Off = ffi::LUAJIT_MODE_OFF,
	On = ffi::LUAJIT_MODE_ON,
	Flush = ffi::LUAJIT_MODE_FLUSH,
}

impl From<bool> for JITMode {
	/// Converts `true` into [`JITMode::On`] and `false` into [`JITMode::Off`].
	#[inline]
	fn from(value: bool) -> Self {
		if value { Self::On } else { Self::Off }
	}
}

impl BitOr<JITMode> for i32 {
	type Output = i32;

	#[inline]
	fn bitor(self, rhs: JITMode) -> Self::Output {
		rhs as i32 | self
	}
}

/// JIT compiler engine handling functions.
impl LuaState {
	/// Generic JIT compiler engine mode controller function.
	///
	/// `mode` should be a `LUAJIT_MODE_*` constant (see the [`ffi`] module) or'd with a [`JITMode`] flag.
	///
	/// Returns `true` on success, `false` otherwise.
	///
	/// # Panics
	///
	/// Panics if `mode` uses `LUAJIT_MODE_FUNC`, `LUAJIT_MODE_ALLFUNC`, or `LUAJIT_MODE_ALLSUBFUNC` and `index` is out of bounds.
	///
	/// Additionally, this function will always panic if `mode` uses `LUAJIT_MODE_WRAPCFUNC`.
	// Use `LuaState::wrap_cfunctions` instead. (TODO)
	#[inline]
	pub fn jit_set_mode(&self, index: i32, mode: i32) -> bool {
		let masked_mode = mode & ffi::LUAJIT_MODE_MASK;
		assert!(masked_mode != ffi::LUAJIT_MODE_WRAPCFUNC, "cannot set `LUAJIT_MODE_WRAPCFUNC` by calling `LuaState::jit_set_mode`");
		assert!(
			(masked_mode != ffi::LUAJIT_MODE_FUNC && masked_mode != ffi::LUAJIT_MODE_ALLFUNC && masked_mode != ffi::LUAJIT_MODE_ALLSUBFUNC) ||
			self.is_index_ok(index),
			"cannot set the JIT compilation mode of the function at index {index}, as there are only {} elements", self.get_top()
		);

		// SAFETY: self.0 is always valid and mode is not LUAJIT_MODE_WRAPCFUNC.
		unsafe { ffi::luaJIT_setmode(self.0, index, mode) != 0 }
	}

	/// Sets the entire JIT compiler on or off or flushes the cached compiled code.
	///
	/// This function always returns `true` unless the version of LuaJIT being used was compiled without the JIT compiler.
	#[inline]
	pub fn jit_set_engine(&self, mode: impl Into<JITMode>) -> bool {
		self.jit_set_mode(0, ffi::LUAJIT_MODE_ENGINE | mode.into())
	}

	/// Sets JIT compilation on or off, or flushes already compiled code, for the specified functions.
	///
	/// If `to_self` is `true`, the function at the given `index` will be affected.
	/// If `to_subs` is `true`, the *sub-functions* of the function at the given `index` will be affected.
	///
	/// If `index` is `0`, the function that called the currently running [`CFunction`] will be used in the above cases.
	///
	/// *(This function only applies to Lua functions, as [`CFunction`]s cannot be JIT compiled.)*
	///
	/// This function will return `true` if at least one function was affected, `false` otherwise.
	/// If the version of LuaJIT being used was compiled without the JIT compiler no function can be affected.
	///
	/// # Panics
	///
	/// Panics if `index` is out of bounds.
	///
	/// [`CFunction`]: ./type.CFunction.html
	#[inline]
	pub fn jit_set_function(&self, index: i32, mode: impl Into<JITMode>, to_self: bool, to_subs: bool) -> bool {
		self.jit_set_mode(index, match (to_self, to_subs) {
			(true, false) => ffi::LUAJIT_MODE_FUNC,
			(true, true) => ffi::LUAJIT_MODE_ALLFUNC,
			(false, true) => ffi::LUAJIT_MODE_ALLSUBFUNC,
			(false, false) => return false,
		} | mode.into())
	}

	/// Flushes the given root `trace` and all of its side traces from the cache.
	///
	/// The code for the trace will be retained as long as there are any other traces which link to it.
	#[inline]
	pub fn jit_flush_trace(&self, trace: u32) {
		self.jit_set_mode(trace.cast_signed(), ffi::LUAJIT_MODE_TRACE | JITMode::Flush);
	}
}