| ... | @@ -1647,12 +1647,6 @@ test readVarInt { | ... | @@ -1647,12 +1647,6 @@ test readVarInt { |
| 1647 | | 1647 | |
| 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 | /// | | |
| 1656 | pub fn readVarPackedInt( | 1650 | pub 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 | } |
| 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 | /// 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) { |
| 1811 | | 1812 | |
| 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 | /// | | |
| 1820 | pub fn readPackedInt(comptime T: type, bytes: []const u8, bit_offset: usize, endian: Endian) T { | 1815 | pub 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 | } |
| 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 | test "comptime read/write int" { | 1829 | test "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) { |
| 1963 | | 1965 | |
| 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 | /// | | |
| 1973 | pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T, endian: Endian) void { | 1968 | pub 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 | } |
| 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 | /// 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 | /// | | |
| 1990 | pub fn writeVarPackedInt(bytes: []u8, bit_offset: usize, bit_count: usize, value: anytype, endian: std.builtin.Endian) void { | 1984 | pub 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]; |
| 2001 | | 1995 | |
| 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 bits | 1999 | // 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 | } |
| 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 | /// Swap the byte order of all the members of the fields of a struct | 2046 | /// Swap the byte order of all the members of the fields of a struct |
| 2043 | /// (Changing their endianness) | 2047 | /// (Changing their endianness) |
| 2044 | pub fn byteSwapAllFields(comptime S: type, ptr: *S) void { | 2048 | pub fn byteSwapAllFields(comptime S: type, ptr: *S) void { |