diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index ae1fcd6f96..172da8e5e1 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -202,34 +202,33 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void { var walker = try std_dir.walk(gpa); defer walker.deinit(); - var archiver = std.tar.writer(response.writer()); - archiver.prefix = "std"; + var tar_buffer: [@sizeOf(std.tar.Writer.Header)]u8 = undefined; + var response_bw = response.writer().buffered(&tar_buffer); + var tar_writer: std.tar.Writer = .{ .underlying_writer = &response_bw }; + tar_writer.prefix = "std"; while (try walker.next()) |entry| { switch (entry.kind) { .file => { - if (!std.mem.endsWith(u8, entry.basename, ".zig")) - continue; - if (std.mem.endsWith(u8, entry.basename, "test.zig")) - continue; + if (!std.mem.endsWith(u8, entry.basename, ".zig")) continue; + if (std.mem.endsWith(u8, entry.basename, "test.zig")) continue; }, else => continue, } var file = try entry.dir.openFile(entry.basename, .{}); defer file.close(); - try archiver.writeFile(entry.path, file); + const stat = try file.stat(); + try tar_writer.writeFile(entry.path, file, stat); } { // Since this command is JIT compiled, the builtin module available in // this source file corresponds to the user's host system. const builtin_zig = @embedFile("builtin"); - archiver.prefix = "builtin"; - try archiver.writeFileBytes("builtin.zig", builtin_zig, .{}); + tar_writer.prefix = "builtin"; + try tar_writer.writeFileBytes("builtin.zig", builtin_zig, .{}); } - // intentionally omitting the pointless trailer - //try archiver.finish(); try response.end(); } @@ -255,16 +254,27 @@ fn serveWasm( }) catch unreachable) catch unreachable), .output_mode = .Exe, }); - // std.http.Server does not have a sendfile API yet. const bin_path = try wasm_base_path.join(arena, bin_name); - const file_contents = try bin_path.root_dir.handle.readFileAlloc(gpa, bin_path.sub_path, 10 * 1024 * 1024); - defer gpa.free(file_contents); - try request.respond(file_contents, .{ - .extra_headers = &.{ - .{ .name = "content-type", .value = "application/wasm" }, - cache_control_header, + const file = try bin_path.root_dir.handle.openFile(bin_path.sub_path, .{}); + defer file.close(); + const content_length = std.math.cast(usize, (try file.stat()).size) orelse return error.FileTooBig; + + var response = try request.respondStreaming(.{ + .content_length = content_length, + .respond_options = .{ + .extra_headers = &.{ + .{ .name = "content-type", .value = "application/wasm" }, + cache_control_header, + }, }, }); + + var bw = response.writer().unbuffered(); + try bw.writeFileAll(file, .{ + .offset = .zero, + .limit = .limited(content_length), + }); + try response.end(); } const autodoc_root_name = "autodoc"; @@ -396,8 +406,8 @@ fn receiveWasmMessage( }, .error_bundle => { const eb_hdr = try br.takeStructEndian(std.zig.Server.Message.ErrorBundle, .little); - const extra_array = try br.readArrayEndianAlloc(arena, u32, eb_hdr.extra_len, .little); - const string_bytes = try br.readAlloc(arena, eb_hdr.string_bytes_len); + const extra_array = try br.readSliceEndianAlloc(arena, u32, eb_hdr.extra_len, .little); + const string_bytes = try br.readSliceAlloc(arena, eb_hdr.string_bytes_len); result_error_bundle.* = .{ .string_bytes = string_bytes, .extra = extra_array, diff --git a/lib/std/compress/flate/inflate.zig b/lib/std/compress/flate/inflate.zig index 1d3b7fcc68..b55a4893a6 100644 --- a/lib/std/compress/flate/inflate.zig +++ b/lib/std/compress/flate/inflate.zig @@ -704,7 +704,7 @@ pub fn BitReader(comptime T: type) type { n += 1; } // Then use forward reader for all other bytes. - try self.forward_reader.read(buf[n..]); + try self.forward_reader.readSlice(buf[n..]); } /// Alias for readF(U, 0). diff --git a/lib/std/io/BufferedReader.zig b/lib/std/io/BufferedReader.zig index 6155a474c9..e7a8c345ab 100644 --- a/lib/std/io/BufferedReader.zig +++ b/lib/std/io/BufferedReader.zig @@ -51,6 +51,19 @@ pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize { return passthruReadVec(br, data); } +pub fn read(br: *BufferedReader, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!usize { + return passthruRead(br, bw, limit); +} + +/// "Pump" data from the reader to the writer. +pub fn readAll(br: *BufferedReader, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!void { + var remaining = limit; + while (true) { + const n = try passthruRead(br, bw, remaining); + remaining = remaining.subtract(n).?; + } +} + fn passthruRead(ctx: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!usize { const br: *BufferedReader = @alignCast(@ptrCast(ctx)); const buffer = br.buffer[0..br.end]; @@ -134,7 +147,6 @@ pub fn seekForwardBy(br: *BufferedReader, seek_by: u64) !void { /// /// See also: /// * `peek` -/// * `tryPeekArray` /// * `toss` pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 { assert(n <= br.buffer.len); @@ -155,7 +167,6 @@ pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 { /// /// See also: /// * `peek` -/// * `tryPeekGreedy` /// * `toss` pub fn peekGreedy(br: *BufferedReader, n: usize) Reader.Error![]u8 { assert(n <= br.buffer.len); @@ -280,7 +291,7 @@ pub fn discardRemaining(br: *BufferedReader) Reader.ShortError!usize { /// /// See also: /// * `peek` -pub fn read(br: *BufferedReader, buffer: []u8) Reader.Error!void { +pub fn readSlice(br: *BufferedReader, buffer: []u8) Reader.Error!void { const in_buffer = br.buffer[br.seek..br.end]; const copy_len = @min(buffer.len, in_buffer.len); @memcpy(buffer[0..copy_len], in_buffer[0..copy_len]); @@ -313,7 +324,7 @@ pub fn readShort(br: *BufferedReader, buffer: []u8) Reader.ShortError!usize { /// The function is inline to avoid the dead code in case `endian` is /// comptime-known and matches host endianness. -pub inline fn readArrayEndianAlloc( +pub inline fn readSliceEndianAlloc( br: *BufferedReader, allocator: Allocator, Elem: type, @@ -322,17 +333,17 @@ pub inline fn readArrayEndianAlloc( ) ReadAllocError![]Elem { const dest = try allocator.alloc(Elem, len); errdefer allocator.free(dest); - try read(br, @ptrCast(dest)); + try readSlice(br, @ptrCast(dest)); if (native_endian != endian) std.mem.byteSwapAllFields(Elem, dest); return dest; } pub const ReadAllocError = Reader.Error || Allocator.Error; -pub fn readAlloc(br: *BufferedReader, allocator: Allocator, len: usize) ReadAllocError![]u8 { +pub fn readSliceAlloc(br: *BufferedReader, allocator: Allocator, len: usize) ReadAllocError![]u8 { const dest = try allocator.alloc(u8, len); errdefer allocator.free(dest); - try read(br, dest); + try readSlice(br, dest); return dest; } diff --git a/lib/std/io/BufferedWriter.zig b/lib/std/io/BufferedWriter.zig index 4ca063b185..69d2478b00 100644 --- a/lib/std/io/BufferedWriter.zig +++ b/lib/std/io/BufferedWriter.zig @@ -453,24 +453,24 @@ pub inline fn writeStructEndian(bw: *BufferedWriter, value: anytype, endian: std } } -pub inline fn writeArrayEndian( +pub inline fn writeSliceEndian( bw: *BufferedWriter, Elem: type, - array: []const Elem, + slice: []const Elem, endian: std.builtin.Endian, ) Writer.Error!void { if (native_endian == endian) { - return writeAll(bw, @ptrCast(array)); + return writeAll(bw, @ptrCast(slice)); } else { - return bw.writeArraySwap(bw, Elem, array); + return bw.writeArraySwap(bw, Elem, slice); } } /// Asserts that the buffer storage capacity is at least enough to store `@sizeOf(Elem)` -pub fn writeArraySwap(bw: *BufferedWriter, Elem: type, array: []const Elem) Writer.Error!void { +pub fn writeSliceSwap(bw: *BufferedWriter, Elem: type, slice: []const Elem) Writer.Error!void { // copy to storage first, then swap in place _ = bw; - _ = array; + _ = slice; @panic("TODO"); } diff --git a/lib/std/io/Reader.zig b/lib/std/io/Reader.zig index 5d54f56399..3ee0220f0d 100644 --- a/lib/std/io/Reader.zig +++ b/lib/std/io/Reader.zig @@ -45,18 +45,26 @@ pub const VTable = struct { discard: *const fn (context: ?*anyopaque, limit: Limit) Error!usize, }; -pub const RwError = RwAllError || error{ +pub const RwError = error{ + /// See the `Reader` implementation for detailed diagnostics. + ReadFailed, + /// See the `Writer` implementation for detailed diagnostics. + WriteFailed, /// End of stream indicated from the `Reader`. This error cannot originate /// from the `Writer`. EndOfStream, }; -pub const Error = ShortError || error{ +pub const Error = error{ + /// See the `Reader` implementation for detailed diagnostics. + ReadFailed, EndOfStream, }; /// For functions that handle end of stream as a success case. -pub const RwAllError = ShortError || error{ +pub const RwAllError = error{ + /// See the `Reader` implementation for detailed diagnostics. + ReadFailed, /// See the `Writer` implementation for detailed diagnostics. WriteFailed, }; diff --git a/lib/std/tar/Writer.zig b/lib/std/tar/Writer.zig index 964be0f013..064168d21c 100644 --- a/lib/std/tar/Writer.zig +++ b/lib/std/tar/Writer.zig @@ -4,7 +4,6 @@ const testing = std.testing; const Writer = @This(); const block_size = @sizeOf(Header); -const empty_block: [block_size]u8 = [_]u8{0} ** block_size; /// Options for writing file/dir/link. If left empty 0o664 is used for /// file mode and current time for mtime. @@ -14,80 +13,91 @@ pub const Options = struct { /// File system modification time. mtime: u64 = 0, }; -const Self = @This(); underlying_writer: *std.io.BufferedWriter, prefix: []const u8 = "", mtime_now: u64 = 0, +const Error = error{ + WriteFailed, + OctalOverflow, + NameTooLong, +}; + /// Sets prefix for all other write* method paths. -pub fn setRoot(self: *Self, root: []const u8) !void { +pub fn setRoot(w: *Writer, root: []const u8) Error!void { if (root.len > 0) - try self.writeDir(root, .{}); + try w.writeDir(root, .{}); - self.prefix = root; + w.prefix = root; } -/// Writes directory. -pub fn writeDir(self: *Self, sub_path: []const u8, opt: Options) !void { - try self.writeHeader(.directory, sub_path, "", 0, opt); +pub fn writeDir(w: *Writer, sub_path: []const u8, options: Options) Error!void { + try w.writeHeader(.directory, sub_path, "", 0, options); } -/// Writes file system file. -pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void { - const stat = try file.stat(); +pub const WriteFileError = std.io.Writer.FileError || Error; + +pub fn writeFile( + w: *Writer, + sub_path: []const u8, + file: std.fs.File, + stat: std.fs.File.Stat, +) WriteFileError!void { const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s)); - var header = Header{}; - try self.setPath(&header, sub_path); + var header: Header = .{}; + try w.setPath(&header, sub_path); try header.setSize(stat.size); try header.setMtime(mtime); - try header.write(self.underlying_writer); + try header.write(w.underlying_writer); - try self.underlying_writer.writeFileAll(file, .{ .limit = .limited(stat.size) }); - try self.writePadding(stat.size); + try w.underlying_writer.writeFileAll(file, .{ .limit = .limited(stat.size) }); + try w.writePadding(stat.size); } -/// Writes file reading file content from `reader`. Number of bytes in -/// reader must be equal to `size`. -pub fn writeFileStream(self: *Self, sub_path: []const u8, size: usize, reader: anytype, opt: Options) !void { - try self.writeHeader(.regular, sub_path, "", @intCast(size), opt); - - var counting_reader = std.io.countingReader(reader); - var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); - try fifo.pump(counting_reader.reader(), self.underlying_writer); - if (counting_reader.bytes_read != size) return error.WrongReaderSize; - try self.writePadding(size); +/// Writes file reading file content from `reader`. Reads exactly `size` bytes +/// from `reader`, or returns `error.EndOfStream`. +pub fn writeFileStream( + w: *Writer, + sub_path: []const u8, + size: usize, + reader: *std.io.BufferedReader, + options: Options, +) std.io.Reader.RwError!void { + try w.writeHeader(.regular, sub_path, "", @intCast(size), options); + try reader.readAll(w.underlying_writer, .limited(size)); + try w.writePadding(size); } /// Writes file using bytes buffer `content` for size and file content. -pub fn writeFileBytes(self: *Self, sub_path: []const u8, content: []const u8, opt: Options) !void { - try self.writeHeader(.regular, sub_path, "", @intCast(content.len), opt); - try self.underlying_writer.writeAll(content); - try self.writePadding(content.len); +pub fn writeFileBytes(w: *Writer, sub_path: []const u8, content: []const u8, options: Options) Error!void { + try w.writeHeader(.regular, sub_path, "", @intCast(content.len), options); + try w.underlying_writer.writeAll(content); + try w.writePadding(content.len); } -/// Writes symlink. -pub fn writeLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void { - try self.writeHeader(.symbolic_link, sub_path, link_name, 0, opt); +pub fn writeLink(w: *Writer, sub_path: []const u8, link_name: []const u8, options: Options) Error!void { + try w.writeHeader(.symbolic_link, sub_path, link_name, 0, options); } /// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and /// default for entry mode . -pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void { +pub fn writeEntry(w: *Writer, entry: std.fs.Dir.Walker.Entry) Error!void { switch (entry.kind) { .directory => { - try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) }); + try w.writeDir(entry.path, .{ .mtime = try entryMtime(entry) }); }, .file => { var file = try entry.dir.openFile(entry.basename, .{}); defer file.close(); - try self.writeFile(entry.path, file); + const stat = try file.stat(); + try w.writeFile(entry.path, file, stat); }, .sym_link => { var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer); - try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) }); + try w.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) }); }, else => { return error.UnsupportedWalkerEntryKind; @@ -96,31 +106,31 @@ pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void { } fn writeHeader( - self: *Self, + w: *Writer, typeflag: Header.FileType, sub_path: []const u8, link_name: []const u8, size: u64, - opt: Options, -) !void { + options: Options, +) Error!void { var header = Header.init(typeflag); - try self.setPath(&header, sub_path); + try w.setPath(&header, sub_path); try header.setSize(size); - try header.setMtime(if (opt.mtime != 0) opt.mtime else self.mtimeNow()); - if (opt.mode != 0) - try header.setMode(opt.mode); + try header.setMtime(if (options.mtime != 0) options.mtime else w.mtimeNow()); + if (options.mode != 0) + try header.setMode(options.mode); if (typeflag == .symbolic_link) header.setLinkname(link_name) catch |err| switch (err) { - error.NameTooLong => try self.writeExtendedHeader(.gnu_long_link, &.{link_name}), + error.NameTooLong => try w.writeExtendedHeader(.gnu_long_link, &.{link_name}), else => return err, }; - try header.write(self.underlying_writer); + try header.write(w.underlying_writer); } -fn mtimeNow(self: *Self) u64 { - if (self.mtime_now == 0) - self.mtime_now = @intCast(std.time.timestamp()); - return self.mtime_now; +fn mtimeNow(w: *Writer) u64 { + if (w.mtime_now == 0) + w.mtime_now = @intCast(std.time.timestamp()); + return w.mtime_now; } fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 { @@ -130,52 +140,51 @@ fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 { /// Writes path in posix header, if don't fit (in name+prefix; 100+155 /// bytes) writes it in gnu extended header. -fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void { - header.setPath(self.prefix, sub_path) catch |err| switch (err) { +fn setPath(w: *Writer, header: *Header, sub_path: []const u8) Error!void { + header.setPath(w.prefix, sub_path) catch |err| switch (err) { error.NameTooLong => { // write extended header - const buffers: []const []const u8 = if (self.prefix.len == 0) + const buffers: []const []const u8 = if (w.prefix.len == 0) &.{sub_path} else - &.{ self.prefix, "/", sub_path }; - try self.writeExtendedHeader(.gnu_long_name, buffers); + &.{ w.prefix, "/", sub_path }; + try w.writeExtendedHeader(.gnu_long_name, buffers); }, else => return err, }; } /// Writes gnu extended header: gnu_long_name or gnu_long_link. -fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void { +fn writeExtendedHeader(w: *Writer, typeflag: Header.FileType, buffers: []const []const u8) Error!void { var len: usize = 0; - for (buffers) |buf| - len += buf.len; + for (buffers) |buf| len += buf.len; - var header = Header.init(typeflag); + var header: Header = .init(typeflag); try header.setSize(len); - try header.write(self.underlying_writer); + try header.write(w.underlying_writer); for (buffers) |buf| - try self.underlying_writer.writeAll(buf); - try self.writePadding(len); + try w.underlying_writer.writeAll(buf); + try w.writePadding(len); } -fn writePadding(self: *Self, bytes: u64) !void { - const pos: usize = @intCast(bytes % block_size); +fn writePadding(w: *Writer, bytes: usize) std.io.Writer.Error!void { + const pos = bytes % block_size; if (pos == 0) return; - try self.underlying_writer.writeAll(empty_block[pos..]); + try w.underlying_writer.splatByteAll(0, block_size - pos); } -/// Tar should finish with two zero blocks, but 'reasonable system must -/// not assume that such a block exists when reading an archive' (from -/// reference). In practice it is safe to skip this finish. -pub fn finish(self: *Self) !void { - try self.underlying_writer.writeAll(&empty_block); - try self.underlying_writer.writeAll(&empty_block); +/// According to the specification, tar should finish with two zero blocks, but +/// "reasonable system must not assume that such a block exists when reading an +/// archive". Therefore, the Zig standard library recommends to not call this +/// function. +pub fn finishPedantically(w: *Writer) std.io.Writer.Error!void { + try w.underlying_writer.writeSplatAll(&.{&.{0}}, block_size * 2); } /// A struct that is exactly 512 bytes and matches tar file format. This is /// intended to be used for outputting tar files; for parsing there is /// `std.tar.Header`. -const Header = extern struct { +pub const Header = extern struct { // This struct was originally copied from // https://github.com/mattnite/tar/blob/main/src/main.zig which is MIT // licensed. @@ -230,11 +239,11 @@ const Header = extern struct { }; } - pub fn setSize(self: *Header, size: u64) !void { - try octal(&self.size, size); + pub fn setSize(w: *Header, size: u64) error{OctalOverflow}!void { + try octal(&w.size, size); } - fn octal(buf: []u8, value: u64) !void { + fn octal(buf: []u8, value: u64) error{OctalOverflow}!void { var remainder: u64 = value; var pos: usize = buf.len; while (remainder > 0 and pos > 0) { @@ -246,36 +255,36 @@ const Header = extern struct { } } - pub fn setMode(self: *Header, mode: u32) !void { - try octal(&self.mode, mode); + pub fn setMode(w: *Header, mode: u32) error{OctalOverflow}!void { + try octal(&w.mode, mode); } // Integer number of seconds since January 1, 1970, 00:00 Coordinated Universal Time. // mtime == 0 will use current time - pub fn setMtime(self: *Header, mtime: u64) !void { - try octal(&self.mtime, mtime); + pub fn setMtime(w: *Header, mtime: u64) error{OctalOverflow}!void { + try octal(&w.mtime, mtime); } - pub fn updateChecksum(self: *Header) !void { - var checksum: usize = ' '; // other 7 self.checksum bytes are initialized to ' ' - for (std.mem.asBytes(self)) |val| + pub fn updateChecksum(w: *Header) !void { + var checksum: usize = ' '; // other 7 w.checksum bytes are initialized to ' ' + for (std.mem.asBytes(w)) |val| checksum += val; - try octal(&self.checksum, checksum); + try octal(&w.checksum, checksum); } - pub fn write(self: *Header, output_writer: anytype) !void { - try self.updateChecksum(); - try output_writer.writeAll(std.mem.asBytes(self)); + pub fn write(h: *Header, bw: *std.io.BufferedWriter) error{ OctalOverflow, WriteFailed }!void { + try h.updateChecksum(); + try bw.writeAll(std.mem.asBytes(h)); } - pub fn setLinkname(self: *Header, link: []const u8) !void { - if (link.len > self.linkname.len) return error.NameTooLong; - @memcpy(self.linkname[0..link.len], link); + pub fn setLinkname(w: *Header, link: []const u8) !void { + if (link.len > w.linkname.len) return error.NameTooLong; + @memcpy(w.linkname[0..link.len], link); } - pub fn setPath(self: *Header, prefix: []const u8, sub_path: []const u8) !void { - const max_prefix = self.prefix.len; - const max_name = self.name.len; + pub fn setPath(w: *Header, prefix: []const u8, sub_path: []const u8) !void { + const max_prefix = w.prefix.len; + const max_name = w.name.len; const sep = std.fs.path.sep_posix; if (prefix.len + sub_path.len > max_name + max_prefix or prefix.len > max_prefix) @@ -283,32 +292,32 @@ const Header = extern struct { // both fit into name if (prefix.len > 0 and prefix.len + sub_path.len < max_name) { - @memcpy(self.name[0..prefix.len], prefix); - self.name[prefix.len] = sep; - @memcpy(self.name[prefix.len + 1 ..][0..sub_path.len], sub_path); + @memcpy(w.name[0..prefix.len], prefix); + w.name[prefix.len] = sep; + @memcpy(w.name[prefix.len + 1 ..][0..sub_path.len], sub_path); return; } // sub_path fits into name // there is no prefix or prefix fits into prefix if (sub_path.len <= max_name) { - @memcpy(self.name[0..sub_path.len], sub_path); - @memcpy(self.prefix[0..prefix.len], prefix); + @memcpy(w.name[0..sub_path.len], sub_path); + @memcpy(w.prefix[0..prefix.len], prefix); return; } if (prefix.len > 0) { - @memcpy(self.prefix[0..prefix.len], prefix); - self.prefix[prefix.len] = sep; + @memcpy(w.prefix[0..prefix.len], prefix); + w.prefix[prefix.len] = sep; } const prefix_pos = if (prefix.len > 0) prefix.len + 1 else 0; // add as much to prefix as you can, must split at / const prefix_remaining = max_prefix - prefix_pos; if (std.mem.lastIndexOf(u8, sub_path[0..@min(prefix_remaining, sub_path.len)], &.{'/'})) |sep_pos| { - @memcpy(self.prefix[prefix_pos..][0..sep_pos], sub_path[0..sep_pos]); + @memcpy(w.prefix[prefix_pos..][0..sep_pos], sub_path[0..sep_pos]); if ((sub_path.len - sep_pos - 1) > max_name) return error.NameTooLong; - @memcpy(self.name[0..][0 .. sub_path.len - sep_pos - 1], sub_path[sep_pos + 1 ..]); + @memcpy(w.name[0..][0 .. sub_path.len - sep_pos - 1], sub_path[sep_pos + 1 ..]); return; } diff --git a/lib/std/zig/Server.zig b/lib/std/zig/Server.zig index 8bb61c0d54..7041778542 100644 --- a/lib/std/zig/Server.zig +++ b/lib/std/zig/Server.zig @@ -173,7 +173,7 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void { .bytes_len = @intCast(bytes_len), }); try s.out.writeStructEndian(eb_hdr, .little); - try s.out.writeArrayEndian(u32, error_bundle.extra, .little); + try s.out.writeSliceEndian(u32, error_bundle.extra, .little); try s.out.writeAll(error_bundle.string_bytes); try s.out.flush(); } @@ -198,8 +198,8 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void { .bytes_len = @intCast(bytes_len), }); try s.out.writeStructEndian(header, .little); - try s.out.writeArrayEndian(u32, test_metadata.names, .little); - try s.out.writeArrayEndian(u32, test_metadata.expected_panic_msgs, .little); + try s.out.writeSliceEndian(u32, test_metadata.names, .little); + try s.out.writeSliceEndian(u32, test_metadata.expected_panic_msgs, .little); try s.out.writeAll(test_metadata.string_bytes); try s.out.flush(); }