1
+ use std:: cell:: Ref ;
2
+
1
3
use libffi:: middle:: Type ;
2
4
use mlua:: prelude:: * ;
3
5
4
- use super :: association_names:: CARR_INNER ;
5
- use super :: c_helper:: { get_ensured_size, libffi_type_from_userdata, pretty_format_userdata} ;
6
- use super :: c_ptr:: CPtr ;
7
- use crate :: ffi:: ffi_association:: { get_association, set_association} ;
6
+ use super :: {
7
+ association_names:: CARR_INNER ,
8
+ c_helper:: { get_conv, get_ensured_size, libffi_type_from_userdata, pretty_format_userdata} ,
9
+ CPtr ,
10
+ } ;
11
+ use crate :: ffi:: {
12
+ ffi_association:: { get_association, set_association} ,
13
+ FfiBox , GetNativeDataHandle , NativeConvert , NativeDataHandle , NativeSignedness , NativeSize ,
14
+ } ;
8
15
9
16
// This is a series of some type.
10
17
// It provides the final size and the offset of the index,
@@ -18,24 +25,30 @@ use crate::ffi::ffi_association::{get_association, set_association};
18
25
// There is no problem even if you create a struct with n fields of a single type within the struct. Array adheres to the condition that there is no additional padding between each element. Padding to a struct is padding inside the struct. Simply think of the padding byte as a trailing unnamed field.
19
26
20
27
pub struct CArr {
21
- element_type : Type ,
28
+ // element_type: Type,
22
29
struct_type : Type ,
23
30
length : usize ,
24
31
field_size : usize ,
25
32
size : usize ,
33
+ conv : * const dyn NativeConvert ,
26
34
}
27
35
28
36
impl CArr {
29
- pub fn new ( element_type : Type , length : usize ) -> LuaResult < Self > {
30
- let struct_type = Type :: structure ( vec ! [ element_type. clone( ) ; length] ) ;
37
+ pub fn new (
38
+ element_type : Type ,
39
+ length : usize ,
40
+ conv : * const dyn NativeConvert ,
41
+ ) -> LuaResult < Self > {
31
42
let field_size = get_ensured_size ( element_type. as_raw_ptr ( ) ) ?;
43
+ let struct_type = Type :: structure ( vec ! [ element_type. clone( ) ; length] ) ;
32
44
33
45
Ok ( Self {
34
- element_type,
46
+ // element_type,
35
47
struct_type,
36
48
length,
37
49
field_size,
38
50
size : field_size * length,
51
+ conv,
39
52
} )
40
53
}
41
54
@@ -45,16 +58,13 @@ impl CArr {
45
58
length : usize ,
46
59
) -> LuaResult < LuaAnyUserData < ' lua > > {
47
60
let fields = libffi_type_from_userdata ( lua, luatype) ?;
48
- let carr = lua. create_userdata ( Self :: new ( fields, length) ?) ?;
61
+ let conv = unsafe { get_conv ( luatype) ? } ;
62
+ let carr = lua. create_userdata ( Self :: new ( fields, length, conv) ?) ?;
49
63
50
64
set_association ( lua, CARR_INNER , & carr, luatype) ?;
51
65
Ok ( carr)
52
66
}
53
67
54
- pub fn get_size ( & self ) -> usize {
55
- self . size
56
- }
57
-
58
68
pub fn get_length ( & self ) -> usize {
59
69
self . length
60
70
}
@@ -63,9 +73,9 @@ impl CArr {
63
73
& self . struct_type
64
74
}
65
75
66
- pub fn get_element_type ( & self ) -> & Type {
67
- & self . element_type
68
- }
76
+ // pub fn get_element_type(&self) -> &Type {
77
+ // &self.element_type
78
+ // }
69
79
70
80
// Stringify cstruct for pretty printing something like:
71
81
// <CStruct( u8, i32, size = 8 )>
@@ -89,6 +99,64 @@ impl CArr {
89
99
}
90
100
}
91
101
102
+ impl NativeSize for CArr {
103
+ fn get_size ( & self ) -> usize {
104
+ self . size
105
+ }
106
+ }
107
+ impl NativeSignedness for CArr {
108
+ fn get_signedness ( & self ) -> bool {
109
+ false
110
+ }
111
+ }
112
+ impl NativeConvert for CArr {
113
+ // FIXME: FfiBox, FfiRef support required
114
+ unsafe fn luavalue_into < ' lua > (
115
+ & self ,
116
+ lua : & ' lua Lua ,
117
+ offset : isize ,
118
+ data_handle : & Ref < dyn NativeDataHandle > ,
119
+ value : LuaValue < ' lua > ,
120
+ ) -> LuaResult < ( ) > {
121
+ let LuaValue :: Table ( ref table) = value else {
122
+ return Err ( LuaError :: external ( "Value is not a table" ) ) ;
123
+ } ;
124
+ for i in 0 ..self . length {
125
+ let field_offset = ( i * self . field_size ) as isize ;
126
+ let data: LuaValue = table. get ( i + 1 ) ?;
127
+
128
+ self . conv . as_ref ( ) . unwrap ( ) . luavalue_into (
129
+ lua,
130
+ field_offset + offset,
131
+ data_handle,
132
+ data,
133
+ ) ?;
134
+ }
135
+ Ok ( ( ) )
136
+ }
137
+
138
+ unsafe fn luavalue_from < ' lua > (
139
+ & self ,
140
+ lua : & ' lua Lua ,
141
+ offset : isize ,
142
+ data_handle : & Ref < dyn NativeDataHandle > ,
143
+ ) -> LuaResult < LuaValue < ' lua > > {
144
+ let table = lua. create_table_with_capacity ( self . length , 0 ) ?;
145
+ for i in 0 ..self . length {
146
+ let field_offset = ( i * self . field_size ) as isize ;
147
+ table. set (
148
+ i + 1 ,
149
+ self . conv . as_ref ( ) . unwrap ( ) . luavalue_from (
150
+ lua,
151
+ field_offset + offset,
152
+ data_handle,
153
+ ) ?,
154
+ ) ?;
155
+ }
156
+ Ok ( LuaValue :: Table ( table) )
157
+ }
158
+ }
159
+
92
160
impl LuaUserData for CArr {
93
161
fn add_fields < ' lua , F : LuaUserDataFields < ' lua , Self > > ( fields : & mut F ) {
94
162
fields. add_field_method_get ( "size" , |_, this| Ok ( this. get_size ( ) ) ) ;
@@ -109,6 +177,44 @@ impl LuaUserData for CArr {
109
177
Err ( LuaError :: external ( "Out of index" ) )
110
178
}
111
179
} ) ;
180
+ methods. add_method ( "box" , |lua, this, table : LuaValue | {
181
+ let result = lua. create_userdata ( FfiBox :: new ( this. get_size ( ) ) ) ?;
182
+
183
+ unsafe { this. luavalue_into ( lua, 0 , & result. get_data_handle ( ) ?, table) ? } ;
184
+ Ok ( result)
185
+ } ) ;
186
+ methods. add_method (
187
+ "from" ,
188
+ |lua, this, ( userdata, offset) : ( LuaAnyUserData , Option < isize > ) | {
189
+ let offset = offset. unwrap_or ( 0 ) ;
190
+
191
+ let data_handle = & userdata. get_data_handle ( ) ?;
192
+ if !data_handle. check_boundary ( offset, this. get_size ( ) ) {
193
+ return Err ( LuaError :: external ( "Out of bounds" ) ) ;
194
+ }
195
+ if !data_handle. check_readable ( & userdata, offset, this. get_size ( ) ) {
196
+ return Err ( LuaError :: external ( "Unreadable data handle" ) ) ;
197
+ }
198
+
199
+ unsafe { this. luavalue_from ( lua, offset, data_handle) }
200
+ } ,
201
+ ) ;
202
+ methods. add_method (
203
+ "into" ,
204
+ |lua, this, ( userdata, value, offset) : ( LuaAnyUserData , LuaValue , Option < isize > ) | {
205
+ let offset = offset. unwrap_or ( 0 ) ;
206
+
207
+ let data_handle = & userdata. get_data_handle ( ) ?;
208
+ if !data_handle. check_boundary ( offset, this. size ) {
209
+ return Err ( LuaError :: external ( "Out of bounds" ) ) ;
210
+ }
211
+ if !data_handle. checek_writable ( & userdata, offset, this. size ) {
212
+ return Err ( LuaError :: external ( "Unwritable data handle" ) ) ;
213
+ }
214
+
215
+ unsafe { this. luavalue_into ( lua, offset, data_handle, value) }
216
+ } ,
217
+ ) ;
112
218
methods. add_function ( "ptr" , |lua, this : LuaAnyUserData | {
113
219
let pointer = CPtr :: new_from_lua_userdata ( lua, & this) ?;
114
220
Ok ( pointer)
0 commit comments