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 {...@@ -1647,12 +1647,6 @@ test readVarInt {
16471647
1648/// Loads an integer from packed memory with provided bit_count, bit_offset, and signedness.1648/// Loads an integer from packed memory with provided bit_count, bit_offset, and signedness.
1649/// Asserts that T is large enough to store the read value.1649/// 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///
1656pub fn readVarPackedInt(1650pub fn readVarPackedInt(
1657 comptime T: type,1651 comptime T: type,
1658 bytes: []const u8,1652 bytes: []const u8,
...@@ -1715,6 +1709,13 @@ pub fn readVarPackedInt(...@@ -1715,6 +1709,13 @@ pub fn readVarPackedInt(
1715 }1709 }
1716}1710}
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
1718/// Reads an integer from memory with bit count specified by T.1719/// Reads an integer from memory with bit count specified by T.
1719/// The bit count of T must be evenly divisible by 8.1720/// The bit count of T must be evenly divisible by 8.
1720/// This function cannot fail and cannot cause undefined behavior.1721/// This function cannot fail and cannot cause undefined behavior.
...@@ -1811,12 +1812,6 @@ pub const readPackedIntForeign = switch (native_endian) {...@@ -1811,12 +1812,6 @@ pub const readPackedIntForeign = switch (native_endian) {
18111812
1812/// Loads an integer from packed memory.1813/// Loads an integer from packed memory.
1813/// Asserts that buffer contains at least bit_offset + @bitSizeOf(T) bits.1814/// 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///
1820pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, endian: Endian) T {1815pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, endian: Endian) T {
1821 switch (endian) {1816 switch (endian) {
1822 .little => return readPackedIntLittle(T, bytes, bit_offset),1817 .little => return readPackedIntLittle(T, bytes, bit_offset),
...@@ -1824,6 +1819,13 @@ pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, end...@@ -1824,6 +1819,13 @@ pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, end
1824 }1819 }
1825}1820}
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
1827test "comptime read/write int" {1829test "comptime read/write int" {
1828 comptime {1830 comptime {
1829 var bytes: [2]u8 = undefined;1831 var bytes: [2]u8 = undefined;
...@@ -1963,13 +1965,6 @@ pub const writePackedIntForeign = switch (native_endian) {...@@ -1963,13 +1965,6 @@ pub const writePackedIntForeign = switch (native_endian) {
19631965
1964/// Stores an integer to packed memory.1966/// Stores an integer to packed memory.
1965/// Asserts that buffer contains at least bit_offset + @bitSizeOf(T) bits.1967/// 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///
1973pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T, endian: Endian) void {1968pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T, endian: Endian) void {
1974 switch (endian) {1969 switch (endian) {
1975 .little => writePackedIntLittle(T, bytes, bit_offset, value),1970 .little => writePackedIntLittle(T, bytes, bit_offset, value),
...@@ -1977,16 +1972,15 @@ pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T...@@ -1977,16 +1972,15 @@ pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T
1977 }1972 }
1978}1973}
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.
1981/// If negative, the written value is sign-extended.1983/// 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///
1990pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value: anytype, endian: std.builtin.Endian) void {1984pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value: anytype, endian: std.builtin.Endian) void {
1991 const T = @TypeOf(value);1985 const T = @TypeOf(value);
1992 const uN = std.meta.Int(.unsigned, @bitSizeOf(T));1986 const uN = std.meta.Int(.unsigned, @bitSizeOf(T));
...@@ -1999,7 +1993,9 @@ pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value...@@ -1999,7 +1993,9 @@ pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value
1999 };1993 };
2000 const write_bytes = bytes[lowest_byte..][0..write_size];1994 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) {
2003 // Single byte writes are handled specially, since we need to mask bits1999 // Single byte writes are handled specially, since we need to mask bits
2004 // on both ends of the byte.2000 // on both ends of the byte.
2005 const mask = (@as(u8, 0xff) >> @as(u3, @intCast(8 - bit_count)));2001 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...@@ -2039,6 +2035,14 @@ pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value
2039 write_bytes[@as(usize, @intCast(i))] |= @as(u8, @intCast(@as(uN, @bitCast(remaining)) & tail_mask));2035 write_bytes[@as(usize, @intCast(i))] |= @as(u8, @intCast(@as(uN, @bitCast(remaining)) & tail_mask));
2040}2036}
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
2042/// Swap the byte order of all the members of the fields of a struct2046/// Swap the byte order of all the members of the fields of a struct
2043/// (Changing their endianness)2047/// (Changing their endianness)
2044pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {2048pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {