lunka 0.12.0

Pretty thin bindings to Lua 5.4
Documentation
//! Representing enum values with strings in Lua.

use core::ffi::c_int;
use lunka::prelude::*;

pub unsafe trait LuaEnum<const N: usize> {
	const OPTIONS: &'static lunka::AuxOptions<'static, N>;
	unsafe fn from_index_unchecked(index: usize) -> Self;
}

#[derive(Debug)]
enum SocketKind {
	Udp,
	Tcp,
	UnixUdp,
	UnixTcp,
}

unsafe impl LuaEnum<4> for SocketKind {
	const OPTIONS: &'static LuaAuxOptions<'static, 4> = &LuaAuxOptions::new([
		c"udp",
		c"tcp",
		c"unix udp",
		c"unix tcp",
	]);
	unsafe fn from_index_unchecked(index: usize) -> Self {
		match index {
			0 => Self::Udp,
			1 => Self::Tcp,
			2 => Self::UnixUdp,
			3 => Self::UnixTcp,
			_ => ::core::hint::unreachable_unchecked(),
		}
	}
}

trait ThreadExt {
	fn check_enum<E: LuaEnum<N>, const N: usize>(&self, arg: c_int) -> E;
}

impl ThreadExt for LuaThread {
	fn check_enum<E: LuaEnum<N>, const N: usize>(&self, arg: c_int) -> E {
		let index = self.check_option(arg, None, E::OPTIONS);
		unsafe { E::from_index_unchecked(index) }
	}
}

unsafe extern "C-unwind" fn l_test(l: *mut LuaState) -> c_int {
	let lua = unsafe { LuaThread::from_ptr(l) };
	let socket_kind: SocketKind = lua.check_enum(1);
	println!("socket kind: {socket_kind:?}");
	0
}

unsafe extern "C-unwind" fn l_main(l: *mut LuaState) -> c_int {
	let lua = unsafe { LuaThread::from_ptr_mut(l) };
	let mut test = move |variant: &[u8]| {
		lua.run_managed(move |mut mg| {
			mg.push_c_function(l_test);
			mg.push_string(variant);
			unsafe { mg.call(1, 0) }
		})
	};
	test(b"udp");
	test(b"tcp");
	test(b"unix udp");
	test(b"unix tcp");
	test(b"invalid");
	0
}

fn main() {
	let mut lua = Lua::new();
	let did_run_ok = lua.run_managed(move |mut mg| {
		mg.push_c_function(l_main);
		unsafe { mg.pcall(0, 1, 0).is_ok() }
	});
	assert!(!did_run_ok, "test code should fail");
}