diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index 4b0e142fb0..11bc05a00d 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -851,6 +851,9 @@ 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, @@ -860,7 +863,22 @@ pub inline fn writeSliceEndian( if (native_endian == endian) { return writeAll(w, @ptrCast(slice)); } else { - return w.writeArraySwap(w, Elem, slice); + return writeSliceSwap(w, Elem, slice); + } +} + +/// 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); } } @@ -2630,3 +2648,11 @@ test writeStruct { }, &buffer); } } + +test writeSliceEndian { + var buffer: [4]u8 align(2) = undefined; + var w: Writer = .fixed(&buffer); + const array: [2]u16 = .{ 0x1234, 0x5678 }; + try writeSliceEndian(&w, u16, &array, .big); + try testing.expectEqualSlices(u8, &.{ 0x12, 0x34, 0x56, 0x78 }, &buffer); +} diff --git a/lib/std/zig/Server.zig b/lib/std/zig/Server.zig index 38ad45e1e1..8fc016d284 100644 --- a/lib/std/zig/Server.zig +++ b/lib/std/zig/Server.zig @@ -118,6 +118,8 @@ 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; }