Commit c40fb96ca3

Andrew Kelley <andrew@ziglang.org>
2025-07-20 06:53:48
std.Io.Writer: fix writeSliceSwap
tried to be too clever, wrote bad code
1 parent 741a66e
Changed files (7)
lib/compiler/test_runner.zig
@@ -10,10 +10,10 @@ pub const std_options: std.Options = .{
 };
 
 var log_err_count: usize = 0;
-var fba_buffer: [8192]u8 = undefined;
 var fba = std.heap.FixedBufferAllocator.init(&fba_buffer);
-var stdin_buffer: [std.heap.page_size_min]u8 align(std.heap.page_size_min) = undefined;
-var stdout_buffer: [std.heap.page_size_min]u8 align(std.heap.page_size_min) = undefined;
+var fba_buffer: [8192]u8 = undefined;
+var stdin_buffer: [4096]u8 = undefined;
+var stdout_buffer: [4096]u8 = undefined;
 
 const crippled = switch (builtin.zig_backend) {
     .stage2_powerpc,
@@ -68,8 +68,8 @@ pub fn main() void {
 
 fn mainServer() !void {
     @disableInstrumentation();
-    var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer);
-    var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
+    var stdin_reader = std.fs.File.stdin().readerStreaming(&stdin_buffer);
+    var stdout_writer = std.fs.File.stdout().writerStreaming(&stdout_buffer);
     var server = try std.zig.Server.init(.{
         .in = &stdin_reader.interface,
         .out = &stdout_writer.interface,
@@ -104,7 +104,7 @@ fn mainServer() !void {
                 defer testing.allocator.free(expected_panic_msgs);
 
                 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {
-                    name.* = @as(u32, @intCast(string_bytes.items.len));
+                    name.* = @intCast(string_bytes.items.len);
                     try string_bytes.ensureUnusedCapacity(testing.allocator, test_fn.name.len + 1);
                     string_bytes.appendSliceAssumeCapacity(test_fn.name);
                     string_bytes.appendAssumeCapacity(0);
lib/std/Build/Step/Run.zig
@@ -1742,7 +1742,7 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
         .tag = tag,
         .bytes_len = 0,
     };
-    try file.writeAll(std.mem.asBytes(&header));
+    try file.writeAll(@ptrCast(&header));
 }
 
 fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: u32) !void {
lib/std/Io/Reader.zig
@@ -1108,9 +1108,9 @@ pub fn takeVarInt(r: *Reader, comptime Int: type, endian: std.builtin.Endian, n:
 /// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
 ///
 /// See also:
-/// * `peekStructReference`
+/// * `peekStructPointer`
 /// * `takeStruct`
-pub fn takeStructReference(r: *Reader, comptime T: type) Error!*align(1) T {
+pub fn takeStructPointer(r: *Reader, comptime T: type) Error!*align(1) T {
     // Only extern and packed structs have defined in-memory layout.
     comptime assert(@typeInfo(T).@"struct".layout != .auto);
     return @ptrCast(try r.takeArray(@sizeOf(T)));
@@ -1122,9 +1122,9 @@ pub fn takeStructReference(r: *Reader, comptime T: type) Error!*align(1) T {
 /// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
 ///
 /// See also:
-/// * `takeStructReference`
+/// * `takeStructPointer`
 /// * `peekStruct`
-pub fn peekStructReference(r: *Reader, comptime T: type) Error!*align(1) T {
+pub fn peekStructPointer(r: *Reader, comptime T: type) Error!*align(1) T {
     // Only extern and packed structs have defined in-memory layout.
     comptime assert(@typeInfo(T).@"struct".layout != .auto);
     return @ptrCast(try r.peekArray(@sizeOf(T)));
@@ -1136,14 +1136,14 @@ pub fn peekStructReference(r: *Reader, comptime T: type) Error!*align(1) T {
 /// when `endian` is comptime-known and matches the host endianness.
 ///
 /// See also:
-/// * `takeStructReference`
+/// * `takeStructPointer`
 /// * `peekStruct`
 pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
     switch (@typeInfo(T)) {
         .@"struct" => |info| switch (info.layout) {
             .auto => @compileError("ill-defined memory layout"),
             .@"extern" => {
-                var res = (try r.takeStructReference(T)).*;
+                var res = (try r.takeStructPointer(T)).*;
                 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
                 return res;
             },
@@ -1162,13 +1162,13 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia
 ///
 /// See also:
 /// * `takeStruct`
-/// * `peekStructReference`
+/// * `peekStructPointer`
 pub inline fn peekStruct(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T {
     switch (@typeInfo(T)) {
         .@"struct" => |info| switch (info.layout) {
             .auto => @compileError("ill-defined memory layout"),
             .@"extern" => {
-                var res = (try r.peekStructReference(T)).*;
+                var res = (try r.peekStructPointer(T)).*;
                 if (native_endian != endian) std.mem.byteSwapAllFields(T, &res);
                 return res;
             },
@@ -1557,27 +1557,27 @@ test takeVarInt {
     try testing.expectError(error.EndOfStream, r.takeVarInt(u16, .little, 1));
 }
 
-test takeStructReference {
+test takeStructPointer {
     var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
     const S = extern struct { a: u8, b: u16 };
     switch (native_endian) {
-        .little => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.takeStructReference(S)).*),
-        .big => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.takeStructReference(S)).*),
+        .little => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.takeStructPointer(S)).*),
+        .big => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.takeStructPointer(S)).*),
     }
-    try testing.expectError(error.EndOfStream, r.takeStructReference(S));
+    try testing.expectError(error.EndOfStream, r.takeStructPointer(S));
 }
 
-test peekStructReference {
+test peekStructPointer {
     var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 });
     const S = extern struct { a: u8, b: u16 };
     switch (native_endian) {
         .little => {
-            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructReference(S)).*);
-            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructReference(S)).*);
+            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructPointer(S)).*);
+            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStructPointer(S)).*);
         },
         .big => {
-            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructReference(S)).*);
-            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructReference(S)).*);
+            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructPointer(S)).*);
+            try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStructPointer(S)).*);
         },
     }
 }
lib/std/Io/Writer.zig
@@ -851,9 +851,6 @@ pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian
     }
 }
 
-/// If, `endian` is not native,
-/// * Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
-/// * Asserts that the buffer is aligned enough for `@alignOf(Elem)`.
 pub inline fn writeSliceEndian(
     w: *Writer,
     Elem: type,
@@ -867,18 +864,11 @@ pub inline fn writeSliceEndian(
     }
 }
 
-/// Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)`
-///
-/// Asserts that the buffer is aligned enough for `@alignOf(Elem)`.
 pub fn writeSliceSwap(w: *Writer, Elem: type, slice: []const Elem) Error!void {
-    var i: usize = 0;
-    while (i < slice.len) {
-        const dest_bytes = try w.writableSliceGreedy(@sizeOf(Elem));
-        const dest: []Elem = @alignCast(@ptrCast(dest_bytes[0 .. dest_bytes.len - dest_bytes.len % @sizeOf(Elem)]));
-        const copy_len = @min(dest.len, slice.len - i);
-        @memcpy(dest[0..copy_len], slice[i..][0..copy_len]);
-        i += copy_len;
-        std.mem.byteSwapAllElements(Elem, dest);
+    for (slice) |elem| {
+        var tmp = elem;
+        std.mem.byteSwapAllFields(Elem, &tmp);
+        try w.writeAll(@ptrCast(&tmp));
     }
 }
 
@@ -2650,9 +2640,10 @@ test writeStruct {
 }
 
 test writeSliceEndian {
-    var buffer: [4]u8 align(2) = undefined;
+    var buffer: [5]u8 align(2) = undefined;
     var w: Writer = .fixed(&buffer);
+    try w.writeByte('x');
     const array: [2]u16 = .{ 0x1234, 0x5678 };
     try writeSliceEndian(&w, u16, &array, .big);
-    try testing.expectEqualSlices(u8, &.{ 0x12, 0x34, 0x56, 0x78 }, &buffer);
+    try testing.expectEqualSlices(u8, &.{ 'x', 0x12, 0x34, 0x56, 0x78 }, &buffer);
 }
lib/std/zig/Server.zig
@@ -118,8 +118,6 @@ pub fn init(options: Options) !Server {
         .in = options.in,
         .out = options.out,
     };
-    assert(s.out.buffer.len >= 4);
-    std.debug.assertAligned(s.out.buffer.ptr, .@"4");
     try s.serveStringMessage(.zig_version, options.zig_version);
     return s;
 }
@@ -203,8 +201,8 @@ pub const TestMetadata = struct {
 
 pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
     const header: OutMessage.TestMetadata = .{
-        .tests_len = @as(u32, @intCast(test_metadata.names.len)),
-        .string_bytes_len = @as(u32, @intCast(test_metadata.string_bytes.len)),
+        .tests_len = @intCast(test_metadata.names.len),
+        .string_bytes_len = @intCast(test_metadata.string_bytes.len),
     };
     const trailing = 2;
     const bytes_len = @sizeOf(OutMessage.TestMetadata) +
src/Zcu/PerThread.zig
@@ -349,7 +349,7 @@ fn loadZirZoirCache(
     const cache_br = &cache_fr.interface;
 
     // First we read the header to determine the lengths of arrays.
-    const header = (cache_br.takeStructReference(Header) catch |err| switch (err) {
+    const header = (cache_br.takeStructPointer(Header) catch |err| switch (err) {
         error.ReadFailed => return cache_fr.err.?,
         // This can happen if Zig bails out of this function between creating
         // the cached file and writing it.
src/Zcu.zig
@@ -2821,7 +2821,7 @@ pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
     var buffer: [2000]u8 = undefined;
     var file_reader = cache_file.reader(&buffer);
     return result: {
-        const header = file_reader.interface.takeStructReference(Zir.Header) catch |err| break :result err;
+        const header = file_reader.interface.takeStructPointer(Zir.Header) catch |err| break :result err;
         break :result loadZirCacheBody(gpa, header.*, &file_reader.interface);
     } catch |err| switch (err) {
         error.ReadFailed => return file_reader.err.?,