| ... | ... | @@ -1647,12 +1647,6 @@ test readVarInt { |
| 1647 | 1647 | |
| 1648 | 1648 | /// Loads an integer from packed memory with provided bit_count, bit_offset, and signedness. |
| 1649 | 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 | | /// |
| 1656 | 1650 | pub fn readVarPackedInt( |
| 1657 | 1651 | comptime T: type, |
| 1658 | 1652 | bytes: []const u8, |
| ... | ... | @@ -1715,6 +1709,13 @@ pub fn readVarPackedInt( |
| 1715 | 1709 | } |
| 1716 | 1710 | } |
| 1717 | 1711 | |
| 1712 | test 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 | 1719 | /// Reads an integer from memory with bit count specified by T. |
| 1719 | 1720 | /// The bit count of T must be evenly divisible by 8. |
| 1720 | 1721 | /// This function cannot fail and cannot cause undefined behavior. |
| ... | ... | @@ -1811,12 +1812,6 @@ pub const readPackedIntForeign = switch (native_endian) { |
| 1811 | 1812 | |
| 1812 | 1813 | /// Loads an integer from packed memory. |
| 1813 | 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 | | /// |
| 1820 | 1815 | pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, endian: Endian) T { |
| 1821 | 1816 | switch (endian) { |
| 1822 | 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 | 1819 | } |
| 1825 | 1820 | } |
| 1826 | 1821 | |
| 1822 | test 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 | |
| 1827 | 1829 | test "comptime read/write int" { |
| 1828 | 1830 | comptime { |
| 1829 | 1831 | var bytes: [2]u8 = undefined; |
| ... | ... | @@ -1963,13 +1965,6 @@ pub const writePackedIntForeign = switch (native_endian) { |
| 1963 | 1965 | |
| 1964 | 1966 | /// Stores an integer to packed memory. |
| 1965 | 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 | | /// |
| 1973 | 1968 | pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T, endian: Endian) void { |
| 1974 | 1969 | switch (endian) { |
| 1975 | 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 | 1972 | } |
| 1978 | 1973 | } |
| 1979 | 1974 | |
| 1980 | | /// Stores an integer to packed memory with provided bit_count, bit_offset, and signedness. |
| 1975 | test 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 | 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 | | /// |
| 1990 | 1984 | pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value: anytype, endian: std.builtin.Endian) void { |
| 1991 | 1985 | const T = @TypeOf(value); |
| 1992 | 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 | 1993 | }; |
| 2000 | 1994 | const write_bytes = bytes[lowest_byte..][0..write_size]; |
| 2001 | 1995 | |
| 2002 | | if (write_size == 1) { |
| 1996 | if (write_size == 0) { |
| 1997 | return; |
| 1998 | } else if (write_size == 1) { |
| 2003 | 1999 | // Single byte writes are handled specially, since we need to mask bits |
| 2004 | 2000 | // on both ends of the byte. |
| 2005 | 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 | 2035 | write_bytes[@as(usize, @intCast(i))] |= @as(u8, @intCast(@as(uN, @bitCast(remaining)) & tail_mask)); |
| 2040 | 2036 | } |
| 2041 | 2037 | |
| 2038 | test 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 | 2046 | /// Swap the byte order of all the members of the fields of a struct |
| 2043 | 2047 | /// (Changing their endianness) |
| 2044 | 2048 | pub fn byteSwapAllFields(comptime S: type, ptr: *S) void { |