From d35d951d6628dbcda41a3d7ff86fbf1c0ebba595 Mon Sep 17 00:00:00 2001 From: Jon C Date: Sat, 9 Nov 2024 11:23:43 +0100 Subject: [PATCH] instruction: Fixup instruction data transmute #### Problem The `InstructionData` helper creator doesn't work for all possible types, since the `@sizeOf` macro does not use packed size. #### Summary of changes Use `@bitSizeOf` instead, and add a test. --- src/instruction.zig | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/instruction.zig b/src/instruction.zig index bba2c68..a39d399 100644 --- a/src/instruction.zig +++ b/src/instruction.zig @@ -72,12 +72,38 @@ pub const Instruction = extern struct { /// .data = data.asBytes(), /// }); pub fn InstructionData(comptime Discriminant: type, comptime Data: type) type { + comptime { + if (@bitSizeOf(Discriminant) % 8 != 0) { + @panic("Discriminant bit size is not divisible by 8"); + } + if (@bitSizeOf(Data) % 8 != 0) { + @panic("Data bit size is not divisible by 8"); + } + } return packed struct { discriminant: Discriminant, data: Data, const Self = @This(); fn asBytes(self: *const Self) []const u8 { - return std.mem.asBytes(self)[0..(@sizeOf(Discriminant) + @sizeOf(Data))]; + return std.mem.asBytes(self)[0..((@bitSizeOf(Discriminant) + @bitSizeOf(Data)) / 8)]; } }; } + +test "instruction: data transmute" { + const Discriminant = enum(u32) { + zero, + one, + two, + three, + }; + + const Data = packed struct { + a: u8, + b: u16, + c: u64, + }; + + const instruction = InstructionData(Discriminant, Data){ .discriminant = Discriminant.three, .data = Data{ .a = 1, .b = 2, .c = 3 } }; + try std.testing.expectEqualSlices(u8, instruction.asBytes(), &[_]u8{ 3, 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0 }); +}