dotfiles/mzte-nv/src/ser.zig

91 lines
3 KiB
Zig

const std = @import("std");
const ffi = @import("ffi.zig");
const c = ffi.c;
pub fn luaPushAny(l: *c.lua_State, x: anytype) void {
const T = @TypeOf(x);
switch (@typeInfo(T)) {
.Void, .Null => c.lua_pushnil(l),
.Bool => c.lua_pushboolean(l, @intCast(c_int, @boolToInt(x))),
.Int, .ComptimeInt => c.lua_pushinteger(l, @intCast(c_int, x)),
.Float, .ComptimeFloat => c.lua_pushnumber(l, @floatCast(c.lua_Number, x)),
.Pointer => |P| {
switch (P.size) {
.One => {
if (T == c.lua_CFunction or
T == @typeInfo(c.lua_CFunction).Optional.child)
{
c.lua_pushcfunction(l, x);
} else if (@typeInfo(P.child) == .Array) {
luaPushAny(l, @as([]const std.meta.Elem(P.child), x));
} else {
luaPushAny(l, x.*);
}
},
.Slice => {
if (P.child == u8) {
ffi.luaPushString(l, x);
} else {
c.lua_createtable(l, x.len, 0);
for (x, 1..) |element, i| {
luaPushAny(l, element);
c.lua_rawseti(l, -2, i);
}
}
},
.C => {
if (P.child != u8)
@compileError("luaPushAny doesn't support " ++ @typeName(T));
c.lua_pushstring(l, x);
},
.Many => {
if (P.child != u8)
@compileError("luaPushAny doesn't support " ++ @typeName(T));
c.lua_pushstring(l, x);
},
}
},
.Array => luaPushAny(l, &x),
.Struct => |S| {
if (comptime std.meta.trait.hasFn("luaPush")(T)) {
return x.luaPush(l);
}
if (S.is_tuple) {
c.lua_createtable(l, S.fields.len, 0);
inline for (S.fields, 1..) |Field, i| {
luaPushAny(l, @field(x, Field.name));
c.lua_rawseti(l, -2, i);
}
} else {
c.lua_createtable(l, 0, S.fields.len);
inline for (S.fields) |Field| {
luaPushAny(l, @field(x, Field.name));
c.lua_setfield(l, -2, Field.name.ptr);
}
}
},
.Optional => {
if (x) |val| {
luaPushAny(l, val);
} else {
c.lua_pushnil(l);
}
},
.Enum, .EnumLiteral => c.lua_pushstring(l, @tagName(x)),
.Type => {
if (@hasDecl(x, "luaPush")) {
return x.luaPush(l);
}
@compileError("luaPushAny doesn't support " ++ @typeName(T));
},
else => @compileError("luaPushAny doesn't support " ++ @typeName(T)),
}
}