Advertisement
andewK

Untitled

Jun 29th, 2025
468
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.     safe: bool = true,
  13.     storage: enum {
  14.         dynamic,
  15.         static,
  16.     },
  17.     size: comptime_int,
  18. };
  19.  
  20. pub fn createSlab(comptime T: type, comptime cfg: SlabConfig) type {
  21.     return struct {
  22.         const Self = @This();
  23.  
  24.         allocator: std.mem.Allocator,
  25.         data: switch (cfg.storage) {
  26.             .dynamic => []?T,
  27.             .static => [cfg.size]?T,
  28.         },
  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.                 @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.             }
  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.         }
  56.  
  57.         pub fn insertAt(self: *Self, index: usize, value: T) SlabError!void {
  58.             try self.checkOutOfRage(index);
  59.             if (self.data[index] != null) return SlabError.SlotOccupied;
  60.             self.data[index] = value;
  61.         }
  62.  
  63.         pub fn remove(self: *Self, index: usize) SlabError!void {
  64.             if (comptime cfg.safe and self.data[index] == null) return SlabError.RemoveEmptySlot;
  65.             self.data[index] = null;
  66.         }
  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.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement