Skip to content

Commit d60a1b9

Browse files
committed
Use CType<T> instead of CType (#243)
1 parent 26706d9 commit d60a1b9

File tree

9 files changed

+128
-202
lines changed

9 files changed

+128
-202
lines changed

crates/lune-std-ffi/src/c/c_arr.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::any::Any;
2+
13
use libffi::middle::Type;
24
use mlua::prelude::*;
35

@@ -54,13 +56,13 @@ impl CArr {
5456
Ok(carr)
5557
}
5658

57-
pub fn get_type(&self) -> Type {
58-
self.struct_type.clone()
59+
pub fn get_type(&self) -> &Type {
60+
&self.struct_type
5961
}
6062

61-
// pub fn get_element_type(&self) -> Type {
62-
// self.element_type.clone()
63-
// }
63+
pub fn get_element_type(&self) -> &Type {
64+
&self.element_type
65+
}
6466

6567
// Stringify cstruct for pretty printing something like:
6668
// <CStruct( u8, i32, size = 8 )>
@@ -73,7 +75,7 @@ impl CArr {
7375
.as_userdata()
7476
.ok_or(LuaError::external("failed to get inner type userdata."))?;
7577

76-
if inner.is::<CType>() {
78+
if inner.is::<CType<dyn Any>>() {
7779
Ok(format!(
7880
" {} ; {} ",
7981
stringify_userdata(inner)?,

crates/lune-std-ffi/src/c/c_helper.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::any::Any;
12
use std::ptr::{self, null_mut};
23

34
use libffi::{low, middle::Type, raw};
@@ -37,11 +38,11 @@ pub fn type_list_from_table(table: &LuaTable) -> LuaResult<Vec<Type>> {
3738
// get libffi_type from any c-type userdata
3839
pub fn type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult<Type> {
3940
if userdata.is::<CStruct>() {
40-
Ok(userdata.borrow::<CStruct>()?.get_type())
41-
} else if userdata.is::<CType>() {
42-
Ok(userdata.borrow::<CType>()?.get_type())
41+
Ok(userdata.borrow::<CStruct>()?.get_type().to_owned())
42+
} else if userdata.is::<CType<dyn Any>>() {
43+
Ok(userdata.borrow::<CType<dyn Any>>()?.get_type().to_owned())
4344
} else if userdata.is::<CArr>() {
44-
Ok(userdata.borrow::<CArr>()?.get_type())
45+
Ok(userdata.borrow::<CArr>()?.get_type().to_owned())
4546
} else if userdata.is::<CPtr>() {
4647
Ok(CPtr::get_type())
4748
} else {
@@ -59,9 +60,10 @@ pub fn type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult<Type> {
5960

6061
// stringify any c-type userdata (for recursive)
6162
pub fn stringify_userdata(userdata: &LuaAnyUserData) -> LuaResult<String> {
62-
if userdata.is::<CType>() {
63-
let name = userdata.borrow::<CType>()?.stringify();
64-
Ok(name)
63+
if userdata.is::<CType<dyn Any>>() {
64+
Ok(String::from(
65+
userdata.borrow::<CType<dyn Any>>()?.stringify(),
66+
))
6567
} else if userdata.is::<CStruct>() {
6668
let name = CStruct::stringify(userdata)?;
6769
Ok(name)
@@ -80,7 +82,7 @@ pub fn stringify_userdata(userdata: &LuaAnyUserData) -> LuaResult<String> {
8082
pub fn name_from_userdata(userdata: &LuaAnyUserData) -> String {
8183
if userdata.is::<CStruct>() {
8284
String::from("CStruct")
83-
} else if userdata.is::<CType>() {
85+
} else if userdata.is::<CType<dyn Any>>() {
8486
String::from("CType")
8587
} else if userdata.is::<CArr>() {
8688
String::from("CArr")

crates/lune-std-ffi/src/c/c_struct.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
#![allow(clippy::cargo_common_metadata)]
22

3-
use std::{borrow::Borrow, vec::Vec};
3+
use std::any::Any;
4+
use std::vec::Vec;
45

5-
use libffi::{
6-
low,
7-
middle::{Cif, Type},
8-
raw,
9-
};
6+
use libffi::{low, middle::Type, raw};
107
use mlua::prelude::*;
118

129
use super::association_names::CSTRUCT_INNER;
@@ -20,22 +17,22 @@ use crate::ffi::ffi_helper::FFI_STATUS_NAMES;
2017
pub struct CStruct {
2118
// libffi_cif: Cif,
2219
fields: Vec<Type>,
23-
libffi_type: Type,
20+
struct_type: Type,
2421
offsets: Vec<usize>,
2522
size: usize,
2623
}
2724

2825
impl CStruct {
2926
pub fn new(fields: Vec<Type>) -> LuaResult<Self> {
30-
let libffi_type = Type::structure(fields.iter().cloned());
27+
let struct_type = Type::structure(fields.iter().cloned());
3128
// let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
3229

3330
// Get field offsets with ffi_get_struct_offsets
3431
let mut offsets = Vec::<usize>::with_capacity(fields.len());
3532
unsafe {
3633
let offset_result: raw::ffi_status = raw::ffi_get_struct_offsets(
3734
low::ffi_abi_FFI_DEFAULT_ABI,
38-
libffi_type.as_raw_ptr(),
35+
struct_type.as_raw_ptr(),
3936
offsets.as_mut_ptr(),
4037
);
4138
if offset_result != raw::ffi_status_FFI_OK {
@@ -49,12 +46,12 @@ impl CStruct {
4946

5047
// Get tailing padded size of struct
5148
// See http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html
52-
let size = unsafe { (*libffi_type.as_raw_ptr()).size };
49+
let size = unsafe { (*struct_type.as_raw_ptr()).size };
5350

5451
Ok(Self {
5552
// libffi_cif: libffi_cfi,
5653
fields,
57-
libffi_type,
54+
struct_type,
5855
offsets,
5956
size,
6057
})
@@ -85,7 +82,7 @@ impl CStruct {
8582
let mut result = String::from(" ");
8683
for i in 0..table.raw_len() {
8784
let child: LuaAnyUserData = table.raw_get(i + 1)?;
88-
if child.is::<CType>() {
85+
if child.is::<CType<dyn Any>>() {
8986
result.push_str(format!("{}, ", stringify_userdata(&child)?).as_str());
9087
} else {
9188
result.push_str(
@@ -117,8 +114,12 @@ impl CStruct {
117114
Ok(offset)
118115
}
119116

120-
pub fn get_type(&self) -> Type {
121-
self.libffi_type.clone()
117+
pub fn get_fields(&self) -> &Vec<Type> {
118+
&self.fields
119+
}
120+
121+
pub fn get_type(&self) -> &Type {
122+
&self.struct_type
122123
}
123124
}
124125

crates/lune-std-ffi/src/c/c_type.rs

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![allow(clippy::cargo_common_metadata)]
22

3+
use std::marker::PhantomData;
4+
35
use libffi::middle::Type;
46
use mlua::prelude::*;
57

@@ -8,106 +10,104 @@ use super::c_helper::get_ensured_size;
810
use super::c_ptr::CPtr;
911
use crate::ffi::ffi_helper::get_ptr_from_userdata;
1012

11-
pub struct CType {
13+
pub struct CType<T: ?Sized> {
1214
// for ffi_ptrarray_to_raw?
1315
// libffi_cif: Cif,
1416
libffi_type: Type,
1517
size: usize,
16-
name: Option<String>,
17-
18-
// Write converted data from luavalue into some ptr
19-
pub luavalue_into_ptr: fn(value: LuaValue, ptr: *mut ()) -> LuaResult<()>,
20-
21-
// Read luavalue from some ptr
22-
pub ptr_into_luavalue: fn(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue>,
18+
name: Option<&'static str>,
19+
_phantom: PhantomData<T>,
2320
}
2421

25-
impl CType {
26-
pub fn new(
27-
libffi_type: Type,
28-
name: Option<String>,
29-
luavalue_into_ptr: fn(value: LuaValue, ptr: *mut ()) -> LuaResult<()>,
30-
ptr_into_luavalue: fn(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue>,
31-
) -> LuaResult<Self> {
22+
impl<T> CType<T>
23+
where
24+
T: ?Sized,
25+
{
26+
pub fn new_with_libffi_type(libffi_type: Type, name: Option<&'static str>) -> LuaResult<Self> {
3227
// let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
3328
let size = get_ensured_size(libffi_type.as_raw_ptr())?;
3429
Ok(Self {
3530
// libffi_cif: libffi_cfi,
3631
libffi_type,
3732
size,
3833
name,
39-
luavalue_into_ptr,
40-
ptr_into_luavalue,
34+
_phantom: PhantomData {},
4135
})
4236
}
4337

44-
pub fn get_type(&self) -> Type {
45-
self.libffi_type.clone()
38+
pub fn get_type(&self) -> &Type {
39+
&self.libffi_type
4640
}
4741

48-
pub fn stringify(&self) -> String {
49-
match &self.name {
50-
Some(t) => t.to_owned(),
51-
None => String::from("unnamed"),
42+
pub fn stringify(&self) -> &str {
43+
match self.name {
44+
Some(t) => t,
45+
None => "unnamed",
5246
}
5347
}
48+
}
49+
50+
pub trait PtrHandle {
51+
// Convert luavalue into data, then write into ptr
52+
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()>;
53+
54+
// Read data from ptr, then convert into luavalue
55+
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue>;
5456

55-
// Read data from ptr and convert it into luavalue
56-
pub unsafe fn read_ptr<'lua>(
57+
// Read data from userdata (such as box or ref) and convert it into luavalue
58+
unsafe fn read_userdata<'lua>(
5759
&self,
5860
lua: &'lua Lua,
5961
userdata: LuaAnyUserData<'lua>,
6062
offset: Option<isize>,
6163
) -> LuaResult<LuaValue<'lua>> {
6264
let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? };
63-
let value = (self.ptr_into_luavalue)(lua, ptr)?;
65+
let value = Self::ptr_into_luavalue(lua, ptr)?;
6466
Ok(value)
6567
}
6668

67-
// Write converted data from luavalue into ptr
68-
pub unsafe fn write_ptr<'lua>(
69+
// Write data into userdata (such as box or ref) from luavalue
70+
unsafe fn write_userdata<'lua>(
6971
&self,
7072
luavalue: LuaValue<'lua>,
7173
userdata: LuaAnyUserData<'lua>,
7274
offset: Option<isize>,
7375
) -> LuaResult<()> {
7476
let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? };
75-
(self.luavalue_into_ptr)(luavalue, ptr)?;
77+
Self::luavalue_into_ptr(luavalue, ptr)?;
7678
Ok(())
7779
}
7880
}
7981

80-
impl LuaUserData for CType {
82+
impl<T> LuaUserData for CType<T>
83+
where
84+
Self: Sized + PtrHandle,
85+
{
8186
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
8287
fields.add_field_method_get("size", |_, this| Ok(this.size));
8388
}
8489

8590
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
8691
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
87-
let pointer = CPtr::from_lua_userdata(lua, &this)?;
88-
Ok(pointer)
92+
CPtr::from_lua_userdata(lua, &this)
8993
});
9094
methods.add_method(
9195
"from",
92-
|lua, ctype, (userdata, offset): (LuaAnyUserData, Option<isize>)| {
93-
let value = unsafe { ctype.read_ptr(lua, userdata, offset)? };
94-
Ok(value)
96+
|lua, ctype, (userdata, offset): (LuaAnyUserData, Option<isize>)| unsafe {
97+
ctype.read_userdata(lua, userdata, offset)
9598
},
9699
);
97100
methods.add_method(
98101
"into",
99-
|_, ctype, (value, userdata, offset): (LuaValue, LuaAnyUserData, Option<isize>)| {
100-
unsafe { ctype.write_ptr(value, userdata, offset)? };
101-
Ok(())
102+
|_, ctype, (value, userdata, offset): (LuaValue, LuaAnyUserData, Option<isize>)| unsafe {
103+
ctype.write_userdata(value, userdata, offset)
102104
},
103105
);
104106
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
105-
let carr = CArr::from_lua_userdata(lua, &this, length)?;
106-
Ok(carr)
107+
CArr::from_lua_userdata(lua, &this, length)
107108
});
108-
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
109-
let name = this.stringify();
110-
Ok(name)
109+
methods.add_meta_method(LuaMetaMethod::ToString, |lua, this, ()| {
110+
lua.create_string(this.stringify())
111111
});
112112
}
113113
}

0 commit comments

Comments
 (0)