Skip to content

Commit 42930da

Browse files
committed
More impl
ffi: Cleaned up the code ref: high, low mem range for bound check platform: add platform value such as ffi.os, ffi.endian, ffi.arch, ffi.family
1 parent 975723f commit 42930da

File tree

13 files changed

+326
-92
lines changed

13 files changed

+326
-92
lines changed

core

79.7 MB
Binary file not shown.

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ use mlua::prelude::*;
33

44
use crate::association::{get_association, set_association};
55
use crate::association_names::CARR_INNER;
6-
use crate::chelper::{get_ensured_size, stringify_userdata, type_from_userdata};
6+
use crate::chelper::{
7+
get_ensured_size, name_from_userdata, stringify_userdata, type_from_userdata,
8+
};
79
use crate::cptr::CPtr;
10+
use crate::ctype::CType;
811

912
// This is a series of some type.
1013
// It provides the final size and the offset of the index,
@@ -60,15 +63,26 @@ impl CArr {
6063
pub fn stringify(userdata: &LuaAnyUserData) -> LuaResult<String> {
6164
let inner: LuaValue = userdata.get("inner")?;
6265
let carr = userdata.borrow::<CArr>()?;
66+
6367
if inner.is_userdata() {
6468
let inner = inner
6569
.as_userdata()
6670
.ok_or(LuaError::external("failed to get inner type userdata."))?;
67-
Ok(format!(
68-
" {} ; {} ",
69-
stringify_userdata(inner)?,
70-
carr.length
71-
))
71+
72+
if inner.is::<CType>() {
73+
Ok(format!(
74+
" {} ; {} ",
75+
stringify_userdata(inner)?,
76+
carr.length
77+
))
78+
} else {
79+
Ok(format!(
80+
" <{}({})> ; {} ",
81+
name_from_userdata(inner),
82+
stringify_userdata(inner)?,
83+
carr.length
84+
))
85+
}
7286
} else {
7387
Err(LuaError::external("failed to get inner type userdata."))
7488
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

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

Lines changed: 113 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,49 @@
11
#![allow(clippy::cargo_common_metadata)]
22

3+
use core::ffi::{
4+
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
5+
c_ulong, c_ulonglong, c_ushort, c_void,
6+
};
7+
38
use libffi::middle::{Cif, Type};
49
use mlua::prelude::*;
510

611
use crate::carr::CArr;
712
use crate::chelper::get_ensured_size;
813
use crate::cptr::CPtr;
14+
use crate::ffihelper::get_ptr_from_userdata;
15+
use crate::platform::CHAR_IS_SIGNED;
916
// use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw};
1017

1118
pub struct CType {
1219
libffi_cif: Cif,
1320
libffi_type: Type,
1421
size: usize,
1522
name: Option<String>,
23+
24+
// Write converted data from luavalue into some ptr
25+
pub luavalue_into_ptr: fn(value: LuaValue, ptr: *mut c_void) -> LuaResult<()>,
26+
27+
// Read luavalue from some ptr
28+
pub ptr_into_luavalue: fn(lua: &Lua, ptr: *mut c_void) -> LuaResult<LuaValue>,
1629
}
1730

1831
impl CType {
19-
pub fn new(libffi_type: Type, name: Option<String>) -> LuaResult<Self> {
32+
pub fn new(
33+
libffi_type: Type,
34+
name: Option<String>,
35+
luavalue_into_ptr: fn(value: LuaValue, ptr: *mut c_void) -> LuaResult<()>,
36+
ptr_into_luavalue: fn(lua: &Lua, ptr: *mut c_void) -> LuaResult<LuaValue>,
37+
) -> LuaResult<Self> {
2038
let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
2139
let size = get_ensured_size(libffi_type.as_raw_ptr())?;
2240
Ok(Self {
2341
libffi_cif: libffi_cfi,
2442
libffi_type,
2543
size,
2644
name,
45+
luavalue_into_ptr,
46+
ptr_into_luavalue,
2747
})
2848
}
2949

@@ -37,6 +57,30 @@ impl CType {
3757
None => String::from("unnamed"),
3858
}
3959
}
60+
61+
// Read data from ptr and convert it into luavalue
62+
pub unsafe fn read_ptr<'lua>(
63+
&self,
64+
lua: &'lua Lua,
65+
userdata: LuaAnyUserData<'lua>,
66+
offset: Option<isize>,
67+
) -> LuaResult<LuaValue<'lua>> {
68+
let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? };
69+
let value = (self.ptr_into_luavalue)(lua, ptr)?;
70+
Ok(value)
71+
}
72+
73+
// Write converted data from luavalue into ptr
74+
pub unsafe fn write_ptr<'lua>(
75+
&self,
76+
luavalue: LuaValue<'lua>,
77+
userdata: LuaAnyUserData<'lua>,
78+
offset: Option<isize>,
79+
) -> LuaResult<()> {
80+
let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? };
81+
(self.luavalue_into_ptr)(luavalue, ptr)?;
82+
Ok(())
83+
}
4084
}
4185

4286
impl LuaUserData for CType {
@@ -49,6 +93,20 @@ impl LuaUserData for CType {
4993
let pointer = CPtr::from_lua_userdata(lua, &this)?;
5094
Ok(pointer)
5195
});
96+
methods.add_method(
97+
"from",
98+
|lua, ctype, (userdata, offset): (LuaAnyUserData, Option<isize>)| {
99+
let value = unsafe { ctype.read_ptr(lua, userdata, offset)? };
100+
Ok(value)
101+
},
102+
);
103+
methods.add_method(
104+
"into",
105+
|_, ctype, (value, userdata, offset): (LuaValue, LuaAnyUserData, Option<isize>)| {
106+
unsafe { ctype.write_ptr(value, userdata, offset)? };
107+
Ok(())
108+
},
109+
);
52110
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
53111
let carr = CArr::from_lua_userdata(lua, &this, length)?;
54112
Ok(carr)
@@ -64,48 +122,62 @@ impl LuaUserData for CType {
64122
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
65123
Ok(vec![
66124
(
67-
"u8",
68-
CType::new(Type::u8(), Some(String::from("u8")))?.into_lua(lua)?,
69-
),
70-
(
71-
"u16",
72-
CType::new(Type::u16(), Some(String::from("u16")))?.into_lua(lua)?,
73-
),
74-
(
75-
"u32",
76-
CType::new(Type::u32(), Some(String::from("u32")))?.into_lua(lua)?,
77-
),
78-
(
79-
"u64",
80-
CType::new(Type::u64(), Some(String::from("u64")))?.into_lua(lua)?,
81-
),
82-
(
83-
"i8",
84-
CType::new(Type::i8(), Some(String::from("i8")))?.into_lua(lua)?,
85-
),
86-
(
87-
"i16",
88-
CType::new(Type::i16(), Some(String::from("i16")))?.into_lua(lua)?,
89-
),
90-
(
91-
"i32",
92-
CType::new(Type::i32(), Some(String::from("i32")))?.into_lua(lua)?,
93-
),
94-
(
95-
"i64",
96-
CType::new(Type::i64(), Some(String::from("i64")))?.into_lua(lua)?,
97-
),
98-
(
99-
"f32",
100-
CType::new(Type::f32(), Some(String::from("f32")))?.into_lua(lua)?,
101-
),
102-
(
103-
"f64",
104-
CType::new(Type::f64(), Some(String::from("f64")))?.into_lua(lua)?,
125+
"int",
126+
CType::new(
127+
Type::c_int(),
128+
Some(String::from("int")),
129+
|data, ptr| {
130+
let value = match data {
131+
LuaValue::Integer(t) => t,
132+
_ => {
133+
return Err(LuaError::external(format!(
134+
"Integer expected, got {}",
135+
data.type_name()
136+
)))
137+
}
138+
} as c_int;
139+
unsafe {
140+
*(ptr.cast::<c_int>()) = value;
141+
}
142+
Ok(())
143+
},
144+
|lua: &Lua, ptr: *mut c_void| {
145+
let value = unsafe { (*ptr.cast::<c_int>()).into_lua(lua)? };
146+
Ok(value)
147+
},
148+
)?
149+
.into_lua(lua)?,
105150
),
106151
(
107-
"void",
108-
CType::new(Type::void(), Some(String::from("void")))?.into_lua(lua)?,
152+
"char",
153+
CType::new(
154+
if CHAR_IS_SIGNED {
155+
Type::c_schar()
156+
} else {
157+
Type::c_uchar()
158+
},
159+
Some(String::from("char")),
160+
|data, ptr| {
161+
let value = match data {
162+
LuaValue::Integer(t) => t,
163+
_ => {
164+
return Err(LuaError::external(format!(
165+
"Integer expected, got {}",
166+
data.type_name()
167+
)))
168+
}
169+
} as c_char;
170+
unsafe {
171+
*(ptr.cast::<c_char>()) = value;
172+
}
173+
Ok(())
174+
},
175+
|lua: &Lua, ptr: *mut c_void| {
176+
let value = unsafe { (*ptr.cast::<c_char>()).into_lua(lua)? };
177+
Ok(value)
178+
},
179+
)?
180+
.into_lua(lua)?,
109181
),
110182
])
111183
}

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

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,25 @@ use core::ffi::c_void;
1515
use mlua::prelude::*;
1616

1717
use crate::association::set_association;
18+
use crate::association_names::BOX_REF_INNER;
19+
use crate::ffiref::FfiRange;
1820
use crate::ffiref::FfiRef;
1921

20-
const BOX_REF_INNER: &str = "__box_ref";
21-
2222
pub struct FfiBox(Box<[u8]>);
2323

2424
impl FfiBox {
25+
// For efficiency, it is initialized non-zeroed.
2526
pub fn new(size: usize) -> Self {
26-
Self(vec![0u8; size].into_boxed_slice())
27+
// Create new vector to allocate heap memory. sized with 'size'
28+
let mut vec_heap = Vec::<u8>::with_capacity(size);
29+
30+
// It is safe to have a length equal to the capacity
31+
#[allow(clippy::uninit_vec)]
32+
unsafe {
33+
vec_heap.set_len(size);
34+
}
35+
36+
Self(vec_heap.into_boxed_slice())
2737
}
2838

2939
pub fn size(&self) -> usize {
@@ -36,14 +46,62 @@ impl FfiBox {
3646
self.0.as_ptr() as *mut c_void
3747
}
3848

49+
pub fn stringify(&self) -> String {
50+
let mut buff = String::from(" ");
51+
for i in &self.0 {
52+
buff.push_str(i.to_string().as_str());
53+
buff.push_str(", ");
54+
}
55+
buff.pop();
56+
buff.pop();
57+
buff.push(' ');
58+
buff
59+
}
60+
61+
pub fn binary_print(&self) -> String {
62+
let mut buff: String = String::with_capacity(self.size() * 10 - 2);
63+
for (pos, value) in self.0.iter().enumerate() {
64+
for i in 0..8 {
65+
if (value & (1 << i)) == 0 {
66+
buff.push('0');
67+
} else {
68+
buff.push('1');
69+
}
70+
}
71+
if pos < self.size() - 1 {
72+
buff.push_str(", ");
73+
}
74+
}
75+
buff
76+
}
77+
3978
// bad naming. i have no idea what should i use
4079
pub fn luaref<'lua>(
4180
lua: &'lua Lua,
4281
this: LuaAnyUserData<'lua>,
82+
offset: Option<isize>,
4383
) -> LuaResult<LuaAnyUserData<'lua>> {
4484
let target = this.borrow::<FfiBox>()?;
45-
46-
let luaref = lua.create_userdata(FfiRef::new(target.get_ptr()))?;
85+
let ptr = if let Some(t) = offset {
86+
if t < 0 || t >= (target.size() as isize) {
87+
return Err(LuaError::external(format!(
88+
"Offset is out of bounds. box.size: {}. offset got {}",
89+
target.size(),
90+
t
91+
)));
92+
}
93+
unsafe { target.get_ptr().offset(t) }
94+
} else {
95+
target.get_ptr()
96+
};
97+
98+
let luaref = lua.create_userdata(FfiRef::new(
99+
ptr,
100+
Some(FfiRange {
101+
low: 0,
102+
high: target.size() as isize,
103+
}),
104+
))?;
47105

48106
set_association(lua, BOX_REF_INNER, luaref.clone(), this.clone())?;
49107

@@ -61,27 +119,19 @@ impl LuaUserData for FfiBox {
61119
}
62120

63121
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
64-
methods.add_method_mut("zero", |_, this, ()| {
65-
this.zero();
66-
Ok(())
122+
methods.add_function_mut("zero", |_, this: LuaAnyUserData| {
123+
this.borrow_mut::<FfiBox>()?.zero();
124+
Ok(this)
67125
});
68-
methods.add_function("ref", |lua, this: LuaAnyUserData| {
69-
let luaref = FfiBox::luaref(lua, this)?;
70-
Ok(luaref)
71-
});
72-
methods.add_meta_method(LuaMetaMethod::Len, |_, this, ()| Ok(this.size()));
73-
methods.add_meta_method(LuaMetaMethod::ToString, |lua, this, ()| {
74-
dbg!(&this.0.len());
75-
let mut buff = String::from("[ ");
76-
for i in &this.0 {
77-
buff.push_str(i.to_owned().to_string().as_str());
78-
buff.push_str(", ");
79-
}
80-
buff.pop();
81-
buff.pop();
82-
buff.push_str(" ]");
83-
let luastr = lua.create_string(buff.as_bytes())?;
84-
Ok(luastr)
126+
methods.add_function(
127+
"ref",
128+
|lua, (this, offset): (LuaAnyUserData, Option<isize>)| {
129+
let luaref = FfiBox::luaref(lua, this, offset)?;
130+
Ok(luaref)
131+
},
132+
);
133+
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
134+
Ok(this.binary_print())
85135
});
86136
}
87137
}

0 commit comments

Comments
 (0)