authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-06-14 11:20:16+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-06-24 10:20:56+01:00
log10c97c26d964ea70230341468e05fdea533a77a3
tree56d96f2d1298bc437aca6769e2127792d994de83
parent6d2c8349c53707f9eeee7554bd7717667718ce4d
signaturelock-open Commit is signed but in an unrecognized format.

std: update for new `@bitCast` semantics


16 files changed, 276 insertions(+), 218 deletions(-)

lib/std/Build/Configuration.zig+4-2
......@@ -3215,7 +3215,8 @@ pub const Storage = enum {
32153215 .@"extern" => {
32163216 const n = @divExact(@sizeOf(Field), @sizeOf(u32));
32173217 defer i.* += n;
3218 return @bitCast(buffer[i.*..][0..n].*);
3218 const ptr: *align(@alignOf(u32)) const Field = @ptrCast(buffer[i.*..][0..n]);
3219 return ptr.*;
32193220 },
32203221 },
32213222 else => comptime unreachable,
......@@ -3381,7 +3382,8 @@ pub const Storage = enum {
33813382 },
33823383 .@"extern" => {
33833384 const n = @divExact(@sizeOf(Field), @sizeOf(u32));
3384 buffer[i..][0..n].* = @bitCast(value);
3385 const ptr: *align(@alignOf(Field)) const [n]u32 = @ptrCast(&value);
3386 buffer[i..][0..n].* = ptr.*;
33853387 return n;
33863388 },
33873389 },
lib/std/Io/Threaded.zig+6-2
......@@ -14188,9 +14188,11 @@ fn addressUnixToPosix(a: *const net.UnixAddress, storage: *UnixAddress) posix.so
1418814188}
1418914189
1419014190fn address4FromPosix(in: *const posix.sockaddr.in) net.Ip4Address {
14191 // The network byte order address in `in.addr` is already the byte order we want.
14192 const addr_bytes: *const [4]u8 = @ptrCast(&in.addr);
1419114193 return .{
1419214194 .port = std.mem.bigToNative(u16, in.port),
14193 .bytes = @bitCast(in.addr),
14195 .bytes = addr_bytes.*,
1419414196 };
1419514197}
1419614198
......@@ -14204,9 +14206,11 @@ fn address6FromPosix(in6: *const posix.sockaddr.in6) net.Ip6Address {
1420414206}
1420514207
1420614208fn address4ToPosix(a: net.Ip4Address) posix.sockaddr.in {
14209 // The byte order of `a.bytes` is already equivalent to a network byte order address.
14210 const addr_raw: *align(1) const u32 = @ptrCast(&a.bytes);
1420714211 return .{
1420814212 .port = std.mem.nativeToBig(u16, a.port),
14209 .addr = @bitCast(a.bytes),
14213 .addr = addr_raw.*,
1421014214 };
1421114215}
1421214216
lib/std/Io/net.zig+1-5
......@@ -592,11 +592,7 @@ pub const Ip6Address = struct {
592592 if (remaining != 0) return .incomplete;
593593 }
594594
595 // Workaround that can be removed when this proposal is
596 // implemented https://github.com/ziglang/zig/issues/19755
597 if ((comptime @import("builtin").cpu.arch.endian()) != .big) {
598 for (&parts) |*part| part.* = @byteSwap(part.*);
599 }
595 for (&parts) |*part| part.* = @byteSwap(part.*);
600596
601597 return .{ .success = .{
602598 .bytes = @bitCast(parts),
lib/std/Random/RomuTrio.zig+2-2
......@@ -33,7 +33,7 @@ fn next(self: *RomuTrio) u64 {
3333}
3434
3535pub fn seedWithBuf(self: *RomuTrio, buf: [24]u8) void {
36 const seed_buf = @as([3]u64, @bitCast(buf));
36 const seed_buf: [3]u64 = @bitCast(buf);
3737 self.x_state = seed_buf[0];
3838 self.y_state = seed_buf[1];
3939 self.z_state = seed_buf[2];
......@@ -121,7 +121,7 @@ test fill {
121121}
122122
123123test "buf seeding test" {
124 const buf0 = @as([24]u8, @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 }));
124 const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 });
125125 const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 };
126126 var r = RomuTrio.init(0);
127127 r.seedWithBuf(buf0);
lib/std/Random/Xoshiro256.zig+2-2
......@@ -46,12 +46,12 @@ pub fn jump(self: *Xoshiro256) void {
4646
4747 while (table != 0) : (table >>= 1) {
4848 if (@as(u1, @truncate(table)) != 0) {
49 s ^= @as(u256, @bitCast(self.s));
49 s ^= @bitCast(self.s);
5050 }
5151 _ = self.next();
5252 }
5353
54 self.s = @as([4]u64, @bitCast(s));
54 self.s = @bitCast(s);
5555}
5656
5757pub fn seed(self: *Xoshiro256, init_s: u64) void {
lib/std/crypto/tls/Client.zig+5-5
......@@ -376,7 +376,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
376376 const nonce = nonce: {
377377 const V = @Vector(P.AEAD.nonce_length, u8);
378378 const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
379 const operand: V = pad ++ @as([8]u8, @bitCast(big(read_seq)));
379 const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(read_seq)));
380380 break :nonce @as(V, pv.server_handshake_iv) ^ operand;
381381 };
382382 P.AEAD.decrypt(cleartext, ciphertext, auth_tag, record_header, nonce, pv.server_handshake_key) catch
......@@ -416,7 +416,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
416416 const nonce: [P.AEAD.nonce_length]u8 = nonce: {
417417 const V = @Vector(P.AEAD.nonce_length, u8);
418418 const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
419 const operand: V = pad ++ @as([8]u8, @bitCast(big(masked_read_seq)));
419 const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(masked_read_seq)));
420420 break :nonce @as(V, pv.app_cipher.server_write_IV ++ record_iv) ^ operand;
421421 };
422422 const ciphertext = record_decoder.slice(message_len);
......@@ -792,7 +792,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client
792792 const nonce: [P.AEAD.nonce_length]u8 = nonce: {
793793 const V = @Vector(P.AEAD.nonce_length, u8);
794794 const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
795 const operand: V = pad ++ @as([8]u8, @bitCast(big(write_seq)));
795 const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(write_seq)));
796796 break :nonce @as(V, pv.app_cipher.client_write_IV ++ pv.app_cipher.client_salt) ^ operand;
797797 };
798798 var client_verify_msg = .{@intFromEnum(tls.ContentType.handshake)} ++
......@@ -1105,7 +1105,7 @@ fn prepareCiphertextRecord(
11051105 const nonce: [P.AEAD.nonce_length]u8 = nonce: {
11061106 const V = @Vector(P.AEAD.nonce_length, u8);
11071107 const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
1108 const operand: V = pad ++ @as([8]u8, @bitCast(big(c.write_seq)));
1108 const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(c.write_seq)));
11091109 break :nonce @as(V, pv.client_write_IV ++ pv.client_salt) ^ operand;
11101110 };
11111111 record_iv.* = nonce[P.fixed_iv_length..].*;
......@@ -1214,7 +1214,7 @@ fn readIndirect(c: *Client) Reader.Error!usize {
12141214 const nonce: [P.AEAD.nonce_length]u8 = nonce: {
12151215 const V = @Vector(P.AEAD.nonce_length, u8);
12161216 const pad: [P.AEAD.nonce_length - 8]u8 = @splat(0);
1217 const operand: V = pad ++ @as([8]u8, @bitCast(big(masked_read_seq)));
1217 const operand: V = pad ++ @as([8]u8, @bitCast(@byteSwap(masked_read_seq)));
12181218 break :nonce @as(V, pv.server_write_IV ++ record_iv) ^ operand;
12191219 };
12201220 const ciphertext = input.take(message_len) catch unreachable; // already peeked
lib/std/hash/xxhash.zig+65-56
......@@ -421,7 +421,18 @@ pub const XxHash32 = struct {
421421};
422422
423423pub const XxHash3 = struct {
424 const block_bytes = 64;
424425 const Block = @Vector(8, u64);
426 const InputBlock = extern struct {
427 raw: [block_bytes]u8,
428 inline fn load(ptr: *const InputBlock) Block {
429 return @bitCast(ptr.raw);
430 }
431 inline fn store(ptr: *InputBlock, val: Block) void {
432 ptr.raw = @bitCast(val);
433 }
434 };
435
425436 const default_secret: [192]u8 = .{
426437 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
427438 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
......@@ -464,10 +475,6 @@ pub const XxHash3 = struct {
464475 return wide[0] ^ wide[1];
465476 }
466477
467 inline fn swap(x: anytype) @TypeOf(x) {
468 return if (native_endian == .big) @byteSwap(x) else x;
469 }
470
471478 inline fn disableAutoVectorization(x: anytype) void {
472479 if (!@inComptime()) asm volatile (""
473480 :
......@@ -476,20 +483,20 @@ pub const XxHash3 = struct {
476483 }
477484
478485 inline fn mix16(seed: u64, input: []const u8, secret: []const u8) u64 {
479 const blk: [4]u64 = @bitCast([_][16]u8{ input[0..16].*, secret[0..16].* });
486 const blk: [4]u64 = @bitCast([2][16]u8{ input[0..16].*, secret[0..16].* });
480487 disableAutoVectorization(seed);
481488
482489 return fold(
483 swap(blk[0]) ^ (swap(blk[2]) +% seed),
484 swap(blk[1]) ^ (swap(blk[3]) -% seed),
490 blk[0] ^ (blk[2] +% seed),
491 blk[1] ^ (blk[3] -% seed),
485492 );
486493 }
487494
488 const Accumulator = extern struct {
495 const Accumulator = struct {
489496 consumed: usize = 0,
490497 seed: u64,
491 secret: [192]u8 = undefined,
492 state: Block = Block{
498 secret: [192]u8,
499 state: Block = .{
493500 XxHash32.prime_3,
494501 XxHash64.prime_1,
495502 XxHash64.prime_2,
......@@ -501,33 +508,35 @@ pub const XxHash3 = struct {
501508 },
502509
503510 inline fn init(seed: u64) Accumulator {
504 var self = Accumulator{ .seed = seed };
505 for (
506 std.mem.bytesAsSlice(Block, &self.secret),
507 std.mem.bytesAsSlice(Block, &default_secret),
508 ) |*dst, src| {
509 dst.* = swap(swap(src) +% Block{
510 seed, @as(u64, 0) -% seed,
511 seed, @as(u64, 0) -% seed,
512 seed, @as(u64, 0) -% seed,
513 seed, @as(u64, 0) -% seed,
514 });
511 const seed_block: Block = .{
512 seed, @as(u64, 0) -% seed,
513 seed, @as(u64, 0) -% seed,
514 seed, @as(u64, 0) -% seed,
515 seed, @as(u64, 0) -% seed,
516 };
517
518 var secret: [192]u8 = undefined;
519 const secret_blocks: []InputBlock = @ptrCast(&secret);
520 const default_secret_blocks: []const InputBlock = @ptrCast(&default_secret);
521 for (secret_blocks, default_secret_blocks) |*dst, *src| {
522 dst.store(src.load() +% seed_block);
515523 }
516 return self;
524
525 return .{ .seed = seed, .secret = secret };
517526 }
518527
519528 inline fn round(
520529 noalias state: *Block,
521 noalias input_block: *align(1) const Block,
522 noalias secret_block: *align(1) const Block,
530 noalias input_block: *const InputBlock,
531 noalias secret_block: *const InputBlock,
523532 ) void {
524 const data = swap(input_block.*);
525 const mixed = data ^ swap(secret_block.*);
533 const data = input_block.load();
534 const mixed = data ^ secret_block.load();
526535 state.* +%= (mixed & @as(Block, @splat(0xffffffff))) *% (mixed >> @splat(32));
527536 state.* +%= @shuffle(u64, data, undefined, [_]i32{ 1, 0, 3, 2, 5, 4, 7, 6 });
528537 }
529538
530 fn accumulate(noalias self: *Accumulator, blocks: []align(1) const Block) void {
539 fn accumulate(noalias self: *Accumulator, blocks: []const InputBlock) void {
531540 const secret = std.mem.bytesAsSlice(u64, self.secret[self.consumed * 8 ..]);
532541 for (blocks, secret[0..blocks.len]) |*input_block, *secret_block| {
533542 @prefetch(@as([*]const u8, @ptrCast(input_block)) + 320, .{});
......@@ -536,14 +545,14 @@ pub const XxHash3 = struct {
536545 }
537546
538547 fn scramble(self: *Accumulator) void {
539 const secret_block: Block = @bitCast(self.secret[192 - @sizeOf(Block) .. 192].*);
548 const secret_block: Block = @bitCast(self.secret[192 - block_bytes .. 192].*);
540549 self.state ^= self.state >> @splat(47);
541 self.state ^= swap(secret_block);
550 self.state ^= secret_block;
542551 self.state *%= @as(Block, @splat(XxHash32.prime_1));
543552 }
544553
545 fn consume(noalias self: *Accumulator, input_blocks: []align(1) const Block) void {
546 const blocks_per_scramble = 1024 / @sizeOf(Block);
554 fn consume(noalias self: *Accumulator, input_blocks: []const InputBlock) void {
555 const blocks_per_scramble = 1024 / block_bytes;
547556 std.debug.assert(self.consumed <= blocks_per_scramble);
548557
549558 var blocks = input_blocks;
......@@ -561,12 +570,12 @@ pub const XxHash3 = struct {
561570 self.consumed += blocks.len;
562571 }
563572
564 fn digest(noalias self: *Accumulator, total_len: u64, noalias last_block: *align(1) const Block) u64 {
565 const secret_block = self.secret[192 - @sizeOf(Block) - 7 ..][0..@sizeOf(Block)];
573 fn digest(noalias self: *Accumulator, total_len: u64, noalias last_block: *const InputBlock) u64 {
574 const secret_block = self.secret[192 - block_bytes - 7 ..][0..block_bytes];
566575 round(&self.state, last_block, @ptrCast(secret_block));
567576
568 const merge_block: Block = @bitCast(self.secret[11 .. 11 + @sizeOf(Block)].*);
569 self.state ^= swap(merge_block);
577 const merge_block: Block = @bitCast(self.secret[11 .. 11 + block_bytes].*);
578 self.state ^= merge_block;
570579
571580 var result = XxHash64.prime_1 *% total_len;
572581 inline for (0..4) |i| {
......@@ -588,7 +597,7 @@ pub const XxHash3 = struct {
588597 if (input.len > 0) return hash3(seed, input, secret);
589598
590599 const flip: [2]u64 = @bitCast(secret[56..72].*);
591 const key = swap(flip[0]) ^ swap(flip[1]);
600 const key = flip[0] ^ flip[1];
592601 return avalanche(.h64, seed ^ key);
593602 }
594603
......@@ -604,8 +613,8 @@ pub const XxHash3 = struct {
604613 input[input.len / 2],
605614 });
606615
607 const key = @as(u64, swap(flip[0]) ^ swap(flip[1])) +% seed;
608 return avalanche(.h64, key ^ swap(blk));
616 const key = @as(u64, flip[0] ^ flip[1]) +% seed;
617 return avalanche(.h64, key ^ blk);
609618 }
610619
611620 fn hash8(seed: u64, input: anytype, noalias secret: *const [192]u8) u64 {
......@@ -619,8 +628,8 @@ pub const XxHash3 = struct {
619628 });
620629
621630 const mixed = seed ^ (@as(u64, @byteSwap(@as(u32, @truncate(seed)))) << 32);
622 const key = (swap(flip[0]) ^ swap(flip[1])) -% mixed;
623 const combined = (@as(u64, swap(blk[0])) << 32) +% swap(blk[1]);
631 const key = (flip[0] ^ flip[1]) -% mixed;
632 const combined = (@as(u64, blk[0]) << 32) +% blk[1];
624633 return avalanche(.{ .rrmxmx = input.len }, key ^ combined);
625634 }
626635
......@@ -634,8 +643,8 @@ pub const XxHash3 = struct {
634643 input[input.len - 8 ..][0..8].*,
635644 });
636645
637 const lo = swap(blk[0]) ^ ((swap(flip[0]) ^ swap(flip[1])) +% seed);
638 const hi = swap(blk[1]) ^ ((swap(flip[2]) ^ swap(flip[3])) -% seed);
646 const lo = blk[0] ^ ((flip[0] ^ flip[1]) +% seed);
647 const hi = blk[1] ^ ((flip[2] ^ flip[3]) -% seed);
639648 const combined = @as(u64, input.len) +% @byteSwap(lo) +% hi +% fold(lo, hi);
640649 return avalanche(.h3, combined);
641650 }
......@@ -679,11 +688,11 @@ pub const XxHash3 = struct {
679688 @branchHint(.unlikely);
680689 std.debug.assert(input.len >= 240);
681690
682 const block_count = ((input.len - 1) / @sizeOf(Block)) * @sizeOf(Block);
683 const last_block = input[input.len - @sizeOf(Block) ..][0..@sizeOf(Block)];
691 const block_count = ((input.len - 1) / block_bytes) * block_bytes;
692 const last_block = input[input.len - block_bytes ..][0..block_bytes];
684693
685694 var acc = Accumulator.init(seed);
686 acc.consume(std.mem.bytesAsSlice(Block, input[0..block_count]));
695 acc.consume(std.mem.bytesAsSlice(InputBlock, input[0..block_count]));
687696 return acc.digest(input.len, @ptrCast(last_block));
688697 }
689698
......@@ -716,21 +725,21 @@ pub const XxHash3 = struct {
716725 @memcpy(self.buffer[self.buffered..], consumable[0..remaining]);
717726 consumable = consumable[remaining..];
718727
719 self.accumulator.consume(std.mem.bytesAsSlice(Block, &self.buffer));
728 self.accumulator.consume(std.mem.bytesAsSlice(InputBlock, &self.buffer));
720729 self.buffered = 0;
721730 }
722731
723732 // The input isn't small enough to fit in the buffer. Consume it directly.
724733 if (consumable.len > self.buffer.len) {
725 const block_count = ((consumable.len - 1) / @sizeOf(Block)) * @sizeOf(Block);
726 self.accumulator.consume(std.mem.bytesAsSlice(Block, consumable[0..block_count]));
734 const block_count = ((consumable.len - 1) / block_bytes) * block_bytes;
735 self.accumulator.consume(std.mem.bytesAsSlice(InputBlock, consumable[0..block_count]));
727736 consumable = consumable[block_count..];
728737
729738 // In case we consume all remaining input, write the last block to end of the buffer
730739 // to populate the last_block_copy in final() similar to hashLong()'s last_block.
731740 @memcpy(
732 self.buffer[self.buffer.len - @sizeOf(Block) .. self.buffer.len],
733 (consumable.ptr - @sizeOf(Block))[0..@sizeOf(Block)],
741 self.buffer[self.buffer.len - block_bytes .. self.buffer.len],
742 (consumable.ptr - block_bytes)[0..block_bytes],
734743 );
735744 }
736745
......@@ -751,16 +760,16 @@ pub const XxHash3 = struct {
751760
752761 // Make a copy of the Accumulator state in case `self` needs to update() / be used later.
753762 var accumulator_copy = self.accumulator;
754 var last_block_copy: [@sizeOf(Block)]u8 = undefined;
763 var last_block_copy: [block_bytes]u8 = undefined;
755764
756765 // Digest the last block onthe Accumulator copy.
757766 return accumulator_copy.digest(self.total_len, last_block: {
758 if (self.buffered >= @sizeOf(Block)) {
759 const block_count = ((self.buffered - 1) / @sizeOf(Block)) * @sizeOf(Block);
760 accumulator_copy.consume(std.mem.bytesAsSlice(Block, self.buffer[0..block_count]));
761 break :last_block @ptrCast(self.buffer[self.buffered - @sizeOf(Block) ..][0..@sizeOf(Block)]);
767 if (self.buffered >= block_bytes) {
768 const block_count = ((self.buffered - 1) / block_bytes) * block_bytes;
769 accumulator_copy.consume(std.mem.bytesAsSlice(InputBlock, self.buffer[0..block_count]));
770 break :last_block @ptrCast(self.buffer[self.buffered - block_bytes ..][0..block_bytes]);
762771 } else {
763 const remaining = @sizeOf(Block) - self.buffered;
772 const remaining = block_bytes - self.buffered;
764773 @memcpy(last_block_copy[0..remaining], self.buffer[self.buffer.len - remaining ..][0..remaining]);
765774 @memcpy(last_block_copy[remaining..][0..self.buffered], self.buffer[0..self.buffered]);
766775 break :last_block @ptrCast(&last_block_copy);
lib/std/hash_map.zig+2-2
......@@ -593,8 +593,8 @@ fn Custom(
593593 fingerprint: FingerPrint = free,
594594 used: u1 = 0,
595595
596 const slot_free = @as(u8, @bitCast(Metadata{ .fingerprint = free }));
597 const slot_tombstone = @as(u8, @bitCast(Metadata{ .fingerprint = tombstone }));
596 const slot_free: u8 = @bitCast(Metadata{ .fingerprint = free });
597 const slot_tombstone: u8 = @bitCast(Metadata{ .fingerprint = tombstone });
598598
599599 pub fn isUsed(self: Metadata) bool {
600600 return self.used == 1;
lib/std/http/HeadParser.zig+5-8
......@@ -116,11 +116,8 @@ pub fn feed(p: *HeadParser, bytes: []const u8) usize {
116116
117117 const chunk = bytes[index..][0..vector_len];
118118 const v: Vector = chunk.*;
119 // depends on https://github.com/ziglang/zig/issues/19755
120 // const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r')));
121 // const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n')));
122 const matches_r: BitVector = @select(u1, v == @as(Vector, @splat('\r')), @as(Vector, @splat(1)), @as(Vector, @splat(0)));
123 const matches_n: BitVector = @select(u1, v == @as(Vector, @splat('\n')), @as(Vector, @splat(1)), @as(Vector, @splat(0)));
119 const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r')));
120 const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n')));
124121 const matches_or: SizeVector = matches_r | matches_n;
125122
126123 const matches = @reduce(.Add, matches_or);
......@@ -331,15 +328,15 @@ pub fn feed(p: *HeadParser, bytes: []const u8) usize {
331328}
332329
333330inline fn int16(array: *const [2]u8) u16 {
334 return @bitCast(array.*);
331 return std.mem.toNative(u16, @bitCast(array.*), .little);
335332}
336333
337334inline fn int24(array: *const [3]u8) u24 {
338 return @bitCast(array.*);
335 return std.mem.toNative(u24, @bitCast(array.*), .little);
339336}
340337
341338inline fn int32(array: *const [4]u8) u32 {
342 return @bitCast(array.*);
339 return std.mem.toNative(u32, @bitCast(array.*), .little);
343340}
344341
345342inline fn intShift(comptime T: type, x: anytype) T {
lib/std/http/Server.zig+10-5
......@@ -726,7 +726,7 @@ pub const WebSocket = struct {
726726 else => @intFromEnum(h1.payload_len),
727727 };
728728 if (len > in.buffer.len) return error.MessageOversize;
729 const mask: u32 = @bitCast((try in.takeArray(4)).*);
729 const mask: [4]u8 = (try in.takeArray(4)).*;
730730 const payload = try in.take(len);
731731
732732 // Skip pongs.
......@@ -734,11 +734,16 @@ pub const WebSocket = struct {
734734
735735 // The last item may contain a partial word of unused data.
736736 const floored_len = (payload.len / 4) * 4;
737 const u32_payload: []align(1) u32 = @ptrCast(payload[0..floored_len]);
738 for (u32_payload) |*elem| elem.* ^= mask;
739 const mask_bytes: []const u8 = @ptrCast(&mask);
740 for (payload[floored_len..], mask_bytes[0 .. payload.len - floored_len]) |*leftover, m|
737
738 const payload_chunks: [][4]u8 = @ptrCast(payload[0..floored_len]);
739 for (payload_chunks) |*chunk| {
740 const mask_i: u32 = @bitCast(mask);
741 const chunk_i: u32 = @bitCast(chunk.*);
742 chunk.* = @bitCast(chunk_i ^ mask_i);
743 }
744 for (payload[floored_len..], mask[0 .. payload.len - floored_len]) |*leftover, m| {
741745 leftover.* ^= m;
746 }
742747
743748 return .{
744749 .opcode = h0.opcode,
lib/std/mem.zig+80-58
......@@ -1848,18 +1848,18 @@ pub fn readVarPackedInt(
18481848 if (@bitSizeOf(T) <= 8) {
18491849 // These are the same shifts/masks we perform below, but adds `@truncate`/`@intCast`
18501850 // where needed since int is smaller than a byte.
1851 const value = if (read_size == 1) b: {
1852 break :b @as(uN, @truncate(read_bytes[0] >> bit_shift));
1851 const value: uN = if (read_size == 1) b: {
1852 break :b @truncate(read_bytes[0] >> bit_shift);
18531853 } else b: {
18541854 const i: u1 = @intFromBool(endian == .big);
1855 const head = @as(uN, @truncate(read_bytes[i] >> bit_shift));
1856 const tail_shift = @as(Log2N, @intCast(@as(u4, 8) - bit_shift));
1857 const tail = @as(uN, @truncate(read_bytes[1 - i]));
1855 const head: uN = @truncate(read_bytes[i] >> bit_shift);
1856 const tail_shift: Log2N = @intCast(@as(u4, 8) - bit_shift);
1857 const tail: uN = @truncate(read_bytes[1 - i]);
18581858 break :b (tail << tail_shift) | head;
18591859 };
18601860 switch (signedness) {
1861 .signed => return @as(T, @intCast((@as(iN, @bitCast(value)) << pad) >> pad)),
1862 .unsigned => return @as(T, @intCast((@as(uN, @bitCast(value)) << pad) >> pad)),
1861 .signed => return @intCast((@as(iN, @bitCast(value)) << pad) >> pad),
1862 .unsigned => return @intCast((value << pad) >> pad),
18631863 }
18641864 }
18651865
......@@ -1880,8 +1880,8 @@ pub fn readVarPackedInt(
18801880 },
18811881 }
18821882 switch (signedness) {
1883 .signed => return @as(T, @intCast((@as(iN, @bitCast(int)) << pad) >> pad)),
1884 .unsigned => return @as(T, @intCast((@as(uN, @bitCast(int)) << pad) >> pad)),
1883 .signed => return @intCast((@as(iN, @bitCast(int)) << pad) >> pad),
1884 .unsigned => return @intCast((int << pad) >> pad),
18851885 }
18861886}
18871887
......@@ -1896,8 +1896,13 @@ test readVarPackedInt {
18961896/// The bit count of T must be evenly divisible by 8.
18971897/// This function cannot fail and cannot cause undefined behavior.
18981898pub inline fn readInt(comptime T: type, buffer: *const [@divExact(@typeInfo(T).int.bits, 8)]u8, endian: Endian) T {
1899 const value: T = @bitCast(buffer.*);
1900 return if (endian == native_endian) value else @byteSwap(value);
1899 // Zig's logical bit order aligns with a little-endian byte array, so when reading in big-endian
1900 // we must `@byteSwap` the int after we `@bitCast` to it.
1901 const little_val: T = @bitCast(buffer.*);
1902 return switch (endian) {
1903 .little => little_val,
1904 .big => @byteSwap(little_val),
1905 };
19011906}
19021907
19031908test readInt {
......@@ -1940,13 +1945,15 @@ fn readPackedIntLittle(comptime T: type, bytes: []const u8, bit_offset: usize) T
19401945 // Read by loading a LoadInt, and then follow it up with a 1-byte read
19411946 // of the tail if bit_offset pushed us over a byte boundary.
19421947 const read_bytes = bytes[bit_offset / 8 ..];
1943 const val = @as(uN, @truncate(readInt(LoadInt, read_bytes[0..load_size], .little) >> bit_shift));
1948 const val: uN = @truncate(readInt(LoadInt, read_bytes[0..load_size], .little) >> bit_shift);
19441949 if (bit_shift > load_tail_bits) {
19451950 const tail_bits = @as(Log2N, @intCast(bit_shift - load_tail_bits));
19461951 const tail_byte = read_bytes[load_size];
19471952 const tail_truncated = if (bit_count < 8) @as(uN, @truncate(tail_byte)) else @as(uN, tail_byte);
1948 return @as(T, @bitCast(val | (tail_truncated << (@as(Log2N, @truncate(bit_count)) -% tail_bits))));
1949 } else return @as(T, @bitCast(val));
1953 return @bitCast(val | (tail_truncated << (@as(Log2N, @truncate(bit_count)) -% tail_bits)));
1954 } else {
1955 return @bitCast(val);
1956 }
19501957}
19511958
19521959fn readPackedIntBig(comptime T: type, bytes: []const u8, bit_offset: usize) T {
......@@ -1972,8 +1979,10 @@ fn readPackedIntBig(comptime T: type, bytes: []const u8, bit_offset: usize) T {
19721979 if (bit_shift > load_tail_bits) {
19731980 const tail_bits = @as(Log2N, @intCast(bit_shift - load_tail_bits));
19741981 const tail_byte = if (bit_count < 8) @as(uN, @truncate(read_bytes[0])) else @as(uN, read_bytes[0]);
1975 return @as(T, @bitCast(val | (tail_byte << (@as(Log2N, @truncate(bit_count)) -% tail_bits))));
1976 } else return @as(T, @bitCast(val));
1982 return @bitCast(val | (tail_byte << (@as(Log2N, @truncate(bit_count)) -% tail_bits)));
1983 } else {
1984 return @bitCast(val);
1985 }
19771986}
19781987
19791988/// Loads an integer from packed memory.
......@@ -2011,7 +2020,12 @@ test "comptime read/write int" {
20112020/// This function always succeeds, has defined behavior for all inputs, but
20122021/// the integer bit width must be divisible by 8.
20132022pub inline fn writeInt(comptime T: type, buffer: *[@divExact(@typeInfo(T).int.bits, 8)]u8, value: T, endian: Endian) void {
2014 buffer.* = @bitCast(if (endian == native_endian) value else @byteSwap(value));
2023 // Zig's logical bit order aligns with a little-endian byte array, so when writing in big-endian
2024 // we must `@byteSwap` the int before we `@bitCast` to an array.
2025 buffer.* = switch (endian) {
2026 .little => @bitCast(value),
2027 .big => @bitCast(@byteSwap(value)),
2028 };
20152029}
20162030
20172031test writeInt {
......@@ -2209,10 +2223,10 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
22092223/// (Changing their endianness)
22102224pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void {
22112225 switch (@typeInfo(S)) {
2212 .@"struct" => |struct_info| {
2213 if (struct_info.backing_integer) |Int| {
2226 .@"struct" => |@"struct"| {
2227 if (@"struct".backing_integer) |Int| {
22142228 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
2215 } else inline for (struct_info.field_types, struct_info.field_names, struct_info.field_attrs) |f_type, f_name, f_attr| {
2229 } else inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| {
22162230 switch (@typeInfo(f_type)) {
22172231 .@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
22182232 .@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)),
......@@ -2220,8 +2234,8 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
22202234 @field(ptr, f_name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f_name))));
22212235 },
22222236 .bool => {},
2223 .float => |float_info| {
2224 @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float_info.bits), @bitCast(@field(ptr, f_name)))));
2237 .float => |float| {
2238 @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name)))));
22252239 },
22262240 else => {
22272241 @field(ptr, f_name) = @byteSwap(@field(ptr, f_name));
......@@ -2229,23 +2243,26 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a
22292243 }
22302244 }
22312245 },
2232 .@"union" => |union_info| {
2233 if (union_info.tag_type != null) {
2234 @compileError("byteSwapAllFields expects an untagged union");
2246 .@"union" => |@"union"| if (@"union".backing_integer) |Int| {
2247 ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*))));
2248 } else {
2249 if (@"union".layout != .@"extern") {
2250 @compileError("byteSwapAllFields expects a packed or extern union");
22352251 }
22362252
2237 const first_size = @bitSizeOf(union_info.field_types[0]);
2238 inline for (union_info.field_types) |field_type| {
2253 const first_size = @bitSizeOf(@"union".field_types[0]);
2254 inline for (@"union".field_types) |field_type| {
22392255 if (@bitSizeOf(field_type) != first_size) {
22402256 @compileError("Unable to byte-swap unions with varying field sizes");
22412257 }
22422258 }
22432259
2244 const BackingInt = @Int(.unsigned, @bitSizeOf(S));
2245 ptr.* = @bitCast(@byteSwap(@as(BackingInt, @bitCast(ptr.*))));
2260 const FieldInt = @Int(.unsigned, first_size);
2261 const field_ptr = &@field(ptr, @"union".field_names[0]);
2262 field_ptr.* = @bitCast(@byteSwap(@as(FieldInt, @bitCast(field_ptr.*))));
22462263 },
2247 .array => |info| {
2248 byteSwapAllElements(info.child, ptr);
2264 .array => |array| {
2265 byteSwapAllElements(array.child, ptr);
22492266 },
22502267 else => {
22512268 ptr.* = @byteSwap(ptr.*);
......@@ -2291,7 +2308,7 @@ test byteSwapAllFields {
22912308 .f2 = 0x12345678,
22922309 .f3 = .{0x12},
22932310 .f4 = true,
2294 .f5 = @as(f32, @bitCast(@as(u32, 0x4640e400))),
2311 .f5 = @bitCast(@as(u32, 0x4640e400)),
22952312 .f6 = .{ .f0 = 0x1234 },
22962313 };
22972314 var k = K{
......@@ -2300,7 +2317,7 @@ test byteSwapAllFields {
23002317 .f2 = 0x1234,
23012318 .f3 = .{0x12},
23022319 .f4 = false,
2303 .f5 = @as(f32, @bitCast(@as(u32, 0x45d42800))),
2320 .f5 = @bitCast(@as(u32, 0x45d42800)),
23042321 };
23052322 var p: P = @bitCast(@as(u32, 0x01234567));
23062323 var a: A = A{
......@@ -2318,7 +2335,7 @@ test byteSwapAllFields {
23182335 .f2 = 0x78563412,
23192336 .f3 = .{0x12},
23202337 .f4 = true,
2321 .f5 = @as(f32, @bitCast(@as(u32, 0x00e44046))),
2338 .f5 = @bitCast(@as(u32, 0x00e44046)),
23222339 .f6 = .{ .f0 = 0x3412 },
23232340 }, s);
23242341 try std.testing.expectEqual(K{
......@@ -2327,7 +2344,7 @@ test byteSwapAllFields {
23272344 .f2 = 0x3412,
23282345 .f3 = .{0x12},
23292346 .f4 = false,
2330 .f5 = @as(f32, @bitCast(@as(u32, 0x0028d445))),
2347 .f5 = @bitCast(@as(u32, 0x0028d445)),
23312348 }, k);
23322349 try std.testing.expectEqual(@as(P, @bitCast(@as(u32, 0x67452301))), p);
23332350 try std.testing.expectEqual(A{
......@@ -2348,8 +2365,9 @@ pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void {
23482365 elem.* = @enumFromInt(@byteSwap(@intFromEnum(elem.*)));
23492366 },
23502367 .bool => {},
2351 .float => |float_info| {
2352 elem.* = @bitCast(@byteSwap(@as(@Int(.unsigned, float_info.bits), @bitCast(elem.*))));
2368 .float => |float| {
2369 const int_repr: @Int(.unsigned, float.bits) = @bitCast(elem.*);
2370 elem.* = @bitCast(@byteSwap(int_repr));
23532371 },
23542372 else => {
23552373 elem.* = @byteSwap(elem.*);
......@@ -3870,25 +3888,29 @@ inline fn reverseVector(comptime N: usize, comptime T: type, a: []T) [N]T {
38703888pub fn reverse(comptime T: type, items: []T) void {
38713889 var i: usize = 0;
38723890 const end = items.len / 2;
3873 if (use_vectors and
3874 !@inComptime() and
3875 @bitSizeOf(T) > 0 and
3876 std.math.isPowerOfTwo(@bitSizeOf(T)))
3877 {
3878 if (std.simd.suggestVectorLength(T)) |simd_size| {
3879 if (simd_size <= end) {
3880 const simd_end = end - (simd_size - 1);
3881 while (i < simd_end) : (i += simd_size) {
3882 const left_slice = items[i .. i + simd_size];
3883 const right_slice = items[items.len - i - simd_size .. items.len - i];
3884
3885 const left_shuffled: [simd_size]T = reverseVector(simd_size, T, left_slice);
3886 const right_shuffled: [simd_size]T = reverseVector(simd_size, T, right_slice);
3887
3888 @memcpy(right_slice, &left_shuffled);
3889 @memcpy(left_slice, &right_shuffled);
3890 }
3891 }
3891
3892 vec: {
3893 if (!use_vectors) break :vec;
3894 if (@inComptime()) break :vec;
3895 switch (@typeInfo(T)) {
3896 .int, .float => {},
3897 .pointer => |pointer| if (pointer.size == .slice) break :vec,
3898 else => break :vec,
3899 }
3900 if (@bitSizeOf(T) == 0 or !comptime std.math.isPowerOfTwo(@bitSizeOf(T))) break :vec;
3901 const simd_size = std.simd.suggestVectorLength(T) orelse break :vec;
3902 if (simd_size > end) break :vec;
3903
3904 const simd_end = end - (simd_size - 1);
3905 while (i < simd_end) : (i += simd_size) {
3906 const left_slice = items[i .. i + simd_size];
3907 const right_slice = items[items.len - i - simd_size .. items.len - i];
3908
3909 const left_shuffled: [simd_size]T = reverseVector(simd_size, T, left_slice);
3910 const right_shuffled: [simd_size]T = reverseVector(simd_size, T, right_slice);
3911
3912 @memcpy(right_slice, &left_shuffled);
3913 @memcpy(left_slice, &right_shuffled);
38923914 }
38933915 }
38943916
......@@ -5009,8 +5031,8 @@ test "read/write(Var)PackedInt" {
50095031 for ([_]PackedType{
50105032 ~@as(PackedType, 0), // all ones: -1 iN / maxInt uN
50115033 @as(PackedType, 0), // all zeros: 0 iN / 0 uN
5012 @as(PackedType, @bitCast(@as(iPackedType, math.maxInt(iPackedType)))), // maxInt iN
5013 @as(PackedType, @bitCast(@as(iPackedType, math.minInt(iPackedType)))), // maxInt iN
5034 @bitCast(@as(iPackedType, math.maxInt(iPackedType))), // maxInt iN
5035 @bitCast(@as(iPackedType, math.minInt(iPackedType))), // maxInt iN
50145036 random.int(PackedType), // random
50155037 random.int(PackedType), // random
50165038 }) |write_value| {
lib/std/os/linux/IoUring/test.zig+24-8
......@@ -526,7 +526,9 @@ test "sendmsg/recvmsg" {
526526
527527 var address_server: linux.sockaddr.in = .{
528528 .port = 0,
529 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
529 .addr = @as(*align(1) const u32, @ptrCast(
530 &@as([4]u8, .{ 127, 0, 0, 1 }),
531 )).*,
530532 };
531533
532534 const server = try socket(address_server.family, posix.SOCK.DGRAM, 0);
......@@ -1028,7 +1030,9 @@ test "shutdown" {
10281030
10291031 var address: linux.sockaddr.in = .{
10301032 .port = 0,
1031 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
1033 .addr = @as(*align(1) const u32, @ptrCast(
1034 &@as([4]u8, .{ 127, 0, 0, 1 }),
1035 )).*,
10321036 };
10331037
10341038 // Socket bound, expect shutdown to work
......@@ -1740,7 +1744,9 @@ test "accept multishot" {
17401744
17411745 var address: linux.sockaddr.in = .{
17421746 .port = 0,
1743 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
1747 .addr = @as(*align(1) const u32, @ptrCast(
1748 &@as([4]u8, .{ 127, 0, 0, 1 }),
1749 )).*,
17441750 };
17451751 const listener_socket = try createListenerSocket(&address);
17461752 defer _ = linux.close(listener_socket);
......@@ -1842,7 +1848,9 @@ test "accept_direct" {
18421848 defer ring.deinit();
18431849 var address: linux.sockaddr.in = .{
18441850 .port = 0,
1845 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
1851 .addr = @as(*align(1) const u32, @ptrCast(
1852 &@as([4]u8, .{ 127, 0, 0, 1 }),
1853 )).*,
18461854 };
18471855
18481856 // register direct file descriptors
......@@ -1931,7 +1939,9 @@ test "accept_multishot_direct" {
19311939
19321940 var address: linux.sockaddr.in = .{
19331941 .port = 0,
1934 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
1942 .addr = @as(*align(1) const u32, @ptrCast(
1943 &@as([4]u8, .{ 127, 0, 0, 1 }),
1944 )).*,
19351945 };
19361946
19371947 var registered_fds: [2]linux.fd_t = @splat(-1);
......@@ -2041,7 +2051,9 @@ test "socket_direct/socket_direct_alloc/close_direct" {
20412051 // use sockets from registered_fds in connect operation
20422052 var address: linux.sockaddr.in = .{
20432053 .port = 0,
2044 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
2054 .addr = @as(*align(1) const u32, @ptrCast(
2055 &@as([4]u8, .{ 127, 0, 0, 1 }),
2056 )).*,
20452057 };
20462058 const listener_socket = try createListenerSocket(&address);
20472059 defer _ = linux.close(listener_socket);
......@@ -2426,7 +2438,9 @@ test "bind/listen/connect" {
24262438
24272439 var addr: linux.sockaddr.in = .{
24282440 .port = 0,
2429 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
2441 .addr = @as(*align(1) const u32, @ptrCast(
2442 &@as([4]u8, .{ 127, 0, 0, 1 }),
2443 )).*,
24302444 };
24312445 const proto: u32 = if (addr.family == linux.AF.UNIX) 0 else linux.IPPROTO.TCP;
24322446
......@@ -2614,7 +2628,9 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness {
26142628 // Create a TCP server socket
26152629 var address: linux.sockaddr.in = .{
26162630 .port = 0,
2617 .addr = @bitCast([4]u8{ 127, 0, 0, 1 }),
2631 .addr = @as(*align(1) const u32, @ptrCast(
2632 &@as([4]u8, .{ 127, 0, 0, 1 }),
2633 )).*,
26182634 };
26192635 const listener_socket = try createListenerSocket(&address);
26202636 errdefer _ = linux.close(listener_socket);
lib/std/os/uefi.zig+1-1
......@@ -218,7 +218,7 @@ pub const TimeCapabilities = extern struct {
218218pub const FileHandle = *opaque {};
219219
220220test "GUID formatting" {
221 const bytes = [_]u8{ 137, 60, 203, 50, 128, 128, 124, 66, 186, 19, 80, 73, 135, 59, 194, 135 };
221 const bytes: [16]u8 = .{ 137, 60, 203, 50, 128, 128, 124, 66, 186, 19, 80, 73, 135, 59, 194, 135 };
222222 const guid: Guid = @bitCast(bytes);
223223
224224 const str = try std.fmt.allocPrint(std.testing.allocator, "{f}", .{guid});
lib/std/os/windows.zig+37-36
......@@ -4189,19 +4189,11 @@ pub const GUID = extern struct {
41894189 Data3: u16,
41904190 Data4: [8]u8,
41914191
4192 const hex_offsets = switch (builtin.target.cpu.arch.endian()) {
4193 .big => [16]u6{
4194 0, 2, 4, 6,
4195 9, 11, 14, 16,
4196 19, 21, 24, 26,
4197 28, 30, 32, 34,
4198 },
4199 .little => [16]u6{
4200 6, 4, 2, 0,
4201 11, 9, 16, 14,
4202 19, 21, 24, 26,
4203 28, 30, 32, 34,
4204 },
4192 const hex_offsets: [16]u6 = .{
4193 6, 4, 2, 0,
4194 11, 9, 16, 14,
4195 19, 21, 24, 26,
4196 28, 30, 32, 34,
42054197 };
42064198
42074199 pub fn parse(s: []const u8) GUID {
......@@ -4216,12 +4208,21 @@ pub const GUID = extern struct {
42164208 assert(s[13] == '-');
42174209 assert(s[18] == '-');
42184210 assert(s[23] == '-');
4219 var bytes: [16]u8 = undefined;
4220 for (hex_offsets, 0..) |hex_offset, i| {
4221 bytes[i] = (try std.fmt.charToDigit(s[hex_offset], 16)) << 4 |
4222 try std.fmt.charToDigit(s[hex_offset + 1], 16);
4223 }
4224 return @as(GUID, @bitCast(bytes));
4211 var raw1: [4]u8 = undefined;
4212 var raw2: [2]u8 = undefined;
4213 var raw3: [2]u8 = undefined;
4214 var raw4: [8]u8 = undefined;
4215 assert((try std.fmt.hexToBytes(&raw1, s[0..8])).len == raw1.len);
4216 assert((try std.fmt.hexToBytes(&raw2, s[9..13])).len == raw2.len);
4217 assert((try std.fmt.hexToBytes(&raw3, s[14..18])).len == raw3.len);
4218 assert((try std.fmt.hexToBytes(raw4[0..2], s[19..23])).len == 2);
4219 assert((try std.fmt.hexToBytes(raw4[2..8], s[24..36])).len == 6);
4220 return .{
4221 .Data1 = @byteSwap(@as(u32, @bitCast(raw1))),
4222 .Data2 = @byteSwap(@as(u16, @bitCast(raw2))),
4223 .Data3 = @byteSwap(@as(u16, @bitCast(raw3))),
4224 .Data4 = raw4,
4225 };
42254226 }
42264227
42274228 pub fn format(self: GUID, w: *std.Io.Writer) std.Io.Writer.Error!void {
......@@ -4233,28 +4234,28 @@ pub const GUID = extern struct {
42334234 self.Data4[2..8],
42344235 });
42354236 }
4236};
42374237
4238test GUID {
4239 try std.testing.expectEqual(
4240 GUID{
4238 test parse {
4239 const expected: GUID = .{
42414240 .Data1 = 0x01234567,
42424241 .Data2 = 0x89ab,
42434242 .Data3 = 0xef10,
42444243 .Data4 = "\x32\x54\x76\x98\xba\xdc\xfe\x91".*,
4245 },
4246 GUID.parse("{01234567-89AB-EF10-3254-7698badcfe91}"),
4247 );
4248 try std.testing.expectFmt(
4249 "{01234567-89ab-ef10-3254-7698badcfe91}",
4250 "{f}",
4251 .{GUID.parse("{01234567-89AB-EF10-3254-7698badcfe91}")},
4252 );
4253 try std.testing.expectFmt(
4254 "{00000001-0001-0001-0001-000000000001}",
4255 "{f}",
4256 .{GUID{ .Data1 = 1, .Data2 = 1, .Data3 = 1, .Data4 = [_]u8{ 0, 1, 0, 0, 0, 0, 0, 1 } }},
4257 );
4244 };
4245 try std.testing.expectEqual(expected, GUID.parse("{01234567-89AB-EF10-3254-7698badcfe91}"));
4246 }
4247
4248 test format {
4249 const guid0: GUID = .{ .Data1 = 1, .Data2 = 1, .Data3 = 1, .Data4 = .{ 0, 1, 0, 0, 0, 0, 0, 1 } };
4250 try std.testing.expectFmt("{00000001-0001-0001-0001-000000000001}", "{f}", .{guid0});
4251
4252 const guid1: GUID = .parse("{01234567-89AB-EF10-3254-7698badcfe91}");
4253 try std.testing.expectFmt("{01234567-89ab-ef10-3254-7698badcfe91}", "{f}", .{guid1});
4254 }
4255};
4256
4257test {
4258 _ = GUID;
42584259}
42594260
42604261pub const COORD = extern struct {
lib/std/testing.zig+30-24
......@@ -141,39 +141,45 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
141141 try expectEqualSlices(info.child, &expect_array, &actual_array);
142142 },
143143
144 .@"struct" => |structType| {
145 inline for (structType.field_names) |field_name| {
144 .@"struct" => |@"struct"| {
145 inline for (@"struct".field_names) |field_name| {
146146 try expectEqual(@field(expected, field_name), @field(actual, field_name));
147147 }
148148 },
149149
150 .@"union" => |union_info| {
151 if (union_info.tag_type == null) {
152 const first_size = @bitSizeOf(union_info.field_types[0]);
153 inline for (union_info.field_types) |field_type| {
150 .@"union" => |@"union"| if (@"union".backing_integer) |Int| {
151 try expectEqual(@as(Int, @bitCast(expected)), @as(Int, @bitCast(actual)));
152 } else switch (@"union".layout) {
153 .@"packed" => {
154 const Int = @Int(.unsigned, @bitSizeOf(T));
155 try expectEqual(@as(Int, @bitCast(expected)), @as(Int, @bitCast(actual)));
156 },
157 .@"extern" => {
158 const first_size = @bitSizeOf(@"union".field_types[0]);
159 inline for (@"union".field_types) |field_type| {
154160 if (@bitSizeOf(field_type) != first_size) {
155 @compileError("Unable to compare untagged unions with varying field sizes for type " ++ @typeName(@TypeOf(actual)));
161 @compileError("Unable to compare extern unions with varying field sizes for type " ++ @typeName(T));
156162 }
157163 }
158
159 const BackingInt = @Int(.unsigned, @bitSizeOf(T));
164 const FieldInt = @Int(.unsigned, first_size);
165 const expected_field = @field(expected, @"union".field_names[0]);
166 const actual_field = @field(actual, @"union".field_names[0]);
160167 return expectEqual(
161 @as(BackingInt, @bitCast(expected)),
162 @as(BackingInt, @bitCast(actual)),
168 @as(FieldInt, @bitCast(expected_field)),
169 @as(FieldInt, @bitCast(actual_field)),
163170 );
164 }
165
166 const Tag = std.meta.Tag(@TypeOf(expected));
167
168 const expectedTag = @as(Tag, expected);
169 const actualTag = @as(Tag, actual);
170
171 try expectEqual(expectedTag, actualTag);
172
173 // we only reach this switch if the tags are equal
174 switch (expected) {
175 inline else => |val, tag| try expectEqual(val, @field(actual, @tagName(tag))),
176 }
171 },
172 .auto => {
173 const Tag = @"union".tag_type orelse @compileError("byteSwapAllFields expects packed, extern, or tagged union");
174
175 try expectEqual(@as(Tag, expected), @as(Tag, actual));
176 switch (expected) {
177 inline else => |expected_payload, tag| {
178 const actual_payload = @field(actual, @tagName(tag));
179 try expectEqual(expected_payload, actual_payload);
180 },
181 }
182 },
177183 },
178184
179185 .optional => {
lib/std/zig/llvm/Builder.zig+2-2
......@@ -1816,7 +1816,7 @@ pub const Linkage = enum(u4) {
18161816 }
18171817};
18181818
1819pub const Preemption = enum {
1819pub const Preemption = enum(u2) {
18201820 dso_preemptable,
18211821 dso_local,
18221822 implicit_dso_local,
......@@ -2011,7 +2011,7 @@ pub const AddrSpace = enum(u24) {
20112011 }
20122012};
20132013
2014pub const ExternallyInitialized = enum {
2014pub const ExternallyInitialized = enum(u1) {
20152015 default,
20162016 externally_initialized,
20172017