Improve code quality (#243)

This commit is contained in:
qwreey 2024-11-09 15:43:15 +00:00
parent b503cc9f5b
commit c3f255db7a
No known key found for this signature in database
GPG key ID: D28DB79297A214BD
14 changed files with 157 additions and 142 deletions

View file

@ -1,3 +1,5 @@
<!-- markdownlint-disable MD033 -->
# `lune-std-ffi` # `lune-std-ffi`
## Tests & Benchmarks ## Tests & Benchmarks
@ -6,24 +8,18 @@ See [tests/ffi](../../tests/ffi/README.md)
## TODO ## TODO
- CString - [CString](./src/c/string_info.rs)
- Add buffer as owned data support - Add buffer as owned data support
- Add math operation for numeric types - Add math operation for numeric types
> Provide related methods: `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow` `:max` `:min` `:gt` `:lt` > 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 > Luau cannot handle f64, i64 or i128, so we should provide math operation for it
- Add bit operation for box/ref - Add bit operation for box/ref
> Luau only supports 32bit bit operations > Luau only supports 32bit bit operations
- Add wchar and wstring support - Add wchar and wstring support
> For windows API support > For windows API support
- Add varargs support - Add varargs support
- Array argument in cfn - Array argument in cfn
- More box/ref methods - [More box/ref methods](./src/data/helper.rs)
- writeString - writeString
- readString - readString
- writeBase64 - writeBase64
@ -35,30 +31,53 @@ See [tests/ffi](../../tests/ffi/README.md)
Define C-ABI type information and provide conversion and casting Define C-ABI type information and provide conversion and casting
- [**Struct ` CArrInfo`:**](./src/c/struct_info.rs) Represents C Array type **Structs:** C ABI type informations
- [**Struct ` CPtrInfo`:**](./src/c/ptr_info.rs) Represents C Pointer type
- [**Struct ` CFnInfo`:**](./src/c/fn_info.rs) Represents C Function signature - [**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 > provide `CallableData` and `ClosureData` creator
- [**Struct ` CStructInfo`:**](./src/c/struct_info.rs) Represents C Struct type - [**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 `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 #### /c/types
Export fixed-size source time known types and non-fixed compile time known 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`:** - **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_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`:** - **Function `get_middle_type`:**
get **`libffi::middle::Type`:** from some ctype userdata get **`libffi::middle::Type`:** from ctype userdata
- **Function `get_size`:**
get size from ctype userdata
- **Function `get_name`:**
get type name from ctype userdata, used for pretty-print
- **Function `is_ctype`:** check userdata is ctype - **Function `is_ctype`:** check userdata is ctype
</details>
--- ---
### /data ### /data
@ -83,12 +102,21 @@ Implememt type-casting for all CTypes
- **Trait `FfiSize`** - **Trait `FfiSize`**
- **Trait `FfiSignedness`** - **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 `FfiArg`:** Used for argument boundary checking and callback argument ref flag
- **Struct `FfiResult`:** Used for result boundary checking - **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 `check_inner_boundary`:** check boundary with offset and size
- **Method `get_inner_pointer`:** returns raw pointer `*mut ()` - **Method `get_inner_pointer`:** returns raw pointer `*mut ()`
@ -96,24 +124,23 @@ Implememt type-casting for all CTypes
- **Method `is_readable`** - **Method `is_readable`**
- **Method `copy_from`** copy data from another data - **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 > Note: `GetFfiData` trait in `data/mod.rs` provides `(LuaValue | LuaAnyUserData).get_data_handle() -> FfiData` method
- **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
**Mods:** Provide common helper functions **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 `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 `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)`:** - **Function `num_cast<From, Into>(from: FfiData, from: FfiData)`:**
Cast number type value inno another number type 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 <ul><li><details><summary><a href="./src/c/struct_info.rs"><strong>Mod <code>libffi_helper.rs</code>:</strong></a> libffi library helper</summary>
- **Function `get_ensured_size`:** Returns ensured `ffi_type` size
- **Const `SIZE_OF_POINTER`:** Platform specific pointer size (Compile time known) - **Const `FFI_STATUS_NAMES`:** Stringify `ffi_status`
- **Function `ffi_status_assert`:** Convert `ffi_status` to `LuaResult<()>` - **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>

View file

@ -11,6 +11,7 @@ use crate::{
pub mod method_provider { pub mod method_provider {
use super::*; use super::*;
// Implement tostring
pub fn provide_to_string<'lua, Target, M>(methods: &mut M) pub fn provide_to_string<'lua, Target, M>(methods: &mut M)
where where
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
@ -20,6 +21,7 @@ pub mod method_provider {
}); });
} }
// Implement ptr method
pub fn provide_ptr<'lua, Target, M>(methods: &mut M) pub fn provide_ptr<'lua, Target, M>(methods: &mut M)
where where
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
@ -29,6 +31,7 @@ pub mod method_provider {
}); });
} }
// Implement arr method
pub fn provide_arr<'lua, Target, M>(methods: &mut M) pub fn provide_arr<'lua, Target, M>(methods: &mut M)
where where
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
@ -38,6 +41,7 @@ pub mod method_provider {
}); });
} }
// Implement readData method
pub fn provide_read_data<'lua, Target, M>(methods: &mut M) pub fn provide_read_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert,
@ -61,6 +65,7 @@ pub mod method_provider {
); );
} }
// Implement writeData method
pub fn provide_write_data<'lua, Target, M>(methods: &mut M) pub fn provide_write_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert,
@ -85,6 +90,7 @@ pub mod method_provider {
); );
} }
// Implement copyData method
pub fn provide_copy_data<'lua, Target, M>(methods: &mut M) pub fn provide_copy_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert,
@ -125,6 +131,7 @@ pub mod method_provider {
); );
} }
// Implement stringifyData method
pub fn provide_stringify_data<'lua, Target, M>(methods: &mut M) pub fn provide_stringify_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert,
@ -138,6 +145,7 @@ pub mod method_provider {
); );
} }
// Implement box method
pub fn provide_box<'lua, Target, M>(methods: &mut M) pub fn provide_box<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert,
@ -149,43 +157,9 @@ pub mod method_provider {
Ok(result) 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 { if let LuaValue::UserData(field_type) = value {
Ok(field_type) Ok(field_type)
} else { } else {
@ -212,9 +186,9 @@ pub fn create_list<T>(
Ok(list) 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) // 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> { pub unsafe fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn FfiConvert> {
if userdata.is::<CStructInfo>() { if userdata.is::<CStructInfo>() {
Ok(userdata.to_pointer().cast::<CStructInfo>() as *const dyn FfiConvert) Ok(userdata.to_pointer().cast::<CStructInfo>() as *const dyn FfiConvert)

View file

@ -23,7 +23,7 @@ pub use self::{
void_info::CVoidInfo, void_info::CVoidInfo,
}; };
// Named registry table names // Named registry keys
mod association_names { mod association_names {
pub const CPTR_INNER: &str = "__cptr_inner"; pub const CPTR_INNER: &str = "__cptr_inner";
pub const CARR_INNER: &str = "__carr_inner"; pub const CARR_INNER: &str = "__carr_inner";

View file

@ -12,7 +12,8 @@ use crate::{
ffi::{libffi_helper::get_ensured_size, FfiConvert, FfiData, FfiSignedness, FfiSize}, 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 { pub trait CTypeCast {
#[inline(always)] #[inline(always)]
fn cast( fn cast(
@ -82,7 +83,7 @@ where
self.name self.name
} }
pub fn get_type(&self) -> Type { pub fn get_middle_type(&self) -> Type {
self.middle_type.clone() self.middle_type.clone()
} }
} }
@ -113,6 +114,9 @@ where
method_provider::provide_copy_data(methods); method_provider::provide_copy_data(methods);
method_provider::provide_stringify_data(methods); method_provider::provide_stringify_data(methods);
// Math
// TODO: Math support for numeric types
methods.add_function( methods.add_function(
"cast", "cast",
|_lua, |_lua,

View file

@ -10,20 +10,20 @@ use num::cast::AsPrimitive;
use super::{CTypeCast, CTypeInfo}; use super::{CTypeCast, CTypeInfo};
use crate::ffi::{num_cast, FfiConvert, FfiData, FfiSize}; use crate::ffi::{num_cast, FfiConvert, FfiData, FfiSize};
pub mod f32; mod f32;
pub mod f64; mod f64;
pub mod i128; mod i128;
pub mod i16; mod i16;
pub mod i32; mod i32;
pub mod i64; mod i64;
pub mod i8; mod i8;
pub mod isize; mod isize;
pub mod u128; mod u128;
pub mod u16; mod u16;
pub mod u32; mod u32;
pub mod u64; mod u64;
pub mod u8; mod u8;
pub mod usize; mod usize;
// CType userdata export // CType userdata export
macro_rules! create_ctypes { macro_rules! create_ctypes {
@ -92,20 +92,20 @@ macro_rules! define_cast_num {
} }
impl<From> CTypeCast for CTypeInfo<From> impl<From> CTypeCast for CTypeInfo<From>
where where
From: AsPrimitive<u8> From: AsPrimitive<f32>
+ AsPrimitive<u16> + AsPrimitive<f64>
+ AsPrimitive<u32> + AsPrimitive<i128>
+ AsPrimitive<u64>
+ AsPrimitive<u128>
+ AsPrimitive<i8>
+ AsPrimitive<i16> + AsPrimitive<i16>
+ AsPrimitive<i32> + AsPrimitive<i32>
+ AsPrimitive<i64> + AsPrimitive<i64>
+ AsPrimitive<i128> + AsPrimitive<i8>
+ AsPrimitive<f32> + AsPrimitive<isize>
+ AsPrimitive<f64> + AsPrimitive<u128>
+ AsPrimitive<usize> + AsPrimitive<u16>
+ AsPrimitive<isize>, + AsPrimitive<u32>
+ AsPrimitive<u64>
+ AsPrimitive<u8>
+ AsPrimitive<usize>,
{ {
fn cast( fn cast(
&self, &self,
@ -118,7 +118,7 @@ where
) -> LuaResult<()> { ) -> LuaResult<()> {
define_cast_num!( define_cast_num!(
From, self, from_info, into_info, from, into, from_offset, into_offset, From, self, from_info, into_info, from, into, from_offset, into_offset,
u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize f32 f64 i128 i16 i32 i64 i8 isize u128 u16 u32 u64 u8 usize
) )
} }
} }
@ -138,7 +138,22 @@ pub mod ctype_helper {
} }
#[inline] #[inline]
pub fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn FfiConvert> { 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, f32 f64 i128 i16 i32 i64 i8 isize u128 u16 u32 u64 u8 usize)
}
// Get libffi_type of ctype
macro_rules! define_get_middle_type {
($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CTypeInfo<$rust_type>>() {
Ok(Some($userdata.borrow::<CTypeInfo<$rust_type>>()?.get_middle_type()))
} else )* {
Ok(None)
}
};
}
#[inline]
pub fn get_middle_type(userdata: &LuaAnyUserData) -> LuaResult<Option<Type>> {
define_get_middle_type!(userdata, f32 f64 i128 i16 i32 i64 i8 isize u128 u16 u32 u64 u8 usize)
} }
// Get size of ctype (not including struct, arr, ... only CType<*>) // Get size of ctype (not including struct, arr, ... only CType<*>)
@ -153,7 +168,7 @@ pub mod ctype_helper {
} }
#[inline] #[inline]
pub fn get_size(userdata: &LuaAnyUserData) -> LuaResult<usize> { pub fn get_size(userdata: &LuaAnyUserData) -> LuaResult<usize> {
define_get_size!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize) define_get_size!(userdata, f32 f64 i128 i16 i32 i64 i8 isize u128 u16 u32 u64 u8 usize)
} }
// Get name of ctype // Get name of ctype
@ -168,22 +183,7 @@ pub mod ctype_helper {
} }
#[inline] #[inline]
pub fn get_name(userdata: &LuaAnyUserData) -> LuaResult<Option<&'static str>> { pub fn get_name(userdata: &LuaAnyUserData) -> LuaResult<Option<&'static str>> {
define_get_name!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize) define_get_name!(userdata, f32 f64 i128 i16 i32 i64 i8 isize u128 u16 u32 u64 u8 usize)
}
// Get libffi_type of ctype
macro_rules! define_get_middle_type {
($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CTypeInfo<$rust_type>>() {
Ok(Some($userdata.borrow::<CTypeInfo<$rust_type>>()?.get_type()))
} else )* {
Ok(None)
}
};
}
#[inline]
pub fn get_middle_type(userdata: &LuaAnyUserData) -> LuaResult<Option<Type>> {
define_get_middle_type!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize)
} }
// Check whether userdata is ctype or not // Check whether userdata is ctype or not
@ -198,6 +198,6 @@ pub mod ctype_helper {
} }
#[inline] #[inline]
pub fn is_ctype(userdata: &LuaAnyUserData) -> bool { pub fn is_ctype(userdata: &LuaAnyUserData) -> bool {
define_is_ctype!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize) define_is_ctype!(userdata, f32 f64 i128 i16 i32 i64 i8 isize u128 u16 u32 u64 u8 usize)
} }
} }

View file

@ -7,7 +7,7 @@ pub enum BoxFlag {
impl BoxFlag { impl BoxFlag {
pub const fn value(&self) -> u8 { pub const fn value(&self) -> u8 {
match self { match self {
Self::Leaked => U8_MASK2, Self::Leaked => U8_MASK1,
} }
} }
} }

View file

@ -73,7 +73,7 @@ impl BoxData {
// Calculate offset // Calculate offset
if let Some(t) = offset { if let Some(t) = offset {
if !bounds.check_boundary(t) { if !bounds.check_offset(t) {
return Err(LuaError::external(format!( return Err(LuaError::external(format!(
"Offset out of bounds (box.size: {}, got {})", "Offset out of bounds (box.size: {}, got {})",
target.size(), target.size(),
@ -113,7 +113,6 @@ impl Drop for BoxData {
} }
impl FfiData for BoxData { impl FfiData for BoxData {
#[inline]
fn check_inner_boundary(&self, offset: isize, size: usize) -> bool { fn check_inner_boundary(&self, offset: isize, size: usize) -> bool {
if offset < 0 { if offset < 0 {
return false; return false;
@ -124,11 +123,9 @@ impl FfiData for BoxData {
unsafe fn get_inner_pointer(&self) -> *mut () { unsafe fn get_inner_pointer(&self) -> *mut () {
self.data.as_ptr().cast_mut().cast::<()>() self.data.as_ptr().cast_mut().cast::<()>()
} }
#[inline]
fn is_readable(&self) -> bool { fn is_readable(&self) -> bool {
true true
} }
#[inline]
fn is_writable(&self) -> bool { fn is_writable(&self) -> bool {
true true
} }

View file

@ -8,7 +8,7 @@ use libffi::{
use mlua::prelude::*; use mlua::prelude::*;
use super::{ use super::{
association_names::CLSOURE_REF_INNER, association_names::REF_INNER,
ref_data::{RefBounds, RefData, RefFlag, UNSIZED_BOUNDS}, ref_data::{RefBounds, RefData, RefFlag, UNSIZED_BOUNDS},
}; };
use crate::ffi::{ use crate::ffi::{
@ -145,7 +145,7 @@ impl LuaUserData for ClosureData {
CLOSURE_REF_FLAGS, CLOSURE_REF_FLAGS,
UNSIZED_BOUNDS, UNSIZED_BOUNDS,
))?; ))?;
association::set(lua, CLSOURE_REF_INNER, &ref_data, &this)?; association::set(lua, REF_INNER, &ref_data, &this)?;
Ok(ref_data) Ok(ref_data)
}); });
} }

View file

@ -38,4 +38,7 @@ pub mod method_provider {
}, },
); );
} }
// TODO: writeString, readString, writeBase64 and readBase64 methods
// TODO: Bit operation support
} }

View file

@ -19,11 +19,10 @@ pub use self::{
}; };
use crate::ffi::FfiData; use crate::ffi::FfiData;
// Named registry table names // Named registry keys
mod association_names { mod association_names {
pub const REF_INNER: &str = "__ref_inner"; pub const REF_INNER: &str = "__ref_inner";
pub const SYM_INNER: &str = "__syn_inner"; pub const SYM_INNER: &str = "__syn_inner";
pub const CLSOURE_REF_INNER: &str = "__closure_ref_inner";
} }
// Get dynamic FfiData handle from LuaValue and LuaAnyUserData // Get dynamic FfiData handle from LuaValue and LuaAnyUserData

View file

@ -1,8 +1,8 @@
// Memory boundaries // Memory boundaries
pub struct RefBounds { pub struct RefBounds {
// How much data available above // How much bytes available above
pub(crate) above: usize, pub(crate) above: usize,
// How much data available below // How much bytes available below
pub(crate) below: usize, pub(crate) below: usize,
} }
@ -16,9 +16,9 @@ impl RefBounds {
Self { above, below } Self { above, below }
} }
// Check boundary // Check offset is in boundary
#[inline] #[inline]
pub fn check_boundary(&self, offset: isize) -> bool { pub fn check_offset(&self, offset: isize) -> bool {
let offset_abs = offset.unsigned_abs(); let offset_abs = offset.unsigned_abs();
match offset.signum() { match offset.signum() {
-1 => self.above >= offset_abs, -1 => self.above >= offset_abs,
@ -52,8 +52,21 @@ impl RefBounds {
end <= 0 || self.below >= end.unsigned_abs() end <= 0 || self.below >= end.unsigned_abs()
} }
// Calculate new boundaries with bounds and offset // Calculate new boundaries with offset
// No boundary checking in here // No boundary checking in here
//
// Above = 3
// ∧ ───∧───
// -3│ │ New above = 2
// -2│ │
// -1│ <────── Offset = -1
// 0│ │
// 1│ │
// 2│ │
// 3│ │ New below = 4
// ───∨───
// Below = 3
//
#[inline] #[inline]
pub fn offset(&self, offset: isize) -> Self { pub fn offset(&self, offset: isize) -> Self {
let sign = offset.signum(); let sign = offset.signum();

View file

@ -8,6 +8,7 @@ pub enum RefFlag {
Offsetable, Offsetable,
Function, Function,
} }
impl RefFlag { impl RefFlag {
pub const fn value(&self) -> u8 { pub const fn value(&self) -> u8 {
match self { match self {

View file

@ -41,7 +41,7 @@ impl RefData {
} }
} }
// Create reference of this reference box // Create reference of this reference
pub fn luaref<'lua>( pub fn luaref<'lua>(
lua: &'lua Lua, lua: &'lua Lua,
this: LuaAnyUserData<'lua>, this: LuaAnyUserData<'lua>,
@ -57,7 +57,7 @@ impl RefData {
}, },
))?; ))?;
// Make new reference live longer then this reference // Make sure new reference live longer then this reference
association::set(lua, REF_INNER, &luaref, &this)?; association::set(lua, REF_INNER, &luaref, &this)?;
Ok(luaref) Ok(luaref)
@ -100,7 +100,7 @@ impl RefData {
} }
// Check boundary // Check boundary
if !self.boundary.check_boundary(offset) { if !self.boundary.check_offset(offset) {
return Err(LuaError::external(format!( return Err(LuaError::external(format!(
"Offset out of bounds (high: {}, low: {}, got {})", "Offset out of bounds (high: {}, low: {}, got {})",
self.boundary.above, self.boundary.below, offset self.boundary.above, self.boundary.below, offset
@ -130,7 +130,6 @@ impl Drop for RefData {
} }
impl FfiData for RefData { impl FfiData for RefData {
#[inline]
fn check_inner_boundary(&self, offset: isize, size: usize) -> bool { fn check_inner_boundary(&self, offset: isize, size: usize) -> bool {
self.boundary.check_sized(offset, size) self.boundary.check_sized(offset, size)
} }
@ -138,11 +137,9 @@ impl FfiData for RefData {
unsafe fn get_inner_pointer(&self) -> *mut () { unsafe fn get_inner_pointer(&self) -> *mut () {
**self.ptr **self.ptr
} }
#[inline]
fn is_readable(&self) -> bool { fn is_readable(&self) -> bool {
u8_test(self.flags, RefFlag::Readable.value()) u8_test(self.flags, RefFlag::Readable.value())
} }
#[inline]
fn is_writable(&self) -> bool { fn is_writable(&self) -> bool {
u8_test(self.flags, RefFlag::Writable.value()) u8_test(self.flags, RefFlag::Writable.value())
} }

View file

@ -23,7 +23,7 @@ pub fn get_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult<usize> {
} }
// Converts ffi status into &str for formatting // Converts ffi status into &str for formatting
pub const FFI_STATUS_NAMES: [&str; 4] = [ const FFI_STATUS_NAMES: [&str; 4] = [
"ffi_status_FFI_OK", "ffi_status_FFI_OK",
"ffi_status_FFI_BAD_TYPEDEF", "ffi_status_FFI_BAD_TYPEDEF",
"ffi_status_FFI_BAD_ABI", "ffi_status_FFI_BAD_ABI",