master
 1pub fn TableSection(comptime Entry: type) type {
 2    return struct {
 3        entries: std.ArrayList(Entry) = .empty,
 4        free_list: std.ArrayList(Index) = .empty,
 5        lookup: std.AutoHashMapUnmanaged(Entry, Index) = .empty,
 6
 7        pub fn deinit(self: *Self, allocator: Allocator) void {
 8            self.entries.deinit(allocator);
 9            self.free_list.deinit(allocator);
10            self.lookup.deinit(allocator);
11        }
12
13        pub fn allocateEntry(self: *Self, allocator: Allocator, entry: Entry) Allocator.Error!Index {
14            try self.entries.ensureUnusedCapacity(allocator, 1);
15            const index = blk: {
16                if (self.free_list.pop()) |index| {
17                    log.debug("  (reusing entry index {d})", .{index});
18                    break :blk index;
19                } else {
20                    log.debug("  (allocating entry at index {d})", .{self.entries.items.len});
21                    const index = @as(u32, @intCast(self.entries.items.len));
22                    _ = self.entries.addOneAssumeCapacity();
23                    break :blk index;
24                }
25            };
26            self.entries.items[index] = entry;
27            try self.lookup.putNoClobber(allocator, entry, index);
28            return index;
29        }
30
31        pub fn freeEntry(self: *Self, allocator: Allocator, entry: Entry) void {
32            const index = self.lookup.get(entry) orelse return;
33            self.free_list.append(allocator, index) catch {};
34            self.entries.items[index] = undefined;
35            _ = self.lookup.remove(entry);
36        }
37
38        pub fn count(self: Self) usize {
39            return self.entries.items.len;
40        }
41
42        pub fn format(self: Self, writer: *std.Io.Writer) std.Io.Writer.Error!void {
43            try writer.writeAll("TableSection:\n");
44            for (self.entries.items, 0..) |entry, i| {
45                try writer.print("  {d} => {}\n", .{ i, entry });
46            }
47        }
48
49        const Self = @This();
50        pub const Index = u32;
51    };
52}
53
54const std = @import("std");
55const assert = std.debug.assert;
56const log = std.log.scoped(.link);
57
58const Allocator = std.mem.Allocator;