summaryrefslogtreecommitdiff
path: root/src/toml_layer.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/toml_layer.zig')
-rw-r--r--src/toml_layer.zig68
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;
+}