1
1
use libffi:: middle:: Type ;
2
2
use mlua:: prelude:: * ;
3
3
4
- use crate :: ctype:: libffi_type_ensured_size;
4
+ use crate :: association:: { get_association, set_association} ;
5
+ use crate :: cptr:: CPtr ;
6
+ use crate :: ctype:: {
7
+ libffi_type_ensured_size, libffi_type_from_userdata, type_userdata_stringify, CType ,
8
+ } ;
5
9
6
10
// This is a series of some type.
7
11
// It provides the final size and the offset of the index,
@@ -14,7 +18,9 @@ use crate::ctype::libffi_type_ensured_size;
14
18
// Padding after each field inside the struct is set to next field can follow the alignment.
15
19
// 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.
16
20
17
- struct CArr {
21
+ const CARR_INNER : & str = "__carr_inner" ;
22
+
23
+ pub struct CArr {
18
24
libffi_type : Type ,
19
25
struct_type : Type ,
20
26
length : usize ,
@@ -23,7 +29,7 @@ struct CArr {
23
29
}
24
30
25
31
impl CArr {
26
- fn new ( libffi_type : Type , length : usize ) -> LuaResult < Self > {
32
+ pub fn new ( libffi_type : Type , length : usize ) -> LuaResult < Self > {
27
33
let struct_type = Type :: structure ( vec ! [ libffi_type. clone( ) ; length] ) ;
28
34
let field_size = libffi_type_ensured_size ( libffi_type. as_raw_ptr ( ) ) ?;
29
35
@@ -35,6 +41,70 @@ impl CArr {
35
41
size : field_size * length,
36
42
} )
37
43
}
44
+
45
+ pub fn from_lua_userdata < ' lua > (
46
+ lua : & ' lua Lua ,
47
+ luatype : & LuaAnyUserData < ' lua > ,
48
+ length : usize ,
49
+ ) -> LuaResult < LuaAnyUserData < ' lua > > {
50
+ let fields = libffi_type_from_userdata ( luatype) ?;
51
+ let carr = lua. create_userdata ( Self :: new ( fields, length) ?) ?;
52
+
53
+ set_association ( lua, CARR_INNER , carr. clone ( ) , luatype) ?;
54
+ Ok ( carr)
55
+ }
56
+
57
+ pub fn get_type ( & self ) -> Type {
58
+ self . libffi_type . clone ( )
59
+ }
60
+
61
+ // Stringify cstruct for pretty printing something like:
62
+ // <CStruct( u8, i32, size = 8 )>
63
+ pub fn stringify ( userdata : & LuaAnyUserData ) -> LuaResult < String > {
64
+ let inner: LuaValue = userdata. get ( "inner" ) ?;
65
+ let carr = userdata. borrow :: < CArr > ( ) ?;
66
+ if inner. is_userdata ( ) {
67
+ let inner = inner
68
+ . as_userdata ( )
69
+ . ok_or ( LuaError :: external ( "failed to get inner type userdata." ) ) ?;
70
+ Ok ( format ! (
71
+ " {} ; {} " ,
72
+ type_userdata_stringify( inner) ?,
73
+ carr. length
74
+ ) )
75
+ } else {
76
+ Err ( LuaError :: external ( "failed to get inner type userdata." ) )
77
+ }
78
+ }
38
79
}
39
80
40
- impl LuaUserData for CArr { }
81
+ impl LuaUserData for CArr {
82
+ fn add_fields < ' lua , F : LuaUserDataFields < ' lua , Self > > ( fields : & mut F ) {
83
+ fields. add_field_method_get ( "size" , |_, this| Ok ( this. size ) ) ;
84
+ fields. add_field_method_get ( "length" , |_, this| Ok ( this. length ) ) ;
85
+ fields. add_field_function_get ( "inner" , |lua, this : LuaAnyUserData | {
86
+ let inner: LuaValue = get_association ( lua, CARR_INNER , this) ?
87
+ // It shouldn't happen.
88
+ . ok_or ( LuaError :: external ( "inner field not found" ) ) ?;
89
+ Ok ( inner)
90
+ } ) ;
91
+ }
92
+
93
+ fn add_methods < ' lua , M : LuaUserDataMethods < ' lua , Self > > ( methods : & mut M ) {
94
+ methods. add_method ( "offset" , |_, this, offset : isize | {
95
+ if this. length > ( offset as usize ) && offset >= 0 {
96
+ Ok ( this. field_size * ( offset as usize ) )
97
+ } else {
98
+ Err ( LuaError :: external ( "Out of index" ) )
99
+ }
100
+ } ) ;
101
+ methods. add_function ( "ptr" , |lua, this : LuaAnyUserData | {
102
+ let pointer = CPtr :: from_lua_userdata ( lua, & this) ?;
103
+ Ok ( pointer)
104
+ } ) ;
105
+ methods. add_meta_function ( LuaMetaMethod :: ToString , |_, this : LuaAnyUserData | {
106
+ let result = CArr :: stringify ( & this) ?;
107
+ Ok ( result)
108
+ } ) ;
109
+ }
110
+ }
0 commit comments