lib/gpalloc/src/large/header.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const size_class = @import("../root.zig").class;
3 const class_policy = @import("class.zig");
4 const model = @import("model.zig");
5
6 const Class = model.Class;
7 const Header = model.Header;
8
9 pub fn initializeHeader(base: [*]u8, class: Class) [*]u8 {
10 const header: *Header = @ptrCast(@alignCast(base));
11 header.* = .{
12 .magic = model.header_magic,
13 .class_index = class.index,
14 };
15 return base + model.header_size;
16 }
17
18 pub fn headerFromUserPointer(ptr: [*]u8) *Header {
19 return @ptrCast(@alignCast(ptr - model.header_size));
20 }
21
22 pub fn classFromHeader(header: *const Header) ?Class {
23 if (header.magic != model.header_magic) return null;
24 if (header.class_index >= model.class_count) return null;
25 return class_policy.classForIndex(header.class_index);
26 }
27
28 pub fn baseFromUserPointer(ptr: [*]u8) [*]u8 {
29 return ptr - model.header_size;
30 }
31
32 test "large cache header stores only class identity" {
33 try std.testing.expectEqual(@as(usize, size_class.min_alignment), model.header_size);
34 const class = class_policy.classFor(size_class.max_small_size + 1, .@"1").?;
35 const storage_len = model.header_size + size_class.min_alignment;
36 var storage: [storage_len]u8 align(size_class.min_alignment) = undefined;
37 const user = initializeHeader(&storage, class);
38 try std.testing.expectEqual(@intFromPtr(&storage) + model.header_size, @intFromPtr(user));
39 try std.testing.expectEqual(class.index, classFromHeader(headerFromUserPointer(user)).?.index);
40
41 var invalid: Header = .{ .magic = model.header_magic, .class_index = model.class_count };
42 try std.testing.expect(classFromHeader(&invalid) == null);
43 invalid = .{ .magic = 0, .class_index = class.index };
44 try std.testing.expect(classFromHeader(&invalid) == null);
45 }