Simplify init interface

This commit is contained in:
2025-04-29 08:46:18 -04:00
parent bcab1e4d00
commit f1dce257be

View File

@@ -76,8 +76,22 @@ pub const ZeroCopyMessage = packed struct {
length: u16, length: u16,
bytes: void = {}, bytes: void = {},
pub fn init(allocator: Allocator, payload_len: u16) !*Self { pub fn init(allocator: Allocator, comptime @"type": PacketType, payload_len: u16) !*Self {
const bytes = try allocator.alignedAlloc(u8, @alignOf(Self), @sizeOf(Self) + payload_len); const header_size = @sizeOf(switch (@"type") {
.relay => Relay,
.connection => Connection,
else => return error.Bad,
});
const size = payload_len + @sizeOf(Self) + header_size;
const bytes = try allocator.alignedAlloc(u8, @alignOf(Self), size);
const res: *Self = @ptrCast(bytes.ptr);
res.type = @"type";
res.length = payload_len + header_size;
return res;
}
pub fn deinit(self: *Self, allocator: Allocator) void {
allocator.free(self.toBytes());
} }
fn getRelay(self: *Self) *align(1) Relay { fn getRelay(self: *Self) *align(1) Relay {
@@ -106,12 +120,13 @@ pub const ZeroCopyMessage = packed struct {
@intFromEnum(self.type), @intFromEnum(self.type),
)); ));
self.length = bigToNative(@TypeOf(self.length), self.length); self.length = bigToNative(@TypeOf(self.length), self.length);
try switch (try self.getSaprusTypePayload()) { switch (try self.getSaprusTypePayload()) {
.relay => {}, .relay => {},
.connection => |*con| con.*.nativeFromNetworkEndian(), .connection => |*con| try con.*.nativeFromNetworkEndian(),
.file_transfer => Error.NotImplementedSaprusType, // We know other values are unreachable,
else => Error.UnknownSaprusType, // because they would have returned an error from the switch condition.
}; else => unreachable,
}
} }
pub fn networkFromNativeEndian(self: *Self) Error!void { pub fn networkFromNativeEndian(self: *Self) Error!void {
@@ -136,33 +151,42 @@ pub const ZeroCopyMessage = packed struct {
const res: *Self = @ptrCast(@alignCast(bytes.ptr)); const res: *Self = @ptrCast(@alignCast(bytes.ptr));
return if (bytes.len == res.length + @sizeOf(Self)) res else Error.InvalidMessage; return if (bytes.len == res.length + @sizeOf(Self)) res else Error.InvalidMessage;
} }
pub fn toBytes(self: *Self) []align(@alignOf(Self)) u8 {
return @as([*]align(@alignOf(Self)) u8, @ptrCast(self))[0 .. @sizeOf(Self) + self.length];
}
}; };
test "testing variable length zero copy struct" { test "testing variable length zero copy struct" {
const gpa = std.testing.allocator; const gpa = std.testing.allocator;
const payload_len = 48; const payload = "Hello darkness my old friend";
defer gpa.free(bytes);
// Create a view of the byte slice as a ZeroCopyMessage // Create a view of the byte slice as a ZeroCopyMessage
const zcm: *ZeroCopyMessage = .fromBytesUnchecked(bytes); const zcm: *ZeroCopyMessage = try .init(gpa, .relay, payload.len);
defer zcm.deinit(gpa); defer zcm.deinit(gpa);
{ {
// Set the message values // Set the message values
zcm.type = .relay; {
// zcm.length = payload_len; // These are both set by the init call.
// zcm.type = .relay;
// zcm.length = payload_len;
}
const relay = (try zcm.getSaprusTypePayload()).relay; const relay = (try zcm.getSaprusTypePayload()).relay;
relay.dest = .{ 1, 2, 3, 4 }; relay.dest = .{ 1, 2, 3, 4 };
const payload = relay.getPayload(); @memcpy(relay.getPayload(), payload);
const p = "Hello darkness my old friend";
@memcpy(payload[0..p.len], p);
} }
{ {
// Print the message as hex using the network const bytes = zcm.toBytes();
zcm.networkFromNativeEndian() catch unreachable;
// Print the message as hex using the network byte order
try zcm.networkFromNativeEndian();
// We know the error from nativeFromNetworkEndian is unreachable because
// it would have returned an error from networkFromNativeEndian.
defer zcm.nativeFromNetworkEndian() catch unreachable; defer zcm.nativeFromNetworkEndian() catch unreachable;
std.debug.print("network bytes: {x}\n", .{bytes}); std.debug.print("network bytes: {s}\n", .{bytes});
std.debug.print("bytes len: {d}\n", .{bytes.len});
} }
if (false) { if (false) {