Skip to content

Commit

Permalink
Improve code quality (lune-org#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
qwreey committed Nov 9, 2024
1 parent b503cc9 commit c3f255d
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 141 deletions.
97 changes: 62 additions & 35 deletions crates/lune-std-ffi/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<!-- markdownlint-disable MD033 -->

# `lune-std-ffi`

## Tests & Benchmarks
Expand All @@ -6,24 +8,18 @@ See [tests/ffi](../../tests/ffi/README.md)

## TODO

- CString
- [CString](./src/c/string_info.rs)
- Add buffer as owned data support
- Add math operation for numeric types

> Provide related methods: `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow` `:max` `:min` `:gt` `:lt`
> Luau cannot handle f64, i64 or i128, so we should provide math operation for it
- Add bit operation for box/ref

> Luau only supports 32bit bit operations
- Add wchar and wstring support

> For windows API support
- Add varargs support
- Array argument in cfn
- More box/ref methods
- [More box/ref methods](./src/data/helper.rs)
- writeString
- readString
- writeBase64
Expand All @@ -35,30 +31,53 @@ See [tests/ffi](../../tests/ffi/README.md)

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
**Structs:** C ABI type informations

- [**Struct `CArrInfo`:**](./src/c/arr_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` creator
- [**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`
- [**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`

<details><summary><a href="./src/c/helper.rs"><strong>Mod <code>helper.rs</code>: C ABI type helper</strong></a></summary>

- **Function `get_conv`, `get_conv_list`:**
get `FfiConvert` from userdata (CStruct, CArr, CPtr, CTypes)
- **Function `get_middle_type`, `get_middle_type_list`:**
get **`libffi::middle::Type`:** from userdata (CFn, CStruct, CArr, CPtr, CTypes)
- **Function `get_size`:**
get size from userdata
- **Function `has_void`:**
check table has void type
- **Function `stringify`:**
stringify any type userdata
- **Function `get_name`:**
get type name from ctype userdata, used for pretty-print
- **Function `is_ctype`:** check userdata is ctype
- **Mod `method_provider`:** provide common userdata method implements

</details>

#### /c/types

Export fixed-size source time known types and non-fixed compile time known types
Implememt type-casting for all CTypes
mod.rs implememts type-casting for all CTypes

**Mod `ctype_helper`:**
<details><summary><a href="./src/c/types/mod.rs"><strong>Mod <code>ctype_helper</code>:</strong></a> c type helper</summary>

- **Function `get_conv`:**
get _FfiConvert_ from some ctype userdata, used for struct and array conversion
get `FfiConvert` from ctype userdata, used for struct and array conversion
- **Function `get_middle_type`:**
get **`libffi::middle::Type`:** from ctype userdata
- **Function `get_size`:**
get size from some ctype userdata, used for call return and arguments boundary checking
get size from ctype userdata
- **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
get type name from ctype userdata, used for pretty-print
- **Function `is_ctype`:** check userdata is ctype

</details>

---

### /data
Expand All @@ -83,37 +102,45 @@ Implememt type-casting for all CTypes
- **Trait `FfiSize`**
- **Trait `FfiSignedness`**

**Structs:** Provide call information trait
<ul><li><details><summary><strong>Trait <code>FfiConvert</code>:</strong> Provide methods for read LuaValue from FfiData or write LuaValue into FfiData</summary>

- **Method `value_into_data`:** set data with lua value
- **Method `value_from_data`:** get lua value from data
- **Method `copy_data`:** copy sized data into another data
- **Method `stringify_data`:** stringify data with specific type

</details></li></ul>

**Structs:** Provide call information

- **Struct `FfiArg`:** Used for argument boundary checking and callback argument ref flag
- **Struct `FfiResult`:** Used for result boundary checking

**Trait `FfiData`:** Provide common data handle, including methods below
<details><summary><strong>Trait <code>FfiData</code>:</strong> Provide common data handle, including methods below</summary>

- **Method `check_inner_boundary`:** check boundary with offset and size
- **Method `get_inner_pointer`:** returns raw pointer `*mut ()`
- **Method `is_writable`**
- **Method `is_readable`**
- **Method `copy_from`** copy data from another data

- **Trait `FfiConvert`:** Provide methods for read LuaValue from FfiData or write LuaValue into FfiData
</details>

- **Method `value_into_data`:** set data with lua value
- **Method `value_from_data`:** get lua value from data
- **Method `copy_data`:** copy sized data into another data
- **Method `stringify_data`:** stringify data with specific type

> Note: `GetFfiData` trait in `data/mod.rs` provides `AnyUserData.get_data_handle() -> FfiData` method
> Note: `GetFfiData` trait in `data/mod.rs` provides `(LuaValue | LuaAnyUserData).get_data_handle() -> FfiData` method
**Mods:** Provide common helper functions

- [**Mod `association.rs`:**](./src/ffi/association.rs) GC utility, used for inner, ret and arg type holding in subtype
- [**Mod `bit_mask.rs`:**](./src/ffi/bit_mask.rs) u8 bitfield helper
- [**Mod `cast.rs`:**](./src/ffi/cast.rs) library
- [**Mod `cast.rs`:**](./src/ffi/cast.rs) num cast library wrapper
- **Function `num_cast<From, Into>(from: FfiData, from: FfiData)`:**
Cast number type value inno another number type
- [**Mod `libffi_helper.rs`:**](./src/ffi/libffi_helper.rs)
- **Const `FFI_STATUS_NAMES`:** Used for `ffi_status` stringify
- **Function `get_ensured_size`:** Returns ensured `ffi_type` size
- **Const `SIZE_OF_POINTER`:** Platform specific pointer size (Compile time known)
- **Function `ffi_status_assert`:** Convert `ffi_status` to `LuaResult<()>`

<ul><li><details><summary><a href="./src/c/struct_info.rs"><strong>Mod <code>libffi_helper.rs</code>:</strong></a> libffi library helper</summary>

- **Const `FFI_STATUS_NAMES`:** Stringify `ffi_status`
- **Function `get_ensured_size`:** Returns ensured size of `ffi_type`
- **Const `SIZE_OF_POINTER`:** Platform specific pointer size (Compile time known)
- **Function `ffi_status_assert`:** Convert `ffi_status` to `LuaResult<()>`

</details></li></ul>
48 changes: 11 additions & 37 deletions crates/lune-std-ffi/src/c/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
pub mod method_provider {
use super::*;

// Implement tostring
pub fn provide_to_string<'lua, Target, M>(methods: &mut M)
where
M: LuaUserDataMethods<'lua, Target>,
Expand All @@ -20,6 +21,7 @@ pub mod method_provider {
});
}

// Implement ptr method
pub fn provide_ptr<'lua, Target, M>(methods: &mut M)
where
M: LuaUserDataMethods<'lua, Target>,
Expand All @@ -29,6 +31,7 @@ pub mod method_provider {
});
}

// Implement arr method
pub fn provide_arr<'lua, Target, M>(methods: &mut M)
where
M: LuaUserDataMethods<'lua, Target>,
Expand All @@ -38,6 +41,7 @@ pub mod method_provider {
});
}

// Implement readData method
pub fn provide_read_data<'lua, Target, M>(methods: &mut M)
where
Target: FfiSize + FfiConvert,
Expand All @@ -61,6 +65,7 @@ pub mod method_provider {
);
}

// Implement writeData method
pub fn provide_write_data<'lua, Target, M>(methods: &mut M)
where
Target: FfiSize + FfiConvert,
Expand All @@ -85,6 +90,7 @@ pub mod method_provider {
);
}

// Implement copyData method
pub fn provide_copy_data<'lua, Target, M>(methods: &mut M)
where
Target: FfiSize + FfiConvert,
Expand Down Expand Up @@ -125,6 +131,7 @@ pub mod method_provider {
);
}

// Implement stringifyData method
pub fn provide_stringify_data<'lua, Target, M>(methods: &mut M)
where
Target: FfiSize + FfiConvert,
Expand All @@ -138,6 +145,7 @@ pub mod method_provider {
);
}

// Implement box method
pub fn provide_box<'lua, Target, M>(methods: &mut M)
where
Target: FfiSize + FfiConvert,
Expand All @@ -149,43 +157,9 @@ pub mod method_provider {
Ok(result)
});
}

// FIXME: Buffer support should be part of another PR
// pub fn provide_write_buffer<'lua, Target, M>(methods: &mut M)
// where
// Target: FfiSize + FfiConvert,
// M: LuaUserDataMethods<'lua, Target>,
// {
// methods.add_method(
// "writeBuffer",
// |lua, this, (target, value, offset): (LuaValue, LuaValue, Option<isize>)| {
// if !target.is_buffer() {
// return Err(LuaError::external(format!(
// "Argument target must be a buffer, got {}",
// target.type_name()
// )));
// }

// target.to_pointer()
// target.as_userdata().unwrap().to_pointer()
// let offset = offset.unwrap_or(0);

// let data_handle = &target.get_ffi_data()?;
// // use or functions
// if !data_handle.check_boundary(offset, this.get_size()) {
// return Err(LuaError::external("Out of bounds"));
// }
// if !data_handle.is_writable() {
// return Err(LuaError::external("Unwritable data handle"));
// }

// unsafe { this.value_into_data(lua, offset, data_handle, value) }
// },
// );
// }
}

pub fn get_userdata(value: LuaValue) -> LuaResult<LuaAnyUserData> {
fn get_userdata(value: LuaValue) -> LuaResult<LuaAnyUserData> {
if let LuaValue::UserData(field_type) = value {
Ok(field_type)
} else {
Expand All @@ -212,9 +186,9 @@ pub fn create_list<T>(
Ok(list)
}

// Get the NativeConvert handle from the ctype userData
// Get the dynamic FfiConvert handle from the userData
// This is intended to avoid lookup userdata and lua table every time. (eg: struct)
// The userdata must live longer than the NativeConvert handle
// The userdata must live longer than the FfiConvert handle
pub unsafe fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn FfiConvert> {
if userdata.is::<CStructInfo>() {
Ok(userdata.to_pointer().cast::<CStructInfo>() as *const dyn FfiConvert)
Expand Down
2 changes: 1 addition & 1 deletion crates/lune-std-ffi/src/c/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub use self::{
void_info::CVoidInfo,
};

// Named registry table names
// Named registry keys
mod association_names {
pub const CPTR_INNER: &str = "__cptr_inner";
pub const CARR_INNER: &str = "__carr_inner";
Expand Down
8 changes: 6 additions & 2 deletions crates/lune-std-ffi/src/c/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use crate::{
ffi::{libffi_helper::get_ensured_size, FfiConvert, FfiData, FfiSignedness, FfiSize},
};

// Cast native data
// Provide type casting
// This trait should be implemented for each types
pub trait CTypeCast {
#[inline(always)]
fn cast(
Expand Down Expand Up @@ -82,7 +83,7 @@ where
self.name
}

pub fn get_type(&self) -> Type {
pub fn get_middle_type(&self) -> Type {
self.middle_type.clone()
}
}
Expand Down Expand Up @@ -113,6 +114,9 @@ where
method_provider::provide_copy_data(methods);
method_provider::provide_stringify_data(methods);

// Math
// TODO: Math support for numeric types

methods.add_function(
"cast",
|_lua,
Expand Down
Loading

0 comments on commit c3f255d

Please sign in to comment.