diff --git a/ly-core/build.zig b/ly-core/build.zig index 37b8668..2dd9725 100644 --- a/ly-core/build.zig +++ b/ly-core/build.zig @@ -24,7 +24,7 @@ pub fn build(b: *std.Build) void { const zlua = b.dependency("zlua", .{ .target = target, .optimize = optimize, - .lang = .luajit, + .lang = .lua53, }); mod.addImport("zlua", zlua.module("zlua")); diff --git a/ly-core/src/root.zig b/ly-core/src/root.zig index 6df7592..26b5f57 100644 --- a/ly-core/src/root.zig +++ b/ly-core/src/root.zig @@ -172,17 +172,54 @@ pub fn LuaParser(comptime Struct: type) type { return; } + // handle missing required fields + if (lua.isNil(-1)) { + return; + } + const actual_type_info = @typeInfo(actual_type); // dispatch depending on type - if (type_info == .int) { - const value = try lua.toInteger(-1); - @field(data, field.name) = @intCast(value); - } else if (type_info == .float) { // all floats + if (actual_type_info == .int and is_optional) { + if (lua.isInteger(-1)) { + const value = try lua.toInteger(-1); + @field(data, field.name) = @intCast(value); + } else { + const str = try lua.toString(-1); + + var view = try std.unicode.Utf8View.init(str); + var iter = view.iterator(); + + const codepoint = iter.nextCodepoint(); + + if (iter.nextCodepoint() != null) + return error.ExpectedSingleCharacter; + + @field(data, field.name) = if (codepoint) |cp| @intCast(cp) else null; + } + // non null integer + } else if (actual_type_info == .int) { + if (lua.isInteger(-1)) { + const value = try lua.toInteger(-1); + @field(data, field.name) = @intCast(value); + } else { + const str = try lua.toString(-1); + + var view = try std.unicode.Utf8View.init(str); + var iter = view.iterator(); + + const codepoint = iter.nextCodepoint() orelse return error.EmptyString; + + if (iter.nextCodepoint() != null) + return error.ExpectedSingleCharacter; + + @field(data, field.name) = @intCast(codepoint); + } + } else if (actual_type_info == .float) { // all floats const value = try lua.toNumber(-1); @field(data, field.name) = @floatCast(value); - } else if (type_info == .bool) { + } else if (actual_type_info == .bool) { const value = lua.toBoolean(-1); @field(data, field.name) = value; - } else if (field.type == []const u8 or field.type == [:0]const u8) { + } else if (actual_type == []const u8 or actual_type == [:0]const u8) { const value = try lua.toString(-1); if (actual_type == []const u8) { const duped = try allocator.dupe(u8, value); @@ -191,7 +228,7 @@ pub fn LuaParser(comptime Struct: type) type { const duped = try allocator.dupeSentinel(u8, value, 0); @field(data, field.name) = duped; } - } else if (type_info == .@"enum") { + } else if (actual_type_info == .@"enum") { const value = try lua.toString(-1); const variant = std.meta.stringToEnum(actual_type, value) orelse return error.InvalidVariant; @field(data, field.name) = variant; diff --git a/src/main.zig b/src/main.zig index f74844d..e2c12d5 100644 --- a/src/main.zig +++ b/src/main.zig @@ -238,7 +238,7 @@ pub fn main(init: std.process.Init) !void { }; // TODO do not hardcode config file name - const config_path = try std.Io.Dir.path.join(state.allocator, &[_][]const u8{ config_parent_path, "config.ini" }); + const config_path = try std.Io.Dir.path.join(state.allocator, &[_][]const u8{ config_parent_path, "config.lua" }); defer state.allocator.free(config_path); custom.binds = .empty; @@ -274,6 +274,7 @@ pub fn main(init: std.process.Init) !void { }; state.config = config_parser.structure(); + std.debug.print("=== {}\n", .{state.config.gameoflife_fg}); var lang_buffer: [16]u8 = undefined; const lang_file = try std.fmt.bufPrint(&lang_buffer, "{s}.ini", .{state.config.lang});