authorgravatar for clickingbuttons@pm.meclickingbuttons <clickingbuttons@pm.me> 2024-08-15 02:03:29-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-15 06:03:29+00:00
logda8fbcc2a9134c52474060ecc240c06e4a7df3cd
tree0dfe0ec51fb43e6862a19c967ef3e5c62cb2427d
parent20f4be4cf9953f97db8ebb302fa0e22c78d39432
signaturebadge-check Signed by PGP key B5690EEEBB952194

std.mem.writeVarPackedInt: handle write_size == 0 (#19745)

Also move example comments into tests.

1 files changed, 33 insertions(+), 29 deletions(-)

lib/std/mem.zig+33-29
......@@ -1647,12 +1647,6 @@ test readVarInt {
16471647
16481648/// Loads an integer from packed memory with provided bit_count, bit_offset, and signedness.
16491649/// Asserts that T is large enough to store the read value.
1650///
1651/// Example:
1652/// const T = packed struct(u16){ a: u3, b: u7, c: u6 };
1653/// var st = T{ .a = 1, .b = 2, .c = 4 };
1654/// const b_field = readVarPackedInt(u64, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, builtin.cpu.arch.endian(), .unsigned);
1655///
16561650pub fn readVarPackedInt(
16571651 comptime T: type,
16581652 bytes: []const u8,
......@@ -1715,6 +1709,13 @@ pub fn readVarPackedInt(
17151709 }
17161710}
17171711
1712test readVarPackedInt {
1713 const T = packed struct(u16) { a: u3, b: u7, c: u6 };
1714 var st = T{ .a = 1, .b = 2, .c = 4 };
1715 const b_field = readVarPackedInt(u64, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, builtin.cpu.arch.endian(), .unsigned);
1716 try std.testing.expectEqual(st.b, b_field);
1717}
1718
17181719/// Reads an integer from memory with bit count specified by T.
17191720/// The bit count of T must be evenly divisible by 8.
17201721/// This function cannot fail and cannot cause undefined behavior.
......@@ -1811,12 +1812,6 @@ pub const readPackedIntForeign = switch (native_endian) {
18111812
18121813/// Loads an integer from packed memory.
18131814/// Asserts that buffer contains at least bit_offset + @bitSizeOf(T) bits.
1814///
1815/// Example:
1816/// const T = packed struct(u16){ a: u3, b: u7, c: u6 };
1817/// var st = T{ .a = 1, .b = 2, .c = 4 };
1818/// const b_field = readPackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), builtin.cpu.arch.endian());
1819///
18201815pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, endian: Endian) T {
18211816 switch (endian) {
18221817 .little => return readPackedIntLittle(T, bytes, bit_offset),
......@@ -1824,6 +1819,13 @@ pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, end
18241819 }
18251820}
18261821
1822test readPackedInt {
1823 const T = packed struct(u16) { a: u3, b: u7, c: u6 };
1824 var st = T{ .a = 1, .b = 2, .c = 4 };
1825 const b_field = readPackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), builtin.cpu.arch.endian());
1826 try std.testing.expectEqual(st.b, b_field);
1827}
1828
18271829test "comptime read/write int" {
18281830 comptime {
18291831 var bytes: [2]u8 = undefined;
......@@ -1963,13 +1965,6 @@ pub const writePackedIntForeign = switch (native_endian) {
19631965
19641966/// Stores an integer to packed memory.
19651967/// Asserts that buffer contains at least bit_offset + @bitSizeOf(T) bits.
1966///
1967/// Example:
1968/// const T = packed struct(u16){ a: u3, b: u7, c: u6 };
1969/// var st = T{ .a = 1, .b = 2, .c = 4 };
1970/// // st.b = 0x7f;
1971/// writePackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 0x7f, builtin.cpu.arch.endian());
1972///
19731968pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T, endian: Endian) void {
19741969 switch (endian) {
19751970 .little => writePackedIntLittle(T, bytes, bit_offset, value),
......@@ -1977,16 +1972,15 @@ pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T
19771972 }
19781973}
19791974
1980/// Stores an integer to packed memory with provided bit_count, bit_offset, and signedness.
1975test writePackedInt {
1976 const T = packed struct(u16) { a: u3, b: u7, c: u6 };
1977 var st = T{ .a = 1, .b = 2, .c = 4 };
1978 writePackedInt(u7, std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 0x7f, builtin.cpu.arch.endian());
1979 try std.testing.expectEqual(T{ .a = 1, .b = 0x7f, .c = 4 }, st);
1980}
1981
1982/// Stores an integer to packed memory with provided bit_offset, bit_count, and signedness.
19811983/// If negative, the written value is sign-extended.
1982///
1983/// Example:
1984/// const T = packed struct(u16){ a: u3, b: u7, c: u6 };
1985/// var st = T{ .a = 1, .b = 2, .c = 4 };
1986/// // st.b = 0x7f;
1987/// var value: u64 = 0x7f;
1988/// writeVarPackedInt(std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, value, builtin.cpu.arch.endian());
1989///
19901984pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value: anytype, endian: std.builtin.Endian) void {
19911985 const T = @TypeOf(value);
19921986 const uN = std.meta.Int(.unsigned, @bitSizeOf(T));
......@@ -1999,7 +1993,9 @@ pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value
19991993 };
20001994 const write_bytes = bytes[lowest_byte..][0..write_size];
20011995
2002 if (write_size == 1) {
1996 if (write_size == 0) {
1997 return;
1998 } else if (write_size == 1) {
20031999 // Single byte writes are handled specially, since we need to mask bits
20042000 // on both ends of the byte.
20052001 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
20392035 write_bytes[@as(usize, @intCast(i))] |= @as(u8, @intCast(@as(uN, @bitCast(remaining)) & tail_mask));
20402036}
20412037
2038test writeVarPackedInt {
2039 const T = packed struct(u16) { a: u3, b: u7, c: u6 };
2040 var st = T{ .a = 1, .b = 2, .c = 4 };
2041 const value: u64 = 0x7f;
2042 writeVarPackedInt(std.mem.asBytes(&st), @bitOffsetOf(T, "b"), 7, value, builtin.cpu.arch.endian());
2043 try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st);
2044}
2045
20422046/// Swap the byte order of all the members of the fields of a struct
20432047/// (Changing their endianness)
20442048pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {