@@ -1651,14 +1651,15 @@ pub const Lua = struct {
1651
1651
/// For userdata it is the size of the block of memory
1652
1652
/// For other values the call returns 0
1653
1653
/// See https://www.lua.org/manual/5.4/manual.html#lua_rawlen
1654
- pub fn rawLen (lua : * Lua , index : i32 ) switch ( lang ) {
1655
- .lua52 , .lua53 = > usize ,
1656
- else = > Unsigned ,
1657
- } {
1658
- return c . lua_rawlen ( lua . state , index );
1654
+ pub fn rawLen (lua : * Lua , index : i32 ) usize {
1655
+ switch ( lang ) {
1656
+ .lua51 , .luau = > return @intCast ( c . lua_objlen ( lua . state , index )) ,
1657
+ else = > return @intCast ( c . lua_rawlen ( lua . state , index )),
1658
+ }
1659
1659
}
1660
1660
1661
- /// Similar to `Lua.setTable()` but does a raw assignment (without metamethods)
1661
+ /// Similar to `Lua.setTable()` but does a raw asskdjfal;sdkfjals;dkfj;dk:q
1662
+ /// gnment (without metamethods)
1662
1663
/// See https://www.lua.org/manual/5.4/manual.html#lua_rawset
1663
1664
pub fn rawSetTable (lua : * Lua , index : i32 ) void {
1664
1665
c .lua_rawset (lua .state , index );
@@ -3026,6 +3027,49 @@ pub const Lua = struct {
3026
3027
_ = c .luaopen_bit32 (lua .state );
3027
3028
}
3028
3029
3030
+ /// Returns if given typeinfo is a string type
3031
+ fn isTypeString (typeinfo : std.builtin.Type.Pointer ) bool {
3032
+ const childinfo = @typeInfo (typeinfo .child );
3033
+ if (typeinfo .child == u8 and typeinfo .size != .One ) {
3034
+ return true ;
3035
+ } else if (typeinfo .size == .One and childinfo == .Array and childinfo .Array .child == u8 ) {
3036
+ return true ;
3037
+ }
3038
+ return false ;
3039
+ }
3040
+
3041
+ /// Pushes any string type
3042
+ fn pushAnyString (lua : * Lua , value : anytype ) ! void {
3043
+ const info = @typeInfo (@TypeOf (value )).Pointer ;
3044
+ switch (info .size ) {
3045
+ .One = > {
3046
+ const childinfo = @typeInfo (info .child ).Array ;
3047
+ std .debug .assert (childinfo .child == u8 );
3048
+ std .debug .assert (childinfo .sentinel != null );
3049
+
3050
+ const casted : * childinfo.child = @ptrCast (@constCast (childinfo .sentinel .? ));
3051
+ if (casted .* != 0 ) {
3052
+ @compileError ("Sentinel of slice must be a null terminator" );
3053
+ }
3054
+ _ = lua .pushString (value );
3055
+ },
3056
+ .C , .Many , .Slice = > {
3057
+ std .debug .assert (info .child == u8 );
3058
+ if (info .sentinel ) | sentinel | {
3059
+ const casted : * info.child = @ptrCast (@constCast (sentinel ));
3060
+ if (casted .* != 0 ) {
3061
+ @compileError ("Sentinel of slice must be a null terminator" );
3062
+ }
3063
+ _ = lua .pushString (value );
3064
+ } else {
3065
+ const null_terminated = try lua .allocator ().dupeZ (u8 , value );
3066
+ defer lua .allocator ().free (null_terminated );
3067
+ _ = lua .pushString (null_terminated );
3068
+ }
3069
+ },
3070
+ }
3071
+ }
3072
+
3029
3073
/// Pushes any valid zig value onto the stack,
3030
3074
/// Works with ints, floats, booleans, structs,
3031
3075
/// optionals, and strings
@@ -3038,42 +3082,41 @@ pub const Lua = struct {
3038
3082
lua .pushNumber (@floatCast (value ));
3039
3083
},
3040
3084
.Pointer = > | info | {
3041
- switch (info .size ) {
3085
+ if (comptime isTypeString (info )) {
3086
+ try lua .pushAnyString (value );
3087
+ } else switch (info .size ) {
3042
3088
.One = > {
3043
- if (@typeInfo (info .child ) == .Array ) {
3044
- if (@typeInfo (info .child ).Array .child != u8 ) {
3045
- @compileError ("only u8 arrays can be pushed" );
3046
- }
3047
- _ = lua .pushString (&(value .* ));
3048
- } else {
3049
- if (info .is_const ) {
3050
- @compileLog (value );
3051
- @compileError ("Pointer must not be const" );
3052
- }
3053
- lua .pushLightUserdata (@ptrCast (value ));
3089
+ if (info .is_const ) {
3090
+ @compileLog (value );
3091
+ @compileLog ("Lua cannot guarantee that references will not be modified" );
3092
+ @compileError ("Pointer must not be const" );
3054
3093
}
3094
+ lua .pushLightUserdata (@ptrCast (value ));
3055
3095
},
3056
3096
.C , .Many , .Slice = > {
3057
- if (info .child != u8 ) {
3058
- @compileError ("Only u8 slices (strings) are valid slice types" );
3059
- }
3060
- if (info .sentinel ) | sentinel | {
3061
- const casted : * info.child = @ptrCast (@constCast (sentinel ));
3062
- if (casted .* != 0 ) {
3063
- @compileError ("Sentinel of slice must be a null terminator" );
3064
- }
3065
- _ = lua .pushString (value );
3066
- } else {
3067
- const null_terminated = try lua .allocator ().dupeZ (u8 , value );
3068
- defer lua .allocator ().free (null_terminated );
3069
- _ = lua .pushString (null_terminated );
3097
+ lua .createTable (0 , 0 );
3098
+ for (value , 0.. ) | index_value , i | {
3099
+ try lua .pushAny (i );
3100
+ try lua .pushAny (index_value );
3101
+ lua .setTable (-3 );
3070
3102
}
3071
3103
},
3072
3104
}
3073
3105
},
3106
+ .Array = > {
3107
+ lua .createTable (0 , 0 );
3108
+ for (value , 0.. ) | index_value , i | {
3109
+ try lua .pushAny (i );
3110
+ try lua .pushAny (index_value );
3111
+ lua .setTable (-3 );
3112
+ }
3113
+ },
3074
3114
.Bool = > {
3075
3115
lua .pushBoolean (value );
3076
3116
},
3117
+ .Enum = > {
3118
+ _ = lua .pushString (@tagName (value ));
3119
+ },
3077
3120
.Optional , .Null = > {
3078
3121
if (value == null ) {
3079
3122
lua .pushNil ();
@@ -3103,8 +3146,6 @@ pub const Lua = struct {
3103
3146
/// Converts the specified index of the lua stack to the specified
3104
3147
/// type if possible and returns it
3105
3148
pub fn toAny (lua : * Lua , comptime T : type , index : i32 ) ! T {
3106
-
3107
- //TODO implement enums
3108
3149
switch (@typeInfo (T )) {
3109
3150
.Int = > {
3110
3151
switch (comptime lang ) {
@@ -3130,32 +3171,37 @@ pub const Lua = struct {
3130
3171
},
3131
3172
}
3132
3173
},
3133
- .Pointer = > | param_info | {
3134
- switch (param_info .size ) {
3174
+ .Pointer = > | info | {
3175
+ if (comptime isTypeString (info )) {
3176
+ const string : [* :0 ]const u8 = try lua .toString (index );
3177
+ const end = std .mem .indexOfSentinel (u8 , 0 , string );
3178
+
3179
+ if (info .sentinel == null ) {
3180
+ return string [0.. end ];
3181
+ } else {
3182
+ return string [0.. end :0 ];
3183
+ }
3184
+ } else switch (info .size ) {
3135
3185
.Slice , .Many = > {
3136
- if (param_info .child != u8 ) {
3137
- @compileError ("Only u8 arrays (strings) may be parameters" );
3138
- }
3139
- if (! param_info .is_const ) {
3140
- @compileError ("Slice must be a const slice" );
3141
- }
3142
- const string : [* :0 ]const u8 = try lua .toString (index );
3143
- const end = std .mem .indexOfSentinel (u8 , 0 , string );
3144
-
3145
- if (param_info .sentinel == null ) {
3146
- return string [0.. end ];
3147
- } else {
3148
- return string [0.. end :0 ];
3149
- }
3186
+ return try lua .toSlice (info .child , index );
3150
3187
},
3151
3188
else = > {
3152
- return try lua .toUserdata (param_info .child , index );
3189
+ return try lua .toUserdata (info .child , index );
3153
3190
},
3154
3191
}
3155
3192
},
3156
3193
.Bool = > {
3157
3194
return lua .toBoolean (index );
3158
3195
},
3196
+ .Enum = > | info | {
3197
+ const string = try lua .toAny ([]const u8 , index );
3198
+ inline for (info .fields ) | enum_member | {
3199
+ if (std .mem .eql (u8 , string , enum_member .name )) {
3200
+ return @field (T , enum_member .name );
3201
+ }
3202
+ }
3203
+ return error .InvalidEnumTagName ;
3204
+ },
3159
3205
.Struct = > {
3160
3206
return try lua .toStruct (T , index );
3161
3207
},
@@ -3173,6 +3219,26 @@ pub const Lua = struct {
3173
3219
}
3174
3220
}
3175
3221
3222
+ /// Converts a lua array to a zig slice, memory is owned by the caller
3223
+ fn toSlice (lua : * Lua , comptime ChildType : type , raw_index : i32 ) ! []ChildType {
3224
+ const index = lua .absIndex (raw_index );
3225
+
3226
+ if (! lua .isTable (index )) {
3227
+ return error .ValueNotATable ;
3228
+ }
3229
+
3230
+ const size = lua .rawLen (index );
3231
+ var result = try lua .allocator ().alloc (ChildType , size );
3232
+
3233
+ for (1.. size + 1 ) | i | {
3234
+ _ = try lua .pushAny (i );
3235
+ _ = lua .getTable (index );
3236
+ result [i - 1 ] = try lua .toAny (ChildType , -1 );
3237
+ }
3238
+
3239
+ return result ;
3240
+ }
3241
+
3176
3242
/// Converts value at given index to a zig struct if possible
3177
3243
fn toStruct (lua : * Lua , comptime T : type , raw_index : i32 ) ! T {
3178
3244
const index = lua .absIndex (raw_index );
0 commit comments