Skip to content

Commit 0eb9326

Browse files
committed
Move helper functions into chelper mod
1 parent 519f72a commit 0eb9326

File tree

7 files changed

+136
-140
lines changed

7 files changed

+136
-140
lines changed

crates/lune-std-ffi/src/carr.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ use libffi::middle::Type;
22
use mlua::prelude::*;
33

44
use crate::association::{get_association, set_association};
5+
use crate::chelper::{get_ensured_size, stringify_userdata, type_from_userdata};
56
use crate::cptr::CPtr;
6-
use crate::ctype::{
7-
libffi_type_ensured_size, libffi_type_from_userdata, type_userdata_stringify, CType,
8-
};
97

108
// This is a series of some type.
119
// It provides the final size and the offset of the index,
@@ -31,7 +29,7 @@ pub struct CArr {
3129
impl CArr {
3230
pub fn new(libffi_type: Type, length: usize) -> LuaResult<Self> {
3331
let struct_type = Type::structure(vec![libffi_type.clone(); length]);
34-
let field_size = libffi_type_ensured_size(libffi_type.as_raw_ptr())?;
32+
let field_size = get_ensured_size(libffi_type.as_raw_ptr())?;
3533

3634
Ok(Self {
3735
libffi_type,
@@ -47,7 +45,7 @@ impl CArr {
4745
luatype: &LuaAnyUserData<'lua>,
4846
length: usize,
4947
) -> LuaResult<LuaAnyUserData<'lua>> {
50-
let fields = libffi_type_from_userdata(luatype)?;
48+
let fields = type_from_userdata(luatype)?;
5149
let carr = lua.create_userdata(Self::new(fields, length)?)?;
5250

5351
set_association(lua, CARR_INNER, carr.clone(), luatype)?;
@@ -69,7 +67,7 @@ impl CArr {
6967
.ok_or(LuaError::external("failed to get inner type userdata."))?;
7068
Ok(format!(
7169
" {} ; {} ",
72-
type_userdata_stringify(inner)?,
70+
stringify_userdata(inner)?,
7371
carr.length
7472
))
7573
} else {

crates/lune-std-ffi/src/cfn.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use libffi::middle::{Cif, Type};
22
use mlua::prelude::*;
33

4-
use crate::ctype::{libffi_type_from_userdata, libffi_types_from_table};
4+
use crate::chelper::{type_from_userdata, type_list_from_table};
55

66
// cfn is a type declaration for a function.
77
// Basically, when calling an external function, this type declaration
@@ -36,8 +36,8 @@ impl CFn {
3636
}
3737

3838
pub fn from_lua_table(args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> {
39-
let args = libffi_types_from_table(&args)?;
40-
let ret = libffi_type_from_userdata(&ret)?;
39+
let args = type_list_from_table(&args)?;
40+
let ret = type_from_userdata(&ret)?;
4141
Ok(Self::new(args, ret))
4242
}
4343
}

crates/lune-std-ffi/src/chelper.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
use std::ptr::{self, null_mut};
2+
3+
use libffi::{low, middle::Type, raw};
4+
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
5+
use mlua::prelude::*;
6+
7+
use crate::carr::CArr;
8+
use crate::cptr::CPtr;
9+
use crate::cstruct::CStruct;
10+
use crate::ctype::CType;
11+
use crate::FFI_STATUS_NAMES;
12+
13+
// get Vec<libffi_type> from table(array) of c-types userdata
14+
pub fn type_list_from_table(table: &LuaTable) -> LuaResult<Vec<Type>> {
15+
let len: usize = table.raw_len();
16+
let mut fields = Vec::with_capacity(len);
17+
18+
for i in 0..len {
19+
// Test required
20+
let value = table.raw_get(i + 1)?;
21+
match value {
22+
LuaValue::UserData(field_type) => {
23+
fields.push(type_from_userdata(&field_type)?);
24+
}
25+
_ => {
26+
return Err(LuaError::external(format!(
27+
"Unexpected field. CStruct, CType or CArr is required for element but got {}",
28+
pretty_format_value(&value, &ValueFormatConfig::new())
29+
)));
30+
}
31+
}
32+
}
33+
34+
Ok(fields)
35+
}
36+
37+
// get libffi_type from any c-type userdata
38+
pub fn type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult<Type> {
39+
if userdata.is::<CStruct>() {
40+
Ok(userdata.borrow::<CStruct>()?.get_type())
41+
} else if userdata.is::<CType>() {
42+
Ok(userdata.borrow::<CType>()?.get_type())
43+
} else if userdata.is::<CArr>() {
44+
Ok(userdata.borrow::<CArr>()?.get_type())
45+
} else if userdata.is::<CPtr>() {
46+
Ok(CPtr::get_type())
47+
} else {
48+
Err(LuaError::external(format!(
49+
"Unexpected field. CStruct, CType, CString or CArr is required for element but got {}",
50+
pretty_format_value(
51+
// Since the data is in the Lua location,
52+
// there is no problem with the clone.
53+
&LuaValue::UserData(userdata.to_owned()),
54+
&ValueFormatConfig::new()
55+
)
56+
)))
57+
}
58+
}
59+
60+
// stringify any c-type userdata (for recursive)
61+
pub fn stringify_userdata(userdata: &LuaAnyUserData) -> LuaResult<String> {
62+
if userdata.is::<CType>() {
63+
let name = userdata.borrow::<CType>()?.stringify();
64+
Ok(name)
65+
} else if userdata.is::<CStruct>() {
66+
let name = CStruct::stringify(userdata)?;
67+
Ok(name)
68+
} else if userdata.is::<CArr>() {
69+
let name = CArr::stringify(userdata)?;
70+
Ok(name)
71+
} else if userdata.is::<CPtr>() {
72+
let name: String = CPtr::stringify(userdata)?;
73+
Ok(name)
74+
} else {
75+
Ok(String::from("unnamed"))
76+
}
77+
}
78+
79+
// get name tag for any c-type userdata
80+
pub fn name_from_userdata(userdata: &LuaAnyUserData) -> String {
81+
if userdata.is::<CStruct>() {
82+
String::from("CStruct")
83+
} else if userdata.is::<CType>() {
84+
String::from("CType")
85+
} else if userdata.is::<CArr>() {
86+
String::from("CArr")
87+
} else if userdata.is::<CPtr>() {
88+
String::from("CPtr")
89+
} else {
90+
String::from("unnamed")
91+
}
92+
}
93+
94+
// Ensure sizeof c-type (raw::libffi_type)
95+
// See: http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html
96+
pub fn get_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult<usize> {
97+
let mut cif = low::ffi_cif::default();
98+
let result = unsafe {
99+
raw::ffi_prep_cif(
100+
ptr::from_mut(&mut cif),
101+
raw::ffi_abi_FFI_DEFAULT_ABI,
102+
0,
103+
ffi_type,
104+
null_mut(),
105+
)
106+
};
107+
108+
if result != raw::ffi_status_FFI_OK {
109+
return Err(LuaError::external(format!(
110+
"ffi_get_struct_offsets failed. expected result {}, got {}",
111+
FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[result as usize]
112+
)));
113+
}
114+
unsafe { Ok((*ffi_type).size) }
115+
}

crates/lune-std-ffi/src/cptr.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use mlua::prelude::*;
77

88
use crate::association::{get_association, set_association};
99
use crate::carr::CArr;
10-
use crate::ctype::{type_name_from_userdata, type_userdata_stringify};
10+
use crate::chelper::{name_from_userdata, stringify_userdata};
1111

1212
const POINTER_INNER: &str = "__pointer_inner";
1313

@@ -37,8 +37,8 @@ impl CPtr {
3737
.ok_or(LuaError::external("failed to get inner type userdata."))?;
3838
Ok(format!(
3939
" <{}({})> ",
40-
type_name_from_userdata(inner),
41-
type_userdata_stringify(inner)?,
40+
name_from_userdata(inner),
41+
stringify_userdata(inner)?,
4242
))
4343
} else {
4444
Err(LuaError::external("failed to get inner type userdata."))

crates/lune-std-ffi/src/cstruct.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@ use libffi::{
99
};
1010
use mlua::prelude::*;
1111

12-
use crate::ctype::{libffi_types_from_table, type_userdata_stringify, CType};
12+
use crate::association::{get_association, set_association};
13+
use crate::chelper::{name_from_userdata, stringify_userdata, type_list_from_table};
14+
use crate::ctype::CType;
1315
use crate::FFI_STATUS_NAMES;
14-
use crate::{
15-
association::{get_association, set_association},
16-
ctype::type_name_from_userdata,
17-
};
1816
use crate::{carr::CArr, cptr::CPtr};
1917

2018
pub struct CStruct {
@@ -68,7 +66,7 @@ impl CStruct {
6866
lua: &'lua Lua,
6967
table: LuaTable<'lua>,
7068
) -> LuaResult<LuaAnyUserData<'lua>> {
71-
let fields = libffi_types_from_table(&table)?;
69+
let fields = type_list_from_table(&table)?;
7270
let cstruct = lua.create_userdata(Self::new(fields)?)?;
7371
table.set_readonly(true);
7472
set_association(lua, CSTRUCT_INNER, cstruct.clone(), table)?;
@@ -88,13 +86,13 @@ impl CStruct {
8886
for i in 0..table.raw_len() {
8987
let child: LuaAnyUserData = table.raw_get(i + 1)?;
9088
if child.is::<CType>() {
91-
result.push_str(format!("{}, ", type_userdata_stringify(&child)?).as_str());
89+
result.push_str(format!("{}, ", stringify_userdata(&child)?).as_str());
9290
} else {
9391
result.push_str(
9492
format!(
9593
"<{}({})>, ",
96-
type_name_from_userdata(&child),
97-
type_userdata_stringify(&child)?
94+
name_from_userdata(&child),
95+
stringify_userdata(&child)?
9896
)
9997
.as_str(),
10098
);

crates/lune-std-ffi/src/ctype.rs

Lines changed: 3 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
11
#![allow(clippy::cargo_common_metadata)]
22

3-
use std::borrow::Borrow;
4-
use std::ptr::{self, null_mut};
5-
6-
use libffi::{
7-
low,
8-
middle::{Cif, Type},
9-
raw,
10-
};
11-
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
3+
use libffi::middle::{Cif, Type};
124
use mlua::prelude::*;
135

14-
use crate::association::{get_association, set_association};
156
use crate::carr::CArr;
7+
use crate::chelper::get_ensured_size;
168
use crate::cptr::CPtr;
17-
use crate::cstruct::CStruct;
18-
use crate::FFI_STATUS_NAMES;
199
// use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw};
2010

21-
const POINTER_INNER: &str = "__pointer_inner";
22-
2311
pub struct CType {
2412
libffi_cif: Cif,
2513
libffi_type: Type,
@@ -30,7 +18,7 @@ pub struct CType {
3018
impl CType {
3119
pub fn new(libffi_type: Type, name: Option<String>) -> LuaResult<Self> {
3220
let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
33-
let size = libffi_type_ensured_size(libffi_type.as_raw_ptr())?;
21+
let size = get_ensured_size(libffi_type.as_raw_ptr())?;
3422
Ok(Self {
3523
libffi_cif: libffi_cfi,
3624
libffi_type,
@@ -121,107 +109,3 @@ pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
121109
),
122110
])
123111
}
124-
125-
// get Vec<libffi_type> from table(array) of c-types userdata
126-
pub fn libffi_types_from_table(table: &LuaTable) -> LuaResult<Vec<Type>> {
127-
let len: usize = table.raw_len();
128-
let mut fields = Vec::with_capacity(len);
129-
130-
for i in 0..len {
131-
// Test required
132-
let value = table.raw_get(i + 1)?;
133-
match value {
134-
LuaValue::UserData(field_type) => {
135-
fields.push(libffi_type_from_userdata(&field_type)?);
136-
}
137-
_ => {
138-
return Err(LuaError::external(format!(
139-
"Unexpected field. CStruct, CType or CArr is required for element but got {}",
140-
pretty_format_value(&value, &ValueFormatConfig::new())
141-
)));
142-
}
143-
}
144-
}
145-
146-
Ok(fields)
147-
}
148-
149-
// get libffi_type from any c-type userdata
150-
pub fn libffi_type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult<Type> {
151-
if userdata.is::<CStruct>() {
152-
Ok(userdata.borrow::<CStruct>()?.get_type())
153-
} else if userdata.is::<CType>() {
154-
Ok(userdata.borrow::<CType>()?.get_type())
155-
} else if userdata.is::<CArr>() {
156-
Ok(userdata.borrow::<CArr>()?.get_type())
157-
} else if userdata.is::<CPtr>() {
158-
Ok(CPtr::get_type())
159-
} else {
160-
Err(LuaError::external(format!(
161-
"Unexpected field. CStruct, CType, CString or CArr is required for element but got {}",
162-
pretty_format_value(
163-
// Since the data is in the Lua location,
164-
// there is no problem with the clone.
165-
&LuaValue::UserData(userdata.to_owned()),
166-
&ValueFormatConfig::new()
167-
)
168-
)))
169-
}
170-
}
171-
172-
// stringify any c-type userdata (for recursive)
173-
pub fn type_userdata_stringify(userdata: &LuaAnyUserData) -> LuaResult<String> {
174-
if userdata.is::<CType>() {
175-
let name = userdata.borrow::<CType>()?.stringify();
176-
Ok(name)
177-
} else if userdata.is::<CStruct>() {
178-
let name = CStruct::stringify(userdata)?;
179-
Ok(name)
180-
} else if userdata.is::<CArr>() {
181-
let name = CArr::stringify(userdata)?;
182-
Ok(name)
183-
} else if userdata.is::<CPtr>() {
184-
let name: String = CPtr::stringify(userdata)?;
185-
Ok(name)
186-
} else {
187-
Ok(String::from("unnamed"))
188-
}
189-
}
190-
191-
// get name tag for any c-type userdata
192-
pub fn type_name_from_userdata(userdata: &LuaAnyUserData) -> String {
193-
if userdata.is::<CStruct>() {
194-
String::from("CStruct")
195-
} else if userdata.is::<CType>() {
196-
String::from("CType")
197-
} else if userdata.is::<CArr>() {
198-
String::from("CArr")
199-
} else if userdata.is::<CPtr>() {
200-
String::from("CPtr")
201-
} else {
202-
String::from("unnamed")
203-
}
204-
}
205-
206-
// Ensure sizeof c-type (raw::libffi_type)
207-
// See: http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html
208-
pub fn libffi_type_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult<usize> {
209-
let mut cif: low::ffi_cif = Default::default();
210-
let result = unsafe {
211-
raw::ffi_prep_cif(
212-
ptr::from_mut(&mut cif),
213-
raw::ffi_abi_FFI_DEFAULT_ABI,
214-
0,
215-
ffi_type,
216-
null_mut(),
217-
)
218-
};
219-
220-
if result != raw::ffi_status_FFI_OK {
221-
return Err(LuaError::external(format!(
222-
"ffi_get_struct_offsets failed. expected result {}, got {}",
223-
FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[result as usize]
224-
)));
225-
}
226-
unsafe { Ok((*ffi_type).size) }
227-
}

crates/lune-std-ffi/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use mlua::prelude::*;
66
mod association;
77
mod carr;
88
mod cfn;
9+
mod chelper;
910
mod cptr;
1011
mod cstring;
1112
mod cstruct;

0 commit comments

Comments
 (0)