diff --git a/ly-core/src/root.zig b/ly-core/src/root.zig index 26b5f57..644106d 100644 --- a/ly-core/src/root.zig +++ b/ly-core/src/root.zig @@ -123,9 +123,10 @@ pub fn LuaParser(comptime Struct: type) type { pub fn init( allocator: std.mem.Allocator, - // io: std.Io, path: []const u8, ) !Self { + var maybe_load_error: ?anyerror = null; + errdefer |err| maybe_load_error = err; var lua: *Lua = try .init(allocator); defer lua.deinit(); @@ -135,22 +136,22 @@ pub fn LuaParser(comptime Struct: type) type { const spath: [:0]const u8 = try allocator.dupeSentinel(u8, path, 0); defer allocator.free(spath); lua.doFile(spath) catch { - const error_str = lua.toString(-1) catch unreachable; - const lua_str = try allocator.dupeSentinel(u8, error_str, 0); - _ = lua_str; // TODO add error logging + return error.LuaError; }; var data: Struct = .{}; switch (@typeInfo(Struct)) { .@"struct" => |struc| { inline for (struc.fields) |field| { - try setField(allocator, lua, field, &data); + setField(allocator, lua, field, &data) catch {}; } }, else => @compileError("Expected a struct."), } - - return .{ .structure = data, .errors = .empty, .maybe_load_error = null }; + if (global_errors.items.len != 0) { + maybe_load_error = error.InvalidConfig; + } + return .{ .structure = data, .errors = global_errors, .maybe_load_error = maybe_load_error }; } pub fn setField(allocator: std.mem.Allocator, lua: *Lua, comptime field: std.builtin.Type.StructField, data: *Struct) !void { _ = lua.getGlobal("ly"); @@ -177,6 +178,9 @@ pub fn LuaParser(comptime Struct: type) type { return; } const actual_type_info = @typeInfo(actual_type); + + errdefer |err| errorHandler(@typeName(field.type), field.name, lua.toStringEx(-1), err); + // dispatch depending on type if (actual_type_info == .int and is_optional) { if (lua.isInteger(-1)) { @@ -217,6 +221,7 @@ pub fn LuaParser(comptime Struct: type) type { const value = try lua.toNumber(-1); @field(data, field.name) = @floatCast(value); } else if (actual_type_info == .bool) { + 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) { @@ -232,7 +237,7 @@ pub fn LuaParser(comptime Struct: type) type { const value = try lua.toString(-1); const variant = std.meta.stringToEnum(actual_type, value) orelse return error.InvalidVariant; @field(data, field.name) = variant; - } + } else unreachable; } pub fn deinit(self: *Self) void { @@ -246,5 +251,14 @@ pub fn LuaParser(comptime Struct: type) type { global_errors.deinit(temporary_allocator); } + + fn errorHandler(type_name: []const u8, key: []const u8, value: []const u8, err: anyerror) void { + global_errors.append(temporary_allocator, .{ + .type_name = temporary_allocator.dupe(u8, type_name) catch return, + .key = temporary_allocator.dupe(u8, key) catch return, + .value = temporary_allocator.dupe(u8, value) catch return, + .error_name = @errorName(err), + }) catch return; + } }; }