diff --git a/src/rust/iced-x86-lua/src/instr.rs b/src/rust/iced-x86-lua/src/instr.rs index 4063ded95..576e597ec 100644 --- a/src/rust/iced-x86-lua/src/instr.rs +++ b/src/rust/iced-x86-lua/src/instr.rs @@ -1323,14 +1323,7 @@ lua_pub_methods! { static INSTRUCTION_EXPORTS => /// ``` unsafe fn cpuid_features(lua, instr: &Instruction) -> 1 { let cpuid_features = instr.inner.cpuid_features(); - unsafe { - lua.create_table(cpuid_features.len() as c_int, 0); - for (i, &cpuid) in cpuid_features.iter().enumerate() { - lua.push(i + 1); - lua.push(cpuid as u32); - lua.raw_set(-3); - } - } + unsafe { lua.push_array(cpuid_features, |_, cpuid| *cpuid as u32); } } /// Control flow info (a `FlowControl` enum value) diff --git a/src/rust/iced-x86-lua/src/opci.rs b/src/rust/iced-x86-lua/src/opci.rs index 4d7e49325..e4f4e02f7 100644 --- a/src/rust/iced-x86-lua/src/opci.rs +++ b/src/rust/iced-x86-lua/src/opci.rs @@ -2,7 +2,6 @@ // Copyright (C) 2018-present iced project and contributors use crate::enum_utils::to_code; -use libc::c_int; use loona::lua_api::lua_CFunction; use loona::prelude::*; @@ -852,15 +851,8 @@ lua_pub_methods! { static OP_CODE_INFO_EXPORTS => /// Gets all operand kinds (a list of `OpCodeOperandKind` enum values) /// @returns integer[] # (`OpCodeOperandKind[]`) All operand kinds unsafe fn op_kinds(lua, opci: &OpCodeInfo) -> 1 { - unsafe { - let op_kinds = opci.inner.op_kinds(); - lua.create_table(op_kinds.len() as c_int, 0); - for (i, &op_kind) in op_kinds.iter().enumerate() { - lua.push(i + 1); - lua.push(op_kind as u32); - lua.raw_set(-3); - } - } + let op_kinds = opci.inner.op_kinds(); + unsafe { lua.push_array(op_kinds, |_, op_kind| *op_kind as u32); } } /// Checks if the instruction is available in 16-bit mode, 32-bit mode or 64-bit mode diff --git a/src/rust/loona/src/lua.rs b/src/rust/loona/src/lua.rs index e6f1eb9d9..583fe65ad 100644 --- a/src/rust/loona/src/lua.rs +++ b/src/rust/loona/src/lua.rs @@ -825,9 +825,9 @@ impl<'lua> Lua<'lua> { /// the Lua stack and then `read_elem()` is called. The callee should return the Rust value /// but not pop the Lua stack. #[inline] - pub unsafe fn read_array(&self, idx: c_int, read_elem: F) -> Vec + pub unsafe fn read_array(&self, idx: c_int, mut read_elem: F) -> Vec where - F: Fn(&Self) -> Result, + F: FnMut(&Self) -> Result, { unsafe { if !self.is_table(idx) { @@ -859,6 +859,45 @@ impl<'lua> Lua<'lua> { result } } + + /// Creates a new array and pushes it onto the Lua stack and initializes it with the input array + #[inline] + pub unsafe fn push_array(&self, elems: &[T], mut convert: F) + where + F: FnMut(&Self, &T) -> TNew, + { + unsafe { + self.create_table(elems.len() as c_int, 0); + for (i, value) in elems.iter().enumerate() { + let new_value = convert(self, value); + self.push(i + 1); + self.push(new_value); + self.raw_set(-3); + } + } + } + + /// Creates a new array and pushes it onto the Lua stack and initializes it with the input array + #[inline] + pub unsafe fn push_array2(&self, elems: &[T], mut push_value: F) + where + F: FnMut(&Self, &T), + { + unsafe { + self.create_table(elems.len() as c_int, 0); + for (i, value) in elems.iter().enumerate() { + self.push(i + 1); + + #[cfg(any(debug_assertions, feature = "extra_checks"))] + let _orig_top = self.get_top(); + push_value(self, value); + #[cfg(any(debug_assertions, feature = "extra_checks"))] + assert_eq!(1, self.get_top().wrapping_sub(_orig_top)); + + self.raw_set(-3); + } + } + } } // Simple wrappers calling the Lua C API