const std = @import("std"); const testing = std.testing; const mem = std.mem; const Allocator = mem.Allocator; pub const IDManager = struct { const Self = @This(); allocator: *Allocator, nextID: usize = 0, availableIDs: std.ArrayList(usize), pub fn init(allocator: *Allocator) Self { return Self { .allocator = allocator, .availableIDs = std.ArrayList(usize).init(allocator), }; } pub fn next(self: *Self) usize { if (self.availableIDs.items.len > 0) { return self.availableIDs.pop(); } else { var result = self.nextID; self.nextID += 1; return result; } } pub fn free(self: *Self, id: usize) !void { self.availableIDs.append(id) catch |err| return err; } }; test "next" { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = &arena.allocator; var id_manager = IDManager.init(allocator); testing.expect(id_manager.next() == 0); testing.expect(id_manager.next() == 1); } test "free" { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = &arena.allocator; var id_manager = IDManager.init(allocator); var id_zero = id_manager.next(); var id_one = id_manager.next(); var id_two = id_manager.next(); try id_manager.free(id_one); testing.expect(id_manager.next() == id_one); testing.expect(id_manager.next() == 3); }