1const mem = @import("std").mem;
2
3/// WriteBuffer adds support allows writing bytes to an underlying buffer
4/// with safety-checked undefined behaviour. That is, the caller should
5/// check in advance whether sufficient space is available via
6/// WriteBuffer.capacity().
7pub const WriteBuffer = struct {
8 slice: []u8,
9 pos: usize = 0,
10
11 pub fn serialized(self: *WriteBuffer) []u8 {
12 return self.slice[0..self.pos];
13 }
14
15 pub fn capacity(self: *WriteBuffer) usize {
16 return self.slice.len - self.pos;
17 }
18
19 pub fn bytes(self: *WriteBuffer, buf: []const u8) void {
20 // mem.copy does provide us with safety-checked
21 // undefined behaviour. Thus we don't need to check
22 // the capacity explicitly here.
23 mem.copy(u8, self.slice[self.pos..], buf);
24 self.pos += buf.len;
25 }
26
27 fn write(self: *WriteBuffer, ptr: anytype) void {
28 self.bytes(mem.asBytes(ptr));
29 }
30
31 pub fn byte(self: *WriteBuffer, b: u8) void {
32 self.write(&b);
33 }
34
35 pub fn half(self: *WriteBuffer, h: u16) void {
36 self.write(&h);
37 }
38
39 pub fn word(self: *WriteBuffer, w: u32) void {
40 self.write(&w);
41 }
42};
43
44pub const ReadBuffer = struct {
45 slice: []const u8,
46
47 pub fn length(self: *ReadBuffer) usize {
48 return self.slice.len;
49 }
50
51 pub fn remaining(self: *ReadBuffer) []const u8 {
52 return self.slice;
53 }
54
55 pub fn bytes(self: *ReadBuffer, numBytes: usize) !([]const u8) {
56 if (self.slice.len < numBytes)
57 return error.OutOfBounds;
58
59 const result = self.slice[0..numBytes];
60 self.slice = self.slice[numBytes..];
61 return result;
62 }
63
64 fn read(self: *ReadBuffer, comptime T: type, dest: anytype) !void {
65 const slice = try self.bytes(@sizeOf(T));
66 dest.* = @bitCast(T, slice[0..@sizeOf(T)].*);
67 }
68
69 pub fn byte(self: *ReadBuffer) !u8 {
70 var r: u8 = undefined;
71 try self.read(u8, &r);
72 return r;
73 }
74
75 pub fn half(self: *ReadBuffer) !u16 {
76 var r: u16 = undefined;
77 try self.read(u16, &r);
78 return r;
79 }
80
81 pub fn word(self: *ReadBuffer) !u32 {
82 var r: u32 = undefined;
83 try self.read(u32, &r);
84 return r;
85 }
86};