Skip to content

Commit 27e250d

Browse files
committed
Implememt CVoid, StringifyData and CopyData (#243)
1 parent 7ee757a commit 27e250d

26 files changed

+551
-107
lines changed

crates/lune-std-ffi/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,9 @@ Add `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `
9090
Add bor band and such bit-related operation
9191

9292
> Luau only supports 32bit bit operations
93+
94+
wchar and wstring support
95+
96+
string(null ending) / buffer support
97+
98+
void support

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl CArrInfo {
5959
self.length
6060
}
6161

62-
pub fn get_type(&self) -> Type {
62+
pub fn get_middle_type(&self) -> Type {
6363
self.struct_type.clone()
6464
}
6565

@@ -87,7 +87,6 @@ impl FfiSize for CArrInfo {
8787
}
8888
}
8989
impl FfiConvert for CArrInfo {
90-
// FIXME: FfiBox, FfiRef support required
9190
unsafe fn value_into_data<'lua>(
9291
&self,
9392
lua: &'lua Lua,
@@ -132,6 +131,20 @@ impl FfiConvert for CArrInfo {
132131
}
133132
Ok(LuaValue::Table(table))
134133
}
134+
135+
unsafe fn copy_data(
136+
&self,
137+
_lua: &Lua,
138+
dst_offset: isize,
139+
src_offset: isize,
140+
dst: &Ref<dyn FfiData>,
141+
src: &Ref<dyn FfiData>,
142+
) -> LuaResult<()> {
143+
dst.get_pointer()
144+
.byte_offset(dst_offset)
145+
.copy_from(src.get_pointer().byte_offset(src_offset), self.get_size());
146+
Ok(())
147+
}
135148
}
136149

137150
impl LuaUserData for CArrInfo {
@@ -157,6 +170,7 @@ impl LuaUserData for CArrInfo {
157170
method_provider::provide_box(methods);
158171
method_provider::provide_read_data(methods);
159172
method_provider::provide_write_data(methods);
173+
method_provider::provide_copy_data(methods);
160174

161175
methods.add_method("offset", |_, this, offset: isize| {
162176
if this.length > (offset as usize) && offset >= 0 {

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

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use libffi::middle::Type;
22
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
33
use mlua::prelude::*;
44

5-
use super::{ctype_helper, CArrInfo, CFnInfo, CPtrInfo, CStructInfo};
5+
use super::{ctype_helper, void_info::CVoidInfo, CArrInfo, CFnInfo, CPtrInfo, CStructInfo};
66
use crate::{
77
data::{BoxData, GetFfiData},
88
ffi::{FfiConvert, FfiSize},
@@ -84,17 +84,104 @@ pub mod method_provider {
8484
);
8585
}
8686

87+
pub fn provide_copy_data<'lua, Target, M>(methods: &mut M)
88+
where
89+
Target: FfiSize + FfiConvert,
90+
M: LuaUserDataMethods<'lua, Target>,
91+
{
92+
methods.add_method(
93+
"copyData",
94+
|lua,
95+
this,
96+
(dst, src, dst_offset, src_offset): (
97+
LuaAnyUserData,
98+
LuaAnyUserData,
99+
Option<isize>,
100+
Option<isize>,
101+
)| {
102+
let dst_offset = dst_offset.unwrap_or(0);
103+
let src_offset = src_offset.unwrap_or(0);
104+
105+
let dst = &dst.get_ffi_data()?;
106+
// use or functions
107+
if !dst.check_boundary(dst_offset, this.get_size()) {
108+
return Err(LuaError::external("Out of bounds"));
109+
}
110+
if !dst.is_writable() {
111+
return Err(LuaError::external("Unwritable data handle"));
112+
}
113+
114+
let src = &src.get_ffi_data()?;
115+
if !src.check_boundary(dst_offset, this.get_size()) {
116+
return Err(LuaError::external("Out of bounds"));
117+
}
118+
if !src.is_readable() {
119+
return Err(LuaError::external("Unreadable value data handle"));
120+
}
121+
122+
unsafe { this.copy_data(lua, dst_offset, src_offset, dst, src) }
123+
},
124+
);
125+
}
126+
127+
pub fn provide_stringify_data<'lua, Target, M>(methods: &mut M)
128+
where
129+
Target: FfiSize + FfiConvert,
130+
M: LuaUserDataMethods<'lua, Target>,
131+
{
132+
methods.add_method(
133+
"stringifyData",
134+
|lua, this, (target, offset): (LuaAnyUserData, Option<isize>)| unsafe {
135+
this.stringify_data(lua, offset.unwrap_or(0), &target.get_ffi_data()?)
136+
},
137+
);
138+
}
139+
87140
pub fn provide_box<'lua, Target, M>(methods: &mut M)
88141
where
89142
Target: FfiSize + FfiConvert,
90143
M: LuaUserDataMethods<'lua, Target>,
91144
{
92-
methods.add_method("box", |lua, this, table: LuaValue| {
145+
methods.add_method("box", |lua, this, value: LuaValue| {
93146
let result = lua.create_userdata(BoxData::new(this.get_size()))?;
94-
unsafe { this.value_into_data(lua, 0, &result.get_ffi_data()?, table)? };
147+
unsafe { this.value_into_data(lua, 0, &result.get_ffi_data()?, value)? };
95148
Ok(result)
96149
});
97150
}
151+
152+
// FIXME: Buffer support should be part of another PR
153+
// pub fn provide_write_buffer<'lua, Target, M>(methods: &mut M)
154+
// where
155+
// Target: FfiSize + FfiConvert,
156+
// M: LuaUserDataMethods<'lua, Target>,
157+
// {
158+
// methods.add_method(
159+
// "writeBuffer",
160+
// |lua, this, (target, value, offset): (LuaValue, LuaValue, Option<isize>)| {
161+
// if !target.is_buffer() {
162+
// return Err(LuaError::external(format!(
163+
// "Argument target must be a buffer, got {}",
164+
// target.type_name()
165+
// )));
166+
// }
167+
168+
// target.to_pointer()
169+
// target.as_userdata().unwrap().to_pointer()
170+
// let offset = offset.unwrap_or(0);
171+
172+
// let data_handle = &target.get_ffi_data()?;
173+
// // use or functions
174+
// if !data_handle.check_boundary(offset, this.get_size()) {
175+
// return Err(LuaError::external("Out of bounds"));
176+
// }
177+
// if !data_handle.is_writable() {
178+
// return Err(LuaError::external("Unwritable data handle"));
179+
// }
180+
181+
// unsafe { this.value_into_data(lua, offset, data_handle, value) }
182+
// },
183+
// );
184+
// }
98185
}
99186

100187
pub fn get_userdata(value: LuaValue) -> LuaResult<LuaAnyUserData> {
@@ -143,28 +230,32 @@ pub unsafe fn get_conv_list(table: &LuaTable) -> LuaResult<Vec<*const dyn FfiCon
143230
create_list(table, |userdata| get_conv(userdata))
144231
}
145232

146-
pub fn get_size(this: &LuaAnyUserData) -> LuaResult<usize> {
147-
if this.is::<CStructInfo>() {
148-
Ok(this.borrow::<CStructInfo>()?.get_size())
149-
} else if this.is::<CArrInfo>() {
150-
Ok(this.borrow::<CArrInfo>()?.get_size())
151-
} else if this.is::<CPtrInfo>() {
152-
Ok(this.borrow::<CPtrInfo>()?.get_size())
233+
pub fn get_size(userdata: &LuaAnyUserData) -> LuaResult<usize> {
234+
if userdata.is::<CStructInfo>() {
235+
Ok(userdata.borrow::<CStructInfo>()?.get_size())
236+
} else if userdata.is::<CArrInfo>() {
237+
Ok(userdata.borrow::<CArrInfo>()?.get_size())
238+
} else if userdata.is::<CPtrInfo>() {
239+
Ok(userdata.borrow::<CPtrInfo>()?.get_size())
240+
} else if userdata.is::<CVoidInfo>() {
241+
Ok(userdata.borrow::<CVoidInfo>()?.get_size())
153242
} else {
154-
ctype_helper::get_size(this)
243+
ctype_helper::get_size(userdata)
155244
}
156245
}
157246

158247
// get libffi_type from any c-type userdata
159248
pub fn get_middle_type(userdata: &LuaAnyUserData) -> LuaResult<Type> {
160249
if userdata.is::<CStructInfo>() {
161-
Ok(userdata.borrow::<CStructInfo>()?.get_type())
250+
Ok(userdata.borrow::<CStructInfo>()?.get_middle_type())
162251
} else if let Some(middle_type) = ctype_helper::get_middle_type(userdata)? {
163252
Ok(middle_type)
164253
} else if userdata.is::<CArrInfo>() {
165-
Ok(userdata.borrow::<CArrInfo>()?.get_type())
254+
Ok(userdata.borrow::<CArrInfo>()?.get_middle_type())
166255
} else if userdata.is::<CPtrInfo>() {
167-
Ok(CPtrInfo::get_type())
256+
Ok(CPtrInfo::get_middle_type())
257+
} else if userdata.is::<CVoidInfo>() {
258+
Ok(CVoidInfo::get_middle_type())
168259
} else {
169260
Err(LuaError::external(format!(
170261
"Unexpected field. CStruct, CType, CString or CArr is required for element but got {}",
@@ -210,6 +301,8 @@ pub fn get_tag_name(userdata: &LuaAnyUserData) -> LuaResult<String> {
210301
String::from("CPtr")
211302
} else if userdata.is::<CFnInfo>() {
212303
String::from("CFn")
304+
} else if userdata.is::<CVoidInfo>() {
305+
String::from("CVoid")
213306
} else if ctype_helper::is_ctype(userdata) {
214307
String::from("CType")
215308
} else {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod ptr_info;
55
mod struct_info;
66
mod type_info;
77
mod types;
8+
mod void_info;
89

910
pub use self::{
1011
arr_info::CArrInfo,

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

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,10 @@ impl FfiConvert for CPtrInfo {
4545
let value_userdata = value
4646
.as_userdata()
4747
.ok_or_else(|| LuaError::external("CPtrInfo:writeRef only allows data"))?;
48-
49-
data_handle
50-
.check_boundary(offset, self.get_size())
51-
.then_some(())
52-
.ok_or_else(|| LuaError::external("Out of bounds"))?;
53-
data_handle
54-
.is_writable()
55-
.then_some(())
56-
.ok_or_else(|| LuaError::external("Unwritable data handle"))?;
57-
5848
*data_handle
5949
.get_pointer()
6050
.byte_offset(offset)
6151
.cast::<*mut ()>() = value_userdata.get_ffi_data()?.get_pointer();
62-
6352
Ok(())
6453
}
6554

@@ -70,10 +59,6 @@ impl FfiConvert for CPtrInfo {
7059
offset: isize,
7160
data_handle: &Ref<dyn FfiData>,
7261
) -> LuaResult<LuaValue<'lua>> {
73-
if !data_handle.check_boundary(offset, SIZE_OF_POINTER) {
74-
return Err(LuaError::external("Out of bounds"));
75-
}
76-
7762
Ok(LuaValue::UserData(lua.create_userdata(RefData::new(
7863
unsafe { data_handle.get_pointer().byte_offset(offset) },
7964
if self.inner_is_cptr {
@@ -84,6 +69,19 @@ impl FfiConvert for CPtrInfo {
8469
RefBounds::new(0, self.inner_size),
8570
))?))
8671
}
72+
73+
unsafe fn copy_data(
74+
&self,
75+
_lua: &Lua,
76+
dst_offset: isize,
77+
src_offset: isize,
78+
dst: &Ref<dyn FfiData>,
79+
src: &Ref<dyn FfiData>,
80+
) -> LuaResult<()> {
81+
*dst.get_pointer().byte_offset(dst_offset).cast::<*mut ()>() =
82+
src.get_pointer().byte_offset(src_offset);
83+
Ok(())
84+
}
8785
}
8886

8987
impl CPtrInfo {
@@ -118,7 +116,7 @@ impl CPtrInfo {
118116
}
119117

120118
// Return void*
121-
pub fn get_type() -> Type {
119+
pub fn get_middle_type() -> Type {
122120
Type::pointer()
123121
}
124122
}

0 commit comments

Comments
 (0)