Remove static ctype reduce duplicated code (#243)

This commit is contained in:
qwreey 2024-10-16 06:35:09 +00:00
parent 7d4e4a24b2
commit f094f2b74a
No known key found for this signature in database
GPG key ID: D28DB79297A214BD
4 changed files with 66 additions and 65 deletions

View file

@ -5,9 +5,8 @@ use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
use mlua::prelude::*; use mlua::prelude::*;
use super::{ use super::{
association_names::CTYPE_STATIC,
types::{get_ctype_conv, get_ctype_size}, types::{get_ctype_conv, get_ctype_size},
CArr, CPtr, CStruct, CTypeStatic, CArr, CPtr, CStruct,
}; };
use crate::ffi::{ffi_association::get_association, NativeConvert, NativeSize}; use crate::ffi::{ffi_association::get_association, NativeConvert, NativeSize};

View file

@ -6,36 +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::{association_names::CTYPE_STATIC, CArr, CPtr}; use super::{CArr, CPtr};
use crate::ffi::{ use crate::ffi::{FfiBox, GetNativeData, NativeConvert, NativeData, NativeSignedness, NativeSize};
ffi_association::set_association, FfiBox, GetNativeData, NativeConvert, NativeData,
NativeSignedness, NativeSize,
};
use crate::libffi_helper::get_ensured_size; use crate::libffi_helper::get_ensured_size;
// We can't get a CType<T> through mlua, something like
// .is::<CType<dyn Any>> will fail.
// So we need data that has a static type.
// each CType<T> userdata instance stores an instance of CTypeStatic.
#[allow(unused)]
pub struct CTypeStatic {
pub libffi_type: Type,
pub size: usize,
pub name: Option<&'static str>,
pub signedness: bool,
}
impl CTypeStatic {
fn new<T>(ctype: &CType<T>, signedness: bool) -> Self {
Self {
libffi_type: ctype.libffi_type.clone(),
size: ctype.size,
name: ctype.name,
signedness,
}
}
}
impl LuaUserData for CTypeStatic {}
// Cast native data // Cast native data
pub trait CTypeCast { pub trait CTypeCast {
#[inline(always)] #[inline(always)]
@ -96,12 +70,8 @@ where
name, name,
_phantom: PhantomData, _phantom: PhantomData,
}; };
let userdata_static =
lua.create_any_userdata(CTypeStatic::new::<T>(&ctype, ctype.get_signedness()))?;
let userdata = lua.create_userdata(ctype)?; let userdata = lua.create_userdata(ctype)?;
set_association(lua, CTYPE_STATIC, &userdata, &userdata_static)?;
Ok(userdata) Ok(userdata)
} }

View file

@ -12,7 +12,7 @@ pub use self::{
c_fn::CFn, c_fn::CFn,
c_ptr::CPtr, c_ptr::CPtr,
c_struct::CStruct, c_struct::CStruct,
c_type::{CType, CTypeCast, CTypeStatic}, c_type::{CType, CTypeCast},
}; };
pub use types::export_ctypes; pub use types::export_ctypes;
@ -22,7 +22,6 @@ 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";
pub const CSTRUCT_INNER: &str = "__cstruct_inner"; pub const CSTRUCT_INNER: &str = "__cstruct_inner";
pub const CTYPE_STATIC: &str = "__ctype_static";
pub const CFN_RESULT: &str = "__cfn_result"; pub const CFN_RESULT: &str = "__cfn_result";
pub const CFN_ARGS: &str = "__cfn_args"; pub const CFN_ARGS: &str = "__cfn_args";
pub const CALLABLE_REF: &str = "__callable_ref"; pub const CALLABLE_REF: &str = "__callable_ref";

View file

@ -25,6 +25,7 @@ pub mod u64;
pub mod u8; pub mod u8;
pub mod usize; pub mod usize;
// create CType userdata and export
macro_rules! create_ctypes { 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![$((
@ -33,8 +34,6 @@ macro_rules! create_ctypes {
),)*]) ),)*])
}; };
} }
// create CType userdata and export
pub fn export_ctypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> { pub fn export_ctypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
create_ctypes!( create_ctypes!(
lua, lua,
@ -56,10 +55,6 @@ pub fn export_ctypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>
("ulong", c_ulong, Type::c_ulong()), ("ulong", c_ulong, Type::c_ulong()),
("longlong", c_longlong, Type::c_longlong()), ("longlong", c_longlong, Type::c_longlong()),
("ulonglong", c_ulonglong, Type::c_ulonglong()), ("ulonglong", c_ulonglong, Type::c_ulonglong()),
// TODO: c_float and c_double sometime can be half and single,
// TODO: but libffi-rs doesn't support it. need work-around or drop support
("float", f32, Type::f32()),
("double", f64, Type::f64()),
// Export Source-time known c-types (fixed) // Export Source-time known c-types (fixed)
("u8", u8, Type::u8()), ("u8", u8, Type::u8()),
("u16", u16, Type::u16()), ("u16", u16, Type::u16()),
@ -75,25 +70,16 @@ pub fn export_ctypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>
("f32", f32, Type::f32()), ("f32", f32, Type::f32()),
("usize", usize, Type::usize()), ("usize", usize, Type::usize()),
("isize", isize, Type::isize()), ("isize", isize, Type::isize()),
// TODO: c_float and c_double sometime can be half and single,
// TODO: but libffi-rs doesn't support it. need work-around or drop support
("float", f32, Type::f32()),
("double", f64, Type::f64()),
) )
} }
macro_rules! define { // Implement type-casting for numeric ctypes
(@get_conv $userdata:ident, $( $rust_type:ty )*) => { macro_rules! define_cast_num {
$( if $userdata.is::<CType<$rust_type>>() { ($from_rust_type:ident, $self:ident, $from_ctype:ident, $into_ctype:ident, $from:ident, $into:ident, $($into_rust_type:ty)*) => {
Ok($userdata.to_pointer().cast::<CType<$rust_type>>() as *const dyn NativeConvert)
} else )* {
Err(LuaError::external("Unexpected type"))
}
};
(@get_size $userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() {
Ok($userdata.borrow::<CType<$rust_type>>()?.get_size())
} else )* {
Err(LuaError::external("Unexpected type"))
}
};
(@cast_num $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::<CType<$into_rust_type>>() {
native_num_cast::<$from_rust_type, $into_rust_type>($from, $into) native_num_cast::<$from_rust_type, $into_rust_type>($from, $into)
} else )* { } else )* {
@ -101,10 +87,9 @@ macro_rules! define {
} }
}; };
} }
impl<From> CTypeCast for CType<From>
impl<T> CTypeCast for CType<T>
where where
T: AsPrimitive<u8> From: AsPrimitive<u8>
+ AsPrimitive<u16> + AsPrimitive<u16>
+ AsPrimitive<u32> + AsPrimitive<u32>
+ AsPrimitive<u64> + AsPrimitive<u64>
@ -126,17 +111,65 @@ where
from: &Ref<dyn NativeData>, from: &Ref<dyn NativeData>,
into: &Ref<dyn NativeData>, into: &Ref<dyn NativeData>,
) -> LuaResult<()> { ) -> LuaResult<()> {
define!( define_cast_num!(
@cast_num T, self, into_ctype, from_ctype, from, into, From, self, into_ctype, from_ctype, 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
) )
} }
} }
// 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 {
($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() {
Ok($userdata.to_pointer().cast::<CType<$rust_type>>() as *const dyn NativeConvert)
} else )* {
Err(LuaError::external("Unexpected type"))
}
};
}
pub fn get_ctype_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn NativeConvert> { pub fn get_ctype_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn NativeConvert> {
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<*>)
macro_rules! define_get_size {
($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() {
Ok($userdata.borrow::<CType<$rust_type>>()?.get_size())
} else )* {
Err(LuaError::external("Unexpected type"))
}
};
} }
pub fn get_ctype_size(userdata: &LuaAnyUserData) -> LuaResult<usize> { pub fn get_ctype_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, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize)
}
// Get name of ctype
macro_rules! define_get_name {
($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() {
Ok($userdata.borrow::<CType<$rust_type>>()?.stringify())
} else )* {
Err(LuaError::external("Unexpected type"))
}
};
}
pub fn get_ctype_name(userdata: &LuaAnyUserData) -> LuaResult<&str> {
define_get_name!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize)
}
// Get libffi_type of ctype
macro_rules! define_get_libffi_type {
($userdata:ident, $( $rust_type:ty )*) => {
$( if $userdata.is::<CType<$rust_type>>() {
Ok($userdata.borrow::<CType<$rust_type>>()?.get_size())
} else )* {
Err(LuaError::external("Unexpected type"))
}
};
}
pub fn get_ctype_libffi_type(userdata: &LuaAnyUserData) -> LuaResult<usize> {
define_get_libffi_type!(userdata, u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 usize isize)
} }