pub const Table = std.StringHashMap(*Package); root_src_dir: std.fs.Dir, /// Relative to `root_src_dir`. root_src_path: []const u8, table: Table, /// No references to `root_src_dir` and `root_src_path` are kept. pub fn create( allocator: *mem.Allocator, base_dir: std.fs.Dir, /// Relative to `base_dir`. root_src_dir: []const u8, /// Relative to `root_src_dir`. root_src_path: []const u8, ) !*Package { const ptr = try allocator.create(Package); errdefer allocator.destroy(ptr); const root_src_path_dupe = try mem.dupe(allocator, u8, root_src_path); errdefer allocator.free(root_src_path_dupe); ptr.* = .{ .root_src_dir = try base_dir.openDir(root_src_dir, .{}), .root_src_path = root_src_path_dupe, .table = Table.init(allocator), }; return ptr; } pub fn destroy(self: *Package) void { const allocator = self.table.allocator; self.root_src_dir.close(); allocator.free(self.root_src_path); { var it = self.table.iterator(); while (it.next()) |kv| { allocator.free(kv.key); } } self.table.deinit(); allocator.destroy(self); } pub fn add(self: *Package, name: []const u8, package: *Package) !void { const name_dupe = try mem.dupe(self.table.allocator, u8, name); errdefer self.table.allocator.deinit(name_dupe); const entry = try self.table.put(name_dupe, package); assert(entry == null); } const std = @import("std"); const mem = std.mem; const assert = std.debug.assert; const Package = @This();