Refactor and documenting code structure (#243)

This commit is contained in:
qwreey 2024-10-17 10:16:43 +00:00
parent a2a8176241
commit da30dfb3f0
No known key found for this signature in database
GPG key ID: D28DB79297A214BD
48 changed files with 803 additions and 701 deletions

2
Cargo.lock generated
View file

@ -807,7 +807,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.72", "syn 2.0.79",
] ]
[[package]] [[package]]

View file

@ -0,0 +1,79 @@
# `lune-std-ffi`
## Code structure
### /c
Define C-ABI type information and provide conversion and casting
- [**Struct ` CArrInfo`:**](./src/c/struct_info.rs) Represents C Array type
- [**Struct ` CPtrInfo`:**](./src/c/ptr_info.rs) Represents C Pointer type
- [**Struct ` CFnInfo`:**](./src/c/fn_info.rs) Represents C Function signature
provide CallableData and ClosureData creation
- [**Struct ` CStructInfo`:**](./src/c/struct_info.rs) Represents C Struct type
- [**Struct ` CTypeInfo<T>`:**](./src/c/type_info.rs) Represents C type, extended in `/c/types`
#### /c/types
Export fixed-size source time known types and non-fixed compile time known types
Implememt type-casting for all CTypes
**Mod `ctype_helper`:**
- **Function `get_conv`:**
get _FfiConvert_ from some ctype userdata, used for struct and array conversion
- **Function `get_size`:**
get size from some ctype userdata, used for call return and arguments boundary checking
- **Function `get_name`:**
get type name from some ctype userdata, used for pretty-print
- **Function `get_middle_type`:**
get **`libffi::middle::Type`:** from some ctype userdata
- **Function `is_ctype`:** check userdata is ctype
---
### /data
**Structs:** Provide memory userdata
- [**Struct `BoxData`:**](./src/data/box_data/mod.rs) A heap allocated memory with user definable lifetime
- [**Struct `LibData`:**](./src/data/lib_data.rs) A dynamic opened library
- [**Struct `RefData`:**](./src/data/ref_data/mod.rs) A reference that can be used for receiving return data from external function or pass pointer arguments
**Structs:** Provide function(pointer) userdata
- [**Struct `CallableData`:**](./src/data/callable_data.rs) A callable function, which can be created from function pointer
- [**Struct `ClosureData`:**](./src/data/closure_data.rs) A closure pointer, which can be created from lua function and can be used for callback
---
### /ffi
**Traits:** Provide ABI shared common type information trait
- **Trait `FfiSize`**
- **Trait `FfiSignedness`**
- **Trait `FfiConvert`:** Provide read LuaValue from FfiData or write LuaValue into FfiData
**Trait `FfiData`:** Provide common data handle, including methods below
- **Method `check_boundary`:** check boundary with offset and size
- **Method `get_pointer`:** returns raw pointer `*mut ()`
- **Method `is_writable`**
- **Method `is_readable`**
> Note: `GetFfiData` trait in `data/mod.rs` provides `AnyUserData.get_data_handle() -> FfiData` method
**Mods:** Provide common helper functions
- **`association.rs`:** GC utility, used for inner, ret and arg type holding in subtype
- **`bit_mask.rs`:** u8 bitfield helper
- **`cast.rs`:** library
- **Function `num_cast<From, Into>(from: FfiData, from: FfiData)`:**
Cast number type value inno another number type
- **`libffi_helper.rs`:**
- **Const `FFI_STATUS_NAMES`:** Used for ffi_status stringify
- **Function `get_ensured_size`:** Returns ensured ffi_type size
- **Const `SIEE_OF_POINTER`:** Platform specific pointer size (Compile time known)
## TODO

View file

@ -3,12 +3,11 @@ use std::cell::Ref;
use libffi::middle::Type; use libffi::middle::Type;
use mlua::prelude::*; use mlua::prelude::*;
use super::{association_names::CARR_INNER, c_helper, method_provider}; use super::{association_names::CARR_INNER, helper, method_provider};
use crate::ffi::{ use crate::{
ffi_association::{get_association, set_association}, data::{FfiConvert, FfiData, FfiSize},
NativeConvert, NativeData, NativeSize, ffi::{association, libffi_helper::get_ensured_size},
}; };
use crate::libffi_helper::get_ensured_size;
// This is a series of some type. // This is a series of some type.
// It provides the final size and the offset of the index, // It provides the final size and the offset of the index,
@ -19,19 +18,19 @@ use crate::libffi_helper::get_ensured_size;
// We can simply provide array type with struct. // We can simply provide array type with struct.
// See: https://stackoverflow.com/a/43525176 // See: https://stackoverflow.com/a/43525176
pub struct CArr { pub struct CArrInfo {
struct_type: Type, struct_type: Type,
length: usize, length: usize,
size: usize, size: usize,
inner_size: usize, inner_size: usize,
inner_conv: *const dyn NativeConvert, inner_conv: *const dyn FfiConvert,
} }
impl CArr { impl CArrInfo {
pub fn new( pub fn new(
element_type: Type, element_type: Type,
length: usize, length: usize,
inner_conv: *const dyn NativeConvert, inner_conv: *const dyn FfiConvert,
) -> LuaResult<Self> { ) -> LuaResult<Self> {
let inner_size = get_ensured_size(element_type.as_raw_ptr())?; let inner_size = get_ensured_size(element_type.as_raw_ptr())?;
let struct_type = Type::structure(vec![element_type.clone(); length]); let struct_type = Type::structure(vec![element_type.clone(); length]);
@ -51,11 +50,11 @@ impl CArr {
type_userdata: &LuaAnyUserData<'lua>, type_userdata: &LuaAnyUserData<'lua>,
length: usize, length: usize,
) -> LuaResult<LuaAnyUserData<'lua>> { ) -> LuaResult<LuaAnyUserData<'lua>> {
let fields = c_helper::get_middle_type(type_userdata)?; let fields = helper::get_middle_type(type_userdata)?;
let conv = unsafe { c_helper::get_conv(type_userdata)? }; let conv = unsafe { helper::get_conv(type_userdata)? };
let carr = lua.create_userdata(Self::new(fields, length, conv)?)?; let carr = lua.create_userdata(Self::new(fields, length, conv)?)?;
set_association(lua, CARR_INNER, &carr, type_userdata)?; association::set(lua, CARR_INNER, &carr, type_userdata)?;
Ok(carr) Ok(carr)
} }
@ -70,13 +69,13 @@ impl CArr {
// Stringify for pretty printing like: // Stringify for pretty printing like:
// <CArr( u8, length = 8 )> // <CArr( u8, length = 8 )>
pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> { pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
let this = userdata.borrow::<CArr>()?; let this = userdata.borrow::<CArrInfo>()?;
if let Some(LuaValue::UserData(inner_userdata)) = if let Some(LuaValue::UserData(inner_userdata)) =
get_association(lua, CARR_INNER, userdata)? association::get(lua, CARR_INNER, userdata)?
{ {
Ok(format!( Ok(format!(
" {}, length = {} ", " {}, length = {} ",
c_helper::pretty_format(lua, &inner_userdata)?, helper::pretty_format(lua, &inner_userdata)?,
this.length, this.length,
)) ))
} else { } else {
@ -85,18 +84,18 @@ impl CArr {
} }
} }
impl NativeSize for CArr { impl FfiSize for CArrInfo {
fn get_size(&self) -> usize { fn get_size(&self) -> usize {
self.size self.size
} }
} }
impl NativeConvert for CArr { impl FfiConvert for CArrInfo {
// FIXME: FfiBox, FfiRef support required // FIXME: FfiBox, FfiRef support required
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let LuaValue::Table(ref table) = value else { let LuaValue::Table(ref table) = value else {
@ -106,7 +105,7 @@ impl NativeConvert for CArr {
let field_offset = (i * self.inner_size) as isize; let field_offset = (i * self.inner_size) as isize;
let data: LuaValue = table.get(i + 1)?; let data: LuaValue = table.get(i + 1)?;
self.inner_conv.as_ref().unwrap().luavalue_into( self.inner_conv.as_ref().unwrap().value_into_data(
lua, lua,
field_offset + offset, field_offset + offset,
data_handle, data_handle,
@ -116,18 +115,18 @@ impl NativeConvert for CArr {
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let table = lua.create_table_with_capacity(self.length, 0)?; let table = lua.create_table_with_capacity(self.length, 0)?;
for i in 0..self.length { for i in 0..self.length {
let field_offset = (i * self.inner_size) as isize; let field_offset = (i * self.inner_size) as isize;
table.set( table.set(
i + 1, i + 1,
self.inner_conv.as_ref().unwrap().luavalue_from( self.inner_conv.as_ref().unwrap().value_from_data(
lua, lua,
field_offset + offset, field_offset + offset,
data_handle, data_handle,
@ -138,12 +137,12 @@ impl NativeConvert for CArr {
} }
} }
impl LuaUserData for CArr { impl LuaUserData for CArrInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("size", |_, this| Ok(this.get_size())); fields.add_field_method_get("size", |_, this| Ok(this.get_size()));
fields.add_field_method_get("length", |_, this| Ok(this.get_length())); fields.add_field_method_get("length", |_, this| Ok(this.get_length()));
fields.add_field_function_get("inner", |lua, this: LuaAnyUserData| { fields.add_field_function_get("inner", |lua, this: LuaAnyUserData| {
let inner: LuaValue = get_association(lua, CARR_INNER, this)? let inner: LuaValue = association::get(lua, CARR_INNER, this)?
// It shouldn't happen. // It shouldn't happen.
.ok_or_else(|| LuaError::external("inner field not found"))?; .ok_or_else(|| LuaError::external("inner field not found"))?;
Ok(inner) Ok(inner)

View file

@ -1,8 +0,0 @@
// This is a string type that can be given to an external function.
// To be exact, it converts the Lua string into a c_char array and puts it in the box.
// For this part, initially, i wanted to allow box("lua string"),
// but separated it for clarity.
// This also allows operations such as ffi.string:intoBox().
// (Write a string to an already existing box)
// FIXME: use buffer instead?

View file

@ -5,13 +5,11 @@ use mlua::prelude::*;
use super::{ use super::{
association_names::{CALLABLE_CFN, CALLABLE_REF, CFN_ARGS, CFN_RESULT}, association_names::{CALLABLE_CFN, CALLABLE_REF, CFN_ARGS, CFN_RESULT},
c_helper, method_provider, helper, method_provider,
}; };
use crate::ffi::{ use crate::{
bit_mask::u8_test_not, data::{CallableData, RefData, RefDataFlag},
ffi_association::{get_association, set_association}, ffi::{association, bit_mask::*, FfiArgInfo, FfiData, FfiResultInfo, FfiSignedness, FfiSize},
FfiCallable, FfiRef, FfiRefFlag, NativeArgInfo, NativeData, NativeResultInfo, NativeSignedness,
NativeSize,
}; };
// cfn is a type declaration for a function. // cfn is a type declaration for a function.
@ -30,29 +28,29 @@ use crate::ffi::{
// The name cfn is intentional. This is because any *c_void is // The name cfn is intentional. This is because any *c_void is
// moved to a Lua function or vice versa. // moved to a Lua function or vice versa.
pub struct CFunc { pub struct CFnInfo {
cif: Cif, cif: Cif,
arg_info_list: Vec<NativeArgInfo>, arg_info_list: Vec<FfiArgInfo>,
result_info: NativeResultInfo, result_info: FfiResultInfo,
} }
impl NativeSignedness for CFunc { impl FfiSignedness for CFnInfo {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeSize for CFunc { impl FfiSize for CFnInfo {
fn get_size(&self) -> usize { fn get_size(&self) -> usize {
size_of::<*mut ()>() size_of::<*mut ()>()
} }
} }
impl CFunc { impl CFnInfo {
pub fn new( pub fn new(
args: Vec<Type>, args: Vec<Type>,
ret: Type, ret: Type,
arg_info_list: Vec<NativeArgInfo>, arg_info_list: Vec<FfiArgInfo>,
result_info: NativeResultInfo, result_info: FfiResultInfo,
) -> LuaResult<Self> { ) -> LuaResult<Self> {
// let cif = ; // let cif = ;
@ -68,29 +66,29 @@ impl CFunc {
arg_table: LuaTable, arg_table: LuaTable,
ret: LuaAnyUserData, ret: LuaAnyUserData,
) -> LuaResult<LuaAnyUserData<'lua>> { ) -> LuaResult<LuaAnyUserData<'lua>> {
let args_types = c_helper::get_middle_type_list(&arg_table)?; let args_types = helper::get_middle_type_list(&arg_table)?;
let ret_type = c_helper::get_middle_type(&ret)?; let ret_type = helper::get_middle_type(&ret)?;
let arg_len = arg_table.raw_len(); let arg_len = arg_table.raw_len();
let mut arg_info_list = Vec::<NativeArgInfo>::with_capacity(arg_len); let mut arg_info_list = Vec::<FfiArgInfo>::with_capacity(arg_len);
for index in 0..arg_len { for index in 0..arg_len {
let userdata = c_helper::get_userdata(arg_table.raw_get(index + 1)?)?; let userdata = helper::get_userdata(arg_table.raw_get(index + 1)?)?;
arg_info_list.push(NativeArgInfo { arg_info_list.push(FfiArgInfo {
conv: unsafe { c_helper::get_conv(&userdata)? }, conv: unsafe { helper::get_conv(&userdata)? },
size: c_helper::get_size(&userdata)?, size: helper::get_size(&userdata)?,
}); });
} }
let result_info = NativeResultInfo { let result_info = FfiResultInfo {
conv: unsafe { c_helper::get_conv(&ret)? }, conv: unsafe { helper::get_conv(&ret)? },
size: c_helper::get_size(&ret)?, size: helper::get_size(&ret)?,
}; };
let cfn = let cfn =
lua.create_userdata(Self::new(args_types, ret_type, arg_info_list, result_info)?)?; lua.create_userdata(Self::new(args_types, ret_type, arg_info_list, result_info)?)?;
// Create association to hold argument and result type // Create association to hold argument and result type
set_association(lua, CFN_ARGS, &cfn, arg_table)?; association::set(lua, CFN_ARGS, &cfn, arg_table)?;
set_association(lua, CFN_RESULT, &cfn, ret)?; association::set(lua, CFN_RESULT, &cfn, ret)?;
Ok(cfn) Ok(cfn)
} }
@ -100,13 +98,13 @@ impl CFunc {
pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> { pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
let mut result = String::from(" ("); let mut result = String::from(" (");
if let (Some(LuaValue::Table(arg_table)), Some(LuaValue::UserData(result_userdata))) = ( if let (Some(LuaValue::Table(arg_table)), Some(LuaValue::UserData(result_userdata))) = (
get_association(lua, CFN_ARGS, userdata)?, association::get(lua, CFN_ARGS, userdata)?,
get_association(lua, CFN_RESULT, userdata)?, association::get(lua, CFN_RESULT, userdata)?,
) { ) {
let len = arg_table.raw_len(); let len = arg_table.raw_len();
for arg_index in 1..=len { for arg_index in 1..=len {
let arg_userdata: LuaAnyUserData = arg_table.raw_get(arg_index)?; let arg_userdata: LuaAnyUserData = arg_table.raw_get(arg_index)?;
let pretty_formatted = c_helper::pretty_format(lua, &arg_userdata)?; let pretty_formatted = helper::pretty_format(lua, &arg_userdata)?;
result.push_str( result.push_str(
(if len == arg_index { (if len == arg_index {
pretty_formatted pretty_formatted
@ -117,7 +115,7 @@ impl CFunc {
); );
} }
result.push_str( result.push_str(
format!(") -> {} ", c_helper::pretty_format(lua, &result_userdata)?,).as_str(), format!(") -> {} ", helper::pretty_format(lua, &result_userdata)?,).as_str(),
); );
Ok(result) Ok(result)
} else { } else {
@ -126,7 +124,7 @@ impl CFunc {
} }
} }
impl LuaUserData for CFunc { impl LuaUserData for CFnInfo {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
// Subtype // Subtype
method_provider::provide_ptr_info(methods); method_provider::provide_ptr_info(methods);
@ -142,19 +140,19 @@ impl LuaUserData for CFunc {
methods.add_function( methods.add_function(
"callable", "callable",
|lua, (cfn, function_ref): (LuaAnyUserData, LuaAnyUserData)| { |lua, (cfn, function_ref): (LuaAnyUserData, LuaAnyUserData)| {
let this = cfn.borrow::<CFunc>()?; let this = cfn.borrow::<CFnInfo>()?;
if !function_ref.is::<FfiRef>() { if !function_ref.is::<RefData>() {
return Err(LuaError::external("argument 0 must be ffiref")); return Err(LuaError::external("argument 0 must be ffiref"));
} }
let ffi_ref = function_ref.borrow::<FfiRef>()?; let ffi_ref = function_ref.borrow::<RefData>()?;
if u8_test_not(ffi_ref.flags, FfiRefFlag::Function.value()) { if u8_test_not(ffi_ref.flags, RefDataFlag::Function.value()) {
return Err(LuaError::external("not a function ref")); return Err(LuaError::external("not a function ref"));
} }
let callable = lua.create_userdata(unsafe { let callable = lua.create_userdata(unsafe {
FfiCallable::new( CallableData::new(
this.cif.as_raw_ptr(), this.cif.as_raw_ptr(),
ptr::from_ref(&this.arg_info_list), ptr::from_ref(&this.arg_info_list),
ptr::from_ref(&this.result_info), ptr::from_ref(&this.result_info),
@ -162,8 +160,8 @@ impl LuaUserData for CFunc {
) )
})?; })?;
set_association(lua, CALLABLE_CFN, &callable, cfn.clone())?; association::set(lua, CALLABLE_CFN, &callable, cfn.clone())?;
set_association(lua, CALLABLE_REF, &callable, function_ref.clone())?; association::set(lua, CALLABLE_REF, &callable, function_ref.clone())?;
Ok(callable) Ok(callable)
}, },

View file

@ -2,8 +2,8 @@ use libffi::middle::Type;
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig}; use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
use mlua::prelude::*; use mlua::prelude::*;
use super::{c_type_helper, CArr, CFunc, CPtr, CStruct}; use super::{ctype_helper, CArrInfo, CFnInfo, CPtrInfo, CStructInfo};
use crate::ffi::{FfiBox, GetNativeData, NativeConvert, NativeSize}; use crate::data::{BoxData, FfiConvert, FfiSize, GetFfiData};
pub mod method_provider { pub mod method_provider {
use super::*; use super::*;
@ -20,8 +20,8 @@ pub mod method_provider {
where where
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_function("ptrInfo", |lua, this: LuaAnyUserData| { methods.add_function("pointerInfo", |lua, this: LuaAnyUserData| {
CPtr::from_userdata(lua, &this) CPtrInfo::from_userdata(lua, &this)
}); });
} }
@ -29,14 +29,14 @@ pub mod method_provider {
where where
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_function("arrInfo", |lua, (this, length): (LuaAnyUserData, usize)| { methods.add_function("ArrInfo", |lua, (this, length): (LuaAnyUserData, usize)| {
CArr::from_userdata(lua, &this, length) CArrInfo::from_userdata(lua, &this, length)
}); });
} }
pub fn provide_from_data<'lua, Target, M>(methods: &mut M) pub fn provide_from_data<'lua, Target, M>(methods: &mut M)
where where
Target: NativeSize + NativeConvert, Target: FfiSize + FfiConvert,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_method(
@ -52,14 +52,14 @@ pub mod method_provider {
return Err(LuaError::external("Unreadable data handle")); return Err(LuaError::external("Unreadable data handle"));
} }
unsafe { this.luavalue_from(lua, offset, data_handle) } unsafe { this.value_from_data(lua, offset, data_handle) }
}, },
); );
} }
pub fn provide_into_data<'lua, Target, M>(methods: &mut M) pub fn provide_into_data<'lua, Target, M>(methods: &mut M)
where where
Target: NativeSize + NativeConvert, Target: FfiSize + FfiConvert,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_method(
@ -76,19 +76,19 @@ pub mod method_provider {
return Err(LuaError::external("Unwritable data handle")); return Err(LuaError::external("Unwritable data handle"));
} }
unsafe { this.luavalue_into(lua, offset, data_handle, value) } unsafe { this.value_into_data(lua, offset, data_handle, value) }
}, },
); );
} }
pub fn provide_box<'lua, Target, M>(methods: &mut M) pub fn provide_box<'lua, Target, M>(methods: &mut M)
where where
Target: NativeSize + NativeConvert, Target: FfiSize + FfiConvert,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method("box", |lua, this, table: LuaValue| { methods.add_method("box", |lua, this, table: LuaValue| {
let result = lua.create_userdata(FfiBox::new(this.get_size()))?; let result = lua.create_userdata(BoxData::new(this.get_size()))?;
unsafe { this.luavalue_into(lua, 0, &result.get_data_handle()?, table)? }; unsafe { this.value_into_data(lua, 0, &result.get_data_handle()?, table)? };
Ok(result) Ok(result)
}); });
} }
@ -109,22 +109,22 @@ pub fn get_userdata(value: LuaValue) -> LuaResult<LuaAnyUserData> {
// this is intended to avoid lookup userdata and lua table every time. (eg: struct) // this is intended to avoid lookup userdata and lua table every time. (eg: struct)
// userdata must live longer than the NativeConvert handle. // userdata must live longer than the NativeConvert handle.
// However, c_struct is a strong reference to each field, so this is not a problem. // However, c_struct is a strong reference to each field, so this is not a problem.
pub unsafe fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn NativeConvert> { pub unsafe fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn FfiConvert> {
if userdata.is::<CStruct>() { if userdata.is::<CStructInfo>() {
Ok(userdata.to_pointer().cast::<CStruct>() as *const dyn NativeConvert) Ok(userdata.to_pointer().cast::<CStructInfo>() as *const dyn FfiConvert)
} else if userdata.is::<CArr>() { } else if userdata.is::<CArrInfo>() {
Ok(userdata.to_pointer().cast::<CArr>() as *const dyn NativeConvert) Ok(userdata.to_pointer().cast::<CArrInfo>() as *const dyn FfiConvert)
} else if userdata.is::<CPtr>() { } else if userdata.is::<CPtrInfo>() {
Ok(userdata.to_pointer().cast::<CPtr>() as *const dyn NativeConvert) Ok(userdata.to_pointer().cast::<CPtrInfo>() as *const dyn FfiConvert)
} else { } else {
c_type_helper::get_conv(userdata) ctype_helper::get_conv(userdata)
// TODO: struct and more // TODO: struct and more
} }
} }
pub unsafe fn get_conv_list(table: &LuaTable) -> LuaResult<Vec<*const dyn NativeConvert>> { pub unsafe fn get_conv_list(table: &LuaTable) -> LuaResult<Vec<*const dyn FfiConvert>> {
let len: usize = table.raw_len(); let len: usize = table.raw_len();
let mut conv_list = Vec::<*const dyn NativeConvert>::with_capacity(len); let mut conv_list = Vec::<*const dyn FfiConvert>::with_capacity(len);
for i in 0..len { for i in 0..len {
let value: LuaValue = table.raw_get(i + 1)?; let value: LuaValue = table.raw_get(i + 1)?;
@ -135,27 +135,27 @@ pub unsafe fn get_conv_list(table: &LuaTable) -> LuaResult<Vec<*const dyn Native
} }
pub fn get_size(this: &LuaAnyUserData) -> LuaResult<usize> { pub fn get_size(this: &LuaAnyUserData) -> LuaResult<usize> {
if this.is::<CStruct>() { if this.is::<CStructInfo>() {
Ok(this.borrow::<CStruct>()?.get_size()) Ok(this.borrow::<CStructInfo>()?.get_size())
} else if this.is::<CArr>() { } else if this.is::<CArrInfo>() {
Ok(this.borrow::<CArr>()?.get_size()) Ok(this.borrow::<CArrInfo>()?.get_size())
} else if this.is::<CPtr>() { } else if this.is::<CPtrInfo>() {
Ok(this.borrow::<CPtr>()?.get_size()) Ok(this.borrow::<CPtrInfo>()?.get_size())
} else { } else {
c_type_helper::get_size(this) ctype_helper::get_size(this)
} }
} }
// get libffi_type from any c-type userdata // get libffi_type from any c-type userdata
pub fn get_middle_type(userdata: &LuaAnyUserData) -> LuaResult<Type> { pub fn get_middle_type(userdata: &LuaAnyUserData) -> LuaResult<Type> {
if userdata.is::<CStruct>() { if userdata.is::<CStructInfo>() {
Ok(userdata.borrow::<CStruct>()?.get_type()) Ok(userdata.borrow::<CStructInfo>()?.get_type())
} else if let Some(middle_type) = c_type_helper::get_middle_type(userdata)? { } else if let Some(middle_type) = ctype_helper::get_middle_type(userdata)? {
Ok(middle_type) Ok(middle_type)
} else if userdata.is::<CArr>() { } else if userdata.is::<CArrInfo>() {
Ok(userdata.borrow::<CArr>()?.get_type()) Ok(userdata.borrow::<CArrInfo>()?.get_type())
} else if userdata.is::<CPtr>() { } else if userdata.is::<CPtrInfo>() {
Ok(CPtr::get_type()) Ok(CPtrInfo::get_type())
} else { } else {
Err(LuaError::external(format!( Err(LuaError::external(format!(
"Unexpected field. CStruct, CType, CString or CArr is required for element but got {}", "Unexpected field. CStruct, CType, CString or CArr is required for element but got {}",
@ -192,15 +192,15 @@ pub fn get_middle_type_list(table: &LuaTable) -> LuaResult<Vec<Type>> {
// stringify any c-type userdata (for recursive) // stringify any c-type userdata (for recursive)
pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> { pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
if userdata.is::<CStruct>() { if userdata.is::<CStructInfo>() {
CStruct::stringify(lua, userdata) CStructInfo::stringify(lua, userdata)
} else if userdata.is::<CArr>() { } else if userdata.is::<CArrInfo>() {
CArr::stringify(lua, userdata) CArrInfo::stringify(lua, userdata)
} else if userdata.is::<CPtr>() { } else if userdata.is::<CPtrInfo>() {
CPtr::stringify(lua, userdata) CPtrInfo::stringify(lua, userdata)
} else if userdata.is::<CFunc>() { } else if userdata.is::<CFnInfo>() {
CFunc::stringify(lua, userdata) CFnInfo::stringify(lua, userdata)
} else if let Some(name) = c_type_helper::get_name(userdata)? { } else if let Some(name) = ctype_helper::get_name(userdata)? {
Ok(String::from(name)) Ok(String::from(name))
} else { } else {
Ok(String::from("unknown")) Ok(String::from("unknown"))
@ -209,15 +209,15 @@ pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
// get name tag for any c-type userdata // get name tag for any c-type userdata
pub fn get_tag_name(userdata: &LuaAnyUserData) -> LuaResult<String> { pub fn get_tag_name(userdata: &LuaAnyUserData) -> LuaResult<String> {
Ok(if userdata.is::<CStruct>() { Ok(if userdata.is::<CStructInfo>() {
String::from("CStruct") String::from("CStruct")
} else if userdata.is::<CArr>() { } else if userdata.is::<CArrInfo>() {
String::from("CArr") String::from("CArr")
} else if userdata.is::<CPtr>() { } else if userdata.is::<CPtrInfo>() {
String::from("CPtr") String::from("CPtr")
} else if userdata.is::<CFunc>() { } else if userdata.is::<CFnInfo>() {
String::from("CFunc") String::from("CFunc")
} else if c_type_helper::is_ctype(userdata) { } else if ctype_helper::is_ctype(userdata) {
String::from("CType") String::from("CType")
} else { } else {
String::from("Unknown") String::from("Unknown")
@ -226,7 +226,7 @@ pub fn get_tag_name(userdata: &LuaAnyUserData) -> LuaResult<String> {
// emulate 'print' for ctype userdata, but ctype is simplified // emulate 'print' for ctype userdata, but ctype is simplified
pub fn pretty_format(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> { pub fn pretty_format(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
if c_type_helper::is_ctype(userdata) { if ctype_helper::is_ctype(userdata) {
stringify(lua, userdata) stringify(lua, userdata)
} else { } else {
Ok(format!( Ok(format!(

View file

@ -1,20 +1,19 @@
mod c_arr; mod arr_info;
mod c_func; mod fn_info;
pub mod c_helper; pub mod helper;
mod c_ptr; mod ptr_info;
mod c_string; mod struct_info;
mod c_struct; mod type_info;
mod c_type;
mod types; mod types;
pub use self::{ pub use self::{
c_arr::CArr, arr_info::CArrInfo,
c_func::CFunc, fn_info::CFnInfo,
c_helper::method_provider, helper::method_provider,
c_ptr::CPtr, ptr_info::CPtrInfo,
c_struct::CStruct, struct_info::CStructInfo,
c_type::{CType, CTypeCast}, type_info::{CTypeCast, CTypeInfo},
types::{c_type_helper, export_ctypes}, types::{ctype_helper, export_ctypes},
}; };
// Named registry table names // Named registry table names

View file

@ -3,41 +3,38 @@ use std::cell::Ref;
use libffi::middle::Type; use libffi::middle::Type;
use mlua::prelude::*; use mlua::prelude::*;
use super::{association_names::CPTR_INNER, c_helper, c_type_helper, method_provider}; use super::{association_names::CPTR_INNER, ctype_helper, helper, method_provider};
use crate::{ use crate::{
ffi::{ data::{FfiConvert, FfiData, FfiSignedness, FfiSize, RefData},
ffi_association::{get_association, set_association}, ffi::{association, libffi_helper::SIEE_OF_POINTER},
FfiRef, NativeConvert, NativeData, NativeSignedness, NativeSize,
},
libffi_helper::SIEE_OF_POINTER,
}; };
pub struct CPtr { pub struct CPtrInfo {
inner_size: usize, inner_size: usize,
} }
impl NativeSignedness for CPtr { impl FfiSignedness for CPtrInfo {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeSize for CPtr { impl FfiSize for CPtrInfo {
fn get_size(&self) -> usize { fn get_size(&self) -> usize {
SIEE_OF_POINTER SIEE_OF_POINTER
} }
} }
impl NativeConvert for CPtr { impl FfiConvert for CPtrInfo {
// Convert luavalue into data, then write into ptr // Convert luavalue into data, then write into ptr
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
if let LuaValue::UserData(value_userdata) = value { if let LuaValue::UserData(value_userdata) = value {
if value_userdata.is::<FfiRef>() { if value_userdata.is::<RefData>() {
let value_ref = value_userdata.borrow::<FfiRef>()?; let value_ref = value_userdata.borrow::<RefData>()?;
value_ref value_ref
.check_boundary(0, self.inner_size) .check_boundary(0, self.inner_size)
.then_some(()) .then_some(())
@ -56,17 +53,17 @@ impl NativeConvert for CPtr {
} }
// Read data from ptr, then convert into luavalue // Read data from ptr, then convert into luavalue
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
_offset: isize, _offset: isize,
_data_handle: &Ref<dyn NativeData>, _data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
Err(LuaError::external("Conversion of pointer is not allowed")) Err(LuaError::external("Conversion of pointer is not allowed"))
} }
} }
impl CPtr { impl CPtrInfo {
// Create pointer type with '.inner' field // Create pointer type with '.inner' field
// inner can be CArr, CType or CStruct // inner can be CArr, CType or CStruct
pub fn from_userdata<'lua>( pub fn from_userdata<'lua>(
@ -74,10 +71,10 @@ impl CPtr {
inner: &LuaAnyUserData, inner: &LuaAnyUserData,
) -> LuaResult<LuaAnyUserData<'lua>> { ) -> LuaResult<LuaAnyUserData<'lua>> {
let value = lua.create_userdata(Self { let value = lua.create_userdata(Self {
inner_size: c_helper::get_size(inner)?, inner_size: helper::get_size(inner)?,
})?; })?;
set_association(lua, CPTR_INNER, &value, inner)?; association::set(lua, CPTR_INNER, &value, inner)?;
Ok(value) Ok(value)
} }
@ -85,8 +82,8 @@ impl CPtr {
// Stringify CPtr with inner ctype // Stringify CPtr with inner ctype
pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> { pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
if let LuaValue::UserData(inner_userdata) = userdata.get("inner")? { if let LuaValue::UserData(inner_userdata) = userdata.get("inner")? {
let pretty_formatted = c_helper::pretty_format(lua, &inner_userdata)?; let pretty_formatted = helper::pretty_format(lua, &inner_userdata)?;
Ok(if c_type_helper::is_ctype(&inner_userdata) { Ok(if ctype_helper::is_ctype(&inner_userdata) {
pretty_formatted pretty_formatted
} else { } else {
format!(" {pretty_formatted} ") format!(" {pretty_formatted} ")
@ -102,11 +99,11 @@ impl CPtr {
} }
} }
impl LuaUserData for CPtr { impl LuaUserData for CPtrInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("size", |_, _| Ok(size_of::<usize>())); fields.add_field_method_get("size", |_, _| Ok(size_of::<usize>()));
fields.add_field_function_get("inner", |lua, this| { fields.add_field_function_get("inner", |lua, this| {
let inner = get_association(lua, CPTR_INNER, this)? let inner = association::get(lua, CPTR_INNER, this)?
.ok_or_else(|| LuaError::external("inner type not found"))?; .ok_or_else(|| LuaError::external("inner type not found"))?;
Ok(inner) Ok(inner)
}); });

View file

@ -3,24 +3,21 @@ use std::{cell::Ref, vec::Vec};
use libffi::{low, middle::Type, raw}; use libffi::{low, middle::Type, raw};
use mlua::prelude::*; use mlua::prelude::*;
use super::{association_names::CSTRUCT_INNER, c_helper, method_provider}; use super::{association_names::CSTRUCT_INNER, helper, method_provider};
use crate::ffi::{ use crate::{
ffi_association::{get_association, set_association}, data::{FfiConvert, FfiData, FfiSignedness, FfiSize},
NativeConvert, NativeData, NativeSignedness, NativeSize, FFI_STATUS_NAMES, ffi::{association, libffi_helper::FFI_STATUS_NAMES},
}; };
pub struct CStruct { pub struct CStructInfo {
middle_type: Type, middle_type: Type,
size: usize, size: usize,
inner_offset_list: Vec<usize>, inner_offset_list: Vec<usize>,
inner_conv_list: Vec<*const dyn NativeConvert>, inner_conv_list: Vec<*const dyn FfiConvert>,
} }
impl CStruct { impl CStructInfo {
pub fn new( pub fn new(fields: Vec<Type>, inner_conv_list: Vec<*const dyn FfiConvert>) -> LuaResult<Self> {
fields: Vec<Type>,
inner_conv_list: Vec<*const dyn NativeConvert>,
) -> LuaResult<Self> {
let len = fields.len(); let len = fields.len();
let mut inner_offset_list = Vec::<usize>::with_capacity(len); let mut inner_offset_list = Vec::<usize>::with_capacity(len);
let middle_type = Type::structure(fields); let middle_type = Type::structure(fields);
@ -60,32 +57,33 @@ impl CStruct {
lua: &'lua Lua, lua: &'lua Lua,
table: LuaTable<'lua>, table: LuaTable<'lua>,
) -> LuaResult<LuaAnyUserData<'lua>> { ) -> LuaResult<LuaAnyUserData<'lua>> {
let cstruct = lua.create_userdata(Self::new( let cstruct = lua
c_helper::get_middle_type_list(&table)?, .create_userdata(Self::new(helper::get_middle_type_list(&table)?, unsafe {
unsafe { c_helper::get_conv_list(&table)? }, helper::get_conv_list(&table)?
)?)?; })?)?;
table.set_readonly(true); table.set_readonly(true);
set_association(lua, CSTRUCT_INNER, &cstruct, table)?; association::set(lua, CSTRUCT_INNER, &cstruct, table)?;
Ok(cstruct) Ok(cstruct)
} }
// Stringify cstruct for pretty printing like: // Stringify cstruct for pretty printing like:
// <CStruct( u8, i32, size = 8 )> // <CStruct( u8, i32, size = 8 )>
pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> { pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
if let LuaValue::Table(fields) = get_association(lua, CSTRUCT_INNER, userdata)? if let LuaValue::Table(fields) = association::get(lua, CSTRUCT_INNER, userdata)?
.ok_or_else(|| LuaError::external("Field table not found"))? .ok_or_else(|| LuaError::external("Field table not found"))?
{ {
let mut result = String::from(" "); let mut result = String::from(" ");
for i in 0..fields.raw_len() { for i in 0..fields.raw_len() {
let child: LuaAnyUserData = fields.raw_get(i + 1)?; let child: LuaAnyUserData = fields.raw_get(i + 1)?;
let pretty_formatted = c_helper::pretty_format(lua, &child)?; let pretty_formatted = helper::pretty_format(lua, &child)?;
result.push_str(format!("{pretty_formatted}, ").as_str()); result.push_str(format!("{pretty_formatted}, ").as_str());
} }
// size of // size of
result result.push_str(
.push_str(format!("size = {} ", userdata.borrow::<CStruct>()?.get_size()).as_str()); format!("size = {} ", userdata.borrow::<CStructInfo>()?.get_size()).as_str(),
);
Ok(result) Ok(result)
} else { } else {
Err(LuaError::external("failed to get inner type table.")) Err(LuaError::external("failed to get inner type table."))
@ -107,23 +105,23 @@ impl CStruct {
} }
} }
impl NativeSize for CStruct { impl FfiSize for CStructInfo {
fn get_size(&self) -> usize { fn get_size(&self) -> usize {
self.size self.size
} }
} }
impl NativeSignedness for CStruct { impl FfiSignedness for CStructInfo {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeConvert for CStruct { impl FfiConvert for CStructInfo {
// FIXME: FfiBox, FfiRef support required // FIXME: FfiBox, FfiRef support required
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let LuaValue::Table(ref table) = value else { let LuaValue::Table(ref table) = value else {
@ -133,18 +131,21 @@ impl NativeConvert for CStruct {
let field_offset = self.offset(i)? as isize; let field_offset = self.offset(i)? as isize;
let data: LuaValue = table.get(i + 1)?; let data: LuaValue = table.get(i + 1)?;
conv.as_ref() conv.as_ref().unwrap().value_into_data(
.unwrap() lua,
.luavalue_into(lua, field_offset + offset, data_handle, data)?; field_offset + offset,
data_handle,
data,
)?;
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let table = lua.create_table_with_capacity(self.inner_conv_list.len(), 0)?; let table = lua.create_table_with_capacity(self.inner_conv_list.len(), 0)?;
for (i, conv) in self.inner_conv_list.iter().enumerate() { for (i, conv) in self.inner_conv_list.iter().enumerate() {
@ -153,14 +154,14 @@ impl NativeConvert for CStruct {
i + 1, i + 1,
conv.as_ref() conv.as_ref()
.unwrap() .unwrap()
.luavalue_from(lua, field_offset + offset, data_handle)?, .value_from_data(lua, field_offset + offset, data_handle)?,
)?; )?;
} }
Ok(LuaValue::Table(table)) Ok(LuaValue::Table(table))
} }
} }
impl LuaUserData for CStruct { impl LuaUserData for CStructInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("size", |_, this| Ok(this.get_size())); fields.add_field_method_get("size", |_, this| Ok(this.get_size()));
} }
@ -184,7 +185,7 @@ impl LuaUserData for CStruct {
// Simply pass type in the locked table used when first creating this object. // 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 // By referencing the table to struct, the types inside do not disappear
methods.add_function("field", |lua, (this, field): (LuaAnyUserData, usize)| { methods.add_function("field", |lua, (this, field): (LuaAnyUserData, usize)| {
if let LuaValue::Table(fields) = get_association(lua, CSTRUCT_INNER, this)? if let LuaValue::Table(fields) = association::get(lua, CSTRUCT_INNER, this)?
.ok_or_else(|| LuaError::external("Field table not found"))? .ok_or_else(|| LuaError::external("Field table not found"))?
{ {
let value: LuaValue = fields.raw_get(field + 1)?; let value: LuaValue = fields.raw_get(field + 1)?;

View file

@ -6,10 +6,10 @@ use libffi::middle::Type;
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig}; use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
use mlua::prelude::*; use mlua::prelude::*;
use super::method_provider;
use crate::{ use crate::{
c::method_provider, data::{FfiConvert, FfiData, FfiSignedness, FfiSize, GetFfiData},
ffi::{GetNativeData, NativeConvert, NativeData, NativeSignedness, NativeSize}, ffi::libffi_helper::get_ensured_size,
libffi_helper::get_ensured_size,
}; };
// Cast native data // Cast native data
@ -19,8 +19,8 @@ pub trait CTypeCast {
&self, &self,
from_ctype: &LuaAnyUserData, from_ctype: &LuaAnyUserData,
into_ctype: &LuaAnyUserData, into_ctype: &LuaAnyUserData,
_from: &Ref<dyn NativeData>, _from: &Ref<dyn FfiData>,
_into: &Ref<dyn NativeData>, _into: &Ref<dyn FfiData>,
) -> LuaResult<()> { ) -> LuaResult<()> {
// Show error if have no cast implement // Show error if have no cast implement
Err(Self::cast_failed_with(self, from_ctype, into_ctype)) Err(Self::cast_failed_with(self, from_ctype, into_ctype))
@ -40,23 +40,23 @@ pub trait CTypeCast {
} }
} }
pub struct CType<T> { pub struct CTypeInfo<T> {
middle_type: Type, middle_type: Type,
size: usize, size: usize,
name: &'static str, name: &'static str,
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
} }
impl<T> NativeSize for CType<T> { impl<T> FfiSize for CTypeInfo<T> {
fn get_size(&self) -> usize { fn get_size(&self) -> usize {
self.size self.size
} }
} }
impl<T> CType<T> impl<T> CTypeInfo<T>
where where
T: 'static, T: 'static,
Self: CTypeCast + NativeSignedness + NativeConvert + NativeSize, Self: CTypeCast + FfiSignedness + FfiConvert + FfiSize,
{ {
pub fn new_with_libffi_type<'lua>( pub fn new_with_libffi_type<'lua>(
lua: &'lua Lua, lua: &'lua Lua,
@ -85,10 +85,10 @@ where
} }
} }
impl<T> LuaUserData for CType<T> impl<T> LuaUserData for CTypeInfo<T>
where where
T: 'static, T: 'static,
Self: CTypeCast + NativeSignedness + NativeConvert + NativeSize, Self: CTypeCast + FfiSignedness + FfiConvert + FfiSize,
{ {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("size", |_, this| Ok(this.get_size())); fields.add_field_method_get("size", |_, this| Ok(this.get_size()));

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<f32> { impl FfiSignedness for CTypeInfo<f32> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<f32> { impl FfiConvert for CTypeInfo<f32> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: f32 = match value { let value: f32 = match value {
@ -40,12 +42,12 @@ impl NativeConvert for CType<f32> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<f32>()).into_lua(lua)? (*data_handle.get_pointer().byte_offset(offset).cast::<f32>()).into_lua(lua)?

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<f64> { impl FfiSignedness for CTypeInfo<f64> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<f64> { impl FfiConvert for CTypeInfo<f64> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: f64 = match value { let value: f64 = match value {
@ -40,12 +42,12 @@ impl NativeConvert for CType<f64> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<f64>()).into_lua(lua)? (*data_handle.get_pointer().byte_offset(offset).cast::<f64>()).into_lua(lua)?

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<i128> { impl FfiSignedness for CTypeInfo<i128> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<i128> { impl FfiConvert for CTypeInfo<i128> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: i128 = match value { let value: i128 = match value {
@ -40,14 +42,16 @@ impl NativeConvert for CType<i128> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<i128>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<i128>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<i16> { impl FfiSignedness for CTypeInfo<i16> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<i16> { impl FfiConvert for CTypeInfo<i16> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: i16 = match value { let value: i16 = match value {
@ -40,14 +42,16 @@ impl NativeConvert for CType<i16> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<i16>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<i16>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<i32> { impl FfiSignedness for CTypeInfo<i32> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<i32> { impl FfiConvert for CTypeInfo<i32> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: i32 = match value { let value: i32 = match value {
@ -40,14 +42,16 @@ impl NativeConvert for CType<i32> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<i32>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<i32>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<i64> { impl FfiSignedness for CTypeInfo<i64> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<i64> { impl FfiConvert for CTypeInfo<i64> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: i64 = match value { let value: i64 = match value {
@ -40,14 +42,16 @@ impl NativeConvert for CType<i64> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<i64>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<i64>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<i8> { impl FfiSignedness for CTypeInfo<i8> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<i8> { impl FfiConvert for CTypeInfo<i8> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: i8 = match value { let value: i8 = match value {
@ -36,14 +38,15 @@ impl NativeConvert for CType<i8> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<i8>()).into_lua(lua)? }; let value =
unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<i8>()).into_lua(lua)? };
Ok(value) Ok(value)
} }
} }

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<isize> { impl FfiSignedness for CTypeInfo<isize> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
true true
} }
} }
impl NativeConvert for CType<isize> { impl FfiConvert for CTypeInfo<isize> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: isize = match value { let value: isize = match value {
@ -36,18 +38,27 @@ impl NativeConvert for CType<isize> {
} }
}; };
unsafe { unsafe {
*(data_handle.get_pointer().byte_offset(offset).cast::<isize>()) = value; *(data_handle
.get_pointer()
.byte_offset(offset)
.cast::<isize>()) = value;
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<isize>()).into_lua(lua)? }; let value = unsafe {
(*data_handle
.get_pointer()
.byte_offset(offset)
.cast::<isize>())
.into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -7,8 +7,8 @@ use libffi::middle::Type;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::{CType, CTypeCast}; use super::{CTypeCast, CTypeInfo};
use crate::ffi::{native_num_cast, NativeConvert, NativeData, NativeSize}; use crate::data::{num_cast, FfiConvert, FfiData, FfiSize};
pub mod f32; pub mod f32;
pub mod f64; pub mod f64;
@ -30,7 +30,7 @@ macro_rules! create_ctypes {
($lua:ident, $(( $name:expr, $rust_type:ty, $libffi_type:expr ),)* ) => { ($lua:ident, $(( $name:expr, $rust_type:ty, $libffi_type:expr ),)* ) => {
Ok(vec![$(( Ok(vec![$((
$name, $name,
CType::<$rust_type>::new_with_libffi_type($lua, $libffi_type, $name)?, CTypeInfo::<$rust_type>::new_with_libffi_type($lua, $libffi_type, $name)?,
),)*]) ),)*])
}; };
} }
@ -80,14 +80,14 @@ pub fn export_ctypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>
// Implement type-casting for numeric ctypes // Implement type-casting for numeric ctypes
macro_rules! define_cast_num { macro_rules! define_cast_num {
($from_rust_type:ident, $self:ident, $from_ctype:ident, $into_ctype:ident, $from:ident, $into:ident, $($into_rust_type:ty)*) => { ($from_rust_type:ident, $self:ident, $from_ctype:ident, $into_ctype:ident, $from:ident, $into:ident, $($into_rust_type:ty)*) => {
$( if $into_ctype.is::<CType<$into_rust_type>>() { $( if $into_ctype.is::<CTypeInfo<$into_rust_type>>() {
native_num_cast::<$from_rust_type, $into_rust_type>($from, $into) num_cast::<$from_rust_type, $into_rust_type>($from, $into)
} else )* { } else )* {
Err($self.cast_failed_with($from_ctype, $into_ctype)) Err($self.cast_failed_with($from_ctype, $into_ctype))
} }
}; };
} }
impl<From> CTypeCast for CType<From> impl<From> CTypeCast for CTypeInfo<From>
where where
From: AsPrimitive<u8> From: AsPrimitive<u8>
+ AsPrimitive<u16> + AsPrimitive<u16>
@ -106,41 +106,41 @@ where
{ {
fn cast( fn cast(
&self, &self,
from_ctype: &LuaAnyUserData, from_info: &LuaAnyUserData,
into_ctype: &LuaAnyUserData, into_info: &LuaAnyUserData,
from: &Ref<dyn NativeData>, from: &Ref<dyn FfiData>,
into: &Ref<dyn NativeData>, into: &Ref<dyn FfiData>,
) -> LuaResult<()> { ) -> LuaResult<()> {
define_cast_num!( define_cast_num!(
From, self, into_ctype, from_ctype, from, into, From, self, into_info, from_info, from, into,
u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize
) )
} }
} }
pub mod c_type_helper { pub mod ctype_helper {
use super::*; use super::*;
// To prevent drop NativeConvert, we must use ffi_association to ensure children keep alive // To prevent drop NativeConvert, we must use ffi_association to ensure children keep alive
macro_rules! define_get_conv { macro_rules! define_get_conv {
($userdata:ident, $( $rust_type:ty )*) => { ($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() { $( if $userdata.is::<CTypeInfo<$rust_type>>() {
Ok($userdata.to_pointer().cast::<CType<$rust_type>>() as *const dyn NativeConvert) Ok($userdata.to_pointer().cast::<CTypeInfo<$rust_type>>() as *const dyn FfiConvert)
} else )* { } else )* {
Err(LuaError::external("Unexpected type")) Err(LuaError::external("Unexpected type"))
} }
}; };
} }
#[inline] #[inline]
pub fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn NativeConvert> { pub fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn FfiConvert> {
define_get_conv!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize) define_get_conv!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize)
} }
// Get size of ctype (not includes struct, arr, ... only CType<*>) // Get size of ctype (not includes struct, arr, ... only CType<*>)
macro_rules! define_get_size { macro_rules! define_get_size {
($userdata:ident, $( $rust_type:ty )*) => { ($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() { $( if $userdata.is::<CTypeInfo<$rust_type>>() {
Ok($userdata.borrow::<CType<$rust_type>>()?.get_size()) Ok($userdata.borrow::<CTypeInfo<$rust_type>>()?.get_size())
} else )* { } else )* {
Err(LuaError::external("Unexpected type")) Err(LuaError::external("Unexpected type"))
} }
@ -154,8 +154,8 @@ pub mod c_type_helper {
// Get name of ctype // Get name of ctype
macro_rules! define_get_name { macro_rules! define_get_name {
($userdata:ident, $( $rust_type:ty )*) => { ($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() { $( if $userdata.is::<CTypeInfo<$rust_type>>() {
Ok(Some($userdata.borrow::<CType<$rust_type>>()?.get_name())) Ok(Some($userdata.borrow::<CTypeInfo<$rust_type>>()?.get_name()))
} else )* { } else )* {
Ok(None) Ok(None)
} }
@ -169,8 +169,8 @@ pub mod c_type_helper {
// Get libffi_type of ctype // Get libffi_type of ctype
macro_rules! define_get_middle_type { macro_rules! define_get_middle_type {
($userdata:ident, $( $rust_type:ty )*) => { ($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() { $( if $userdata.is::<CTypeInfo<$rust_type>>() {
Ok(Some($userdata.borrow::<CType<$rust_type>>()?.get_type())) Ok(Some($userdata.borrow::<CTypeInfo<$rust_type>>()?.get_type()))
} else )* { } else )* {
Ok(None) Ok(None)
} }
@ -183,7 +183,7 @@ pub mod c_type_helper {
macro_rules! define_is_ctype { macro_rules! define_is_ctype {
($userdata:ident, $( $rust_type:ty )*) => { ($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() { $( if $userdata.is::<CTypeInfo<$rust_type>>() {
true true
} else )* { } else )* {
false false

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<u128> { impl FfiSignedness for CTypeInfo<u128> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeConvert for CType<u128> { impl FfiConvert for CTypeInfo<u128> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: u128 = match value { let value: u128 = match value {
@ -40,14 +42,16 @@ impl NativeConvert for CType<u128> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<u128>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<u128>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,23 +3,25 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<u16> { impl FfiSignedness for CTypeInfo<u16> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeConvert for CType<u16> { impl FfiConvert for CTypeInfo<u16> {
// Convert luavalue into data, then write into ptr // Convert luavalue into data, then write into ptr
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: u16 = match value { let value: u16 = match value {
@ -41,14 +43,16 @@ impl NativeConvert for CType<u16> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<u16>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<u16>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<u32> { impl FfiSignedness for CTypeInfo<u32> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeConvert for CType<u32> { impl FfiConvert for CTypeInfo<u32> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: u32 = match value { let value: u32 = match value {
@ -40,14 +42,16 @@ impl NativeConvert for CType<u32> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<u32>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<u32>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<u64> { impl FfiSignedness for CTypeInfo<u64> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeConvert for CType<u64> { impl FfiConvert for CTypeInfo<u64> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: u64 = match value { let value: u64 = match value {
@ -40,14 +42,16 @@ impl NativeConvert for CType<u64> {
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<u64>()).into_lua(lua)? }; let value = unsafe {
(*data_handle.get_pointer().byte_offset(offset).cast::<u64>()).into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -3,23 +3,25 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<u8> { impl FfiSignedness for CTypeInfo<u8> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeConvert for CType<u8> { impl FfiConvert for CTypeInfo<u8> {
// Convert luavalue into data, then write into ptr // Convert luavalue into data, then write into ptr
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: u8 = match value { let value: u8 = match value {
@ -39,12 +41,12 @@ impl NativeConvert for CType<u8> {
} }
// Read data from ptr, then convert into luavalue // Read data from ptr, then convert into luavalue
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = let value =
unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<u8>()).into_lua(lua)? }; unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<u8>()).into_lua(lua)? };

View file

@ -3,22 +3,24 @@ use std::cell::Ref;
use mlua::prelude::*; use mlua::prelude::*;
use num::cast::AsPrimitive; use num::cast::AsPrimitive;
use super::super::c_type::CType; use crate::{
use crate::ffi::{NativeConvert, NativeData, NativeSignedness}; c::type_info::CTypeInfo,
data::{FfiConvert, FfiData, FfiSignedness},
};
impl NativeSignedness for CType<usize> { impl FfiSignedness for CTypeInfo<usize> {
fn get_signedness(&self) -> bool { fn get_signedness(&self) -> bool {
false false
} }
} }
impl NativeConvert for CType<usize> { impl FfiConvert for CTypeInfo<usize> {
unsafe fn luavalue_into<'lua>( unsafe fn value_into_data<'lua>(
&self, &self,
_lua: &'lua Lua, _lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>, value: LuaValue<'lua>,
) -> LuaResult<()> { ) -> LuaResult<()> {
let value: usize = match value { let value: usize = match value {
@ -36,18 +38,27 @@ impl NativeConvert for CType<usize> {
} }
}; };
unsafe { unsafe {
*(data_handle.get_pointer().byte_offset(offset).cast::<usize>()) = value; *(data_handle
.get_pointer()
.byte_offset(offset)
.cast::<usize>()) = value;
} }
Ok(()) Ok(())
} }
unsafe fn luavalue_from<'lua>( unsafe fn value_from_data<'lua>(
&self, &self,
lua: &'lua Lua, lua: &'lua Lua,
// _type_userdata: &LuaAnyUserData<'lua>, // _type_userdata: &LuaAnyUserData<'lua>,
offset: isize, offset: isize,
data_handle: &Ref<dyn NativeData>, data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> { ) -> LuaResult<LuaValue<'lua>> {
let value = unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::<usize>()).into_lua(lua)? }; let value = unsafe {
(*data_handle
.get_pointer()
.byte_offset(offset)
.cast::<usize>())
.into_lua(lua)?
};
Ok(value) Ok(value)
} }
} }

View file

@ -1,10 +1,10 @@
use super::super::bit_mask::*; use crate::ffi::bit_mask::*;
pub enum FfiBoxFlag { pub enum BoxDataFlag {
Leaked, Leaked,
} }
impl FfiBoxFlag { impl BoxDataFlag {
pub const fn value(&self) -> u8 { pub const fn value(&self) -> u8 {
match self { match self {
Self::Leaked => U8_MASK2, Self::Leaked => U8_MASK2,

View file

@ -2,21 +2,18 @@ use std::{alloc, alloc::Layout, boxed::Box, mem::ManuallyDrop, ptr};
use mlua::prelude::*; use mlua::prelude::*;
use super::{ use crate::{
association_names::REF_INNER, data::{association_names::REF_INNER, RefData, RefDataBounds, RefDataFlag},
bit_mask::*, ffi::{association, bit_mask::*, FfiData},
ffi_association::set_association,
ffi_ref::{FfiRef, FfiRefBounds, FfiRefFlag},
NativeData,
}; };
mod flag; mod flag;
pub use self::flag::FfiBoxFlag; pub use self::flag::BoxDataFlag;
// Ref which created by lua should not be dereferenceable, // Ref which created by lua should not be dereferenceable,
const BOX_REF_FLAGS: u8 = const BOX_REF_FLAGS: u8 =
FfiRefFlag::Readable.value() | FfiRefFlag::Writable.value() | FfiRefFlag::Offsetable.value(); RefDataFlag::Readable.value() | RefDataFlag::Writable.value() | RefDataFlag::Offsetable.value();
// It is an untyped, sized memory area that Lua can manage. // It is an untyped, sized memory area that Lua can manage.
// This area is safe within Lua. Operations have their boundaries checked. // This area is safe within Lua. Operations have their boundaries checked.
@ -27,14 +24,14 @@ const BOX_REF_FLAGS: u8 =
// rather, it creates more heap space, so it should be used appropriately // rather, it creates more heap space, so it should be used appropriately
// where necessary. // where necessary.
pub struct FfiBox { pub struct BoxData {
flags: u8, flags: u8,
data: ManuallyDrop<Box<[u8]>>, data: ManuallyDrop<Box<[u8]>>,
} }
const FFI_BOX_PRINT_MAX_LENGTH: usize = 1024; const FFI_BOX_PRINT_MAX_LENGTH: usize = 1024;
impl FfiBox { impl BoxData {
// For efficiency, it is initialized non-zeroed. // For efficiency, it is initialized non-zeroed.
pub fn new(size: usize) -> Self { pub fn new(size: usize) -> Self {
let slice = unsafe { let slice = unsafe {
@ -66,7 +63,7 @@ impl FfiBox {
} }
pub fn leak(&mut self) { pub fn leak(&mut self) {
self.flags = u8_set(self.flags, FfiBoxFlag::Leaked.value(), true); self.flags = u8_set(self.flags, BoxDataFlag::Leaked.value(), true);
} }
// Make FfiRef from box, with boundary checking // Make FfiRef from box, with boundary checking
@ -75,8 +72,8 @@ impl FfiBox {
this: LuaAnyUserData<'lua>, this: LuaAnyUserData<'lua>,
offset: Option<isize>, offset: Option<isize>,
) -> LuaResult<LuaAnyUserData<'lua>> { ) -> LuaResult<LuaAnyUserData<'lua>> {
let target = this.borrow::<FfiBox>()?; let target = this.borrow::<BoxData>()?;
let mut bounds = FfiRefBounds::new(0, target.size()); let mut bounds = RefDataBounds::new(0, target.size());
let mut ptr = unsafe { target.get_pointer() }; let mut ptr = unsafe { target.get_pointer() };
// Calculate offset // Calculate offset
@ -92,10 +89,10 @@ impl FfiBox {
bounds = bounds.offset(t); bounds = bounds.offset(t);
} }
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), BOX_REF_FLAGS, bounds))?; let luaref = lua.create_userdata(RefData::new(ptr.cast(), BOX_REF_FLAGS, bounds))?;
// Makes box alive longer then ref // Makes box alive longer then ref
set_association(lua, REF_INNER, &luaref, &this)?; association::set(lua, REF_INNER, &luaref, &this)?;
Ok(luaref) Ok(luaref)
} }
@ -115,15 +112,15 @@ impl FfiBox {
} }
} }
impl Drop for FfiBox { impl Drop for BoxData {
fn drop(&mut self) { fn drop(&mut self) {
if u8_test_not(self.flags, FfiBoxFlag::Leaked.value()) { if u8_test_not(self.flags, BoxDataFlag::Leaked.value()) {
unsafe { self.drop() }; unsafe { self.drop() };
} }
} }
} }
impl NativeData for FfiBox { impl FfiData for BoxData {
fn check_boundary(&self, offset: isize, size: usize) -> bool { fn check_boundary(&self, offset: isize, size: usize) -> bool {
if offset < 0 { if offset < 0 {
return false; return false;
@ -141,27 +138,27 @@ impl NativeData for FfiBox {
} }
} }
impl LuaUserData for FfiBox { impl LuaUserData for BoxData {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("size", |_, this| Ok(this.size())); fields.add_field_method_get("size", |_, this| Ok(this.size()));
} }
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
// For convenience, :zero returns self. // For convenience, :zero returns self.
methods.add_function_mut("zero", |_, this: LuaAnyUserData| { methods.add_function_mut("zero", |_, this: LuaAnyUserData| {
this.borrow_mut::<FfiBox>()?.zero(); this.borrow_mut::<BoxData>()?.zero();
Ok(this) Ok(this)
}); });
methods.add_function_mut( methods.add_function_mut(
"leak", "leak",
|lua, (this, offset): (LuaAnyUserData, Option<isize>)| { |lua, (this, offset): (LuaAnyUserData, Option<isize>)| {
this.borrow_mut::<FfiBox>()?.leak(); this.borrow_mut::<BoxData>()?.leak();
FfiBox::luaref(lua, this, offset) BoxData::luaref(lua, this, offset)
}, },
); );
methods.add_function( methods.add_function(
"ref", "ref",
|lua, (this, offset): (LuaAnyUserData, Option<isize>)| { |lua, (this, offset): (LuaAnyUserData, Option<isize>)| {
FfiBox::luaref(lua, this, offset) BoxData::luaref(lua, this, offset)
}, },
); );
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(this.stringify())); methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(this.stringify()));

View file

@ -7,20 +7,20 @@ use libffi::{
}; };
use mlua::prelude::*; use mlua::prelude::*;
use super::{GetNativeData, NativeArgInfo, NativeData, NativeResultInfo}; use super::{FfiArgInfo, FfiData, FfiResultInfo, GetFfiData};
pub struct FfiCallable { pub struct CallableData {
cif: *mut ffi_cif, cif: *mut ffi_cif,
arg_info_list: *const Vec<NativeArgInfo>, arg_info_list: *const Vec<FfiArgInfo>,
result_info: *const NativeResultInfo, result_info: *const FfiResultInfo,
code: CodePtr, code: CodePtr,
} }
impl FfiCallable { impl CallableData {
pub unsafe fn new( pub unsafe fn new(
cif: *mut ffi_cif, cif: *mut ffi_cif,
arg_info_list: *const Vec<NativeArgInfo>, arg_info_list: *const Vec<FfiArgInfo>,
result_info: *const NativeResultInfo, result_info: *const FfiResultInfo,
function_pointer: *const (), function_pointer: *const (),
) -> Self { ) -> Self {
Self { Self {
@ -33,7 +33,7 @@ impl FfiCallable {
// TODO? async call: if have no lua closure in arguments, fficallble can be called with async way // TODO? async call: if have no lua closure in arguments, fficallble can be called with async way
pub unsafe fn call(&self, result: &Ref<dyn NativeData>, args: LuaMultiValue) -> LuaResult<()> { pub unsafe fn call(&self, result: &Ref<dyn FfiData>, args: LuaMultiValue) -> LuaResult<()> {
result result
.check_boundary(0, self.result_info.as_ref().unwrap().size) .check_boundary(0, self.result_info.as_ref().unwrap().size)
.then_some(()) .then_some(())
@ -74,11 +74,11 @@ impl FfiCallable {
} }
} }
impl LuaUserData for FfiCallable { impl LuaUserData for CallableData {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_method( methods.add_method(
"call", "call",
|_lua, this: &FfiCallable, mut args: LuaMultiValue| { |_lua, this: &CallableData, mut args: LuaMultiValue| {
let result_userdata = args.pop_front().ok_or_else(|| { let result_userdata = args.pop_front().ok_or_else(|| {
LuaError::external("first argument must be result data handle") LuaError::external("first argument must be result data handle")
})?; })?;

View file

@ -8,17 +8,18 @@ use libffi::{
use mlua::prelude::*; use mlua::prelude::*;
use super::{ use super::{
ffi_ref::{FfiRefBounds, FfiRefFlag}, ref_data::{RefDataBounds, RefDataFlag},
FfiRef, FFI_STATUS_NAMES, RefData,
}; };
use crate::ffi::libffi_helper::FFI_STATUS_NAMES;
pub struct FfiClosure<'a> { pub struct ClosureData<'a> {
closure: *mut ffi_closure, closure: *mut ffi_closure,
code: CodePtr, code: CodePtr,
userdata: CallbackUserdata<'a>, userdata: CallbackUserdata<'a>,
} }
impl<'a> Drop for FfiClosure<'a> { impl<'a> Drop for ClosureData<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
closure_free(self.closure); closure_free(self.closure);
@ -35,7 +36,7 @@ pub struct CallbackUserdata<'a> {
pub result_size: usize, pub result_size: usize,
} }
const RESULT_REF_FLAGS: u8 = FfiRefFlag::Leaked.value() | FfiRefFlag::Writable.value(); const RESULT_REF_FLAGS: u8 = RefDataFlag::Leaked.value() | RefDataFlag::Writable.value();
unsafe extern "C" fn callback( unsafe extern "C" fn callback(
cif: *mut ffi_cif, cif: *mut ffi_cif,
@ -51,10 +52,10 @@ unsafe extern "C" fn callback(
args.push(LuaValue::UserData( args.push(LuaValue::UserData(
(*userdata) (*userdata)
.lua .lua
.create_userdata(FfiRef::new( .create_userdata(RefData::new(
result_pointer.cast::<()>(), result_pointer.cast::<()>(),
RESULT_REF_FLAGS, RESULT_REF_FLAGS,
FfiRefBounds::new(0, (*userdata).result_size), RefDataBounds::new(0, (*userdata).result_size),
)) ))
.unwrap(), .unwrap(),
)); ));
@ -64,10 +65,10 @@ unsafe extern "C" fn callback(
args.push(LuaValue::UserData( args.push(LuaValue::UserData(
(*userdata) (*userdata)
.lua .lua
.create_userdata(FfiRef::new( .create_userdata(RefData::new(
(*arg_pointers.add(i)).cast::<()>(), (*arg_pointers.add(i)).cast::<()>(),
(*userdata).arg_ref_flags.get(i).unwrap().to_owned(), (*userdata).arg_ref_flags.get(i).unwrap().to_owned(),
FfiRefBounds::new(0, (*userdata).arg_ref_size.get(i).unwrap().to_owned()), RefDataBounds::new(0, (*userdata).arg_ref_size.get(i).unwrap().to_owned()),
)) ))
.unwrap(), .unwrap(),
)); ));
@ -76,11 +77,11 @@ unsafe extern "C" fn callback(
(*userdata).func.call::<_, ()>(args).unwrap(); (*userdata).func.call::<_, ()>(args).unwrap();
} }
impl<'a> FfiClosure<'a> { impl<'a> ClosureData<'a> {
pub unsafe fn new( pub unsafe fn new(
cif: *mut ffi_cif, cif: *mut ffi_cif,
userdata: CallbackUserdata<'a>, userdata: CallbackUserdata<'a>,
) -> LuaResult<FfiClosure<'a>> { ) -> LuaResult<ClosureData<'a>> {
let (closure, code) = closure_alloc(); let (closure, code) = closure_alloc();
let prep_result = ffi_prep_closure_loc( let prep_result = ffi_prep_closure_loc(
closure, closure,
@ -96,7 +97,7 @@ impl<'a> FfiClosure<'a> {
FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[prep_result as usize] FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[prep_result as usize]
))) )))
} else { } else {
Ok(FfiClosure { Ok(ClosureData {
closure, closure,
code, code,
userdata, userdata,

View file

@ -2,19 +2,19 @@ use dlopen2::raw::Library;
use mlua::prelude::*; use mlua::prelude::*;
use super::{ use super::{
association,
association_names::SYM_INNER, association_names::SYM_INNER,
ffi_association::set_association, ref_data::{RefData, RefDataFlag, UNSIZED_BOUNDS},
ffi_ref::{FfiRef, FfiRefFlag, UNSIZED_BOUNDS},
}; };
const LIB_REF_FLAGS: u8 = FfiRefFlag::Offsetable.value() const LIB_REF_FLAGS: u8 = RefDataFlag::Offsetable.value()
| FfiRefFlag::Readable.value() | RefDataFlag::Readable.value()
| FfiRefFlag::Dereferenceable.value() | RefDataFlag::Dereferenceable.value()
| FfiRefFlag::Function.value(); | RefDataFlag::Function.value();
pub struct FfiLib(Library); pub struct LibData(Library);
impl FfiLib { impl LibData {
pub fn new(libname: String) -> LuaResult<Self> { pub fn new(libname: String) -> LuaResult<Self> {
match Library::open(libname) { match Library::open(libname) {
Ok(t) => Ok(Self(t)), Ok(t) => Ok(Self(t)),
@ -27,7 +27,7 @@ impl FfiLib {
this: LuaAnyUserData<'lua>, this: LuaAnyUserData<'lua>,
name: String, name: String,
) -> LuaResult<LuaAnyUserData<'lua>> { ) -> LuaResult<LuaAnyUserData<'lua>> {
let lib = this.borrow::<FfiLib>()?; let lib = this.borrow::<LibData>()?;
let sym = unsafe { let sym = unsafe {
lib.0 lib.0
.symbol::<*const ()>(name.as_str()) .symbol::<*const ()>(name.as_str())
@ -35,18 +35,18 @@ impl FfiLib {
}; };
let ffi_ref = let ffi_ref =
lua.create_userdata(FfiRef::new(sym.cast_mut(), LIB_REF_FLAGS, UNSIZED_BOUNDS))?; lua.create_userdata(RefData::new(sym.cast_mut(), LIB_REF_FLAGS, UNSIZED_BOUNDS))?;
set_association(lua, SYM_INNER, &ffi_ref, &this)?; association::set(lua, SYM_INNER, &ffi_ref, &this)?;
Ok(ffi_ref) Ok(ffi_ref)
} }
} }
impl LuaUserData for FfiLib { impl LuaUserData for LibData {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_function("find", |lua, (this, name): (LuaAnyUserData, String)| { methods.add_function("find", |lua, (this, name): (LuaAnyUserData, String)| {
FfiLib::get_sym(lua, this, name) LibData::get_sym(lua, this, name)
}); });
} }
} }

View file

@ -0,0 +1,53 @@
use std::cell::Ref;
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
use mlua::prelude::*;
mod box_data;
mod callable_data;
mod closure_data;
mod lib_data;
mod ref_data;
pub use crate::{
data::{
box_data::BoxData,
callable_data::CallableData,
closure_data::ClosureData,
lib_data::LibData,
ref_data::{create_nullptr, RefData, RefDataBounds, RefDataFlag},
},
ffi::{
association, num_cast, FfiArgInfo, FfiConvert, FfiData, FfiResultInfo, FfiSignedness,
FfiSize,
},
};
// Named registry table names
mod association_names {
pub const REF_INNER: &str = "__ref_inner";
pub const SYM_INNER: &str = "__syn_inner";
}
pub trait GetFfiData {
fn get_data_handle(&self) -> LuaResult<Ref<dyn FfiData>>;
}
impl GetFfiData for LuaAnyUserData<'_> {
fn get_data_handle(&self) -> LuaResult<Ref<dyn FfiData>> {
if self.is::<BoxData>() {
Ok(self.borrow::<BoxData>()? as Ref<dyn FfiData>)
} else if self.is::<RefData>() {
Ok(self.borrow::<RefData>()? as Ref<dyn FfiData>)
// } else if self.is::<FfiRaw>() {
// Ok(self.borrow::<FfiRaw>()? as Ref<dyn ReadWriteHandle>)
} else {
let config = ValueFormatConfig::new();
Err(LuaError::external(format!(
"Expected FfiBox, FfiRef or FfiRaw. got {}",
// what?
pretty_format_value(&LuaValue::UserData(self.to_owned()), &config)
)))
}
}
}

View file

@ -1,17 +1,17 @@
// Memory range for ref or box data. For boundary checking // Memory range for ref or box data. For boundary checking
pub struct FfiRefBounds { pub struct RefDataBounds {
// Indicates how much data is above the pointer // Indicates how much data is above the pointer
pub(crate) above: usize, pub(crate) above: usize,
// Indicates how much data is below the pointer // Indicates how much data is below the pointer
pub(crate) below: usize, pub(crate) below: usize,
} }
pub const UNSIZED_BOUNDS: FfiRefBounds = FfiRefBounds { pub const UNSIZED_BOUNDS: RefDataBounds = RefDataBounds {
above: usize::MAX, above: usize::MAX,
below: usize::MAX, below: usize::MAX,
}; };
impl FfiRefBounds { impl RefDataBounds {
pub fn new(above: usize, below: usize) -> Self { pub fn new(above: usize, below: usize) -> Self {
Self { above, below } Self { above, below }
} }
@ -88,7 +88,7 @@ impl FfiRefBounds {
} }
} }
impl Clone for FfiRefBounds { impl Clone for RefDataBounds {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
above: self.above, above: self.above,

View file

@ -1,6 +1,6 @@
use super::super::bit_mask::*; use crate::ffi::bit_mask::*;
pub enum FfiRefFlag { pub enum RefDataFlag {
Leaked, Leaked,
Dereferenceable, Dereferenceable,
Readable, Readable,
@ -9,7 +9,7 @@ pub enum FfiRefFlag {
Function, Function,
Uninit, Uninit,
} }
impl FfiRefFlag { impl RefDataFlag {
pub const fn value(&self) -> u8 { pub const fn value(&self) -> u8 {
match self { match self {
Self::Leaked => U8_MASK1, Self::Leaked => U8_MASK1,

View file

@ -2,24 +2,22 @@ use std::{mem::ManuallyDrop, ptr};
use mlua::prelude::*; use mlua::prelude::*;
use super::{ use crate::{
association_names::REF_INNER, data::association_names::REF_INNER,
bit_mask::{u8_test, u8_test_not}, ffi::{association, bit_mask::*, FfiData},
ffi_association::{get_association, set_association},
NativeData,
}; };
mod bounds; mod bounds;
mod flag; mod flag;
pub use self::{ pub use self::{
bounds::{FfiRefBounds, UNSIZED_BOUNDS}, bounds::{RefDataBounds, UNSIZED_BOUNDS},
flag::FfiRefFlag, flag::RefDataFlag,
}; };
// Box:ref():ref() should not be able to modify, Only for external // Box:ref():ref() should not be able to modify, Only for external
const BOX_REF_REF_FLAGS: u8 = 0; const BOX_REF_REF_FLAGS: u8 = 0;
const UNINIT_REF_FLAGS: u8 = FfiRefFlag::Uninit.value(); const UNINIT_REF_FLAGS: u8 = RefDataFlag::Uninit.value();
// | FfiRefFlag::Writable.value() // | FfiRefFlag::Writable.value()
// | FfiRefFlag::Readable.value() // | FfiRefFlag::Readable.value()
// | FfiRefFlag::Dereferenceable.value() // | FfiRefFlag::Dereferenceable.value()
@ -32,14 +30,14 @@ const UNINIT_REF_FLAGS: u8 = FfiRefFlag::Uninit.value();
// If it references an area managed by Lua, // If it references an area managed by Lua,
// the box will remain as long as this reference is alive. // the box will remain as long as this reference is alive.
pub struct FfiRef { pub struct RefData {
ptr: ManuallyDrop<Box<*mut ()>>, ptr: ManuallyDrop<Box<*mut ()>>,
pub flags: u8, pub flags: u8,
pub boundary: FfiRefBounds, pub boundary: RefDataBounds,
} }
impl FfiRef { impl RefData {
pub fn new(ptr: *mut (), flags: u8, boundary: FfiRefBounds) -> Self { pub fn new(ptr: *mut (), flags: u8, boundary: RefDataBounds) -> Self {
Self { Self {
ptr: ManuallyDrop::new(Box::new(ptr)), ptr: ManuallyDrop::new(Box::new(ptr)),
flags, flags,
@ -60,25 +58,25 @@ impl FfiRef {
lua: &'lua Lua, lua: &'lua Lua,
this: LuaAnyUserData<'lua>, this: LuaAnyUserData<'lua>,
) -> LuaResult<LuaAnyUserData<'lua>> { ) -> LuaResult<LuaAnyUserData<'lua>> {
let target = this.borrow::<FfiRef>()?; let target = this.borrow::<RefData>()?;
let luaref = lua.create_userdata(FfiRef::new( let luaref = lua.create_userdata(RefData::new(
ptr::from_ref(&target.ptr) as *mut (), ptr::from_ref(&target.ptr) as *mut (),
BOX_REF_REF_FLAGS, BOX_REF_REF_FLAGS,
FfiRefBounds { RefDataBounds {
below: 0, below: 0,
above: size_of::<usize>(), above: size_of::<usize>(),
}, },
))?; ))?;
// If the ref holds a box, make sure the new ref also holds the box by holding ref // If the ref holds a box, make sure the new ref also holds the box by holding ref
set_association(lua, REF_INNER, &luaref, &this)?; association::set(lua, REF_INNER, &luaref, &this)?;
Ok(luaref) Ok(luaref)
} }
pub unsafe fn deref(&self) -> LuaResult<Self> { pub unsafe fn deref(&self) -> LuaResult<Self> {
u8_test(self.flags, FfiRefFlag::Dereferenceable.value()) u8_test(self.flags, RefDataFlag::Dereferenceable.value())
.then_some(()) .then_some(())
.ok_or_else(|| LuaError::external("This pointer is not dereferenceable."))?; .ok_or_else(|| LuaError::external("This pointer is not dereferenceable."))?;
@ -106,7 +104,7 @@ impl FfiRef {
} }
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> { pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
u8_test(self.flags, FfiRefFlag::Offsetable.value()) u8_test(self.flags, RefDataFlag::Offsetable.value())
.then_some(()) .then_some(())
.ok_or_else(|| LuaError::external("This pointer is not offsetable."))?; .ok_or_else(|| LuaError::external("This pointer is not offsetable."))?;
@ -132,15 +130,15 @@ impl FfiRef {
} }
} }
impl Drop for FfiRef { impl Drop for RefData {
fn drop(&mut self) { fn drop(&mut self) {
if u8_test_not(self.flags, FfiRefFlag::Leaked.value()) { if u8_test_not(self.flags, RefDataFlag::Leaked.value()) {
unsafe { ManuallyDrop::drop(&mut self.ptr) }; unsafe { ManuallyDrop::drop(&mut self.ptr) };
} }
} }
} }
impl NativeData for FfiRef { impl FfiData for RefData {
fn check_boundary(&self, offset: isize, size: usize) -> bool { fn check_boundary(&self, offset: isize, size: usize) -> bool {
self.boundary.check_sized(offset, size) self.boundary.check_sized(offset, size)
} }
@ -148,42 +146,42 @@ impl NativeData for FfiRef {
**self.ptr **self.ptr
} }
fn is_readable(&self) -> bool { fn is_readable(&self) -> bool {
u8_test(self.flags, FfiRefFlag::Readable.value()) u8_test(self.flags, RefDataFlag::Readable.value())
} }
fn is_writable(&self) -> bool { fn is_writable(&self) -> bool {
u8_test(self.flags, FfiRefFlag::Writable.value()) u8_test(self.flags, RefDataFlag::Writable.value())
} }
} }
impl LuaUserData for FfiRef { impl LuaUserData for RefData {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
// FIXME: // FIXME:
methods.add_function("deref", |lua, this: LuaAnyUserData| { methods.add_function("deref", |lua, this: LuaAnyUserData| {
let inner = get_association(lua, REF_INNER, &this)?; let inner = association::get(lua, REF_INNER, &this)?;
let ffiref = this.borrow::<FfiRef>()?; let ffiref = this.borrow::<RefData>()?;
let result = lua.create_userdata(unsafe { ffiref.deref()? })?; let result = lua.create_userdata(unsafe { ffiref.deref()? })?;
if let Some(t) = inner { if let Some(t) = inner {
// if let Some(u) = get_association(lua, regname, value) {} // if let Some(u) = association::get(lua, regname, value) {}
set_association(lua, REF_INNER, &result, &t)?; association::set(lua, REF_INNER, &result, &t)?;
} }
Ok(result) Ok(result)
}); });
methods.add_function("offset", |lua, (this, offset): (LuaAnyUserData, isize)| { methods.add_function("offset", |lua, (this, offset): (LuaAnyUserData, isize)| {
let ffiref = unsafe { this.borrow::<FfiRef>()?.offset(offset)? }; let ffiref = unsafe { this.borrow::<RefData>()?.offset(offset)? };
let userdata = lua.create_userdata(ffiref)?; let userdata = lua.create_userdata(ffiref)?;
// If the ref holds a box, make sure the new ref also holds the box // If the ref holds a box, make sure the new ref also holds the box
if let Some(t) = get_association(lua, REF_INNER, &this)? { if let Some(t) = association::get(lua, REF_INNER, &this)? {
set_association(lua, REF_INNER, &userdata, t)?; association::set(lua, REF_INNER, &userdata, t)?;
} }
Ok(userdata) Ok(userdata)
}); });
// FIXME: // FIXME:
methods.add_function("ref", |lua, this: LuaAnyUserData| { methods.add_function("ref", |lua, this: LuaAnyUserData| {
let ffiref = FfiRef::luaref(lua, this)?; let ffiref = RefData::luaref(lua, this)?;
Ok(ffiref) Ok(ffiref)
}); });
methods.add_method("isNull", |_, this, ()| Ok(this.is_nullptr())); methods.add_method("isNull", |_, this, ()| Ok(this.is_nullptr()));
@ -192,7 +190,7 @@ impl LuaUserData for FfiRef {
pub fn create_nullptr(lua: &Lua) -> LuaResult<LuaAnyUserData> { pub fn create_nullptr(lua: &Lua) -> LuaResult<LuaAnyUserData> {
// https://en.cppreference.com/w/cpp/types/nullptr_t // https://en.cppreference.com/w/cpp/types/nullptr_t
lua.create_userdata(FfiRef::new( lua.create_userdata(RefData::new(
ptr::null_mut::<()>().cast(), ptr::null_mut::<()>().cast(),
0, 0,
// usize::MAX means that nullptr is can be 'any' pointer type // usize::MAX means that nullptr is can be 'any' pointer type

View file

@ -1,16 +1,16 @@
use super::NativeConvert; use super::FfiConvert;
pub struct FfiArgRefOption { pub struct FfiArgRefOption {
pub flag: u8, pub flag: u8,
} }
pub enum NativeArgType { pub enum FfiArgType {
FfiBox, FfiBox,
FfiRef(FfiArgRefOption), FfiRef(FfiArgRefOption),
} }
pub struct NativeArgInfo { pub struct FfiArgInfo {
pub conv: *const dyn NativeConvert, pub conv: *const dyn FfiConvert,
pub size: usize, pub size: usize,
// pub kind: NativeArgType, // pub kind: NativeArgType,
} }

View file

@ -29,12 +29,7 @@ use mlua::prelude::*;
// You can delete the relationship by changing 'associated' to nil // You can delete the relationship by changing 'associated' to nil
#[inline] #[inline]
pub fn set_association<'lua, T, U>( pub fn set<'lua, T, U>(lua: &'lua Lua, regname: &str, value: T, associated: U) -> LuaResult<()>
lua: &'lua Lua,
regname: &str,
value: T,
associated: U,
) -> LuaResult<()>
where where
T: IntoLua<'lua>, T: IntoLua<'lua>,
U: IntoLua<'lua>, U: IntoLua<'lua>,
@ -61,11 +56,7 @@ where
// If there is no table in registry, it returns None. // If there is no table in registry, it returns None.
// If there is no value in table, it returns LuaNil. // If there is no value in table, it returns LuaNil.
#[inline] #[inline]
pub fn get_association<'lua, T>( pub fn get<'lua, T>(lua: &'lua Lua, regname: &str, value: T) -> LuaResult<Option<LuaValue<'lua>>>
lua: &'lua Lua,
regname: &str,
value: T,
) -> LuaResult<Option<LuaValue<'lua>>>
where where
T: IntoLua<'lua>, T: IntoLua<'lua>,
{ {

View file

@ -0,0 +1,29 @@
#![allow(unused)]
pub const U8_MASK1: u8 = 1;
pub const U8_MASK2: u8 = 2;
pub const U8_MASK3: u8 = 4;
pub const U8_MASK4: u8 = 8;
pub const U8_MASK5: u8 = 16;
pub const U8_MASK6: u8 = 32;
pub const U8_MASK7: u8 = 64;
pub const U8_MASK8: u8 = 128;
#[inline]
pub fn u8_test(bits: u8, mask: u8) -> bool {
bits & mask != 0
}
#[inline]
pub fn u8_test_not(bits: u8, mask: u8) -> bool {
bits & mask == 0
}
#[inline]
pub fn u8_set(bits: u8, mask: u8, val: bool) -> u8 {
if val {
bits | mask
} else {
bits & !mask
}
}

View file

@ -0,0 +1,22 @@
use std::cell::Ref;
use mlua::prelude::*;
use num::cast::AsPrimitive;
use super::FfiData;
#[inline]
pub fn num_cast<From, Into>(from: &Ref<dyn FfiData>, into: &Ref<dyn FfiData>) -> LuaResult<()>
where
From: AsPrimitive<Into>,
Into: 'static + Copy,
{
let from_ptr = unsafe { from.get_pointer().cast::<From>() };
let into_ptr = unsafe { into.get_pointer().cast::<Into>() };
unsafe {
*into_ptr = (*from_ptr).as_();
}
Ok(())
}

View file

@ -1,29 +0,0 @@
#![allow(clippy::inline_always)]
use std::cell::Ref;
use mlua::prelude::*;
use num::cast::AsPrimitive;
use super::NativeData;
// Cast T as U
#[inline(always)]
pub fn native_num_cast<T, U>(
from: &Ref<dyn NativeData>,
into: &Ref<dyn NativeData>,
) -> LuaResult<()>
where
T: AsPrimitive<U>,
U: 'static + Copy,
{
let from_ptr = unsafe { from.get_pointer().cast::<T>() };
let into_ptr = unsafe { into.get_pointer().cast::<U>() };
unsafe {
*into_ptr = (*from_ptr).as_();
}
Ok(())
}

View file

@ -1,27 +0,0 @@
#![allow(clippy::inline_always)]
use std::cell::Ref;
use mlua::prelude::*;
use super::NativeData;
// Handle native data, provide type conversion between luavalue and native types
pub trait NativeConvert {
// Convert luavalue into data, then write into ptr
unsafe fn luavalue_into<'lua>(
&self,
lua: &'lua Lua,
offset: isize,
data_handle: &Ref<dyn NativeData>,
value: LuaValue<'lua>,
) -> LuaResult<()>;
// Read data from ptr, then convert into luavalue
unsafe fn luavalue_from<'lua>(
&self,
lua: &'lua Lua,
offset: isize,
data_handle: &Ref<dyn NativeData>,
) -> LuaResult<LuaValue<'lua>>;
}

View file

@ -1,40 +0,0 @@
use std::cell::Ref;
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
use mlua::prelude::*;
use super::super::{FfiBox, FfiRef};
pub trait NativeData {
fn check_boundary(&self, offset: isize, size: usize) -> bool;
unsafe fn get_pointer(&self) -> *mut ();
fn is_writable(&self) -> bool;
fn is_readable(&self) -> bool;
}
pub trait GetNativeData {
fn get_data_handle(&self) -> LuaResult<Ref<dyn NativeData>>;
}
// I tried to remove dyn (which have little bit costs)
// But, maybe this is best option for now.
// If remove dyn, we must spam self.is::<>() / self.borrow::<>()?
// more costly....
impl GetNativeData for LuaAnyUserData<'_> {
fn get_data_handle(&self) -> LuaResult<Ref<dyn NativeData>> {
if self.is::<FfiBox>() {
Ok(self.borrow::<FfiBox>()? as Ref<dyn NativeData>)
} else if self.is::<FfiRef>() {
Ok(self.borrow::<FfiRef>()? as Ref<dyn NativeData>)
// } else if self.is::<FfiRaw>() {
// Ok(self.borrow::<FfiRaw>()? as Ref<dyn ReadWriteHandle>)
} else {
let config = ValueFormatConfig::new();
Err(LuaError::external(format!(
"Expected FfiBox, FfiRef or FfiRaw. got {}",
// what?
pretty_format_value(&LuaValue::UserData(self.to_owned()), &config)
)))
}
}
}

View file

@ -1,25 +0,0 @@
mod arg;
mod cast;
mod convert;
mod data;
mod result;
pub trait NativeSize {
fn get_size(&self) -> usize;
}
pub trait NativeSignedness {
fn get_signedness(&self) -> bool {
false
}
}
pub use self::{
arg::NativeArgInfo,
cast::native_num_cast,
convert::NativeConvert,
data::GetNativeData,
data::NativeData,
result::NativeResultInfo,
// result::NativeResultType,
};

View file

@ -3,8 +3,6 @@ use std::ptr::{self, null_mut};
use libffi::{low, raw}; use libffi::{low, raw};
use mlua::prelude::*; use mlua::prelude::*;
use crate::ffi::FFI_STATUS_NAMES;
// Get ensured size of c-type (raw::libffi_type) // Get ensured size of c-type (raw::libffi_type)
// See: http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html // See: http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html
pub fn get_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult<usize> { pub fn get_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult<usize> {
@ -29,3 +27,11 @@ pub fn get_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult<usize> {
} }
pub const SIEE_OF_POINTER: usize = size_of::<*mut ()>(); pub const SIEE_OF_POINTER: usize = size_of::<*mut ()>();
// Converts ffi status into &str
pub const FFI_STATUS_NAMES: [&str; 4] = [
"ffi_status_FFI_OK",
"ffi_status_FFI_BAD_TYPEDEF",
"ffi_status_FFI_BAD_ABI",
"ffi_status_FFI_BAD_ARGTYPE",
];

View file

@ -1,71 +1,49 @@
pub mod ffi_association; use std::cell::Ref;
mod ffi_box;
mod ffi_callable;
mod ffi_closure;
mod ffi_lib;
mod ffi_native;
mod ffi_ref;
use mlua::prelude::*; use mlua::prelude::*;
pub use self::{ mod arg;
ffi_box::FfiBox, pub mod association;
ffi_callable::FfiCallable, pub mod bit_mask;
ffi_closure::FfiClosure, mod cast;
ffi_lib::FfiLib, pub mod libffi_helper;
ffi_native::{ mod result;
native_num_cast, GetNativeData, NativeArgInfo, NativeConvert, NativeData, NativeResultInfo,
NativeSignedness, NativeSize,
},
ffi_ref::{create_nullptr, FfiRef, FfiRefFlag},
};
// Named registry table names pub trait FfiSize {
mod association_names { fn get_size(&self) -> usize;
pub const REF_INNER: &str = "__ref_inner";
pub const SYM_INNER: &str = "__syn_inner";
} }
// Converts ffi status into &str pub trait FfiSignedness {
pub const FFI_STATUS_NAMES: [&str; 4] = [ fn get_signedness(&self) -> bool {
"ffi_status_FFI_OK", false
"ffi_status_FFI_BAD_TYPEDEF",
"ffi_status_FFI_BAD_ABI",
"ffi_status_FFI_BAD_ARGTYPE",
];
#[allow(unused)]
pub mod bit_mask {
pub const U8_MASK1: u8 = 1;
pub const U8_MASK2: u8 = 2;
pub const U8_MASK3: u8 = 4;
pub const U8_MASK4: u8 = 8;
pub const U8_MASK5: u8 = 16;
pub const U8_MASK6: u8 = 32;
pub const U8_MASK7: u8 = 64;
pub const U8_MASK8: u8 = 128;
#[inline]
pub fn u8_test(bits: u8, mask: u8) -> bool {
bits & mask != 0
}
#[inline]
pub fn u8_test_not(bits: u8, mask: u8) -> bool {
bits & mask == 0
}
#[inline]
pub fn u8_set(bits: u8, mask: u8, val: bool) -> u8 {
if val {
bits | mask
} else {
bits & !mask
}
} }
} }
#[inline] // Provide type conversion between luavalue and ffidata types
pub fn is_integer(num: LuaValue) -> bool { pub trait FfiConvert {
num.is_integer() // Write LuaValue into FfiData
unsafe fn value_into_data<'lua>(
&self,
lua: &'lua Lua,
offset: isize,
data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>,
) -> LuaResult<()>;
// Read LuaValue from FfiData
unsafe fn value_from_data<'lua>(
&self,
lua: &'lua Lua,
offset: isize,
data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>>;
} }
pub trait FfiData {
fn check_boundary(&self, offset: isize, size: usize) -> bool;
unsafe fn get_pointer(&self) -> *mut ();
fn is_writable(&self) -> bool;
fn is_readable(&self) -> bool;
}
pub use self::{arg::FfiArgInfo, cast::num_cast, result::FfiResultInfo};

View file

@ -1,12 +1,12 @@
use super::NativeConvert; use super::FfiConvert;
// pub enum NativeResultType { // pub enum NativeResultType {
// FfiBox, // FfiBox,
// FfiRef, // FfiRef,
// } // }
pub struct NativeResultInfo { pub struct FfiResultInfo {
pub conv: *const dyn NativeConvert, pub conv: *const dyn FfiConvert,
pub size: usize, pub size: usize,
// kind: NativeResultType, // kind: NativeResultType,
} }

View file

@ -1,16 +1,16 @@
#![allow(clippy::cargo_common_metadata)] #![allow(clippy::cargo_common_metadata)]
use ffi::FfiRef; use data::RefData;
use lune_utils::TableBuilder; use lune_utils::TableBuilder;
use mlua::prelude::*; use mlua::prelude::*;
mod c; mod c;
mod data;
mod ffi; mod ffi;
mod libffi_helper;
use crate::{ use crate::{
c::{export_ctypes, CFunc, CStruct}, c::{export_ctypes, CFnInfo, CStructInfo},
ffi::{create_nullptr, is_integer, FfiBox, FfiLib}, data::{create_nullptr, BoxData, LibData},
}; };
/** /**
@ -24,22 +24,21 @@ pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
let result = TableBuilder::new(lua)? let result = TableBuilder::new(lua)?
.with_values(export_ctypes(lua)?)? .with_values(export_ctypes(lua)?)?
.with_function("nullRef", |lua, ()| create_nullptr(lua))? .with_function("nullRef", |lua, ()| create_nullptr(lua))?
.with_function("box", |_lua, size: usize| Ok(FfiBox::new(size)))? .with_function("box", |_lua, size: usize| Ok(BoxData::new(size)))?
.with_function("open", |_lua, name: String| FfiLib::new(name))? .with_function("open", |_lua, name: String| LibData::new(name))?
.with_function("structInfo", |lua, types: LuaTable| { .with_function("structInfo", |lua, types: LuaTable| {
CStruct::from_table(lua, types) CStructInfo::from_table(lua, types)
})? })?
.with_function("uninitRef", |_lua, ()| Ok(FfiRef::new_uninit()))? .with_function("uninitRef", |_lua, ()| Ok(RefData::new_uninit()))?
.with_function("isInteger", |_lua, num: LuaValue| Ok(is_integer(num)))? .with_function("isInteger", |_lua, num: LuaValue| Ok(num.is_integer()))?
.with_function( .with_function("fnInfo", |lua, (args, ret): (LuaTable, LuaAnyUserData)| {
"funcInfo", CFnInfo::new_from_table(lua, args, ret)
|lua, (args, ret): (LuaTable, LuaAnyUserData)| CFunc::new_from_table(lua, args, ret), })?;
)?;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
let result = result.with_function("debug_associate", |lua, str: String| { let result = result.with_function("debug_associate", |lua, str: String| {
println!("WARNING: ffi.debug_associate is GC debug function, which only works for debug build. Do not use this function in production level codes."); println!("WARNING: ffi.debug_associate is GC debug function, which only works for debug build. Do not use this function in production level codes.");
crate::ffi::ffi_association::get_table(lua, str.as_ref()) ffi::association::get_table(lua, str.as_ref())
})?; })?;
result.build_readonly() result.build_readonly()

View file

@ -1,37 +1,57 @@
-- NOTE: T is a unique identifier for the `CType` and R is the closest Lua type. -- NOTE: T is a unique identifier for the `CType` and R is the closest Lua type.
export type CType<T, R> = { export type CTypeInfo<T, R> = {
size: number, size: number,
signedness: boolean, signedness: boolean,
ptr: (self: CType<T, R>) -> CPtr<R>, -- subtype
box: (self: CType<T, R>, val: R) -> Box, ptrInfo: (self: CTypeInfo<T, R>) -> CPtrInfo<CTypeInfo<T, R>>,
-- FIXME: recursive types; ud should be CTypes arrInfo: (self: CTypeInfo<T, R>, len: number) -> CArrInfo<CTypeInfo<T, R>, R>,
from: (self: CType<T, R>, ud: any, offset: number?) -> R,
into: (self: CType<T, R>, ud: any, value: R, offset: number?) -> (), -- realize
arr: (self: CType<T, R>, len: number) -> CArr<R>, box: (self: CTypeInfo<T, R>, val: R) -> Box,
-- FIXME: recursive types; intoType should be CTypes fromData: (self: CTypeInfo<T, R>, data: (Ref|Box), offset: number?) -> R,
cast: <F, I>(self: CType<T, R>, intoType: any, from: F, into: I) -> (), intoData: (self: CTypeInfo<T, R>, data: (Ref|Box), value: R, offset: number?) -> (),
-- FIXME: recursive types; 'intoType' should be CTypes
cast: (self: CTypeInfo<T, R>, intoType: any, fromData: (Ref|Box), intoData: (Ref|Box)) -> (),
} & { ["__phantom"]: T } } & { ["__phantom"]: T }
export type CPtr<T> = { export type CPtrInfo<T> = {
size: number, size: number,
inner: T?, inner: T,
-- subtype
-- FIXME: recursive types; 'any' should be CPtrInfo
arrInfo: (self: CPtrInfo<T>, len: number) -> any,
ptrInfo: (self: CPtrInfo<T>) -> any,
} }
export type CArr<T> = { export type CArrInfo<T, R> = {
size: number, size: number,
length: number, length: number,
inner: { T }?, inner: T,
offset: (self: CArr<T>, offset: number) -> number, -- subtype
ptr: (self: CArr<T>) -> CPtr<{ T }>, ptrInfo: (self: CArrInfo<T, R>) -> CPtrInfo<T>,
box: (self: CArr<T>, table: { T }) -> Box,
-- FIXME: recursive types; ud should be CTypes -- realize
from: (self: CArr<T>, ud: any, offset: number?) -> { T }, box: (self: CArrInfo<T, R>, table: { T }) -> Box,
into: (self: CArr<T>, ud: any, value: { T }, offset: number?) -> (), fromData: (self: CArrInfo<T, R>, data: (Ref|Box), offset: number?) -> { T },
intoData: (self: CArrInfo<T, R>, data: (Ref|Box), value: { T }, offset: number?) -> (),
offset: (self: CArrInfo<T, R>, offset: number) -> number,
} }
type NumCType<T> = CType<T, number> export type CFuncInfo = {
callable: (self: CFuncInfo, functionRef: Ref) -> Callable,
}
export type CStructInfo = {
arrInfo: (self: CStructInfo, len: number) -> CArrInfo<CStructInfo, {any}>,
ptrInfo: (self: CStructInfo) -> CPtrInfo<CStructInfo>,
}
type NumCType<T> = CTypeInfo<T, (number|any)>
-- Fixed size Rust-style types -- -- Fixed size Rust-style types --
export type u8 = NumCType<"u8"> export type u8 = NumCType<"u8">
@ -64,10 +84,6 @@ export type ulong = NumCType<"ulong">
export type longlong = NumCType<"longlong"> export type longlong = NumCType<"longlong">
export type ulonglong = NumCType<"ulonglong"> export type ulonglong = NumCType<"ulonglong">
export type CFn = {
caller: (self: CFn, fnPtr: Ref) -> Callable,
}
export type CTypes = export type CTypes =
| u8 | u8
| u16 | u16
@ -96,12 +112,15 @@ export type CTypes =
| ulong | ulong
| longlong | longlong
| ulonglong | ulonglong
| CArrInfo<CTypes, any>
| CPtrInfo<CTypes>
| CFuncInfo
export type Ref = { export type Ref = {
deref: (self: Ref) -> Ref, deref: (self: Ref) -> Ref,
offset: (self: Ref, offset: number) -> Ref, offset: (self: Ref, offset: number) -> Ref,
ref: (self: Ref) -> Ref, ref: (self: Ref) -> Ref,
isNullptr: (self: Ref) -> boolean, isNull: (self: Ref) -> boolean,
} }
export type Box = { export type Box = {
@ -112,12 +131,12 @@ export type Box = {
ref: (self: Box, offset: number?) -> Ref, ref: (self: Box, offset: number?) -> Ref,
} }
export type Library = { export type Lib = {
find: (self: Library, sym: string) -> Ref, find: (self: Lib, sym: string) -> Ref,
} }
export type Callable = { export type Callable = {
call: (self: Callable, retPtr: Ref, ...Box) -> (), call: (self: Callable, result: Ref, ...(Ref | Box))->();
} }
local ffi = {} local ffi = {}
@ -151,17 +170,19 @@ ffi.ulong = {} :: ulong
ffi.longlong = {} :: longlong ffi.longlong = {} :: longlong
ffi.ulonglong = {} :: ulonglong ffi.ulonglong = {} :: ulonglong
ffi.nullptr = {} :: Ref function ffi.nullRef(): Ref
return nil :: any
end
function ffi.box(size: number): Box function ffi.box(size: number): Box
return nil :: any return nil :: any
end end
function ffi.open(path: string): Library function ffi.open(name: string): Lib
return nil :: any return nil :: any
end end
function ffi.ref(): Ref function ffi.uninitRef(): Ref
return nil :: any return nil :: any
end end
@ -169,7 +190,7 @@ function ffi.isInteger<T>(val: T): boolean
return nil :: any return nil :: any
end end
function ffi.fn<T>(args: { CTypes }, ret: CTypes): CFn function ffi.funcInfo<T>(args: { CTypes }, ret: CTypes): CFuncInfo
return nil :: any return nil :: any
end end