Commit da8fbcc2a9

clickingbuttons <clickingbuttons@pm.me>
2024-08-15 08:03:29
std.mem.writeVarPackedInt: handle write_size == 0 (#19745)
Also move example comments into tests.
1 parent 20f4be4
Changed files (1)
lib
lib/std/mem.zig
@@ -1647,12 +1647,6 @@ test readVarInt {
 
 /// Loads an integer from packed memory with provided bit_count, bit_offset, and signedness.
 /// Asserts that T is large enough to store the read value.
-///
-/// Example:
-///     const T = packed struct(u16){ a: u3, b: u7, c: u6 };
-///     var st = T{ .a = 1, .b = 2, .c = 4 };
-///     const b_field = readVarPackedInt(u64, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, builtin.cpu.arch.endian(), .unsigned);
-///
 pub fn readVarPackedInt(
     comptime T: type,
     bytes: []const u8,
@@ -1715,6 +1709,13 @@ pub fn readVarPackedInt(
     }
 }
 
+test readVarPackedInt {
+    const T = packed struct(u16) { a: u3, b: u7, c: u6 };
+    var st = T{ .a = 1, .b = 2, .c = 4 };
+    const b_field = readVarPackedInt(u64, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, builtin.cpu.arch.endian(), .unsigned);
+    try std.testing.expectEqual(st.b, b_field);
+}
+
 /// Reads an integer from memory with bit count specified by T.
 /// The bit count of T must be evenly divisible by 8.
 /// This function cannot fail and cannot cause undefined behavior.
@@ -1811,12 +1812,6 @@ pub const readPackedIntForeign = switch (native_endian) {
 
 /// Loads an integer from packed memory.
 /// Asserts that buffer contains at least bit_offset + @bitSizeOf(T) bits.
-///
-/// Example:
-///     const T = packed struct(u16){ a: u3, b: u7, c: u6 };
-///     var st = T{ .a = 1, .b = 2, .c = 4 };
-///     const b_field = readPackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), builtin.cpu.arch.endian());
-///
 pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, endian: Endian) T {
     switch (endian) {
         .little => return readPackedIntLittle(T, bytes, bit_offset),
@@ -1824,6 +1819,13 @@ pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, end
     }
 }
 
+test readPackedInt {
+    const T = packed struct(u16) { a: u3, b: u7, c: u6 };
+    var st = T{ .a = 1, .b = 2, .c = 4 };
+    const b_field = readPackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), builtin.cpu.arch.endian());
+    try std.testing.expectEqual(st.b, b_field);
+}
+
 test "comptime read/write int" {
     comptime {
         var bytes: [2]u8 = undefined;
@@ -1963,13 +1965,6 @@ pub const writePackedIntForeign = switch (native_endian) {
 
 /// Stores an integer to packed memory.
 /// Asserts that buffer contains at least bit_offset + @bitSizeOf(T) bits.
-///
-/// Example:
-///     const T = packed struct(u16){ a: u3, b: u7, c: u6 };
-///     var st = T{ .a = 1, .b = 2, .c = 4 };
-///     // st.b = 0x7f;
-///     writePackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 0x7f, builtin.cpu.arch.endian());
-///
 pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T, endian: Endian) void {
     switch (endian) {
         .little => writePackedIntLittle(T, bytes, bit_offset, value),
@@ -1977,16 +1972,15 @@ pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T
     }
 }
 
-/// Stores an integer to packed memory with provided bit_count, bit_offset, and signedness.
+test writePackedInt {
+    const T = packed struct(u16) { a: u3, b: u7, c: u6 };
+    var st = T{ .a = 1, .b = 2, .c = 4 };
+    writePackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 0x7f, builtin.cpu.arch.endian());
+    try std.testing.expectEqual(T{ .a = 1, .b = 0x7f, .c = 4 }, st);
+}
+
+/// Stores an integer to packed memory with provided bit_offset, bit_count, and signedness.
 /// If negative, the written value is sign-extended.
-///
-/// Example:
-///     const T = packed struct(u16){ a: u3, b: u7, c: u6 };
-///     var st = T{ .a = 1, .b = 2, .c = 4 };
-///     // st.b = 0x7f;
-///     var value: u64 = 0x7f;
-///     writeVarPackedInt(std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, value, builtin.cpu.arch.endian());
-///
 pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value: anytype, endian: std.builtin.Endian) void {
     const T = @TypeOf(value);
     const uN = std.meta.Int(.unsigned, @bitSizeOf(T));
@@ -1999,7 +1993,9 @@ pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value
     };
     const write_bytes = bytes[lowest_byte..][0..write_size];
 
-    if (write_size == 1) {
+    if (write_size == 0) {
+        return;
+    } else if (write_size == 1) {
         // Single byte writes are handled specially, since we need to mask bits
         // on both ends of the byte.
         const mask = (@as(u8, 0xff) >> @as(u3, @intCast(8 - bit_count)));
@@ -2039,6 +2035,14 @@ pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value
     write_bytes[@as(usize, @intCast(i))] |= @as(u8, @intCast(@as(uN, @bitCast(remaining)) & tail_mask));
 }
 
+test writeVarPackedInt {
+    const T = packed struct(u16) { a: u3, b: u7, c: u6 };
+    var st = T{ .a = 1, .b = 2, .c = 4 };
+    const value: u64 = 0x7f;
+    writeVarPackedInt(std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, value, builtin.cpu.arch.endian());
+    try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st);
+}
+
 /// Swap the byte order of all the members of the fields of a struct
 /// (Changing their endianness)
 pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {