diff options
Diffstat (limited to 'src/toml_layer.zig')
| -rw-r--r-- | src/toml_layer.zig | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/toml_layer.zig b/src/toml_layer.zig new file mode 100644 index 0000000..a2c1942 --- /dev/null +++ b/src/toml_layer.zig @@ -0,0 +1,68 @@ +const std = @import("std"); +const toml = @import("toml"); + +const Allocator = std.mem.Allocator; +const Io = std.Io; +const tvalue = toml.value_mod; + +pub const ReadError = Allocator.Error || Io.Cancelable || error{ FileNotFound, ReadFailed }; + +pub fn readFileAlloc(allocator: Allocator, io: Io, path: []const u8) ReadError![]u8 { + const file = Io.Dir.cwd().openFile(io, path, .{ .mode = .read_only }) catch |err| switch (err) { + error.FileNotFound => return error.FileNotFound, + error.Canceled => return error.Canceled, + else => return error.ReadFailed, + }; + defer file.close(io); + + const len = file.length(io) catch return error.ReadFailed; + const bytes = try allocator.alloc(u8, @intCast(len)); + errdefer allocator.free(bytes); + _ = file.readPositionalAll(io, bytes, 0) catch |err| switch (err) { + error.Canceled => return error.Canceled, + else => return error.ReadFailed, + }; + return bytes; +} + +pub fn mergeTable(alloc: Allocator, dst: *toml.Value, src: *const toml.Value) Allocator.Error!void { + std.debug.assert(dst.* == .table); + if (src.* != .table) return; + + var it = toml.tableIterator(src); + while (it.next()) |entry| { + const existing = dst.get(entry.key); + if (existing != null and existing.?.* == .table and entry.value.* == .table) { + try mergeTable(alloc, @constCast(existing.?), entry.value); + } else { + const copy = try cloneValue(alloc, entry.value); + const key_copy = try alloc.dupe(u8, entry.key); + try tvalue.tableSet(alloc, dst, key_copy, copy); + } + } +} + +fn cloneValue(alloc: Allocator, src: *const toml.Value) Allocator.Error!*toml.Value { + const out = try alloc.create(toml.Value); + switch (src.*) { + .table => { + out.* = .{ .table = .{} }; + var it = toml.tableIterator(src); + while (it.next()) |entry| { + const child = try cloneValue(alloc, entry.value); + const key_copy = try alloc.dupe(u8, entry.key); + try tvalue.tableSet(alloc, out, key_copy, child); + } + }, + .array => |*a| { + out.* = .{ .array = .{} }; + for (a.items.items) |*item| { + const child = try cloneValue(alloc, item); + try tvalue.arrayAppend(alloc, out, child.*); + } + }, + .string => |s| out.* = .{ .string = try alloc.dupe(u8, s) }, + else => out.* = src.*, + } + return out; +} |
