lib/ui/src/abi/scalar.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 
 3 /// `bind` checks the ten header table spans and rejects the buffer with the first check that fails.
 4 /// A span whose `count` is 0 is not checked, whatever its `offset`. An `offset` below the 152 byte
 5 /// header is rejected with `error.SpanOutOfBounds`. An `offset` that is not a multiple of the
 6 /// element alignment is rejected with `error.SpanMisaligned`. A span whose byte length overflows
 7 /// or whose end passes the buffer is rejected with `error.SpanOutOfBounds`.
 8 pub const Span = extern struct {
 9     /// `Span.offset` is a byte offset from the start of the buffer.
10     offset: u32 = 0,
11     /// `Span.count` is a number of elements, not bytes.
12     count: u32 = 0,
13 };
14 
15 pub const Rect = extern struct {
16     x: f32 = 0,
17     y: f32 = 0,
18     width: f32 = 0,
19     height: f32 = 0,
20 };
21 
22 pub const IRect = extern struct {
23     x: i32 = 0,
24     y: i32 = 0,
25     width: u32 = 0,
26     height: u32 = 0,
27 };
28 
29 pub const Color = extern struct {
30     r: u8 = 0,
31     g: u8 = 0,
32     b: u8 = 0,
33     a: u8 = 0,
34 };
35 
36 pub const AssetHandle = extern struct {
37     index: u32 = 0,
38     generation: u32 = 0,
39 };
40 
41 /// `Atom.offset` and `Atom.len` locate the atom's bytes in the string table. An atom that runs
42 /// past that table is rejected with `error.AtomTextOutOfBounds`.
43 pub const Atom = extern struct {
44     offset: u32 = 0,
45     len: u32 = 0,
46 };
47 
48 /// `atom_absent` is 0. Entry 0 of the atom table is reserved and never dereferenced. `View.text`
49 /// returns an empty slice for it. The survey still bounds-checks its record like every other atom.
50 pub const atom_absent: u32 = 0;
51 
52 comptime {
53     std.debug.assert(@sizeOf(Span) == 8);
54     std.debug.assert(@alignOf(Span) == 4);
55     std.debug.assert(@offsetOf(Span, "offset") == 0);
56     std.debug.assert(@offsetOf(Span, "count") == 4);
57     std.debug.assert(@sizeOf(Rect) == 16);
58     std.debug.assert(@alignOf(Rect) == 4);
59     std.debug.assert(@offsetOf(Rect, "width") == 8);
60     std.debug.assert(@sizeOf(IRect) == 16);
61     std.debug.assert(@alignOf(IRect) == 4);
62     std.debug.assert(@offsetOf(IRect, "width") == 8);
63     std.debug.assert(@sizeOf(Color) == 4);
64     std.debug.assert(@alignOf(Color) == 1);
65     std.debug.assert(@offsetOf(Color, "a") == 3);
66     std.debug.assert(@sizeOf(AssetHandle) == 8);
67     std.debug.assert(@alignOf(AssetHandle) == 4);
68     std.debug.assert(@offsetOf(AssetHandle, "generation") == 4);
69     std.debug.assert(@sizeOf(Atom) == 8);
70     std.debug.assert(@alignOf(Atom) == 4);
71     std.debug.assert(@offsetOf(Atom, "len") == 4);
72 }
73 
74 test "every scalar record carries defaults a consumer can rely on" {
75     try std.testing.expectEqual(Span{ .offset = 0, .count = 0 }, Span{});
76     try std.testing.expectEqual(Rect{ .x = 0, .y = 0, .width = 0, .height = 0 }, Rect{});
77     try std.testing.expectEqual(IRect{ .x = 0, .y = 0, .width = 0, .height = 0 }, IRect{});
78     try std.testing.expectEqual(Color{ .r = 0, .g = 0, .b = 0, .a = 0 }, Color{});
79     try std.testing.expectEqual(AssetHandle{ .index = 0, .generation = 0 }, AssetHandle{});
80     try std.testing.expectEqual(Atom{ .offset = 0, .len = 0 }, Atom{});
81 }
82 
83 test "a span measures its own extent in bytes at its element size" {
84     const span = Span{ .offset = 64, .count = 3 };
85     try std.testing.expectEqual(@as(u64, 64), span.offset);
86     try std.testing.expectEqual(@as(u64, 88), span.offset + span.count * @sizeOf(Atom));
87 }