use std::ffi::CStr;
use low_luajit::{AmountReturned, LuaState, LuaType, reg};
const NUM_VECTOR_TYPE_NAME: &CStr = c"numerical vector";
fn check_vec(lua: &LuaState) -> &Vec<f64> {
unsafe { lua.check_full_userdata::<Vec<f64>>(1, NUM_VECTOR_TYPE_NAME) }
}
fn check_vec_mut(lua: &mut LuaState) -> &mut Vec<f64> {
unsafe { lua.check_full_userdata::<Vec<f64>>(1, NUM_VECTOR_TYPE_NAME) }
}
extern "C-unwind" fn to_string(lua: LuaState) -> AmountReturned {
let vec = check_vec(&lua);
let string = format!("{vec:?}");
lua.return_string(string)
}
extern "C-unwind" fn push(mut lua: LuaState) -> AmountReturned {
let n = lua.check_number(2);
let vec = check_vec_mut(&mut lua);
vec.push(n);
lua.return_none()
}
extern "C-unwind" fn pop(mut lua: LuaState) -> AmountReturned {
let vec = check_vec_mut(&mut lua);
match vec.pop() {
Some(n) => lua.return_number(n),
None => lua.return_nil(),
}
}
extern "C-unwind" fn index(mut lua: LuaState) -> AmountReturned {
let vec = check_vec(&lua);
match lua.type_of(2) {
LuaType::String => {
lua.new_module(reg![push, pop]);
lua.insert(2);
lua.get_table(2);
},
LuaType::Number if let Some(n) = vec.get(lua.to_integer(2).cast_unsigned()) => lua.push_number(*n),
_ => lua.push_nil(),
}
lua.return_any(1)
}
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
extern "C-unwind" fn new_index(mut lua: LuaState) -> AmountReturned {
let i = lua.check_number(2);
let new = lua.check_number(3);
let vec = check_vec_mut(&mut lua);
let Some(value) = vec.get_mut(i as usize) else { lua.error(c"invalid index"); };
*value = new;
lua.return_none()
}
extern "C-unwind" fn constructor(mut lua: LuaState) -> AmountReturned {
let mut vec = Vec::new();
for i in 1..=lua.get_top() {
vec.push(lua.to_number(i));
}
lua.new_full_userdata::<Vec<f64>>(vec);
if lua.new_userdata_metatable(NUM_VECTOR_TYPE_NAME) {
unsafe { lua.set_drop_gc_metamethod::<Vec<f64>>(); }
lua.push_cfunction(to_string);
lua.set_field(-2, c"__tostring");
lua.push_cfunction(index);
lua.set_field(-2, c"__index");
lua.push_cfunction(new_index);
lua.set_field(-2, c"__newindex");
}
lua.set_metatable(-2);
lua.return_any(1)
}
#[unsafe(no_mangle)]
extern "C-unwind" fn luaopen_num_vector(lua: LuaState) -> AmountReturned {
lua.return_cfunction(constructor)
}