SHOW:
|
|
- or go back to the newest paste.
1 | ||
2 | const std = @import("std"); | |
3 | ||
4 | const SlabError = error{ | |
5 | OutOfRange, | |
6 | SlotOccupied, | |
7 | EmptySlot, | |
8 | RemoveEmptySlot, | |
9 | }; | |
10 | ||
11 | const SlabConfig = struct { | |
12 | - | dynamic: bool = true, |
12 | + | |
13 | storage: enum { | |
14 | dynamic, | |
15 | static, | |
16 | }, | |
17 | size: comptime_int, | |
18 | }; | |
19 | ||
20 | - | data: []?T, |
20 | + | |
21 | return struct { | |
22 | - | pub fn init(allocator: ?std.mem.Allocator) !Self { |
22 | + | |
23 | - | if (comptime cfg.dynamic) { |
23 | + | |
24 | - | if (allocator == null) @compileError("Allocator is required for dynamic slab."); |
24 | + | |
25 | - | const data = try allocator.?.alloc(?T, cfg.size); |
25 | + | data: switch (cfg.storage) { |
26 | - | for (data) |*slot| slot.* = null; |
26 | + | .dynamic => []?T, |
27 | .static => [cfg.size]?T, | |
28 | - | .allocator = allocator.?, |
28 | + | }, |
29 | - | // .data = comptime @as(&T, &[_]?T{null} ** cfg.size), |
29 | + | |
30 | fn init(allocator: ?std.mem.Allocator) !Self { | |
31 | if (cfg.storage == .dynamic) { | |
32 | const alloc = allocator orelse @panic("Allocator is required for dynamic slab."); | |
33 | const data = try alloc.alloc(?T, cfg.size); | |
34 | - | .data = @memset(, elem), |
34 | + | @memset(data, null); |
35 | return Self{ | |
36 | .allocator = alloc, | |
37 | .data = data, | |
38 | }; | |
39 | } else { | |
40 | return Self{ | |
41 | .allocator = undefined, | |
42 | .data = @splat(null), | |
43 | }; | |
44 | - | try checkOutOfRage(index); |
44 | + | |
45 | } | |
46 | ||
47 | pub fn deinit(self: *Self, alloc: ?std.mem.Allocator) void { | |
48 | if (cfg.storage == .dynamic) { | |
49 | alloc.?.free(self.data); | |
50 | } | |
51 | } | |
52 | ||
53 | inline fn checkOutOfRage(self: *Self, index: usize) !void { | |
54 | if (cfg.safe and index >= self.data.len) return SlabError.OutOfRange; | |
55 | - | try checkOutOfRage(index); |
55 | + | |
56 | ||
57 | - | const maybe = self.data[index] orelse return SlabError.EmptySlot; |
57 | + | |
58 | - | return &maybe; |
58 | + | try self.checkOutOfRage(index); |
59 | if (self.data[index] != null) return SlabError.SlotOccupied; | |
60 | self.data[index] = value; | |
61 | } | |
62 | ||
63 | - | test "init" { |
63 | + | |
64 | - | const Slab = createSlab(u32, .{ .dynamic = false, .size = 3000, .safe = false }); |
64 | + | |
65 | - | const slab = try Slab.init(null); |
65 | + | |
66 | } | |
67 | - | std.debug.print("{}\n", .{slab.get(2500)}); |
67 | + | |
68 | pub fn get(self: *Self, index: usize) SlabError!*T { | |
69 | try self.checkOutOfRage(index); | |
70 | ||
71 | const maybe = &(self.data[index] orelse return SlabError.EmptySlot); | |
72 | return maybe; | |
73 | } | |
74 | }; | |
75 | } | |
76 | ||
77 | test "init static" { | |
78 | const Slab = createSlab(u32, .{ .storage = .static, .size = 3000, .safe = false }); | |
79 | var slab = try Slab.init(null); | |
80 | try slab.insertAt(2500, 25); | |
81 | std.debug.print("{}\n", .{(try slab.get(2500)).*}); | |
82 | } | |
83 | ||
84 | test "init dynamic" { | |
85 | const Slab = createSlab(u32, .{ .storage = .dynamic, .size = 3000, .safe = false }); | |
86 | ||
87 | var slab = try Slab.init(std.testing.allocator); | |
88 | defer slab.deinit(std.testing.allocator); | |
89 | ||
90 | try slab.insertAt(2500, 25); | |
91 | std.debug.print("{}\n", .{(try slab.get(2500)).*}); | |
92 | } | |
93 |