Skip to content

Commit

Permalink
add vector support
Browse files Browse the repository at this point in the history
  • Loading branch information
bjcscat committed Dec 6, 2024
1 parent ec3d0f9 commit cfc3fb9
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 11 deletions.
4 changes: 4 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ fn do_cfg(config: &mut Config) {
// maximum number of captures supported by pattern matching
define_lua_cfg!(config, "LUA_MAXCAPTURES", "32");

#[cfg(not(feature="luau_vector4"))]
define_lua_cfg!(config, "LUA_VECTOR_SIZE", "3");

#[cfg(feature="luau_vector4")]
define_lua_cfg!(config, "LUA_VECTOR_SIZE", "4");
}

fn main() {
Expand Down
2 changes: 2 additions & 0 deletions src/ffi/luau.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub const fn lua_ispseudo(i: c_int) -> bool {

// thread status; 0 is OK
#[repr(C)]
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub enum LuauStatus {
/// OK status
Expand Down Expand Up @@ -1050,6 +1051,7 @@ pub unsafe fn lua_tostring(state: *mut _LuaState, i: c_int) -> *const c_char {
lua_tolstring(state, i, null_mut())
}

#[macro_export]
macro_rules! lua_pushformat {
($state:expr, $fmt:expr, $($args:tt)*) => {
let string = std::fmt::format(format_args!($fmt, $($args)*));
Expand Down
95 changes: 84 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use ffi::{
prelude::*,
};
use memory::{luau_alloc_cb, DefaultLuauAllocator};
use threads::{LuauThread, MainStateDeadError};
use threads::LuauThread;
use userdata::{
drop_userdata, dtor_rs_luau_userdata_callback, Userdata, UserdataBorrowError, UserdataRef,
UserdataRefMut, UD_TAG,
Expand Down Expand Up @@ -176,26 +176,22 @@ impl Luau {
}

/// Yields the luau state with the number of results
///
///
/// Should be used as the end expression or a return from a function as this returns `-1`
pub fn yield_luau(&self, nresults: c_int) -> c_int {
assert!(
self.top() >= nresults,
"The number of yield returns must not exceed the stack size"
);

unsafe {
lua_yield(self.state, nresults)
}
unsafe { lua_yield(self.state, nresults) }
}

/// Breaks the luau state for the purposes of a debug interrupt
///
///
/// Should be used as the end expression or a return from a function as this returns `-1`
pub fn break_luau(&self) -> c_int {
unsafe {
lua_break(self.state)
}
unsafe { lua_break(self.state) }
}

/// Returns the type of a luau value at `idx`
Expand Down Expand Up @@ -277,6 +273,26 @@ impl Luau {
}
}

pub fn check_args(&self, count: c_int, extra_message: Option<&str>) {
if self.top() >= count {
return;
}

unsafe {
luaL_argerrorL(
self.state,
count - self.top(),
extra_message
.map(|v| {
let cstr =
CString::new(v).expect("extra_message should not contain a null byte");
cstr.as_ptr()
})
.unwrap_or(null()),
);
}
}

/// Returns true if the value at `idx` is nil
pub fn is_nil(&self, idx: c_int) -> bool {
self.type_of(idx) == LuauType::LUA_TNIL
Expand Down Expand Up @@ -747,10 +763,42 @@ impl Luau {
}
}

/// Returns true if the value at idx is a vector, false otherwise
pub fn is_vector(&self, idx: c_int) -> bool {
self.type_of(idx) == LuauType::LUA_TVECTOR
}

/// Pushes a vector to the Luau stack
pub fn push_vector(&self, x: f32, y: f32, z: f32, #[cfg(feature = "luau_vector4")] w: f32) {
luau_stack_precondition!(self.check_stack(1));

// SAFETY: stack size is validated by precondition
unsafe {
#[cfg(not(feature = "luau_vector4"))]
lua_pushvector(self.state, x, y, z);
#[cfg(feature = "luau_vector4")]
lua_pushvector(self.state, x, y, z, w);
}
}

#[cfg(not(feature = "luau_vector4"))]
/// Returns the value of a vector if the value at idx is a vector or will return None
pub fn to_vector(&self, idx: c_int) -> Option<(f32, f32, f32)> {
luau_stack_precondition!(self.check_index(idx));
unsafe {
Option::from(lua_tovector(self.state, idx)).map(|ptr| (*ptr, *ptr.add(1), *ptr.add(2)))
}
}

#[cfg(feature = "luau_vector4")]
/// Returns the value of a vector if the value at idx is a vector or will return None
pub fn to_vector(&self, idx: c_int) -> Option<(f32, f32, f32, f32)> {
luau_stack_precondition!(self.check_index(idx));
unsafe {
Option::from(lua_tovector(self.state, idx)).map(|ptr| (*ptr, *ptr.add(1), *ptr.add(2), *ptr.add(3)))
}
}

/// Returns true if the value at `idx` is a thread, false otherwise
pub fn is_thread(&self, idx: c_int) -> bool {
self.type_of(idx) == LuauType::LUA_TTHREAD
Expand Down Expand Up @@ -781,7 +829,9 @@ impl Luau {
/// Resumes the given Luau thread with the number of arguments.
///
/// Will resume the function on the top of the given Luau thread's execution stack
pub fn resume(&self, luau_thread: LuauThread, nargs: c_int) -> LuauStatus {
pub fn resume(&self, luau_thread: &LuauThread, nargs: c_int) -> LuauStatus {
assert!(luau_thread.get_state().is_function(-1));

unsafe { lua_resume(luau_thread.get_state().state, self.state, nargs) }
}

Expand Down Expand Up @@ -1051,6 +1101,7 @@ mod tests {
use crate::{
Luau, LuauAllocator, _LuaState, lua_error, lua_tonumber, lua_upvalueindex,
userdata::{UserdataBorrowError, UserdataRef},
LuauStatus,
};

#[test]
Expand Down Expand Up @@ -1206,7 +1257,7 @@ mod tests {
0,
);

luau.resume(thread, 0);
luau.resume(&thread, 0);

assert!(was_called, "Expected thread function to be called");
}
Expand Down Expand Up @@ -1309,6 +1360,28 @@ mod tests {
// todo!();
// }

#[test]
fn function_check() {
let luau = Luau::default();

luau.push_function(
|l| {
l.check_args(1, None);

0
},
None,
0,
);

let status = luau.call(0, 0);

assert!(
matches!(status, LuauStatus::LUA_ERRRUN),
"Expected there to be a runtime error."
);
}

#[test]
fn userdata_borrow() {
let luau = Luau::default();
Expand Down

0 comments on commit cfc3fb9

Please sign in to comment.