std.mem.writeVarPackedInt: handle write_size == 0 (#19745)
Also move example comments into tests.
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user