diff --git a/ly-core/src/root.zig b/ly-core/src/root.zig index f3523be..917cb8b 100644 --- a/ly-core/src/root.zig +++ b/ly-core/src/root.zig @@ -137,9 +137,7 @@ pub fn LuaParser(comptime Struct: type) type { // convert to sentinel terminated slice const spath: [:0]const u8 = try allocator.dupeSentinel(u8, path, 0); defer allocator.free(spath); - lua.doFile(spath) catch { - return error.LuaError; - }; + lua.doFile(spath) catch return error.LuaError; var data: Struct = .{}; switch (@typeInfo(Struct)) { @@ -149,7 +147,7 @@ pub fn LuaParser(comptime Struct: type) type { if (ly_type == .nil) return error.MissingLyTable; inline for (struc.fields) |field| { - setField(allocator, lua, field, &data) catch {}; + try setField(allocator, lua, field, &data); } }, else => @compileError("Expected a struct."), @@ -189,7 +187,7 @@ pub fn LuaParser(comptime Struct: type) type { // handle missing required fields if (lua.isNil(-1)) { - return; + return error.MissingRequiredField; } const actual_type_info = @typeInfo(actual_type); @@ -208,8 +206,7 @@ pub fn LuaParser(comptime Struct: type) type { const codepoint = iter.nextCodepoint(); - if (iter.nextCodepoint() != null) - return error.ExpectedSingleCharacter; + if (iter.nextCodepoint() != null) return error.ExpectedSingleCharacter; @field(data, field.name) = if (codepoint) |cp| @intCast(cp) else null; } @@ -226,8 +223,7 @@ pub fn LuaParser(comptime Struct: type) type { const codepoint = iter.nextCodepoint() orelse return error.EmptyString; - if (iter.nextCodepoint() != null) - return error.ExpectedSingleCharacter; + if (iter.nextCodepoint() != null) return error.ExpectedSingleCharacter; @field(data, field.name) = @intCast(codepoint); } @@ -238,15 +234,14 @@ pub fn LuaParser(comptime Struct: type) type { if (!lua.isBoolean(-1)) return error.ExpectedBoolean; const value = lua.toBoolean(-1); @field(data, field.name) = value; - } else if (actual_type == []const u8 or actual_type == [:0]const u8) { + } else if (actual_type == []const u8) { const value = try lua.toString(-1); - if (actual_type == []const u8) { - const duped = try allocator.dupe(u8, value); - @field(data, field.name) = duped; - } else { - const duped = try allocator.dupeSentinel(u8, value, 0); - @field(data, field.name) = duped; - } + const duped = try allocator.dupe(u8, value); + @field(data, field.name) = duped; + } else if (actual_type == [:0]const u8) { + const value = try lua.toString(-1); + const duped = try allocator.dupeSentinel(u8, value, 0); + @field(data, field.name) = duped; } else if (actual_type_info == .@"enum") { const value = try lua.toString(-1); const variant = std.meta.stringToEnum(actual_type, value) orelse return error.InvalidVariant; @@ -261,107 +256,100 @@ pub fn LuaParser(comptime Struct: type) type { _ = lua.getField(-1, "custom_commands"); // custom_commands can be omitted or empty, so we just skip instead of erroring - binds: { - if (lua.isTable(-1)) { - const len = @as(usize, @intCast(lua.lenRaiseErr(-1))); - if (len == 0) break :binds; - for (1..len + 1) |i| { - // push i-th table to stack - const ith_table_type = lua.getIndex(-1, @intCast(i)); - defer lua.pop(1); // i-th table in custom_commands - if (ith_table_type != .table) continue; + if (lua.isTable(-1)) binds: { + const len: usize = @intCast(lua.lenRaiseErr(-1)); + if (len == 0) break :binds; - // skip command if binding isn't set or not a string - const binding_type = lua.getField(-1, "binding"); - if (binding_type != .string) continue; - const binding = lua.toString(-1) catch continue; - const bindingZ = temporary_allocator.dupe(u8, binding) catch ""; - lua.pop(1); // binding value + for (1..len + 1) |i| { + // push i-th table to stack + const ith_table_type = lua.getIndex(-1, @intCast(i)); + defer lua.pop(1); // i-th table in custom_commands + if (ith_table_type != .table) continue; - if (!custom.binds.contains(bindingZ)) { - custom.binds.put(temporary_allocator, bindingZ, .{}) catch {}; - } - if (custom.binds.getPtr(bindingZ)) |command| { - // binding name - const name_type = lua.getField(-1, "name"); - if (name_type != .string) continue; - const binding_name = lua.toString(-1) catch ""; - command.name = temporary_allocator.dupe(u8, binding_name) catch ""; - lua.pop(1); // name value + // skip command if binding isn't set or not a string + const binding_type = lua.getField(-1, "binding"); + if (binding_type != .string) continue; + const binding = lua.toString(-1) catch continue; + const bindingZ = temporary_allocator.dupe(u8, binding) catch ""; + lua.pop(1); // binding value - // binding command - const cmd_type = lua.getField(-1, "cmd"); - if (cmd_type != .string) continue; - const binding_cmd = lua.toString(-1) catch ""; - command.cmd = temporary_allocator.dupe(u8, binding_cmd) catch ""; - lua.pop(1); // cmd value - } + if (!custom.binds.contains(bindingZ)) { + custom.binds.put(temporary_allocator, bindingZ, .{}) catch {}; + } + if (custom.binds.getPtr(bindingZ)) |command| { + // binding name + const name_type = lua.getField(-1, "name"); + if (name_type != .string) continue; + const binding_name = lua.toString(-1) catch ""; + command.name = temporary_allocator.dupe(u8, binding_name) catch ""; + lua.pop(1); // name value + + // binding command + const cmd_type = lua.getField(-1, "cmd"); + if (cmd_type != .string) continue; + const binding_cmd = lua.toString(-1) catch ""; + command.cmd = temporary_allocator.dupe(u8, binding_cmd) catch ""; + lua.pop(1); // cmd value } } } + lua.pop(1); _ = lua.getField(-1, "custom_labels"); // custom_labels can be omitted, so we just skip instead of erroring - labels: { - if (lua.isTable(-1)) { - const len = @as(usize, @intCast(lua.lenRaiseErr(-1))); - if (len == 0) break :labels; - for (1..len + 1) |i| { - // push i-th table to stack - const ith_table_type = lua.getIndex(-1, @intCast(i)); - defer lua.pop(1); // i-th table in custom_labels - if (ith_table_type != .table) continue; + if (lua.isTable(-1)) labels: { + const len: usize = @intCast(lua.lenRaiseErr(-1)); + if (len == 0) break :labels; - // skip command if binding isn't set or not a string - const label_type = lua.getField(-1, "label"); - if (label_type != .string) continue; - const label = lua.toString(-1) catch continue; - const labelZ = temporary_allocator.dupe(u8, label) catch ""; - lua.pop(1); // label value + for (1..len + 1) |i| { + // push i-th table to stack + const ith_table_type = lua.getIndex(-1, @intCast(i)); + defer lua.pop(1); // i-th table in custom_labels + if (ith_table_type != .table) continue; - if (!custom.labels.contains(labelZ)) { - custom.labels.put(temporary_allocator, labelZ, .{ .name = labelZ }) catch {}; - } - if (custom.labels.getPtr(labelZ)) |label_ptr| { - // label command - const cmd_type = lua.getField(-1, "cmd"); - if (cmd_type != .string) continue; - const label_cmd = lua.toString(-1) catch ""; - label_ptr.cmd = temporary_allocator.dupe(u8, label_cmd) catch ""; - lua.pop(1); // cmd value + // skip command if binding isn't set or not a string + const label_type = lua.getField(-1, "label"); + if (label_type != .string) continue; + const label = lua.toString(-1) catch continue; + const labelZ = temporary_allocator.dupe(u8, label) catch ""; + lua.pop(1); // label value - // label refresh - const name_type = lua.getField(-1, "refresh"); - if (name_type != .number) continue; - const label_refresh: u32 = @intCast(lua.toInteger(-1) catch 0); - label_ptr.refresh = label_refresh; - lua.pop(1); // name value - } + if (!custom.labels.contains(labelZ)) { + custom.labels.put(temporary_allocator, labelZ, .{ .name = labelZ }) catch {}; + } + if (custom.labels.getPtr(labelZ)) |label_ptr| { + // label command + const cmd_type = lua.getField(-1, "cmd"); + if (cmd_type != .string) continue; + const label_cmd = lua.toString(-1) catch ""; + label_ptr.cmd = temporary_allocator.dupe(u8, label_cmd) catch ""; + lua.pop(1); // cmd value + + // label refresh + const name_type = lua.getField(-1, "refresh"); + if (name_type != .number) continue; + const label_refresh: u32 = @intCast(lua.toInteger(-1) catch 0); + label_ptr.refresh = label_refresh; + lua.pop(1); // name value } } } + lua.pop(1); } pub fn deinit(self: *Self) void { inline for (@typeInfo(Struct).@"struct".fields) |field| { const type_info = @typeInfo(field.type); - const actual_type = blk: { - if (type_info == .optional) { - break :blk type_info.optional.child; - } - break :blk field.type; - }; + const actual_type = if (type_info == .optional) type_info.optional.child else field.type; const value = @field(self.structure, field.name); if (actual_type == []const u8 or actual_type == [:0]const u8) { if (type_info == .optional) { - if (value) |inner| { - self.allocator.free(inner); - } + if (value) |inner| self.allocator.free(inner); } else { self.allocator.free(value); }