From 27e250daa5196b3153ee2901f20e07bc985f57c4 Mon Sep 17 00:00:00 2001 From: qwreey Date: Fri, 18 Oct 2024 06:12:53 +0000 Subject: [PATCH] Implememt CVoid, StringifyData and CopyData (#243) --- crates/lune-std-ffi/README.md | 6 + crates/lune-std-ffi/src/c/arr_info.rs | 18 ++- crates/lune-std-ffi/src/c/helper.rs | 121 ++++++++++++++++--- crates/lune-std-ffi/src/c/mod.rs | 1 + crates/lune-std-ffi/src/c/ptr_info.rs | 30 +++-- crates/lune-std-ffi/src/c/struct_info.rs | 102 +++++++++------- crates/lune-std-ffi/src/c/type_info.rs | 2 + crates/lune-std-ffi/src/c/types/f32.rs | 21 +++- crates/lune-std-ffi/src/c/types/f64.rs | 21 +++- crates/lune-std-ffi/src/c/types/i128.rs | 21 +++- crates/lune-std-ffi/src/c/types/i16.rs | 21 +++- crates/lune-std-ffi/src/c/types/i32.rs | 21 +++- crates/lune-std-ffi/src/c/types/i64.rs | 21 +++- crates/lune-std-ffi/src/c/types/i8.rs | 21 +++- crates/lune-std-ffi/src/c/types/isize.rs | 25 +++- crates/lune-std-ffi/src/c/types/u128.rs | 21 +++- crates/lune-std-ffi/src/c/types/u16.rs | 21 +++- crates/lune-std-ffi/src/c/types/u32.rs | 21 +++- crates/lune-std-ffi/src/c/types/u64.rs | 21 +++- crates/lune-std-ffi/src/c/types/u8.rs | 21 +++- crates/lune-std-ffi/src/c/types/usize.rs | 25 +++- crates/lune-std-ffi/src/c/void_info.rs | 25 +++- crates/lune-std-ffi/src/data/closure_data.rs | 15 +-- crates/lune-std-ffi/src/ffi/libffi_helper.rs | 11 ++ crates/lune-std-ffi/src/ffi/mod.rs | 18 +++ types/ffi.luau | 3 +- 26 files changed, 549 insertions(+), 105 deletions(-) diff --git a/crates/lune-std-ffi/README.md b/crates/lune-std-ffi/README.md index 05a98ee..192f298 100644 --- a/crates/lune-std-ffi/README.md +++ b/crates/lune-std-ffi/README.md @@ -90,3 +90,9 @@ Add `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` ` Add bor band and such bit-related operation > Luau only supports 32bit bit operations + +wchar and wstring support + +string(null ending) / buffer support + +void support diff --git a/crates/lune-std-ffi/src/c/arr_info.rs b/crates/lune-std-ffi/src/c/arr_info.rs index 759661b..59dce1a 100644 --- a/crates/lune-std-ffi/src/c/arr_info.rs +++ b/crates/lune-std-ffi/src/c/arr_info.rs @@ -59,7 +59,7 @@ impl CArrInfo { self.length } - pub fn get_type(&self) -> Type { + pub fn get_middle_type(&self) -> Type { self.struct_type.clone() } @@ -87,7 +87,6 @@ impl FfiSize for CArrInfo { } } impl FfiConvert for CArrInfo { - // FIXME: FfiBox, FfiRef support required unsafe fn value_into_data<'lua>( &self, lua: &'lua Lua, @@ -132,6 +131,20 @@ impl FfiConvert for CArrInfo { } Ok(LuaValue::Table(table)) } + + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + dst.get_pointer() + .byte_offset(dst_offset) + .copy_from(src.get_pointer().byte_offset(src_offset), self.get_size()); + Ok(()) + } } impl LuaUserData for CArrInfo { @@ -157,6 +170,7 @@ impl LuaUserData for CArrInfo { method_provider::provide_box(methods); method_provider::provide_read_data(methods); method_provider::provide_write_data(methods); + method_provider::provide_copy_data(methods); methods.add_method("offset", |_, this, offset: isize| { if this.length > (offset as usize) && offset >= 0 { diff --git a/crates/lune-std-ffi/src/c/helper.rs b/crates/lune-std-ffi/src/c/helper.rs index e00fd05..8a22a5b 100644 --- a/crates/lune-std-ffi/src/c/helper.rs +++ b/crates/lune-std-ffi/src/c/helper.rs @@ -2,7 +2,7 @@ use libffi::middle::Type; use lune_utils::fmt::{pretty_format_value, ValueFormatConfig}; use mlua::prelude::*; -use super::{ctype_helper, CArrInfo, CFnInfo, CPtrInfo, CStructInfo}; +use super::{ctype_helper, void_info::CVoidInfo, CArrInfo, CFnInfo, CPtrInfo, CStructInfo}; use crate::{ data::{BoxData, GetFfiData}, ffi::{FfiConvert, FfiSize}, @@ -84,17 +84,104 @@ pub mod method_provider { ); } + pub fn provide_copy_data<'lua, Target, M>(methods: &mut M) + where + Target: FfiSize + FfiConvert, + M: LuaUserDataMethods<'lua, Target>, + { + methods.add_method( + "copyData", + |lua, + this, + (dst, src, dst_offset, src_offset): ( + LuaAnyUserData, + LuaAnyUserData, + Option, + Option, + )| { + let dst_offset = dst_offset.unwrap_or(0); + let src_offset = src_offset.unwrap_or(0); + + let dst = &dst.get_ffi_data()?; + // use or functions + if !dst.check_boundary(dst_offset, this.get_size()) { + return Err(LuaError::external("Out of bounds")); + } + if !dst.is_writable() { + return Err(LuaError::external("Unwritable data handle")); + } + + let src = &src.get_ffi_data()?; + if !src.check_boundary(dst_offset, this.get_size()) { + return Err(LuaError::external("Out of bounds")); + } + if !src.is_readable() { + return Err(LuaError::external("Unreadable value data handle")); + } + + unsafe { this.copy_data(lua, dst_offset, src_offset, dst, src) } + }, + ); + } + + pub fn provide_stringify_data<'lua, Target, M>(methods: &mut M) + where + Target: FfiSize + FfiConvert, + M: LuaUserDataMethods<'lua, Target>, + { + methods.add_method( + "stringifyData", + |lua, this, (target, offset): (LuaAnyUserData, Option)| unsafe { + this.stringify_data(lua, offset.unwrap_or(0), &target.get_ffi_data()?) + }, + ); + } + pub fn provide_box<'lua, Target, M>(methods: &mut M) where Target: FfiSize + FfiConvert, M: LuaUserDataMethods<'lua, Target>, { - methods.add_method("box", |lua, this, table: LuaValue| { + methods.add_method("box", |lua, this, value: LuaValue| { let result = lua.create_userdata(BoxData::new(this.get_size()))?; - unsafe { this.value_into_data(lua, 0, &result.get_ffi_data()?, table)? }; + unsafe { this.value_into_data(lua, 0, &result.get_ffi_data()?, value)? }; Ok(result) }); } + + // FIXME: Buffer support should be part of another PR + // pub fn provide_write_buffer<'lua, Target, M>(methods: &mut M) + // where + // Target: FfiSize + FfiConvert, + // M: LuaUserDataMethods<'lua, Target>, + // { + // methods.add_method( + // "writeBuffer", + // |lua, this, (target, value, offset): (LuaValue, LuaValue, Option)| { + // if !target.is_buffer() { + // return Err(LuaError::external(format!( + // "Argument target must be a buffer, got {}", + // target.type_name() + // ))); + // } + + // target.to_pointer() + // target.as_userdata().unwrap().to_pointer() + // let offset = offset.unwrap_or(0); + + // let data_handle = &target.get_ffi_data()?; + // // use or functions + // if !data_handle.check_boundary(offset, this.get_size()) { + // return Err(LuaError::external("Out of bounds")); + // } + // if !data_handle.is_writable() { + // return Err(LuaError::external("Unwritable data handle")); + // } + + // unsafe { this.value_into_data(lua, offset, data_handle, value) } + // }, + // ); + // } } pub fn get_userdata(value: LuaValue) -> LuaResult { @@ -143,28 +230,32 @@ pub unsafe fn get_conv_list(table: &LuaTable) -> LuaResult LuaResult { - if this.is::() { - Ok(this.borrow::()?.get_size()) - } else if this.is::() { - Ok(this.borrow::()?.get_size()) - } else if this.is::() { - Ok(this.borrow::()?.get_size()) +pub fn get_size(userdata: &LuaAnyUserData) -> LuaResult { + if userdata.is::() { + Ok(userdata.borrow::()?.get_size()) + } else if userdata.is::() { + Ok(userdata.borrow::()?.get_size()) + } else if userdata.is::() { + Ok(userdata.borrow::()?.get_size()) + } else if userdata.is::() { + Ok(userdata.borrow::()?.get_size()) } else { - ctype_helper::get_size(this) + ctype_helper::get_size(userdata) } } // get libffi_type from any c-type userdata pub fn get_middle_type(userdata: &LuaAnyUserData) -> LuaResult { if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) + Ok(userdata.borrow::()?.get_middle_type()) } else if let Some(middle_type) = ctype_helper::get_middle_type(userdata)? { Ok(middle_type) } else if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) + Ok(userdata.borrow::()?.get_middle_type()) } else if userdata.is::() { - Ok(CPtrInfo::get_type()) + Ok(CPtrInfo::get_middle_type()) + } else if userdata.is::() { + Ok(CVoidInfo::get_middle_type()) } else { Err(LuaError::external(format!( "Unexpected field. CStruct, CType, CString or CArr is required for element but got {}", @@ -210,6 +301,8 @@ pub fn get_tag_name(userdata: &LuaAnyUserData) -> LuaResult { String::from("CPtr") } else if userdata.is::() { String::from("CFn") + } else if userdata.is::() { + String::from("CVoid") } else if ctype_helper::is_ctype(userdata) { String::from("CType") } else { diff --git a/crates/lune-std-ffi/src/c/mod.rs b/crates/lune-std-ffi/src/c/mod.rs index ad5b8f1..c2cdbc3 100644 --- a/crates/lune-std-ffi/src/c/mod.rs +++ b/crates/lune-std-ffi/src/c/mod.rs @@ -5,6 +5,7 @@ mod ptr_info; mod struct_info; mod type_info; mod types; +mod void_info; pub use self::{ arr_info::CArrInfo, diff --git a/crates/lune-std-ffi/src/c/ptr_info.rs b/crates/lune-std-ffi/src/c/ptr_info.rs index 519b922..603c63f 100644 --- a/crates/lune-std-ffi/src/c/ptr_info.rs +++ b/crates/lune-std-ffi/src/c/ptr_info.rs @@ -45,21 +45,10 @@ impl FfiConvert for CPtrInfo { let value_userdata = value .as_userdata() .ok_or_else(|| LuaError::external("CPtrInfo:writeRef only allows data"))?; - - data_handle - .check_boundary(offset, self.get_size()) - .then_some(()) - .ok_or_else(|| LuaError::external("Out of bounds"))?; - data_handle - .is_writable() - .then_some(()) - .ok_or_else(|| LuaError::external("Unwritable data handle"))?; - *data_handle .get_pointer() .byte_offset(offset) .cast::<*mut ()>() = value_userdata.get_ffi_data()?.get_pointer(); - Ok(()) } @@ -70,10 +59,6 @@ impl FfiConvert for CPtrInfo { offset: isize, data_handle: &Ref, ) -> LuaResult> { - if !data_handle.check_boundary(offset, SIZE_OF_POINTER) { - return Err(LuaError::external("Out of bounds")); - } - Ok(LuaValue::UserData(lua.create_userdata(RefData::new( unsafe { data_handle.get_pointer().byte_offset(offset) }, if self.inner_is_cptr { @@ -84,6 +69,19 @@ impl FfiConvert for CPtrInfo { RefBounds::new(0, self.inner_size), ))?)) } + + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::<*mut ()>() = + src.get_pointer().byte_offset(src_offset); + Ok(()) + } } impl CPtrInfo { @@ -118,7 +116,7 @@ impl CPtrInfo { } // Return void* - pub fn get_type() -> Type { + pub fn get_middle_type() -> Type { Type::pointer() } } diff --git a/crates/lune-std-ffi/src/c/struct_info.rs b/crates/lune-std-ffi/src/c/struct_info.rs index 836dbe3..9430a2f 100644 --- a/crates/lune-std-ffi/src/c/struct_info.rs +++ b/crates/lune-std-ffi/src/c/struct_info.rs @@ -1,11 +1,11 @@ use std::{cell::Ref, vec::Vec}; -use libffi::{low, middle::Type, raw}; +use libffi::{low, middle::Type, raw::ffi_get_struct_offsets}; use mlua::prelude::*; use super::{association_names::CSTRUCT_INNER, helper, method_provider}; use crate::ffi::{ - association, libffi_helper::FFI_STATUS_NAMES, FfiConvert, FfiData, FfiSignedness, FfiSize, + association, libffi_helper::ffi_status_assert, FfiConvert, FfiData, FfiSignedness, FfiSize, }; pub struct CStructInfo { @@ -15,6 +15,21 @@ pub struct CStructInfo { inner_conv_list: Vec<*const dyn FfiConvert>, } +fn get_field_table<'lua>( + lua: &'lua Lua, + userdata: &LuaAnyUserData<'lua>, +) -> LuaResult> { + let value = association::get(lua, CSTRUCT_INNER, userdata)? + .ok_or_else(|| LuaError::external("Failed to get inner field table. not found"))?; + if let LuaValue::Table(table) = value { + Ok(table) + } else { + Err(LuaError::external( + "Failed to get inner field table. not a table", + )) + } +} + impl CStructInfo { pub fn new(fields: Vec, inner_conv_list: Vec<*const dyn FfiConvert>) -> LuaResult { let len = fields.len(); @@ -23,17 +38,11 @@ impl CStructInfo { // Get field offsets with ffi_get_struct_offsets unsafe { - let offset_result: raw::ffi_status = raw::ffi_get_struct_offsets( + ffi_status_assert(ffi_get_struct_offsets( low::ffi_abi_FFI_DEFAULT_ABI, middle_type.as_raw_ptr(), inner_offset_list.as_mut_ptr(), - ); - if offset_result != raw::ffi_status_FFI_OK { - return Err(LuaError::external(format!( - "ffi_get_struct_offsets failed. expected result {}, got {}", - FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[offset_result as usize] - ))); - } + ))?; inner_offset_list.set_len(len); } @@ -50,7 +59,7 @@ impl CStructInfo { }) } - // Create new CStruct UserData with LuaTable. + // Create new CStruct UserData from LuaTable. // Lock and hold table for .inner ref pub fn from_table<'lua>( lua: &'lua Lua, @@ -60,7 +69,6 @@ impl CStructInfo { .create_userdata(Self::new(helper::get_middle_type_list(&table)?, unsafe { helper::get_conv_list(&table)? })?)?; - table.set_readonly(true); association::set(lua, CSTRUCT_INNER, &cstruct, table)?; Ok(cstruct) @@ -69,24 +77,20 @@ impl CStructInfo { // Stringify cstruct for pretty printing like: // pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult { - if let LuaValue::Table(fields) = association::get(lua, CSTRUCT_INNER, userdata)? - .ok_or_else(|| LuaError::external("Field table not found"))? - { - let mut result = String::from(" "); - for i in 0..fields.raw_len() { - let child: LuaAnyUserData = fields.raw_get(i + 1)?; - let pretty_formatted = helper::pretty_format(lua, &child)?; - result.push_str(format!("{pretty_formatted}, ").as_str()); - } + let fields = get_field_table(lua, userdata)?; + let mut stringified = String::from(" "); - // size of - result.push_str( - format!("size = {} ", userdata.borrow::()?.get_size()).as_str(), - ); - Ok(result) - } else { - Err(LuaError::external("failed to get inner type table.")) + // children + for i in 0..fields.raw_len() { + let child: LuaAnyUserData = fields.raw_get(i + 1)?; + let pretty_formatted = helper::pretty_format(lua, &child)?; + stringified.push_str(format!("{pretty_formatted}, ").as_str()); } + + // size of + stringified + .push_str(format!("size = {} ", userdata.borrow::()?.get_size()).as_str()); + Ok(stringified) } // Get byte offset of nth field @@ -99,7 +103,7 @@ impl CStructInfo { Ok(offset) } - pub fn get_type(&self) -> Type { + pub fn get_middle_type(&self) -> Type { self.middle_type.clone() } } @@ -128,7 +132,6 @@ impl FfiConvert for CStructInfo { for (index, conv) in self.inner_conv_list.iter().enumerate() { let field_offset = self.offset(index)? as isize; let data: LuaValue = table.get(index + 1)?; - conv.as_ref().unwrap().value_into_data( lua, field_offset + offset, @@ -157,6 +160,19 @@ impl FfiConvert for CStructInfo { } Ok(LuaValue::Table(table)) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + dst.get_pointer() + .byte_offset(dst_offset) + .copy_from(src.get_pointer().byte_offset(src_offset), self.get_size()); + Ok(()) + } } impl LuaUserData for CStructInfo { @@ -175,22 +191,16 @@ impl LuaUserData for CStructInfo { method_provider::provide_box(methods); method_provider::provide_read_data(methods); method_provider::provide_write_data(methods); + method_provider::provide_copy_data(methods); - methods.add_method("offset", |_, this, index: usize| { - let offset = this.offset(index)?; - Ok(offset) - }); - // Simply pass type in the locked table used when first creating this object. - // By referencing the table to struct, the types inside do not disappear - methods.add_function("field", |lua, (this, field): (LuaAnyUserData, usize)| { - if let LuaValue::Table(fields) = association::get(lua, CSTRUCT_INNER, this)? - .ok_or_else(|| LuaError::external("Field table not found"))? - { - let value: LuaValue = fields.raw_get(field + 1)?; - Ok(value) - } else { - Err(LuaError::external("Failed to read field table")) - } - }); + methods.add_method("offset", |_, this, index: usize| this.offset(index)); + // Get nth field type userdata + methods.add_function( + "field", + |lua, (this, field_index): (LuaAnyUserData, usize)| { + let field_table = get_field_table(lua, &this)?; + field_table.raw_get::<_, LuaAnyUserData>(field_index + 1) + }, + ); } } diff --git a/crates/lune-std-ffi/src/c/type_info.rs b/crates/lune-std-ffi/src/c/type_info.rs index e60e143..7e4b16d 100644 --- a/crates/lune-std-ffi/src/c/type_info.rs +++ b/crates/lune-std-ffi/src/c/type_info.rs @@ -108,6 +108,8 @@ where method_provider::provide_box(methods); method_provider::provide_read_data(methods); method_provider::provide_write_data(methods); + method_provider::provide_copy_data(methods); + method_provider::provide_stringify_data(methods); methods.add_function( "cast", diff --git a/crates/lune-std-ffi/src/c/types/f32.rs b/crates/lune-std-ffi/src/c/types/f32.rs index 434c981..00d06fb 100644 --- a/crates/lune-std-ffi/src/c/types/f32.rs +++ b/crates/lune-std-ffi/src/c/types/f32.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/f64.rs b/crates/lune-std-ffi/src/c/types/f64.rs index dd59a89..fafa98d 100644 --- a/crates/lune-std-ffi/src/c/types/f64.rs +++ b/crates/lune-std-ffi/src/c/types/f64.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/i128.rs b/crates/lune-std-ffi/src/c/types/i128.rs index 2c51f79..6069e74 100644 --- a/crates/lune-std-ffi/src/c/types/i128.rs +++ b/crates/lune-std-ffi/src/c/types/i128.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/i16.rs b/crates/lune-std-ffi/src/c/types/i16.rs index 077eb2a..a1c702a 100644 --- a/crates/lune-std-ffi/src/c/types/i16.rs +++ b/crates/lune-std-ffi/src/c/types/i16.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/i32.rs b/crates/lune-std-ffi/src/c/types/i32.rs index bfdf543..fa2b982 100644 --- a/crates/lune-std-ffi/src/c/types/i32.rs +++ b/crates/lune-std-ffi/src/c/types/i32.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/i64.rs b/crates/lune-std-ffi/src/c/types/i64.rs index 1dea347..f458f9c 100644 --- a/crates/lune-std-ffi/src/c/types/i64.rs +++ b/crates/lune-std-ffi/src/c/types/i64.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/i8.rs b/crates/lune-std-ffi/src/c/types/i8.rs index 6ac64ff..5f902cd 100644 --- a/crates/lune-std-ffi/src/c/types/i8.rs +++ b/crates/lune-std-ffi/src/c/types/i8.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -49,4 +48,24 @@ impl FfiConvert for CTypeInfo { unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/isize.rs b/crates/lune-std-ffi/src/c/types/isize.rs index d1fda6c..6e1ef6c 100644 --- a/crates/lune-std-ffi/src/c/types/isize.rs +++ b/crates/lune-std-ffi/src/c/types/isize.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -61,4 +60,28 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle + .get_pointer() + .byte_offset(offset) + .cast::()) + .to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/u128.rs b/crates/lune-std-ffi/src/c/types/u128.rs index a22ce8f..12b0652 100644 --- a/crates/lune-std-ffi/src/c/types/u128.rs +++ b/crates/lune-std-ffi/src/c/types/u128.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/u16.rs b/crates/lune-std-ffi/src/c/types/u16.rs index c6946c6..fd51298 100644 --- a/crates/lune-std-ffi/src/c/types/u16.rs +++ b/crates/lune-std-ffi/src/c/types/u16.rs @@ -19,7 +19,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -55,4 +54,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/u32.rs b/crates/lune-std-ffi/src/c/types/u32.rs index b63b67f..d28d310 100644 --- a/crates/lune-std-ffi/src/c/types/u32.rs +++ b/crates/lune-std-ffi/src/c/types/u32.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/u64.rs b/crates/lune-std-ffi/src/c/types/u64.rs index ff90b76..2ef7afc 100644 --- a/crates/lune-std-ffi/src/c/types/u64.rs +++ b/crates/lune-std-ffi/src/c/types/u64.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -54,4 +53,24 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/u8.rs b/crates/lune-std-ffi/src/c/types/u8.rs index 3278579..ad6436f 100644 --- a/crates/lune-std-ffi/src/c/types/u8.rs +++ b/crates/lune-std-ffi/src/c/types/u8.rs @@ -19,7 +19,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -52,4 +51,24 @@ impl FfiConvert for CTypeInfo { unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/types/usize.rs b/crates/lune-std-ffi/src/c/types/usize.rs index 1d7d0f4..007c3ca 100644 --- a/crates/lune-std-ffi/src/c/types/usize.rs +++ b/crates/lune-std-ffi/src/c/types/usize.rs @@ -18,7 +18,6 @@ impl FfiConvert for CTypeInfo { unsafe fn value_into_data<'lua>( &self, _lua: &'lua Lua, - // _type_userdata: &LuaAnyUserData<'lua>, offset: isize, data_handle: &Ref, value: LuaValue<'lua>, @@ -61,4 +60,28 @@ impl FfiConvert for CTypeInfo { }; Ok(value) } + unsafe fn copy_data( + &self, + _lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()> { + *dst.get_pointer().byte_offset(dst_offset).cast::() = + *src.get_pointer().byte_offset(src_offset).cast::(); + Ok(()) + } + unsafe fn stringify_data( + &self, + _lua: &Lua, + offset: isize, + data_handle: &Ref, + ) -> LuaResult { + Ok((*data_handle + .get_pointer() + .byte_offset(offset) + .cast::()) + .to_string()) + } } diff --git a/crates/lune-std-ffi/src/c/void_info.rs b/crates/lune-std-ffi/src/c/void_info.rs index b1e6fcb..6d70081 100644 --- a/crates/lune-std-ffi/src/c/void_info.rs +++ b/crates/lune-std-ffi/src/c/void_info.rs @@ -1 +1,24 @@ -use core::ffi::c_void; +use libffi::middle::Type; +use mlua::prelude::*; + +use crate::ffi::{FfiSignedness, FfiSize}; + +pub struct CVoidInfo(); + +impl FfiSignedness for CVoidInfo { + fn get_signedness(&self) -> bool { + false + } +} +impl FfiSize for CVoidInfo { + fn get_size(&self) -> usize { + 0 + } +} +impl CVoidInfo { + pub fn get_middle_type() -> Type { + Type::void() + } +} + +impl LuaUserData for CVoidInfo {} diff --git a/crates/lune-std-ffi/src/data/closure_data.rs b/crates/lune-std-ffi/src/data/closure_data.rs index 93eece3..e05e961 100644 --- a/crates/lune-std-ffi/src/data/closure_data.rs +++ b/crates/lune-std-ffi/src/data/closure_data.rs @@ -9,7 +9,7 @@ use mlua::prelude::*; use super::ref_data::{RefBounds, RefData, RefFlag}; use crate::ffi::{ - libffi_helper::{FFI_STATUS_NAMES, SIZE_OF_POINTER}, + libffi_helper::{ffi_status_assert, SIZE_OF_POINTER}, FfiArg, FfiData, FfiResult, }; @@ -97,7 +97,7 @@ impl ClosureData { func, }; - let prep_result = unsafe { + ffi_status_assert(unsafe { ffi_prep_closure_loc( closure, cif, @@ -105,16 +105,9 @@ impl ClosureData { ptr::from_ref(&closure_data).cast::().cast_mut(), code.as_mut_ptr(), ) - }; + })?; - if prep_result != 0 { - Err(LuaError::external(format!( - "ffi_get_struct_offsets failed. expected result {}, got {}", - FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[prep_result as usize] - ))) - } else { - Ok(closure_data) - } + Ok(closure_data) } } diff --git a/crates/lune-std-ffi/src/ffi/libffi_helper.rs b/crates/lune-std-ffi/src/ffi/libffi_helper.rs index fc93d04..04d764d 100644 --- a/crates/lune-std-ffi/src/ffi/libffi_helper.rs +++ b/crates/lune-std-ffi/src/ffi/libffi_helper.rs @@ -35,3 +35,14 @@ pub const FFI_STATUS_NAMES: [&str; 4] = [ "ffi_status_FFI_BAD_ABI", "ffi_status_FFI_BAD_ARGTYPE", ]; + +pub fn ffi_status_assert(result: raw::ffi_status) -> LuaResult<()> { + if result == raw::ffi_status_FFI_OK { + Ok(()) + } else { + Err(LuaError::external(format!( + "ffi_status assertion failed. expected result {}, got {}", + FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[result as usize] + ))) + } +} diff --git a/crates/lune-std-ffi/src/ffi/mod.rs b/crates/lune-std-ffi/src/ffi/mod.rs index bebe31f..5144bbd 100644 --- a/crates/lune-std-ffi/src/ffi/mod.rs +++ b/crates/lune-std-ffi/src/ffi/mod.rs @@ -37,6 +37,24 @@ pub trait FfiConvert { offset: isize, data_handle: &Ref, ) -> LuaResult>; + + unsafe fn copy_data( + &self, + lua: &Lua, + dst_offset: isize, + src_offset: isize, + dst: &Ref, + src: &Ref, + ) -> LuaResult<()>; + + unsafe fn stringify_data( + &self, + _lua: &Lua, + _offset: isize, + _data_handle: &Ref, + ) -> LuaResult { + Err(LuaError::external("stringify not implemented")) + } } pub trait FfiData { diff --git a/types/ffi.luau b/types/ffi.luau index 9c890e1..80927a1 100644 --- a/types/ffi.luau +++ b/types/ffi.luau @@ -11,6 +11,7 @@ export type CTypeInfo = { box: (self: CTypeInfo, val: R) -> Box, readData: (self: CTypeInfo, target: (Ref|Box), offset: number?) -> R, writeData: (self: CTypeInfo, target: (Ref|Box), value: R, offset: number?) -> (), + stringifyData: (self: CTypeInfo, target: (Ref|Box), offset: number?) -> string, -- FIXME: recursive types; 'intoType' should be CTypes cast: (self: CTypeInfo, intoType: any, fromData: (Ref|Box), intoData: (Ref|Box)) -> (), @@ -27,7 +28,6 @@ export type CPtrInfo = { readRef: (self: CPtrInfo, target: (Ref|Box), offset: number?) -> Ref, writeRef: (self: CPtrInfo, target: (Ref|Box), value: (Ref|Box), offset: number?) -> (), - } export type CArrInfo = { @@ -42,6 +42,7 @@ export type CArrInfo = { box: (self: CArrInfo, table: { T }) -> Box, readData: (self: CArrInfo, target: (Ref|Box), offset: number?) -> { T }, writeData: (self: CArrInfo, target: (Ref|Box), value: { T }, offset: number?) -> (), + copyData: (self: CArrInfo, dst: (Ref|Box), src: (Ref|Box), dst_offset: number?, src_offset: number?) -> (), offset: (self: CArrInfo, offset: number) -> number, }