lib/stabilizer/src/stack.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 const config = @import("config.zig");
4 const Marsaglia = @import("rng.zig").Marsaglia;
5
6 const Allocator = std.mem.Allocator;
7 const StackConfig = config.StackConfig;
8
9 pub const StackPad = struct {
10 unit: u8,
11 bytes: usize,
12 };
13
14 pub const StackPads = struct {
15 allocator: Allocator,
16 config: StackConfig,
17 entries: []u8 = &.{},
18 index: usize = 0,
19
20 pub fn init(allocator: Allocator, stack_config: StackConfig, rng: *Marsaglia) !StackPads {
21 var self: StackPads = .{
22 .allocator = allocator,
23 .config = normalizeStackConfig(stack_config),
24 };
25 if (self.config.enabled) {
26 self.entries = try allocator.alloc(u8, self.config.entries);
27 self.refill(rng);
28 }
29 return self;
30 }
31
32 pub fn deinit(self: *StackPads) void {
33 if (self.entries.len > 0) self.allocator.free(self.entries);
34 self.* = undefined;
35 }
36
37 pub fn refill(self: *StackPads, rng: *Marsaglia) void {
38 for (self.entries) |*entry| entry.* = rng.nextByte();
39 self.index = 0;
40 }
41
42 pub fn next(self: *StackPads, rng: *Marsaglia) StackPad {
43 if (!self.config.enabled) return .{ .unit = 0, .bytes = 0 };
44 if (self.index >= self.entries.len) self.refill(rng);
45 const unit = self.entries[self.index];
46 self.index += 1;
47 return .{ .unit = unit, .bytes = @as(usize, unit) * self.config.alignment };
48 }
49 };
50
51 fn normalizeStackConfig(stack_config: StackConfig) StackConfig {
52 var out = stack_config;
53 if (out.entries == 0) out.entries = 1;
54 out.alignment = config.stack_alignment;
55 return out;
56 }