| author | |
| committer | |
| log | 7664c3bc11988fd1ee2b3f26d1f08ac80d873c64 |
| tree | 5470775882ec5d4379fde64ea5eb6cd10d3d0342 |
| parent | 783e8ad0319b950a1d42d5a93e4fbb9e9df1be10 |
14 files changed, 141 insertions(+), 181 deletions(-)
doc/langref.html.in+11-50| ... | ... | @@ -2025,7 +2025,8 @@ test "volatile" { |
| 2025 | 2025 | conversions are not possible. |
| 2026 | 2026 | </p> |
| 2027 | 2027 | {#code_begin|test#} |
| 2028 | const assert = @import("std").debug.assert; | |
| 2028 | const std = @import("std"); | |
| 2029 | const assert = std.debug.assert; | |
| 2029 | 2030 | |
| 2030 | 2031 | test "pointer casting" { |
| 2031 | 2032 | const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 }; |
| ... | ... | @@ -2034,7 +2035,7 @@ test "pointer casting" { |
| 2034 | 2035 | |
| 2035 | 2036 | // Even this example is contrived - there are better ways to do the above than |
| 2036 | 2037 | // pointer casting. For example, using a slice narrowing cast: |
| 2037 | const u32_value = @bytesToSlice(u32, bytes[0..])[0]; | |
| 2038 | const u32_value = std.mem.bytesAsSlice(u32, bytes[0..])[0]; | |
| 2038 | 2039 | assert(u32_value == 0x12121212); |
| 2039 | 2040 | |
| 2040 | 2041 | // And even another way, the most straightforward way to do it: |
| ... | ... | @@ -2114,16 +2115,16 @@ test "function alignment" { |
| 2114 | 2115 | {#link|safety check|Incorrect Pointer Alignment#}: |
| 2115 | 2116 | </p> |
| 2116 | 2117 | {#code_begin|test_safety|incorrect alignment#} |
| 2117 | const assert = @import("std").debug.assert; | |
| 2118 | const std = @import("std"); | |
| 2118 | 2119 | |
| 2119 | 2120 | test "pointer alignment safety" { |
| 2120 | 2121 | var array align(4) = [_]u32{ 0x11111111, 0x11111111 }; |
| 2121 | const bytes = @sliceToBytes(array[0..]); | |
| 2122 | assert(foo(bytes) == 0x11111111); | |
| 2122 | const bytes = std.mem.sliceAsBytes(array[0..]); | |
| 2123 | std.debug.assert(foo(bytes) == 0x11111111); | |
| 2123 | 2124 | } |
| 2124 | 2125 | fn foo(bytes: []u8) u32 { |
| 2125 | 2126 | const slice4 = bytes[1..5]; |
| 2126 | const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); | |
| 2127 | const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); | |
| 2127 | 2128 | return int_slice[0]; |
| 2128 | 2129 | } |
| 2129 | 2130 | {#code_end#} |
| ... | ... | @@ -2249,7 +2250,7 @@ test "slice widening" { |
| 2249 | 2250 | // Zig supports slice widening and slice narrowing. Cast a slice of u8 |
| 2250 | 2251 | // to a slice of anything else, and Zig will perform the length conversion. |
| 2251 | 2252 | const array align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 }; |
| 2252 | const slice = @bytesToSlice(u32, array[0..]); | |
| 2253 | const slice = mem.bytesAsSlice(u32, array[0..]); | |
| 2253 | 2254 | assert(slice.len == 2); |
| 2254 | 2255 | assert(slice[0] == 0x12121212); |
| 2255 | 2256 | assert(slice[1] == 0x13131313); |
| ... | ... | @@ -5186,7 +5187,6 @@ test "coercion of zero bit types" { |
| 5186 | 5187 | <li>{#link|@bitCast#} - change type but maintain bit representation</li> |
| 5187 | 5188 | <li>{#link|@alignCast#} - make a pointer have more alignment</li> |
| 5188 | 5189 | <li>{#link|@boolToInt#} - convert true to 1 and false to 0</li> |
| 5189 | <li>{#link|@bytesToSlice#} - convert a slice of bytes to a slice of another type</li> | |
| 5190 | 5190 | <li>{#link|@enumToInt#} - obtain the integer tag value of an enum or tagged union</li> |
| 5191 | 5191 | <li>{#link|@errSetCast#} - convert to a smaller error set</li> |
| 5192 | 5192 | <li>{#link|@errorToInt#} - obtain the integer value of an error code</li> |
| ... | ... | @@ -5199,7 +5199,6 @@ test "coercion of zero bit types" { |
| 5199 | 5199 | <li>{#link|@intToPtr#} - convert an address to a pointer</li> |
| 5200 | 5200 | <li>{#link|@ptrCast#} - convert between pointer types</li> |
| 5201 | 5201 | <li>{#link|@ptrToInt#} - obtain the address of a pointer</li> |
| 5202 | <li>{#link|@sliceToBytes#} - convert a slice of anything to a slice of bytes</li> | |
| 5203 | 5202 | <li>{#link|@truncate#} - convert between integer types, chopping off bits</li> |
| 5204 | 5203 | </ul> |
| 5205 | 5204 | {#header_close#} |
| ... | ... | @@ -6929,18 +6928,6 @@ async fn func(y: *i32) void { |
| 6929 | 6928 | {#see_also|@bitOffsetOf#} |
| 6930 | 6929 | {#header_close#} |
| 6931 | 6930 | |
| 6932 | {#header_open|@bytesToSlice#} | |
| 6933 | <pre>{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}</pre> | |
| 6934 | <p> | |
| 6935 | Converts a slice of bytes or array of bytes into a slice of {#syntax#}Element{#endsyntax#}. | |
| 6936 | The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter. | |
| 6937 | </p> | |
| 6938 | <p> | |
| 6939 | Attempting to convert a number of bytes with a length that does not evenly divide into a slice of | |
| 6940 | elements results in safety-protected {#link|Undefined Behavior#}. | |
| 6941 | </p> | |
| 6942 | {#header_close#} | |
| 6943 | ||
| 6944 | 6931 | {#header_open|@call#} |
| 6945 | 6932 | <pre>{#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}</pre> |
| 6946 | 6933 | <p> |
| ... | ... | @@ -8101,14 +8088,6 @@ test "@setRuntimeSafety" { |
| 8101 | 8088 | {#see_also|@bitSizeOf|@typeInfo#} |
| 8102 | 8089 | {#header_close#} |
| 8103 | 8090 | |
| 8104 | {#header_open|@sliceToBytes#} | |
| 8105 | <pre>{#syntax#}@sliceToBytes(value: var) []u8{#endsyntax#}</pre> | |
| 8106 | <p> | |
| 8107 | Converts a slice or array to a slice of {#syntax#}u8{#endsyntax#}. The resulting slice has the same | |
| 8108 | {#link|pointer|Pointers#} properties as the parameter. | |
| 8109 | </p> | |
| 8110 | {#header_close#} | |
| 8111 | ||
| 8112 | 8091 | {#header_open|@splat#} |
| 8113 | 8092 | <pre>{#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @TypeOf(scalar)){#endsyntax#}</pre> |
| 8114 | 8093 | <p> |
| ... | ... | @@ -8919,25 +8898,6 @@ pub fn main() void { |
| 8919 | 8898 | var b: u32 = 3; |
| 8920 | 8899 | var c = @divExact(a, b); |
| 8921 | 8900 | std.debug.warn("value: {}\n", .{c}); |
| 8922 | } | |
| 8923 | {#code_end#} | |
| 8924 | {#header_close#} | |
| 8925 | {#header_open|Slice Widen Remainder#} | |
| 8926 | <p>At compile-time:</p> | |
| 8927 | {#code_begin|test_err|unable to convert#} | |
| 8928 | comptime { | |
| 8929 | var bytes = [5]u8{ 1, 2, 3, 4, 5 }; | |
| 8930 | var slice = @bytesToSlice(u32, bytes[0..]); | |
| 8931 | } | |
| 8932 | {#code_end#} | |
| 8933 | <p>At runtime:</p> | |
| 8934 | {#code_begin|exe_err#} | |
| 8935 | const std = @import("std"); | |
| 8936 | ||
| 8937 | pub fn main() void { | |
| 8938 | var bytes = [5]u8{ 1, 2, 3, 4, 5 }; | |
| 8939 | var slice = @bytesToSlice(u32, bytes[0..]); | |
| 8940 | std.debug.warn("value: {}\n", .{slice[0]}); | |
| 8941 | 8901 | } |
| 8942 | 8902 | {#code_end#} |
| 8943 | 8903 | {#header_close#} |
| ... | ... | @@ -9119,14 +9079,15 @@ comptime { |
| 9119 | 9079 | {#code_end#} |
| 9120 | 9080 | <p>At runtime:</p> |
| 9121 | 9081 | {#code_begin|exe_err#} |
| 9082 | const mem = @import("std").mem; | |
| 9122 | 9083 | pub fn main() !void { |
| 9123 | 9084 | var array align(4) = [_]u32{ 0x11111111, 0x11111111 }; |
| 9124 | const bytes = @sliceToBytes(array[0..]); | |
| 9085 | const bytes = mem.sliceAsBytes(array[0..]); | |
| 9125 | 9086 | if (foo(bytes) != 0x11111111) return error.Wrong; |
| 9126 | 9087 | } |
| 9127 | 9088 | fn foo(bytes: []u8) u32 { |
| 9128 | 9089 | const slice4 = bytes[1..5]; |
| 9129 | const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); | |
| 9090 | const int_slice = mem.bytesAsSlice(u32, @alignCast(4, slice4)); | |
| 9130 | 9091 | return int_slice[0]; |
| 9131 | 9092 | } |
| 9132 | 9093 | {#code_end#} |
lib/std/mem.zig+100-14| ... | ... | @@ -1488,28 +1488,34 @@ test "bytesToValue" { |
| 1488 | 1488 | |
| 1489 | 1489 | //TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. |
| 1490 | 1490 | fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type { |
| 1491 | if (comptime !trait.isSlice(bytesType) or comptime meta.Child(bytesType) != u8) { | |
| 1492 | @compileError("expected []u8, passed " ++ @typeName(bytesType)); | |
| 1491 | if (!(trait.isSlice(bytesType) and meta.Child(bytesType) == u8) and !(trait.isPtrTo(.Array)(bytesType) and meta.Child(meta.Child(bytesType)) == u8)) { | |
| 1492 | @compileError("expected []u8 or *[_]u8, passed " ++ @typeName(bytesType)); | |
| 1493 | 1493 | } |
| 1494 | 1494 | |
| 1495 | const alignment = comptime meta.alignment(bytesType); | |
| 1495 | if (trait.isPtrTo(.Array)(bytesType) and @typeInfo(meta.Child(bytesType)).Array.len % @sizeOf(T) != 0) { | |
| 1496 | @compileError("number of bytes in " ++ @typeName(bytesType) ++ " is not divisible by size of " ++ @typeName(T)); | |
| 1497 | } | |
| 1496 | 1498 | |
| 1497 | return if (comptime trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; | |
| 1499 | const alignment = meta.alignment(bytesType); | |
| 1500 | ||
| 1501 | return if (trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; | |
| 1498 | 1502 | } |
| 1499 | 1503 | |
| 1500 | 1504 | pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) { |
| 1505 | const bytesSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(bytes))) bytes[0..] else bytes; | |
| 1506 | ||
| 1501 | 1507 | // let's not give an undefined pointer to @ptrCast |
| 1502 | 1508 | // it may be equal to zero and fail a null check |
| 1503 | if (bytes.len == 0) { | |
| 1509 | if (bytesSlice.len == 0) { | |
| 1504 | 1510 | return &[0]T{}; |
| 1505 | 1511 | } |
| 1506 | 1512 | |
| 1507 | const bytesType = @TypeOf(bytes); | |
| 1513 | const bytesType = @TypeOf(bytesSlice); | |
| 1508 | 1514 | const alignment = comptime meta.alignment(bytesType); |
| 1509 | 1515 | |
| 1510 | 1516 | const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T; |
| 1511 | 1517 | |
| 1512 | return @ptrCast(castTarget, bytes.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; | |
| 1518 | return @ptrCast(castTarget, bytesSlice.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; | |
| 1513 | 1519 | } |
| 1514 | 1520 | |
| 1515 | 1521 | test "bytesAsSlice" { |
| ... | ... | @@ -1520,30 +1526,59 @@ test "bytesAsSlice" { |
| 1520 | 1526 | testing.expect(bigToNative(u16, slice[1]) == 0xBEEF); |
| 1521 | 1527 | } |
| 1522 | 1528 | |
| 1529 | test "bytesAsSlice keeps pointer alignment" { | |
| 1530 | var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 }; | |
| 1531 | const numbers = bytesAsSlice(u32, bytes[0..]); | |
| 1532 | comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32); | |
| 1533 | } | |
| 1534 | ||
| 1535 | test "bytesAsSlice on a packed struct" { | |
| 1536 | const F = packed struct { | |
| 1537 | a: u8, | |
| 1538 | }; | |
| 1539 | ||
| 1540 | var b = [1]u8{9}; | |
| 1541 | var f = bytesAsSlice(F, &b); | |
| 1542 | testing.expect(f[0].a == 9); | |
| 1543 | } | |
| 1544 | ||
| 1545 | test "bytesAsSlice with specified alignment" { | |
| 1546 | var bytes align(4) = [_]u8{ | |
| 1547 | 0x33, | |
| 1548 | 0x33, | |
| 1549 | 0x33, | |
| 1550 | 0x33, | |
| 1551 | }; | |
| 1552 | const slice: []u32 = std.mem.bytesAsSlice(u32, bytes[0..]); | |
| 1553 | testing.expect(slice[0] == 0x33333333); | |
| 1554 | } | |
| 1555 | ||
| 1523 | 1556 | //TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. |
| 1524 | 1557 | fn SliceAsBytesReturnType(comptime sliceType: type) type { |
| 1525 | if (comptime !trait.isSlice(sliceType)) { | |
| 1526 | @compileError("expected []T, passed " ++ @typeName(sliceType)); | |
| 1558 | if (!trait.isSlice(sliceType) and !trait.isPtrTo(.Array)(sliceType)) { | |
| 1559 | @compileError("expected []T or *[_]T, passed " ++ @typeName(sliceType)); | |
| 1527 | 1560 | } |
| 1528 | 1561 | |
| 1529 | const alignment = comptime meta.alignment(sliceType); | |
| 1562 | const alignment = meta.alignment(sliceType); | |
| 1530 | 1563 | |
| 1531 | return if (comptime trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; | |
| 1564 | return if (trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; | |
| 1532 | 1565 | } |
| 1533 | 1566 | |
| 1534 | 1567 | pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { |
| 1568 | const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice; | |
| 1569 | ||
| 1535 | 1570 | // let's not give an undefined pointer to @ptrCast |
| 1536 | 1571 | // it may be equal to zero and fail a null check |
| 1537 | if (slice.len == 0) { | |
| 1572 | if (actualSlice.len == 0) { | |
| 1538 | 1573 | return &[0]u8{}; |
| 1539 | 1574 | } |
| 1540 | 1575 | |
| 1541 | const sliceType = @TypeOf(slice); | |
| 1576 | const sliceType = @TypeOf(actualSlice); | |
| 1542 | 1577 | const alignment = comptime meta.alignment(sliceType); |
| 1543 | 1578 | |
| 1544 | 1579 | const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8; |
| 1545 | 1580 | |
| 1546 | return @ptrCast(castTarget, slice.ptr)[0 .. slice.len * @sizeOf(comptime meta.Child(sliceType))]; | |
| 1581 | return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))]; | |
| 1547 | 1582 | } |
| 1548 | 1583 | |
| 1549 | 1584 | test "sliceAsBytes" { |
| ... | ... | @@ -1556,6 +1591,57 @@ test "sliceAsBytes" { |
| 1556 | 1591 | })); |
| 1557 | 1592 | } |
| 1558 | 1593 | |
| 1594 | test "sliceAsBytes packed struct at runtime and comptime" { | |
| 1595 | const Foo = packed struct { | |
| 1596 | a: u4, | |
| 1597 | b: u4, | |
| 1598 | }; | |
| 1599 | const S = struct { | |
| 1600 | fn doTheTest() void { | |
| 1601 | var foo: Foo = undefined; | |
| 1602 | var slice = sliceAsBytes(@as(*[1]Foo, &foo)[0..1]); | |
| 1603 | slice[0] = 0x13; | |
| 1604 | switch (builtin.endian) { | |
| 1605 | .Big => { | |
| 1606 | testing.expect(foo.a == 0x1); | |
| 1607 | testing.expect(foo.b == 0x3); | |
| 1608 | }, | |
| 1609 | .Little => { | |
| 1610 | testing.expect(foo.a == 0x3); | |
| 1611 | testing.expect(foo.b == 0x1); | |
| 1612 | }, | |
| 1613 | } | |
| 1614 | } | |
| 1615 | }; | |
| 1616 | S.doTheTest(); | |
| 1617 | comptime S.doTheTest(); | |
| 1618 | } | |
| 1619 | ||
| 1620 | test "sliceAsBytes and bytesAsSlice back" { | |
| 1621 | testing.expect(@sizeOf(i32) == 4); | |
| 1622 | ||
| 1623 | var big_thing_array = [_]i32{ 1, 2, 3, 4 }; | |
| 1624 | const big_thing_slice: []i32 = big_thing_array[0..]; | |
| 1625 | ||
| 1626 | const bytes = sliceAsBytes(big_thing_slice); | |
| 1627 | testing.expect(bytes.len == 4 * 4); | |
| 1628 | ||
| 1629 | bytes[4] = 0; | |
| 1630 | bytes[5] = 0; | |
| 1631 | bytes[6] = 0; | |
| 1632 | bytes[7] = 0; | |
| 1633 | testing.expect(big_thing_slice[1] == 0); | |
| 1634 | ||
| 1635 | const big_thing_again = bytesAsSlice(i32, bytes); | |
| 1636 | testing.expect(big_thing_again[2] == 3); | |
| 1637 | ||
| 1638 | big_thing_again[2] = -1; | |
| 1639 | testing.expect(bytes[8] == math.maxInt(u8)); | |
| 1640 | testing.expect(bytes[9] == math.maxInt(u8)); | |
| 1641 | testing.expect(bytes[10] == math.maxInt(u8)); | |
| 1642 | testing.expect(bytes[11] == math.maxInt(u8)); | |
| 1643 | } | |
| 1644 | ||
| 1559 | 1645 | fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { |
| 1560 | 1646 | if (trait.isConstPtr(T)) |
| 1561 | 1647 | return *const [length]meta.Child(meta.Child(T)); |
lib/std/meta/trait.zig+16| ... | ... | @@ -135,6 +135,22 @@ test "std.meta.trait.isPtrTo" { |
| 135 | 135 | testing.expect(!isPtrTo(.Struct)(**struct {})); |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | pub fn isSliceOf(comptime id: builtin.TypeId) TraitFn { | |
| 139 | const Closure = struct { | |
| 140 | pub fn trait(comptime T: type) bool { | |
| 141 | if (!comptime isSlice(T)) return false; | |
| 142 | return id == @typeId(meta.Child(T)); | |
| 143 | } | |
| 144 | }; | |
| 145 | return Closure.trait; | |
| 146 | } | |
| 147 | ||
| 148 | test "std.meta.trait.isSliceOf" { | |
| 149 | testing.expect(!isSliceOf(.Struct)(struct {})); | |
| 150 | testing.expect(isSliceOf(.Struct)([]struct {})); | |
| 151 | testing.expect(!isSliceOf(.Struct)([][]struct {})); | |
| 152 | } | |
| 153 | ||
| 138 | 154 | ///////////Strait trait Fns |
| 139 | 155 | |
| 140 | 156 | //@TODO: |
test/compile_errors.zig-10| ... | ... | @@ -4747,16 +4747,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4747 | 4747 | "tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'", |
| 4748 | 4748 | }); |
| 4749 | 4749 | |
| 4750 | cases.add("convert fixed size array to slice with invalid size", | |
| 4751 | \\export fn f() void { | |
| 4752 | \\ var array: [5]u8 = undefined; | |
| 4753 | \\ var foo = @bytesToSlice(u32, &array)[0]; | |
| 4754 | \\} | |
| 4755 | , &[_][]const u8{ | |
| 4756 | "tmp.zig:3:15: error: unable to convert [5]u8 to []align(1) u32: size mismatch", | |
| 4757 | "tmp.zig:3:29: note: u32 has size 4; remaining bytes: 1", | |
| 4758 | }); | |
| 4759 | ||
| 4760 | 4750 | cases.add("non-pure function returns type", |
| 4761 | 4751 | \\var a: u32 = 0; |
| 4762 | 4752 | \\pub fn List(comptime T: type) type { |
test/runtime_safety.zig+9-7| ... | ... | @@ -553,15 +553,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 553 | 553 | ); |
| 554 | 554 | |
| 555 | 555 | cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size", |
| 556 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | |
| 557 | \\ @import("std").os.exit(126); | |
| 556 | \\const std = @import("std"); | |
| 557 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | |
| 558 | \\ std.os.exit(126); | |
| 558 | 559 | \\} |
| 559 | 560 | \\pub fn main() !void { |
| 560 | 561 | \\ const x = widenSlice(&[_]u8{1, 2, 3, 4, 5}); |
| 561 | 562 | \\ if (x.len == 0) return error.Whatever; |
| 562 | 563 | \\} |
| 563 | 564 | \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { |
| 564 | \\ return @bytesToSlice(i32, slice); | |
| 565 | \\ return std.mem.bytesAsSlice(i32, slice); | |
| 565 | 566 | \\} |
| 566 | 567 | ); |
| 567 | 568 | |
| ... | ... | @@ -656,17 +657,18 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 656 | 657 | ); |
| 657 | 658 | |
| 658 | 659 | cases.addRuntimeSafety("@alignCast misaligned", |
| 659 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | |
| 660 | \\ @import("std").os.exit(126); | |
| 660 | \\const std = @import("std"); | |
| 661 | \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { | |
| 662 | \\ std.os.exit(126); | |
| 661 | 663 | \\} |
| 662 | 664 | \\pub fn main() !void { |
| 663 | 665 | \\ var array align(4) = [_]u32{0x11111111, 0x11111111}; |
| 664 | \\ const bytes = @sliceToBytes(array[0..]); | |
| 666 | \\ const bytes = std.mem.sliceAsBytes(array[0..]); | |
| 665 | 667 | \\ if (foo(bytes) != 0x11111111) return error.Wrong; |
| 666 | 668 | \\} |
| 667 | 669 | \\fn foo(bytes: []u8) u32 { |
| 668 | 670 | \\ const slice4 = bytes[1..5]; |
| 669 | \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); | |
| 671 | \\ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); | |
| 670 | 672 | \\ return int_slice[0]; |
| 671 | 673 | \\} |
| 672 | 674 | ); |
test/stage1/behavior.zig-1| ... | ... | @@ -92,7 +92,6 @@ comptime { |
| 92 | 92 | _ = @import("behavior/shuffle.zig"); |
| 93 | 93 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 94 | 94 | _ = @import("behavior/slice.zig"); |
| 95 | _ = @import("behavior/slicetobytes.zig"); | |
| 96 | 95 | _ = @import("behavior/struct.zig"); |
| 97 | 96 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); |
| 98 | 97 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); |
test/stage1/behavior/align.zig-14| ... | ... | @@ -81,20 +81,6 @@ fn testBytesAlign(b: u8) void { |
| 81 | 81 | expect(ptr.* == 0x33333333); |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | test "specifying alignment allows slice cast" { | |
| 85 | testBytesAlignSlice(0x33); | |
| 86 | } | |
| 87 | fn testBytesAlignSlice(b: u8) void { | |
| 88 | var bytes align(4) = [_]u8{ | |
| 89 | b, | |
| 90 | b, | |
| 91 | b, | |
| 92 | b, | |
| 93 | }; | |
| 94 | const slice: []u32 = @bytesToSlice(u32, bytes[0..]); | |
| 95 | expect(slice[0] == 0x33333333); | |
| 96 | } | |
| 97 | ||
| 98 | 84 | test "@alignCast pointers" { |
| 99 | 85 | var x: u32 align(4) = 1; |
| 100 | 86 | expectsOnly1(&x); |
test/stage1/behavior/async_fn.zig+2-2| ... | ... | @@ -334,7 +334,7 @@ test "async fn with inferred error set" { |
| 334 | 334 | var frame: [1]@Frame(middle) = undefined; |
| 335 | 335 | var fn_ptr = middle; |
| 336 | 336 | var result: @TypeOf(fn_ptr).ReturnType.ErrorSet!void = undefined; |
| 337 | _ = @asyncCall(@sliceToBytes(frame[0..]), &result, fn_ptr); | |
| 337 | _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr); | |
| 338 | 338 | resume global_frame; |
| 339 | 339 | std.testing.expectError(error.Fail, result); |
| 340 | 340 | } |
| ... | ... | @@ -954,7 +954,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" { |
| 954 | 954 | fn doTheTest() void { |
| 955 | 955 | var frame: [1]@Frame(middle) = undefined; |
| 956 | 956 | var result: @TypeOf(middle).ReturnType.ErrorSet!void = undefined; |
| 957 | _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle); | |
| 957 | _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle); | |
| 958 | 958 | resume global_frame; |
| 959 | 959 | std.testing.expectError(error.Fail, result); |
| 960 | 960 | } |
test/stage1/behavior/bugs/1851.zig+1-1| ... | ... | @@ -13,7 +13,7 @@ test "allocation and looping over 3-byte integer" { |
| 13 | 13 | x[0] = 0xFFFFFF; |
| 14 | 14 | x[1] = 0xFFFFFF; |
| 15 | 15 | |
| 16 | const bytes = @sliceToBytes(x); | |
| 16 | const bytes = std.mem.sliceAsBytes(x); | |
| 17 | 17 | expect(@TypeOf(bytes) == []align(4) u8); |
| 18 | 18 | expect(bytes.len == 8); |
| 19 | 19 |
test/stage1/behavior/cast.zig-20| ... | ... | @@ -304,20 +304,6 @@ fn cast128Float(x: u128) f128 { |
| 304 | 304 | return @bitCast(f128, x); |
| 305 | 305 | } |
| 306 | 306 | |
| 307 | test "const slice widen cast" { | |
| 308 | const bytes align(4) = [_]u8{ | |
| 309 | 0x12, | |
| 310 | 0x12, | |
| 311 | 0x12, | |
| 312 | 0x12, | |
| 313 | }; | |
| 314 | ||
| 315 | const u32_value = @bytesToSlice(u32, bytes[0..])[0]; | |
| 316 | expect(u32_value == 0x12121212); | |
| 317 | ||
| 318 | expect(@bitCast(u32, bytes) == 0x12121212); | |
| 319 | } | |
| 320 | ||
| 321 | 307 | test "single-item pointer of array to slice and to unknown length pointer" { |
| 322 | 308 | testCastPtrOfArrayToSliceAndPtr(); |
| 323 | 309 | comptime testCastPtrOfArrayToSliceAndPtr(); |
| ... | ... | @@ -392,12 +378,6 @@ test "comptime_int @intToFloat" { |
| 392 | 378 | } |
| 393 | 379 | } |
| 394 | 380 | |
| 395 | test "@bytesToSlice keeps pointer alignment" { | |
| 396 | var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 }; | |
| 397 | const numbers = @bytesToSlice(u32, bytes[0..]); | |
| 398 | comptime expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32); | |
| 399 | } | |
| 400 | ||
| 401 | 381 | test "@intCast i32 to u7" { |
| 402 | 382 | var x: u128 = maxInt(u128); |
| 403 | 383 | var y: i32 = 120; |
test/stage1/behavior/eval.zig-10| ... | ... | @@ -711,16 +711,6 @@ test "bit shift a u1" { |
| 711 | 711 | expect(y == 1); |
| 712 | 712 | } |
| 713 | 713 | |
| 714 | test "@bytesToslice on a packed struct" { | |
| 715 | const F = packed struct { | |
| 716 | a: u8, | |
| 717 | }; | |
| 718 | ||
| 719 | var b = [1]u8{9}; | |
| 720 | var f = @bytesToSlice(F, &b); | |
| 721 | expect(f[0].a == 9); | |
| 722 | } | |
| 723 | ||
| 724 | 714 | test "comptime pointer cast array and then slice" { |
| 725 | 715 | const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; |
| 726 | 716 |
test/stage1/behavior/misc.zig-21| ... | ... | @@ -3,7 +3,6 @@ const expect = std.testing.expect; |
| 3 | 3 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 4 | 4 | const mem = std.mem; |
| 5 | 5 | const builtin = @import("builtin"); |
| 6 | const maxInt = std.math.maxInt; | |
| 7 | 6 | |
| 8 | 7 | // normal comment |
| 9 | 8 | |
| ... | ... | @@ -377,26 +376,6 @@ test "string concatenation" { |
| 377 | 376 | expect(b[len] == 0); |
| 378 | 377 | } |
| 379 | 378 | |
| 380 | test "cast slice to u8 slice" { | |
| 381 | expect(@sizeOf(i32) == 4); | |
| 382 | var big_thing_array = [_]i32{ 1, 2, 3, 4 }; | |
| 383 | const big_thing_slice: []i32 = big_thing_array[0..]; | |
| 384 | const bytes = @sliceToBytes(big_thing_slice); | |
| 385 | expect(bytes.len == 4 * 4); | |
| 386 | bytes[4] = 0; | |
| 387 | bytes[5] = 0; | |
| 388 | bytes[6] = 0; | |
| 389 | bytes[7] = 0; | |
| 390 | expect(big_thing_slice[1] == 0); | |
| 391 | const big_thing_again = @bytesToSlice(i32, bytes); | |
| 392 | expect(big_thing_again[2] == 3); | |
| 393 | big_thing_again[2] = -1; | |
| 394 | expect(bytes[8] == maxInt(u8)); | |
| 395 | expect(bytes[9] == maxInt(u8)); | |
| 396 | expect(bytes[10] == maxInt(u8)); | |
| 397 | expect(bytes[11] == maxInt(u8)); | |
| 398 | } | |
| 399 | ||
| 400 | 379 | test "pointer to void return type" { |
| 401 | 380 | testPointerToVoidReturnType() catch unreachable; |
| 402 | 381 | } |
test/stage1/behavior/slicetobytes.zig deleted-29| ... | ... | @@ -1,29 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const expect = std.testing.expect; | |
| 4 | ||
| 5 | test "@sliceToBytes packed struct at runtime and comptime" { | |
| 6 | const Foo = packed struct { | |
| 7 | a: u4, | |
| 8 | b: u4, | |
| 9 | }; | |
| 10 | const S = struct { | |
| 11 | fn doTheTest() void { | |
| 12 | var foo: Foo = undefined; | |
| 13 | var slice = @sliceToBytes(@as(*[1]Foo, &foo)[0..1]); | |
| 14 | slice[0] = 0x13; | |
| 15 | switch (builtin.endian) { | |
| 16 | builtin.Endian.Big => { | |
| 17 | expect(foo.a == 0x1); | |
| 18 | expect(foo.b == 0x3); | |
| 19 | }, | |
| 20 | builtin.Endian.Little => { | |
| 21 | expect(foo.a == 0x3); | |
| 22 | expect(foo.b == 0x1); | |
| 23 | }, | |
| 24 | } | |
| 25 | } | |
| 26 | }; | |
| 27 | S.doTheTest(); | |
| 28 | comptime S.doTheTest(); | |
| 29 | } |
test/stage1/behavior/struct.zig+2-2| ... | ... | @@ -315,7 +315,7 @@ test "packed array 24bits" { |
| 315 | 315 | |
| 316 | 316 | var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1); |
| 317 | 317 | bytes[bytes.len - 1] = 0xaa; |
| 318 | const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; | |
| 318 | const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; | |
| 319 | 319 | expect(ptr.a == 0); |
| 320 | 320 | expect(ptr.b[0].field == 0); |
| 321 | 321 | expect(ptr.b[1].field == 0); |
| ... | ... | @@ -364,7 +364,7 @@ test "aligned array of packed struct" { |
| 364 | 364 | } |
| 365 | 365 | |
| 366 | 366 | var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned); |
| 367 | const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; | |
| 367 | const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0]; | |
| 368 | 368 | |
| 369 | 369 | expect(ptr.a[0].a == 0xbb); |
| 370 | 370 | expect(ptr.a[0].b == 0xbb); |