mirror of
https://github.com/lune-org/lune.git
synced 2025-04-03 18:10:54 +01:00
Refactor and documenting code structure (#243)
This commit is contained in:
parent
a2a8176241
commit
da30dfb3f0
48 changed files with 803 additions and 701 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -807,7 +807,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.79",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
79
crates/lune-std-ffi/README.md
Normal file
79
crates/lune-std-ffi/README.md
Normal 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
|
|
@ -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)
|
|
@ -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?
|
|
|
@ -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)
|
||||||
},
|
},
|
|
@ -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!(
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
});
|
});
|
|
@ -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)?;
|
|
@ -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()));
|
|
@ -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)?
|
||||||
|
|
|
@ -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)?
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)? };
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
|
@ -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()));
|
|
@ -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")
|
||||||
})?;
|
})?;
|
|
@ -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,
|
|
@ -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)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
53
crates/lune-std-ffi/src/data/mod.rs
Normal file
53
crates/lune-std-ffi/src/data/mod.rs
Normal 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)
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
|
@ -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,
|
|
@ -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
|
|
@ -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,
|
||||||
}
|
}
|
|
@ -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>,
|
||||||
{
|
{
|
29
crates/lune-std-ffi/src/ffi/bit_mask.rs
Normal file
29
crates/lune-std-ffi/src/ffi/bit_mask.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
22
crates/lune-std-ffi/src/ffi/cast.rs
Normal file
22
crates/lune-std-ffi/src/ffi/cast.rs
Normal 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(())
|
||||||
|
}
|
|
@ -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(())
|
|
||||||
}
|
|
|
@ -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>>;
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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,
|
|
||||||
};
|
|
|
@ -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",
|
||||||
|
];
|
|
@ -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};
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue