authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-17 12:29:32-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:27-07:00
logffb0e283d7aaaa896cd3db32ca11460ea63c8855
treec12b079906590b17d1edd0394b92ee4aa10c4ba7
parent3b390e4f139220ed11918524288238c289ce0c6d

build_runner: fix compile errors


27 files changed, 463 insertions(+), 362 deletions(-)

lib/compiler/build_runner.zig+15-17
...@@ -379,9 +379,11 @@ pub fn main() !void {...@@ -379,9 +379,11 @@ pub fn main() !void {
379 validateSystemLibraryOptions(builder);379 validateSystemLibraryOptions(builder);
380380
381 {381 {
382 var stdout_bw = std.fs.File.stdout().writer().buffered(&stdio_buffer);382 var fw = std.fs.File.stdout().writer();
383 if (help_menu) return usage(builder, &stdout_bw);383 var bw = fw.interface().buffered(&stdio_buffer);
384 if (steps_menu) return steps(builder, &stdout_bw);384 defer bw.flush() catch {};
385 if (help_menu) return usage(builder, &bw);
386 if (steps_menu) return steps(builder, &bw);
385 }387 }
386388
387 var run: Run = .{389 var run: Run = .{
...@@ -694,16 +696,13 @@ fn runStepNames(...@@ -694,16 +696,13 @@ fn runStepNames(
694 const ttyconf = run.ttyconf;696 const ttyconf = run.ttyconf;
695697
696 if (run.summary != .none) {698 if (run.summary != .none) {
697 var bw = std.debug.lockStdErr2(&stdio_buffer);699 const bw = std.debug.lockStderrWriter(&stdio_buffer);
698 defer {700 defer std.debug.unlockStderrWriter();
699 bw.flush() catch {};
700 std.debug.unlockStdErr();
701 }
702701
703 const total_count = success_count + failure_count + pending_count + skipped_count;702 const total_count = success_count + failure_count + pending_count + skipped_count;
704 ttyconf.setColor(&bw, .cyan) catch {};703 ttyconf.setColor(bw, .cyan) catch {};
705 bw.writeAll("Build Summary:") catch {};704 bw.writeAll("Build Summary:") catch {};
706 ttyconf.setColor(&bw, .reset) catch {};705 ttyconf.setColor(bw, .reset) catch {};
707 bw.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};706 bw.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
708 if (skipped_count > 0) bw.print("; {d} skipped", .{skipped_count}) catch {};707 if (skipped_count > 0) bw.print("; {d} skipped", .{skipped_count}) catch {};
709 if (failure_count > 0) bw.print("; {d} failed", .{failure_count}) catch {};708 if (failure_count > 0) bw.print("; {d} failed", .{failure_count}) catch {};
...@@ -713,8 +712,6 @@ fn runStepNames(...@@ -713,8 +712,6 @@ fn runStepNames(
713 if (test_fail_count > 0) bw.print("; {d} failed", .{test_fail_count}) catch {};712 if (test_fail_count > 0) bw.print("; {d} failed", .{test_fail_count}) catch {};
714 if (test_leak_count > 0) bw.print("; {d} leaked", .{test_leak_count}) catch {};713 if (test_leak_count > 0) bw.print("; {d} leaked", .{test_leak_count}) catch {};
715714
716 bw.writeByte('\n') catch {};
717
718 // Print a fancy tree with build results.715 // Print a fancy tree with build results.
719 var step_stack_copy = try step_stack.clone(gpa);716 var step_stack_copy = try step_stack.clone(gpa);
720 defer step_stack_copy.deinit(gpa);717 defer step_stack_copy.deinit(gpa);
...@@ -722,7 +719,7 @@ fn runStepNames(...@@ -722,7 +719,7 @@ fn runStepNames(
722 var print_node: PrintNode = .{ .parent = null };719 var print_node: PrintNode = .{ .parent = null };
723 if (step_names.len == 0) {720 if (step_names.len == 0) {
724 print_node.last = true;721 print_node.last = true;
725 printTreeStep(b, b.default_step, run, &bw, ttyconf, &print_node, &step_stack_copy) catch {};722 printTreeStep(b, b.default_step, run, bw, ttyconf, &print_node, &step_stack_copy) catch {};
726 } else {723 } else {
727 const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: {724 const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: {
728 var i: usize = step_names.len;725 var i: usize = step_names.len;
...@@ -741,9 +738,10 @@ fn runStepNames(...@@ -741,9 +738,10 @@ fn runStepNames(
741 for (step_names, 0..) |step_name, i| {738 for (step_names, 0..) |step_name, i| {
742 const tls = b.top_level_steps.get(step_name).?;739 const tls = b.top_level_steps.get(step_name).?;
743 print_node.last = i + 1 == last_index;740 print_node.last = i + 1 == last_index;
744 printTreeStep(b, &tls.step, run, &bw, ttyconf, &print_node, &step_stack_copy) catch {};741 printTreeStep(b, &tls.step, run, bw, ttyconf, &print_node, &step_stack_copy) catch {};
745 }742 }
746 }743 }
744 bw.writeByte('\n') catch {};
747 }745 }
748746
749 if (failure_count == 0) {747 if (failure_count == 0) {
...@@ -1129,11 +1127,11 @@ fn workerMakeOneStep(...@@ -1129,11 +1127,11 @@ fn workerMakeOneStep(
1129 const show_stderr = s.result_stderr.len > 0;1127 const show_stderr = s.result_stderr.len > 0;
11301128
1131 if (show_error_msgs or show_compile_errors or show_stderr) {1129 if (show_error_msgs or show_compile_errors or show_stderr) {
1132 var bw = std.debug.lockStdErr2(&stdio_buffer);1130 const bw = std.debug.lockStderrWriter(&stdio_buffer);
1133 defer std.debug.unlockStdErr();1131 defer std.debug.unlockStderrWriter();
11341132
1135 const gpa = b.allocator;1133 const gpa = b.allocator;
1136 printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, &bw, run.prominent_compile_errors) catch {};1134 printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, bw, run.prominent_compile_errors) catch {};
1137 }1135 }
11381136
1139 handle_result: {1137 handle_result: {
lib/std/Build.zig+11-11
...@@ -2766,7 +2766,7 @@ fn dumpBadDirnameHelp(...@@ -2766,7 +2766,7 @@ fn dumpBadDirnameHelp(
2766 comptime msg: []const u8,2766 comptime msg: []const u8,
2767 args: anytype,2767 args: anytype,
2768) anyerror!void {2768) anyerror!void {
2769 const w = debug.lockStderrWriter();2769 const w = debug.lockStderrWriter(&.{});
2770 defer debug.unlockStderrWriter();2770 defer debug.unlockStderrWriter();
27712771
2772 const stderr: fs.File = .stderr();2772 const stderr: fs.File = .stderr();
...@@ -2802,9 +2802,9 @@ pub fn dumpBadGetPathHelp(...@@ -2802,9 +2802,9 @@ pub fn dumpBadGetPathHelp(
2802 src_builder: *Build,2802 src_builder: *Build,
2803 asking_step: ?*Step,2803 asking_step: ?*Step,
2804) anyerror!void {2804) anyerror!void {
2805 var buffered_writer = stderr.writer().unbuffered();2805 var fw = stderr.writer();
2806 const w = &buffered_writer;2806 var bw = fw.interface().unbuffered();
2807 try w.print(2807 try bw.print(
2808 \\getPath() was called on a GeneratedFile that wasn't built yet.2808 \\getPath() was called on a GeneratedFile that wasn't built yet.
2809 \\ source package path: {s}2809 \\ source package path: {s}
2810 \\ Is there a missing Step dependency on step '{s}'?2810 \\ Is there a missing Step dependency on step '{s}'?
...@@ -2815,21 +2815,21 @@ pub fn dumpBadGetPathHelp(...@@ -2815,21 +2815,21 @@ pub fn dumpBadGetPathHelp(
2815 });2815 });
28162816
2817 const tty_config = std.io.tty.detectConfig(stderr);2817 const tty_config = std.io.tty.detectConfig(stderr);
2818 tty_config.setColor(w, .red) catch {};2818 tty_config.setColor(&bw, .red) catch {};
2819 try stderr.writeAll(" The step was created by this stack trace:\n");2819 try stderr.writeAll(" The step was created by this stack trace:\n");
2820 tty_config.setColor(w, .reset) catch {};2820 tty_config.setColor(&bw, .reset) catch {};
28212821
2822 s.dump(stderr);2822 s.dump(stderr);
2823 if (asking_step) |as| {2823 if (asking_step) |as| {
2824 tty_config.setColor(w, .red) catch {};2824 tty_config.setColor(&bw, .red) catch {};
2825 try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});2825 try bw.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
2826 tty_config.setColor(w, .reset) catch {};2826 tty_config.setColor(&bw, .reset) catch {};
28272827
2828 as.dump(stderr);2828 as.dump(stderr);
2829 }2829 }
2830 tty_config.setColor(w, .red) catch {};2830 tty_config.setColor(&bw, .red) catch {};
2831 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");2831 try stderr.writeAll(" Hope that helps. Proceeding to panic.\n");
2832 tty_config.setColor(w, .reset) catch {};2832 tty_config.setColor(&bw, .reset) catch {};
2833}2833}
28342834
2835pub const InstallDir = union(enum) {2835pub const InstallDir = union(enum) {
lib/std/Build/Cache.zig+4-3
...@@ -68,7 +68,7 @@ const PrefixedPath = struct {...@@ -68,7 +68,7 @@ const PrefixedPath = struct {
6868
69fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {69fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {
70 const gpa = cache.gpa;70 const gpa = cache.gpa;
71 const resolved_path = try fs.path.resolve(gpa, &[_][]const u8{file_path});71 const resolved_path = try fs.path.resolve(gpa, &.{file_path});
72 errdefer gpa.free(resolved_path);72 errdefer gpa.free(resolved_path);
73 return findPrefixResolved(cache, resolved_path);73 return findPrefixResolved(cache, resolved_path);
74}74}
...@@ -132,7 +132,7 @@ pub const Hasher = crypto.auth.siphash.SipHash128(1, 3);...@@ -132,7 +132,7 @@ pub const Hasher = crypto.auth.siphash.SipHash128(1, 3);
132/// Initial state with random bytes, that can be copied.132/// Initial state with random bytes, that can be copied.
133/// Refresh this with new random bytes when the manifest133/// Refresh this with new random bytes when the manifest
134/// format is modified in a non-backwards-compatible way.134/// format is modified in a non-backwards-compatible way.
135pub const hasher_init: Hasher = Hasher.init(&[_]u8{135pub const hasher_init: Hasher = Hasher.init(&.{
136 0x33, 0x52, 0xa2, 0x84,136 0x33, 0x52, 0xa2, 0x84,
137 0xcf, 0x17, 0x56, 0x57,137 0xcf, 0x17, 0x56, 0x57,
138 0x01, 0xbb, 0xcd, 0xe4,138 0x01, 0xbb, 0xcd, 0xe4,
...@@ -1143,7 +1143,8 @@ pub const Manifest = struct {...@@ -1143,7 +1143,8 @@ pub const Manifest = struct {
1143 }1143 }
11441144
1145 try manifest_file.setEndPos(contents.items.len);1145 try manifest_file.setEndPos(contents.items.len);
1146 try manifest_file.pwriteAll(contents.items, 0);1146 var pos: usize = 0;
1147 while (pos < contents.items.len) pos += try manifest_file.pwrite(contents.items[pos..], pos);
1147 }1148 }
11481149
1149 if (self.want_shared_lock) {1150 if (self.want_shared_lock) {
lib/std/Build/Fuzz.zig+2-2
...@@ -124,7 +124,7 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par...@@ -124,7 +124,7 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par
124 const show_stderr = compile.step.result_stderr.len > 0;124 const show_stderr = compile.step.result_stderr.len > 0;
125125
126 if (show_error_msgs or show_compile_errors or show_stderr) {126 if (show_error_msgs or show_compile_errors or show_stderr) {
127 const bw = std.debug.lockStderrWriter();127 const bw = std.debug.lockStderrWriter(&.{});
128 defer std.debug.unlockStderrWriter();128 defer std.debug.unlockStderrWriter();
129 build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, bw, false) catch {};129 build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, bw, false) catch {};
130 }130 }
...@@ -151,7 +151,7 @@ fn fuzzWorkerRun(...@@ -151,7 +151,7 @@ fn fuzzWorkerRun(
151151
152 run.rerunInFuzzMode(web_server, unit_test_index, prog_node) catch |err| switch (err) {152 run.rerunInFuzzMode(web_server, unit_test_index, prog_node) catch |err| switch (err) {
153 error.MakeFailed => {153 error.MakeFailed => {
154 const bw = std.debug.lockStderrWriter();154 const bw = std.debug.lockStderrWriter(&.{});
155 defer std.debug.unlockStderrWriter();155 defer std.debug.unlockStderrWriter();
156 build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, bw, false) catch {};156 build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, bw, false) catch {};
157 return;157 return;
lib/std/Build/Fuzz/WebServer.zig+10-2
...@@ -98,8 +98,16 @@ fn now(s: *const WebServer) i64 {...@@ -98,8 +98,16 @@ fn now(s: *const WebServer) i64 {
98fn accept(ws: *WebServer, connection: std.net.Server.Connection) void {98fn accept(ws: *WebServer, connection: std.net.Server.Connection) void {
99 defer connection.stream.close();99 defer connection.stream.close();
100100
101 var read_buffer: [0x4000]u8 = undefined;101 var sr = connection.stream.reader();
102 var server = std.http.Server.init(connection, &read_buffer);102 var rb: [0x4000]u8 = undefined;
103 var br: std.io.BufferedReader = undefined;
104 br.init(sr.interface(), &rb);
105
106 var sw = connection.stream.writer();
107 var wb: [0x4000]u8 = undefined;
108 var bw = sw.interface().buffered(&wb);
109
110 var server: std.http.Server = .init(&br, &bw);
103 var web_socket: std.http.WebSocket = undefined;111 var web_socket: std.http.WebSocket = undefined;
104 var send_buffer: [0x4000]u8 = undefined;112 var send_buffer: [0x4000]u8 = undefined;
105 var ws_recv_buffer: [0x4000]u8 align(4) = undefined;113 var ws_recv_buffer: [0x4000]u8 align(4) = undefined;
lib/std/Build/Step.zig+6-5
...@@ -287,7 +287,8 @@ pub fn cast(step: *Step, comptime T: type) ?*T {...@@ -287,7 +287,8 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
287287
288/// For debugging purposes, prints identifying information about this Step.288/// For debugging purposes, prints identifying information about this Step.
289pub fn dump(step: *Step, file: std.fs.File) void {289pub fn dump(step: *Step, file: std.fs.File) void {
290 var bw = file.writer().unbuffered();290 var fw = file.writer();
291 var bw = fw.interface().unbuffered();
291 const tty_config = std.io.tty.detectConfig(file);292 const tty_config = std.io.tty.detectConfig(file);
292 const debug_info = std.debug.getSelfDebugInfo() catch |err| {293 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
293 bw.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{294 bw.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
...@@ -469,7 +470,7 @@ pub fn evalZigProcess(...@@ -469,7 +470,7 @@ pub fn evalZigProcess(
469 // This is intentionally printed for failure on the first build but not for470 // This is intentionally printed for failure on the first build but not for
470 // subsequent rebuilds.471 // subsequent rebuilds.
471 if (s.result_error_bundle.errorMessageCount() > 0) {472 if (s.result_error_bundle.errorMessageCount() > 0) {
472 return s.fail("the following command failed with {d} compilation errors:\n{s}\n", .{473 return s.fail("the following command failed with {d} compilation errors:\n{s}", .{
473 s.result_error_bundle.errorMessageCount(),474 s.result_error_bundle.errorMessageCount(),
474 try allocPrintCmd(arena, null, argv),475 try allocPrintCmd(arena, null, argv),
475 });476 });
...@@ -689,7 +690,7 @@ pub inline fn handleChildProcUnsupported(...@@ -689,7 +690,7 @@ pub inline fn handleChildProcUnsupported(
689) error{ OutOfMemory, MakeFailed }!void {690) error{ OutOfMemory, MakeFailed }!void {
690 if (!std.process.can_spawn) {691 if (!std.process.can_spawn) {
691 return s.fail(692 return s.fail(
692 "unable to execute the following command: host cannot spawn child processes\n{s}\n",693 "unable to execute the following command: host cannot spawn child processes\n{s}",
693 .{try allocPrintCmd(s.owner.allocator, opt_cwd, argv)},694 .{try allocPrintCmd(s.owner.allocator, opt_cwd, argv)},
694 );695 );
695 }696 }
...@@ -706,14 +707,14 @@ pub fn handleChildProcessTerm(...@@ -706,14 +707,14 @@ pub fn handleChildProcessTerm(
706 .Exited => |code| {707 .Exited => |code| {
707 if (code != 0) {708 if (code != 0) {
708 return s.fail(709 return s.fail(
709 "the following command exited with error code {d}:\n{s}\n",710 "the following command exited with error code {d}:\n{s}",
710 .{ code, try allocPrintCmd(arena, opt_cwd, argv) },711 .{ code, try allocPrintCmd(arena, opt_cwd, argv) },
711 );712 );
712 }713 }
713 },714 },
714 .Signal, .Stopped, .Unknown => {715 .Signal, .Stopped, .Unknown => {
715 return s.fail(716 return s.fail(
716 "the following command terminated unexpectedly:\n{s}\n",717 "the following command terminated unexpectedly:\n{s}",
717 .{try allocPrintCmd(arena, opt_cwd, argv)},718 .{try allocPrintCmd(arena, opt_cwd, argv)},
718 );719 );
719 },720 },
lib/std/Build/Step/CheckObject.zig+1-1
...@@ -1791,7 +1791,7 @@ const ElfDumper = struct {...@@ -1791,7 +1791,7 @@ const ElfDumper = struct {
1791 .p64 => @sizeOf(u64),1791 .p64 => @sizeOf(u64),
1792 };1792 };
1793 try br.discard(num * ptr_size);1793 try br.discard(num * ptr_size);
1794 const strtab = try br.peekAll(0);1794 const strtab = try br.peekGreedy(0);
17951795
1796 assert(ctx.symtab.len == 0);1796 assert(ctx.symtab.len == 0);
1797 ctx.symtab = try ctx.gpa.alloc(ArSymtabEntry, num);1797 ctx.symtab = try ctx.gpa.alloc(ArSymtabEntry, num);
lib/std/Build/Step/Run.zig+14-7
...@@ -73,9 +73,12 @@ skip_foreign_checks: bool,...@@ -73,9 +73,12 @@ skip_foreign_checks: bool,
73/// external executor (such as qemu) but not fail if the executor is unavailable.73/// external executor (such as qemu) but not fail if the executor is unavailable.
74failing_to_execute_foreign_is_an_error: bool,74failing_to_execute_foreign_is_an_error: bool,
7575
76/// Deprecated for `stdio_limit`.
77max_stdio_size: usize,
78
76/// If stderr or stdout exceeds this amount, the child process is killed and79/// If stderr or stdout exceeds this amount, the child process is killed and
77/// the step fails.80/// the step fails.
78max_stdio_size: usize,81stdio_limit: std.io.Reader.Limit,
7982
80captured_stdout: ?*Output,83captured_stdout: ?*Output,
81captured_stderr: ?*Output,84captured_stderr: ?*Output,
...@@ -186,6 +189,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {...@@ -186,6 +189,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {
186 .skip_foreign_checks = false,189 .skip_foreign_checks = false,
187 .failing_to_execute_foreign_is_an_error = true,190 .failing_to_execute_foreign_is_an_error = true,
188 .max_stdio_size = 10 * 1024 * 1024,191 .max_stdio_size = 10 * 1024 * 1024,
192 .stdio_limit = .unlimited,
189 .captured_stdout = null,193 .captured_stdout = null,
190 .captured_stderr = null,194 .captured_stderr = null,
191 .dep_output_file = null,195 .dep_output_file = null,
...@@ -1772,6 +1776,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {...@@ -1772,6 +1776,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
1772 var stdout_bytes: ?[]const u8 = null;1776 var stdout_bytes: ?[]const u8 = null;
1773 var stderr_bytes: ?[]const u8 = null;1777 var stderr_bytes: ?[]const u8 = null;
17741778
1779 run.stdio_limit = .limited(run.stdio_limit.min(run.max_stdio_size));
1775 if (child.stdout) |stdout| {1780 if (child.stdout) |stdout| {
1776 if (child.stderr) |stderr| {1781 if (child.stderr) |stderr| {
1777 var poller = std.io.poll(arena, enum { stdout, stderr }, .{1782 var poller = std.io.poll(arena, enum { stdout, stderr }, .{
...@@ -1781,19 +1786,21 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {...@@ -1781,19 +1786,21 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
1781 defer poller.deinit();1786 defer poller.deinit();
17821787
1783 while (try poller.poll()) {1788 while (try poller.poll()) {
1784 if (poller.fifo(.stdout).count > run.max_stdio_size)1789 if (run.stdio_limit.toInt()) |limit| {
1785 return error.StdoutStreamTooLong;1790 if (poller.fifo(.stderr).count > limit)
1786 if (poller.fifo(.stderr).count > run.max_stdio_size)1791 return error.StdoutStreamTooLong;
1787 return error.StderrStreamTooLong;1792 if (poller.fifo(.stderr).count > limit)
1793 return error.StderrStreamTooLong;
1794 }
1788 }1795 }
17891796
1790 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();1797 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
1791 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();1798 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
1792 } else {1799 } else {
1793 stdout_bytes = try stdout.reader().readAlloc(arena, run.max_stdio_size);1800 stdout_bytes = try stdout.readToEndAlloc(arena, run.stdio_limit);
1794 }1801 }
1795 } else if (child.stderr) |stderr| {1802 } else if (child.stderr) |stderr| {
1796 stderr_bytes = try stderr.reader().readAlloc(arena, run.max_stdio_size);1803 stderr_bytes = try stderr.readToEndAlloc(arena, run.stdio_limit);
1797 }1804 }
17981805
1799 if (stderr_bytes) |bytes| if (bytes.len > 0) {1806 if (stderr_bytes) |bytes| if (bytes.len > 0) {
lib/std/crypto/siphash.zig+32-7
...@@ -239,16 +239,41 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -239,16 +239,41 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
239 return State.hash(msg, key);239 return State.hash(msg, key);
240 }240 }
241241
242 pub const Error = error{};242 pub fn writer(self: *Self) std.io.Writer {
243 pub const Writer = std.io.Writer(*Self, Error, write);243 return .{
244 .context = self,
245 .vtable = &.{
246 .writeSplat = &writeSplat,
247 .writeFile = &writeFile,
248 },
249 };
250 }
244251
245 fn write(self: *Self, bytes: []const u8) Error!usize {252 fn writeSplat(ctx: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
246 self.update(bytes);253 const self: *Self = @alignCast(@ptrCast(ctx));
247 return bytes.len;254 var len: usize = 0;
255 for (0..splat) |_| for (data) |slice| {
256 self.update(slice);
257 len += slice.len;
258 };
259 return len;
248 }260 }
249261
250 pub fn writer(self: *Self) Writer {262 fn writeFile(
251 return .{ .context = self };263 ctx: ?*anyopaque,
264 file: std.fs.File,
265 offset: std.io.Writer.Offset,
266 limit: std.io.Writer.Limit,
267 headers_and_trailers: []const []const u8,
268 headers_len: usize,
269 ) anyerror!usize {
270 _ = ctx;
271 _ = file;
272 _ = offset;
273 _ = limit;
274 _ = headers_and_trailers;
275 _ = headers_len;
276 return error.Unimplemented;
252 }277 }
253 };278 };
254}279}
lib/std/fs/Dir.zig+1-1
...@@ -2052,7 +2052,7 @@ pub fn readFileIntoArrayList(...@@ -2052,7 +2052,7 @@ pub fn readFileIntoArrayList(
2052 try list.ensureUnusedCapacity(gpa, std.math.cast(usize, size) orelse return error.FileTooBig);2052 try list.ensureUnusedCapacity(gpa, std.math.cast(usize, size) orelse return error.FileTooBig);
2053 } else |err| switch (err) {2053 } else |err| switch (err) {
2054 // Ignore most errors; size hint is only an optimization.2054 // Ignore most errors; size hint is only an optimization.
2055 error.Unseekable, error.Unexpected, error.AccessDenied, error.PermissionDenied => {},2055 error.Unexpected, error.AccessDenied, error.PermissionDenied => {},
2056 else => |e| return e,2056 else => |e| return e,
2057 }2057 }
20582058
lib/std/http/Client.zig+2-2
...@@ -115,14 +115,14 @@ pub const ConnectionPool = struct {...@@ -115,14 +115,14 @@ pub const ConnectionPool = struct {
115 ///115 ///
116 /// Threadsafe.116 /// Threadsafe.
117 pub fn release(pool: *ConnectionPool, allocator: Allocator, connection: *Connection) void {117 pub fn release(pool: *ConnectionPool, allocator: Allocator, connection: *Connection) void {
118 if (connection.closing) return connection.destroy(allocator);118 if (connection.closing) return connection.destroy();
119119
120 pool.mutex.lock();120 pool.mutex.lock();
121 defer pool.mutex.unlock();121 defer pool.mutex.unlock();
122122
123 pool.used.remove(&connection.pool_node);123 pool.used.remove(&connection.pool_node);
124124
125 if (pool.free_size == 0) return connection.destroy(allocator);125 if (pool.free_size == 0) return connection.destroy();
126126
127 if (pool.free_len >= pool.free_size) {127 if (pool.free_len >= pool.free_size) {
128 const popped: *Connection = @fieldParentPtr("pool_node", pool.free.popFirst().?);128 const popped: *Connection = @fieldParentPtr("pool_node", pool.free.popFirst().?);
lib/std/http/Server.zig+42-30
...@@ -21,6 +21,9 @@ out: *std.io.BufferedWriter,...@@ -21,6 +21,9 @@ out: *std.io.BufferedWriter,
21state: State,21state: State,
22head_parse_err: Request.Head.ParseError,22head_parse_err: Request.Head.ParseError,
2323
24/// being deleted...
25next_request_start: usize = 0,
26
24pub const State = enum {27pub const State = enum {
25 /// The connection is available to be used for the first time, or reused.28 /// The connection is available to be used for the first time, or reused.
26 ready,29 ready,
...@@ -45,6 +48,7 @@ pub fn init(in: *std.io.BufferedReader, out: *std.io.BufferedWriter) Server {...@@ -45,6 +48,7 @@ pub fn init(in: *std.io.BufferedReader, out: *std.io.BufferedWriter) Server {
45 .in = in,48 .in = in,
46 .out = out,49 .out = out,
47 .state = .ready,50 .state = .ready,
51 .head_parse_err = undefined,
48 };52 };
49}53}
5054
...@@ -63,7 +67,7 @@ pub const ReceiveHeadError = error{...@@ -63,7 +67,7 @@ pub const ReceiveHeadError = error{
63 /// In other words, a keep-alive connection was finally closed.67 /// In other words, a keep-alive connection was finally closed.
64 HttpConnectionClosing,68 HttpConnectionClosing,
65 /// Transitive error occurred reading from `in`.69 /// Transitive error occurred reading from `in`.
66 ReadFailure,70 ReadFailed,
67};71};
6872
69/// The header bytes reference the internal storage of `in`, which are73/// The header bytes reference the internal storage of `in`, which are
...@@ -73,7 +77,7 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {...@@ -73,7 +77,7 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {
73 s.state = .received_head;77 s.state = .received_head;
74 errdefer s.state = .receiving_head;78 errdefer s.state = .receiving_head;
7579
76 const in = &s.in;80 const in = s.in;
77 var hp: http.HeadParser = .{};81 var hp: http.HeadParser = .{};
78 var head_end: usize = 0;82 var head_end: usize = 0;
7983
...@@ -84,7 +88,7 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {...@@ -84,7 +88,7 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {
84 0 => return error.HttpConnectionClosing,88 0 => return error.HttpConnectionClosing,
85 else => return error.HttpRequestTruncated,89 else => return error.HttpRequestTruncated,
86 },90 },
87 error.ReadFailure => return error.ReadFailure,91 error.ReadFailed => return error.ReadFailed,
88 };92 };
89 head_end += hp.feed(buf[head_end..]);93 head_end += hp.feed(buf[head_end..]);
90 if (hp.state == .finished) return .{94 if (hp.state == .finished) return .{
...@@ -279,7 +283,7 @@ pub const Request = struct {...@@ -279,7 +283,7 @@ pub const Request = struct {
279 };283 };
280284
281 pub fn iterateHeaders(r: *Request) http.HeaderIterator {285 pub fn iterateHeaders(r: *Request) http.HeaderIterator {
282 return http.HeaderIterator.init(r.in.bufferContents()[0..r.head_end]);286 return http.HeaderIterator.init(r.server.in.bufferContents()[0..r.head_end]);
283 }287 }
284288
285 test iterateHeaders {289 test iterateHeaders {
...@@ -398,8 +402,7 @@ pub const Request = struct {...@@ -398,8 +402,7 @@ pub const Request = struct {
398 h.appendSliceAssumeCapacity("HTTP/1.1 417 Expectation Failed\r\n");402 h.appendSliceAssumeCapacity("HTTP/1.1 417 Expectation Failed\r\n");
399 if (!keep_alive) h.appendSliceAssumeCapacity("connection: close\r\n");403 if (!keep_alive) h.appendSliceAssumeCapacity("connection: close\r\n");
400 h.appendSliceAssumeCapacity("content-length: 0\r\n\r\n");404 h.appendSliceAssumeCapacity("content-length: 0\r\n\r\n");
401 var w = request.server.connection.stream.writer().unbuffered();405 try request.server.out.writeAll(h.items);
402 try w.writeAll(h.items);
403 return;406 return;
404 }407 }
405 h.printAssumeCapacity("{s} {d} {s}\r\n", .{408 h.printAssumeCapacity("{s} {d} {s}\r\n", .{
...@@ -472,8 +475,7 @@ pub const Request = struct {...@@ -472,8 +475,7 @@ pub const Request = struct {
472 }475 }
473 }476 }
474477
475 var w = request.server.connection.stream.writer().unbuffered();478 try request.server.out.writeVecAll(iovecs[0..iovecs_len]);
476 try w.writevAll(iovecs[0..iovecs_len]);
477 }479 }
478480
479 pub const RespondStreamingOptions = struct {481 pub const RespondStreamingOptions = struct {
...@@ -553,7 +555,7 @@ pub const Request = struct {...@@ -553,7 +555,7 @@ pub const Request = struct {
553 };555 };
554556
555 return .{557 return .{
556 .stream = request.server.connection.stream,558 .out = request.server.out,
557 .send_buffer = options.send_buffer,559 .send_buffer = options.send_buffer,
558 .send_buffer_start = 0,560 .send_buffer_start = 0,
559 .send_buffer_end = h.items.len,561 .send_buffer_end = h.items.len,
...@@ -577,7 +579,7 @@ pub const Request = struct {...@@ -577,7 +579,7 @@ pub const Request = struct {
577 ctx: ?*anyopaque,579 ctx: ?*anyopaque,
578 bw: *std.io.BufferedWriter,580 bw: *std.io.BufferedWriter,
579 limit: std.io.Reader.Limit,581 limit: std.io.Reader.Limit,
580 ) std.io.Reader.Error!std.io.Reader.Status {582 ) std.io.Reader.Error!usize {
581 const request: *Request = @alignCast(@ptrCast(ctx));583 const request: *Request = @alignCast(@ptrCast(ctx));
582 _ = request;584 _ = request;
583 _ = bw;585 _ = bw;
...@@ -585,13 +587,20 @@ pub const Request = struct {...@@ -585,13 +587,20 @@ pub const Request = struct {
585 @panic("TODO");587 @panic("TODO");
586 }588 }
587589
588 fn contentLengthReader_readv(ctx: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize {590 fn contentLengthReader_readVec(ctx: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize {
589 const request: *Request = @alignCast(@ptrCast(ctx));591 const request: *Request = @alignCast(@ptrCast(ctx));
590 _ = request;592 _ = request;
591 _ = data;593 _ = data;
592 @panic("TODO");594 @panic("TODO");
593 }595 }
594596
597 fn contentLengthReader_discard(ctx: ?*anyopaque, limit: std.io.Reader.Limit) std.io.Reader.Error!usize {
598 const request: *Request = @alignCast(@ptrCast(ctx));
599 _ = request;
600 _ = limit;
601 @panic("TODO");
602 }
603
595 fn chunkedReader_read(604 fn chunkedReader_read(
596 ctx: ?*anyopaque,605 ctx: ?*anyopaque,
597 bw: *std.io.BufferedWriter,606 bw: *std.io.BufferedWriter,
...@@ -604,13 +613,20 @@ pub const Request = struct {...@@ -604,13 +613,20 @@ pub const Request = struct {
604 @panic("TODO");613 @panic("TODO");
605 }614 }
606615
607 fn chunkedReader_readv(ctx: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize {616 fn chunkedReader_readVec(ctx: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize {
608 const request: *Request = @alignCast(@ptrCast(ctx));617 const request: *Request = @alignCast(@ptrCast(ctx));
609 _ = request;618 _ = request;
610 _ = data;619 _ = data;
611 @panic("TODO");620 @panic("TODO");
612 }621 }
613622
623 fn chunkedReader_discard(ctx: ?*anyopaque, limit: std.io.Reader.Limit) std.io.Reader.Error!usize {
624 const request: *Request = @alignCast(@ptrCast(ctx));
625 _ = request;
626 _ = limit;
627 @panic("TODO");
628 }
629
614 fn read_cl(context: *const anyopaque, buffer: []u8) ReadError!usize {630 fn read_cl(context: *const anyopaque, buffer: []u8) ReadError!usize {
615 const request: *Request = @alignCast(@ptrCast(context));631 const request: *Request = @alignCast(@ptrCast(context));
616 const s = request.server;632 const s = request.server;
...@@ -751,8 +767,7 @@ pub const Request = struct {...@@ -751,8 +767,7 @@ pub const Request = struct {
751767
752 if (request.head.expect) |expect| {768 if (request.head.expect) |expect| {
753 if (mem.eql(u8, expect, "100-continue")) {769 if (mem.eql(u8, expect, "100-continue")) {
754 var w = request.server.connection.stream.writer().unbuffered();770 try request.server.out.writeAll("HTTP/1.1 100 Continue\r\n\r\n");
755 try w.writeAll("HTTP/1.1 100 Continue\r\n\r\n");
756 request.head.expect = null;771 request.head.expect = null;
757 } else {772 } else {
758 return error.HttpExpectationFailed;773 return error.HttpExpectationFailed;
...@@ -766,7 +781,8 @@ pub const Request = struct {...@@ -766,7 +781,8 @@ pub const Request = struct {
766 .context = request,781 .context = request,
767 .vtable = &.{782 .vtable = &.{
768 .read = &chunkedReader_read,783 .read = &chunkedReader_read,
769 .readv = &chunkedReader_readv,784 .readVec = &chunkedReader_readVec,
785 .discard = &chunkedReader_discard,
770 },786 },
771 };787 };
772 },788 },
...@@ -778,7 +794,8 @@ pub const Request = struct {...@@ -778,7 +794,8 @@ pub const Request = struct {
778 .context = request,794 .context = request,
779 .vtable = &.{795 .vtable = &.{
780 .read = &contentLengthReader_read,796 .read = &contentLengthReader_read,
781 .readv = &contentLengthReader_readv,797 .readVec = &contentLengthReader_readVec,
798 .discard = &contentLengthReader_discard,
782 },799 },
783 };800 };
784 },801 },
...@@ -801,7 +818,7 @@ pub const Request = struct {...@@ -801,7 +818,7 @@ pub const Request = struct {
801 if (keep_alive and request.head.keep_alive) switch (s.state) {818 if (keep_alive and request.head.keep_alive) switch (s.state) {
802 .received_head => {819 .received_head => {
803 const r = request.reader() catch return false;820 const r = request.reader() catch return false;
804 _ = r.discardUntilEnd() catch return false;821 _ = r.discardRemaining() catch return false;
805 assert(s.state == .ready);822 assert(s.state == .ready);
806 return true;823 return true;
807 },824 },
...@@ -819,7 +836,7 @@ pub const Request = struct {...@@ -819,7 +836,7 @@ pub const Request = struct {
819};836};
820837
821pub const Response = struct {838pub const Response = struct {
822 stream: net.Stream,839 out: *std.io.BufferedWriter,
823 send_buffer: []u8,840 send_buffer: []u8,
824 /// Index of the first byte in `send_buffer`.841 /// Index of the first byte in `send_buffer`.
825 /// This is 0 unless a short write happens in `write`.842 /// This is 0 unless a short write happens in `write`.
...@@ -909,7 +926,7 @@ pub const Response = struct {...@@ -909,7 +926,7 @@ pub const Response = struct {
909 _ = limit;926 _ = limit;
910 _ = headers_and_trailers;927 _ = headers_and_trailers;
911 _ = headers_len;928 _ = headers_len;
912 return error.Unimplemented;929 @panic("TODO");
913 }930 }
914931
915 fn cl_write(context: ?*anyopaque, bytes: []const u8) std.io.Writer.Error!usize {932 fn cl_write(context: ?*anyopaque, bytes: []const u8) std.io.Writer.Error!usize {
...@@ -932,8 +949,7 @@ pub const Response = struct {...@@ -932,8 +949,7 @@ pub const Response = struct {
932 r.send_buffer[r.send_buffer_start..][0..send_buffer_len],949 r.send_buffer[r.send_buffer_start..][0..send_buffer_len],
933 bytes,950 bytes,
934 };951 };
935 var w = r.stream.writer().unbuffered();952 const n = try r.out.writeVec(&iovecs);
936 const n = try w.writev(&iovecs);
937953
938 if (n >= send_buffer_len) {954 if (n >= send_buffer_len) {
939 // It was enough to reset the buffer.955 // It was enough to reset the buffer.
...@@ -976,7 +992,7 @@ pub const Response = struct {...@@ -976,7 +992,7 @@ pub const Response = struct {
976 _ = limit;992 _ = limit;
977 _ = headers_and_trailers;993 _ = headers_and_trailers;
978 _ = headers_len;994 _ = headers_len;
979 return error.Unimplemented; // TODO lower to a call to writeFile on the output995 @panic("TODO"); // TODO lower to a call to writeFile on the output
980 }996 }
981997
982 fn chunked_write(context: ?*anyopaque, bytes: []const u8) std.io.Writer.Error!usize {998 fn chunked_write(context: ?*anyopaque, bytes: []const u8) std.io.Writer.Error!usize {
...@@ -1001,8 +1017,7 @@ pub const Response = struct {...@@ -1001,8 +1017,7 @@ pub const Response = struct {
1001 };1017 };
1002 // TODO make this writev instead of writevAll, which involves1018 // TODO make this writev instead of writevAll, which involves
1003 // complicating the logic of this function.1019 // complicating the logic of this function.
1004 var w = r.stream.writer().unbuffered();1020 try r.out.writeVecAll(&iovecs);
1005 try w.writevAll(&iovecs);
1006 r.send_buffer_start = 0;1021 r.send_buffer_start = 0;
1007 r.send_buffer_end = 0;1022 r.send_buffer_end = 0;
1008 r.chunk_len = 0;1023 r.chunk_len = 0;
...@@ -1036,8 +1051,7 @@ pub const Response = struct {...@@ -1036,8 +1051,7 @@ pub const Response = struct {
1036 }1051 }
10371052
1038 fn flush_cl(r: *Response) std.io.Writer.Error!void {1053 fn flush_cl(r: *Response) std.io.Writer.Error!void {
1039 var w = r.stream.writer().unbuffered();1054 try r.out.writeAll(r.send_buffer[r.send_buffer_start..r.send_buffer_end]);
1040 try w.writeAll(r.send_buffer[r.send_buffer_start..r.send_buffer_end]);
1041 r.send_buffer_start = 0;1055 r.send_buffer_start = 0;
1042 r.send_buffer_end = 0;1056 r.send_buffer_end = 0;
1043 }1057 }
...@@ -1050,8 +1064,7 @@ pub const Response = struct {...@@ -1050,8 +1064,7 @@ pub const Response = struct {
1050 const http_headers = r.send_buffer[r.send_buffer_start .. r.send_buffer_end - r.chunk_len];1064 const http_headers = r.send_buffer[r.send_buffer_start .. r.send_buffer_end - r.chunk_len];
10511065
1052 if (r.elide_body) {1066 if (r.elide_body) {
1053 var w = r.stream.writer().unbuffered();1067 try r.out.writeAll(http_headers);
1054 try w.writeAll(http_headers);
1055 r.send_buffer_start = 0;1068 r.send_buffer_start = 0;
1056 r.send_buffer_end = 0;1069 r.send_buffer_end = 0;
1057 r.chunk_len = 0;1070 r.chunk_len = 0;
...@@ -1102,8 +1115,7 @@ pub const Response = struct {...@@ -1102,8 +1115,7 @@ pub const Response = struct {
1102 iovecs_len += 1;1115 iovecs_len += 1;
1103 }1116 }
11041117
1105 var w = r.stream.writer().unbuffered();1118 try r.out.writeVecAll(iovecs[0..iovecs_len]);
1106 try w.writevAll(iovecs[0..iovecs_len]);
1107 r.send_buffer_start = 0;1119 r.send_buffer_start = 0;
1108 r.send_buffer_end = 0;1120 r.send_buffer_end = 0;
1109 r.chunk_len = 0;1121 r.chunk_len = 0;
lib/std/http/WebSocket.zig+2-4
...@@ -194,16 +194,14 @@ fn recvReadInt(ws: *WebSocket, comptime I: type) !I {...@@ -194,16 +194,14 @@ fn recvReadInt(ws: *WebSocket, comptime I: type) !I {
194 };194 };
195}195}
196196
197pub const WriteError = std.http.Server.Response.WriteError;197pub fn writeMessage(ws: *WebSocket, message: []const u8, opcode: Opcode) std.io.Writer.Error!void {
198
199pub fn writeMessage(ws: *WebSocket, message: []const u8, opcode: Opcode) WriteError!void {
200 const iovecs: [1]std.posix.iovec_const = .{198 const iovecs: [1]std.posix.iovec_const = .{
201 .{ .base = message.ptr, .len = message.len },199 .{ .base = message.ptr, .len = message.len },
202 };200 };
203 return writeMessagev(ws, &iovecs, opcode);201 return writeMessagev(ws, &iovecs, opcode);
204}202}
205203
206pub fn writeMessagev(ws: *WebSocket, message: []const std.posix.iovec_const, opcode: Opcode) WriteError!void {204pub fn writeMessagev(ws: *WebSocket, message: []const std.posix.iovec_const, opcode: Opcode) std.io.Writer.Error!void {
207 const total_len = l: {205 const total_len = l: {
208 var total_len: u64 = 0;206 var total_len: u64 = 0;
209 for (message) |iovec| total_len += iovec.len;207 for (message) |iovec| total_len += iovec.len;
lib/std/io/AllocatingWriter.zig+2-3
...@@ -93,9 +93,8 @@ pub fn toArrayList(aw: *AllocatingWriter) std.ArrayListUnmanaged(u8) {...@@ -93,9 +93,8 @@ pub fn toArrayList(aw: *AllocatingWriter) std.ArrayListUnmanaged(u8) {
93}93}
9494
95pub fn toOwnedSlice(aw: *AllocatingWriter) error{OutOfMemory}![]u8 {95pub fn toOwnedSlice(aw: *AllocatingWriter) error{OutOfMemory}![]u8 {
96 const gpa = aw.allocator;96 var list = aw.toArrayList();
97 var list = toArrayList(aw);97 return list.toOwnedSlice(aw.allocator);
98 return list.toOwnedSlice(gpa);
99}98}
10099
101pub fn toOwnedSliceSentinel(aw: *AllocatingWriter, comptime sentinel: u8) error{OutOfMemory}![:sentinel]u8 {100pub fn toOwnedSliceSentinel(aw: *AllocatingWriter, comptime sentinel: u8) error{OutOfMemory}![:sentinel]u8 {
lib/std/io/BufferedReader.zig+11-9
...@@ -97,19 +97,20 @@ pub fn seekForwardBy(br: *BufferedReader, seek_by: u64) !void {...@@ -97,19 +97,20 @@ pub fn seekForwardBy(br: *BufferedReader, seek_by: u64) !void {
97 br.seek = seek;97 br.seek = seek;
98}98}
9999
100/// Returns the next `n` bytes from `unbuffered_reader`, filling the buffer as100/// Returns the next `len` bytes from `unbuffered_reader`, filling the buffer as
101/// necessary.101/// necessary.
102///102///
103/// Invalidates previously returned values from `peek`.103/// Invalidates previously returned values from `peek`.
104///104///
105/// Asserts that the `BufferedReader` was initialized with a buffer capacity at105/// Asserts that the `BufferedReader` was initialized with a buffer capacity at
106/// least as big as `n`.106/// least as big as `len`.
107///107///
108/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`108/// If there are fewer than `len` bytes left in the stream, `error.EndOfStream`
109/// is returned instead.109/// is returned instead.
110///110///
111/// See also:111/// See also:
112/// * `peekGreedy`112/// * `peek`
113/// * `tryPeekArray`
113/// * `toss`114/// * `toss`
114pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 {115pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 {
115 const storage = &br.storage;116 const storage = &br.storage;
...@@ -119,18 +120,19 @@ pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 {...@@ -119,18 +120,19 @@ pub fn peek(br: *BufferedReader, n: usize) Reader.Error![]u8 {
119}120}
120121
121/// Returns all the next buffered bytes from `unbuffered_reader`, after filling122/// Returns all the next buffered bytes from `unbuffered_reader`, after filling
122/// the buffer to ensure it contains at least `n` bytes.123/// the buffer to ensure it contains at least `min_len` bytes.
123///124///
124/// Invalidates previously returned values from `peek` and `peekGreedy`.125/// Invalidates previously returned values from `peek` and `peekGreedy`.
125///126///
126/// Asserts that the `BufferedReader` was initialized with a buffer capacity at127/// Asserts that the `BufferedReader` was initialized with a buffer capacity at
127/// least as big as `n`.128/// least as big as `min_len`.
128///129///
129/// If there are fewer than `n` bytes left in the stream, `error.EndOfStream`130/// If there are fewer than `min_len` bytes left in the stream, `error.EndOfStream`
130/// is returned instead.131/// is returned instead.
131///132///
132/// See also:133/// See also:
133/// * `peek`134/// * `peek`
135/// * `tryPeekGreedy`
134/// * `toss`136/// * `toss`
135pub fn peekGreedy(br: *BufferedReader, n: usize) Reader.Error![]u8 {137pub fn peekGreedy(br: *BufferedReader, n: usize) Reader.Error![]u8 {
136 const storage = &br.storage;138 const storage = &br.storage;
...@@ -214,7 +216,7 @@ pub fn discardShort(br: *BufferedReader, n: usize) Reader.ShortError!usize {...@@ -214,7 +216,7 @@ pub fn discardShort(br: *BufferedReader, n: usize) Reader.ShortError!usize {
214 storage.end = 0;216 storage.end = 0;
215 br.seek = 0;217 br.seek = 0;
216 while (true) {218 while (true) {
217 const discard_len = br.unbuffered_reader.discard(remaining, .unlimited) catch |err| switch (err) {219 const discard_len = br.unbuffered_reader.discard(.limited(remaining)) catch |err| switch (err) {
218 error.EndOfStream => return n - remaining,220 error.EndOfStream => return n - remaining,
219 error.ReadFailed => return error.ReadFailed,221 error.ReadFailed => return error.ReadFailed,
220 };222 };
...@@ -564,7 +566,7 @@ pub inline fn takeStructEndian(br: *BufferedReader, comptime T: type, endian: st...@@ -564,7 +566,7 @@ pub inline fn takeStructEndian(br: *BufferedReader, comptime T: type, endian: st
564/// it. Otherwise, returns `error.InvalidEnumTag`.566/// it. Otherwise, returns `error.InvalidEnumTag`.
565///567///
566/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.568/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
567pub fn takeEnum(br: *BufferedReader, comptime Enum: type, endian: std.builtin.Endian) Reader.Error!Enum {569pub fn takeEnum(br: *BufferedReader, comptime Enum: type, endian: std.builtin.Endian) (Reader.Error || std.meta.IntToEnumError)!Enum {
568 const Tag = @typeInfo(Enum).@"enum".tag_type;570 const Tag = @typeInfo(Enum).@"enum".tag_type;
569 const int = try br.takeInt(Tag, endian);571 const int = try br.takeInt(Tag, endian);
570 return std.meta.intToEnum(Enum, int);572 return std.meta.intToEnum(Enum, int);
lib/std/io/BufferedWriter.zig+5
...@@ -83,6 +83,11 @@ pub fn unusedCapacitySlice(bw: *const BufferedWriter) []u8 {...@@ -83,6 +83,11 @@ pub fn unusedCapacitySlice(bw: *const BufferedWriter) []u8 {
83 return bw.buffer[bw.end..];83 return bw.buffer[bw.end..];
84}84}
8585
86/// Asserts the provided buffer has total capacity enough for `len`.
87pub fn writableArray(bw: *BufferedWriter, comptime len: usize) anyerror!*[len]u8 {
88 return (try bw.writableSlice(len))[0..len];
89}
90
86/// Asserts the provided buffer has total capacity enough for `minimum_length`.91/// Asserts the provided buffer has total capacity enough for `minimum_length`.
87pub fn writableSlice(bw: *BufferedWriter, minimum_length: usize) Writer.Error![]u8 {92pub fn writableSlice(bw: *BufferedWriter, minimum_length: usize) Writer.Error![]u8 {
88 assert(bw.buffer.len >= minimum_length);93 assert(bw.buffer.len >= minimum_length);
lib/std/io/multi_writer.zig+1-1
...@@ -6,7 +6,7 @@ pub fn MultiWriter(comptime Writers: type) type {...@@ -6,7 +6,7 @@ pub fn MultiWriter(comptime Writers: type) type {
6 comptime var ErrSet = error{};6 comptime var ErrSet = error{};
7 inline for (@typeInfo(Writers).@"struct".fields) |field| {7 inline for (@typeInfo(Writers).@"struct".fields) |field| {
8 const StreamType = field.type;8 const StreamType = field.type;
9 ErrSet = ErrSet || StreamType.Error;9 ErrSet = ErrSet || if (@hasDecl(StreamType, "Error")) StreamType.Error else anyerror;
10 }10 }
1111
12 return struct {12 return struct {
lib/std/net.zig+251-212
...@@ -1817,7 +1817,10 @@ pub const Stream = struct {...@@ -1817,7 +1817,10 @@ pub const Stream = struct {
1817 /// interchangeable with a file system file descriptor.1817 /// interchangeable with a file system file descriptor.
1818 handle: Handle,1818 handle: Handle,
18191819
1820 pub const Handle = if (native_os == .windows) windows.ws2_32.SOCKET else posix.fd_t;1820 pub const Handle = switch (native_os) {
1821 .windows => windows.ws2_32.SOCKET,
1822 else => posix.fd_t,
1823 };
18211824
1822 pub fn close(s: Stream) void {1825 pub fn close(s: Stream) void {
1823 switch (native_os) {1826 switch (native_os) {
...@@ -1826,238 +1829,274 @@ pub const Stream = struct {...@@ -1826,238 +1829,274 @@ pub const Stream = struct {
1826 }1829 }
1827 }1830 }
18281831
1829 pub const ReadError = posix.ReadError;1832 pub const Reader = struct {
1830 pub const WriteError = posix.SendMsgError || error{1833 impl: switch (native_os) {
1831 ConnectionResetByPeer,1834 .windows => Stream,
1832 SocketNotBound,1835 else => struct {
1833 MessageTooBig,1836 fr: std.fs.File.Reader,
1834 NetworkSubsystemFailed,1837 err: Error!void,
1835 SystemResources,
1836 SocketNotConnected,
1837 Unexpected,
1838 };
1839
1840 pub fn reader(stream: Stream) std.io.Reader {
1841 return .{
1842 .context = handleToOpaque(stream.handle),
1843 .vtable = switch (native_os) {
1844 .windows => &.{
1845 .read = windows_read,
1846 .readv = windows_readv,
1847 },
1848 else => &.{
1849 .read = std.fs.File.streamRead,
1850 .readv = std.fs.File.streamReadVec,
1851 },
1852 },1838 },
1853 };1839 },
1854 }
18551840
1856 pub fn writer(stream: Stream) std.io.Writer {1841 pub const Error = posix.ReadError;
1857 return .{1842
1858 .context = handleToOpaque(stream.handle),1843 pub fn interface(r: *Reader) std.io.Reader {
1859 .vtable = switch (native_os) {1844 return switch (native_os) {
1860 .windows => &.{1845 .windows => .{
1861 .writeSplat = windows_writeSplat,1846 .context = r.impl.stream.handle,
1862 .writeFile = windows_writeFile,1847 .vtable = &.{
1848 .read = windows_read,
1849 .readVec = windows_readVec,
1850 .discard = windows_discard,
1851 },
1863 },1852 },
1864 else => &.{1853 else => r.interface(),
1865 .writeSplat = posix_writeSplat,1854 };
1866 .writeFile = std.fs.File.writeFile,1855 }
1867 },
1868 },
1869 };
1870 }
18711856
1872 fn windows_read(1857 fn windows_read(
1873 context: ?*anyopaque,1858 context: ?*anyopaque,
1874 bw: *std.io.BufferedWriter,1859 bw: *std.io.BufferedWriter,
1875 limit: std.io.Reader.Limit,1860 limit: std.io.Reader.Limit,
1876 ) std.io.Reader.Error!usize {1861 ) std.io.Reader.Error!usize {
1877 const buf = limit.slice(try bw.writableSlice(1));1862 const buf = limit.slice(try bw.writableSlice(1));
1878 const status = try windows_readv(context, &.{buf});1863 const status = try windows_readVec(context, &.{buf});
1879 bw.advance(status.len);1864 bw.advance(status.len);
1880 return status;1865 return status;
1881 }1866 }
18821867
1883 fn windows_readv(context: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize {1868 fn windows_readVec(context: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize {
1884 var iovecs: [max_buffers_len]windows.WSABUF = undefined;1869 var iovecs: [max_buffers_len]windows.WSABUF = undefined;
1885 var iovecs_i: usize = 0;1870 var iovecs_i: usize = 0;
1886 for (data) |d| {1871 for (data) |d| {
1887 // In case Windows checks pointer address before length, we must omit1872 // In case Windows checks pointer address before length, we must omit
1888 // length-zero vectors.1873 // length-zero vectors.
1889 if (d.len == 0) continue;1874 if (d.len == 0) continue;
1890 iovecs[iovecs_i] = .{ .buf = d.ptr, .len = d.len };1875 iovecs[iovecs_i] = .{ .buf = d.ptr, .len = d.len };
1891 iovecs_i += 1;1876 iovecs_i += 1;
1892 if (iovecs_i >= iovecs.len) break;1877 if (iovecs_i >= iovecs.len) break;
1878 }
1879 const bufs = iovecs[0..iovecs_i];
1880 if (bufs.len == 0) return .{}; // Prevent false positive end detection on empty `data`.
1881 var n: u32 = undefined;
1882 var flags: u32 = 0;
1883 const rc = windows.ws2_32.WSARecvFrom(context, bufs.ptr, bufs.len, &n, &flags, null, null, null, null);
1884 if (rc != 0) switch (windows.ws2_32.WSAGetLastError()) {
1885 .WSAECONNRESET => return error.ConnectionResetByPeer,
1886 .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space.
1887 .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2
1888 .WSAEINVAL => return error.SocketNotBound,
1889 .WSAEMSGSIZE => return error.MessageTooBig,
1890 .WSAENETDOWN => return error.NetworkSubsystemFailed,
1891 .WSAENETRESET => return error.ConnectionResetByPeer,
1892 .WSAENOTCONN => return error.SocketNotConnected,
1893 .WSAEWOULDBLOCK => return error.WouldBlock,
1894 .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function
1895 .WSA_IO_PENDING => unreachable, // not using overlapped I/O
1896 .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O
1897 else => |err| return windows.unexpectedWSAError(err),
1898 };
1899 return .{ .len = n, .end = n == 0 };
1893 }1900 }
1894 const bufs = iovecs[0..iovecs_i];
1895 if (bufs.len == 0) return .{}; // Prevent false positive end detection on empty `data`.
1896 const handle = opaqueToHandle(context);
1897 var n: u32 = undefined;
1898 var flags: u32 = 0;
1899 const rc = windows.ws2_32.WSARecvFrom(handle, bufs.ptr, bufs.len, &n, &flags, null, null, null, null);
1900 if (rc != 0) switch (windows.ws2_32.WSAGetLastError()) {
1901 .WSAECONNRESET => return error.ConnectionResetByPeer,
1902 .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space.
1903 .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2
1904 .WSAEINVAL => return error.SocketNotBound,
1905 .WSAEMSGSIZE => return error.MessageTooBig,
1906 .WSAENETDOWN => return error.NetworkSubsystemFailed,
1907 .WSAENETRESET => return error.ConnectionResetByPeer,
1908 .WSAENOTCONN => return error.SocketNotConnected,
1909 .WSAEWOULDBLOCK => return error.WouldBlock,
1910 .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function
1911 .WSA_IO_PENDING => unreachable, // not using overlapped I/O
1912 .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O
1913 else => |err| return windows.unexpectedWSAError(err),
1914 };
1915 return .{ .len = n, .end = n == 0 };
1916 }
19171901
1918 fn windows_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {1902 fn windows_discard(context: ?*anyopaque, limit: std.io.Reader.Limit) std.io.Reader.Error!usize {
1919 comptime assert(native_os == .windows);1903 _ = context;
1920 if (data.len == 1 and splat == 0) return 0;1904 _ = limit;
1921 var splat_buffer: [256]u8 = undefined;1905 @panic("TODO");
1922 var iovecs: [max_buffers_len]windows.WSABUF = undefined;
1923 var len: u32 = @min(iovecs.len, data.len);
1924 for (iovecs[0..len], data[0..len]) |*v, d| v.* = .{
1925 .buf = if (d.len == 0) "" else d.ptr, // TODO: does Windows allow ptr=undefined len=0 ?
1926 .len = d.len,
1927 };
1928 switch (splat) {
1929 0 => len -= 1,
1930 1 => {},
1931 else => {
1932 const pattern = data[data.len - 1];
1933 if (pattern.len == 1) {
1934 const memset_len = @min(splat_buffer.len, splat);
1935 const buf = splat_buffer[0..memset_len];
1936 @memset(buf, pattern[0]);
1937 iovecs[len - 1] = .{ .base = buf.ptr, .len = buf.len };
1938 var remaining_splat = splat - buf.len;
1939 while (remaining_splat > splat_buffer.len and len < iovecs.len) {
1940 iovecs[len] = .{ .base = &splat_buffer, .len = splat_buffer.len };
1941 remaining_splat -= splat_buffer.len;
1942 len += 1;
1943 }
1944 if (remaining_splat > 0 and len < iovecs.len) {
1945 iovecs[len] = .{ .base = &splat_buffer, .len = remaining_splat };
1946 len += 1;
1947 }
1948 }
1949 },
1950 }1906 }
1951 const handle = opaqueToHandle(context);1907 };
1952 var n: u32 = undefined;1908
1953 const rc = windows.ws2_32.WSASend(handle, &iovecs, len, &n, 0, null, null);1909 pub const Writer = struct {
1954 if (rc == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) {1910 impl: switch (native_os) {
1955 .WSAECONNABORTED => return error.ConnectionResetByPeer,1911 .windows => Stream,
1956 .WSAECONNRESET => return error.ConnectionResetByPeer,1912 else => PosixImpl,
1957 .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space.1913 },
1958 .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2
1959 .WSAEINVAL => return error.SocketNotBound,
1960 .WSAEMSGSIZE => return error.MessageTooBig,
1961 .WSAENETDOWN => return error.NetworkSubsystemFailed,
1962 .WSAENETRESET => return error.ConnectionResetByPeer,
1963 .WSAENOBUFS => return error.SystemResources,
1964 .WSAENOTCONN => return error.SocketNotConnected,
1965 .WSAENOTSOCK => unreachable, // not a socket
1966 .WSAEOPNOTSUPP => unreachable, // only for message-oriented sockets
1967 .WSAESHUTDOWN => unreachable, // cannot send on a socket after write shutdown
1968 .WSAEWOULDBLOCK => return error.WouldBlock,
1969 .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function
1970 .WSA_IO_PENDING => unreachable, // not using overlapped I/O
1971 .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O
1972 else => |err| return windows.unexpectedWSAError(err),
1973 };
1974 return n;
1975 }
19761914
1977 fn posix_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {1915 const PosixImpl = struct {
1978 const sock_fd = opaqueToHandle(context);1916 fw: std.fs.File.Writer,
1979 comptime assert(native_os != .windows);1917 err: Error!void,
1980 var splat_buffer: [256]u8 = undefined;
1981 var iovecs: [max_buffers_len]std.posix.iovec_const = undefined;
1982 var len: usize = @min(iovecs.len, data.len);
1983 for (iovecs[0..len], data[0..len]) |*v, d| v.* = .{
1984 .base = if (d.len == 0) "" else d.ptr, // OS sadly checks ptr addr before length.
1985 .len = d.len,
1986 };1918 };
1987 var msg: posix.msghdr_const = .{1919
1988 .name = null,1920 pub const Error = posix.SendMsgError || error{
1989 .namelen = 0,1921 ConnectionResetByPeer,
1990 .iov = &iovecs,1922 SocketNotBound,
1991 .iovlen = len,1923 MessageTooBig,
1992 .control = null,1924 NetworkSubsystemFailed,
1993 .controllen = 0,1925 SystemResources,
1994 .flags = 0,1926 SocketNotConnected,
1927 Unexpected,
1995 };1928 };
1996 switch (splat) {1929
1997 0 => msg.iovlen = len - 1,1930 pub fn interface(w: *Writer) std.io.Writer {
1998 1 => {},1931 return switch (native_os) {
1999 else => {1932 .windows => .{
2000 const pattern = data[data.len - 1];1933 .context = w.impl.stream.handle,
2001 if (pattern.len == 1) {1934 .vtable = &.{
2002 const memset_len = @min(splat_buffer.len, splat);1935 .writeSplat = windows_writeSplat,
2003 const buf = splat_buffer[0..memset_len];1936 .writeFile = windows_writeFile,
2004 @memset(buf, pattern[0]);1937 },
2005 iovecs[len - 1] = .{ .base = buf.ptr, .len = buf.len };1938 },
2006 var remaining_splat = splat - buf.len;1939 else => .{
2007 while (remaining_splat > splat_buffer.len and len < iovecs.len) {1940 .context = &w.impl,
2008 iovecs[len] = .{ .base = &splat_buffer, .len = splat_buffer.len };1941 .vtable = &.{
2009 remaining_splat -= splat_buffer.len;1942 .writeSplat = posix_writeSplat,
2010 len += 1;1943 .writeFile = std.fs.File.Writer.writeFile,
2011 }1944 },
2012 if (remaining_splat > 0 and len < iovecs.len) {1945 },
2013 iovecs[len] = .{ .base = &splat_buffer, .len = remaining_splat };1946 };
2014 len += 1;1947 }
1948
1949 fn windows_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
1950 comptime assert(native_os == .windows);
1951 if (data.len == 1 and splat == 0) return 0;
1952 var splat_buffer: [256]u8 = undefined;
1953 var iovecs: [max_buffers_len]windows.WSABUF = undefined;
1954 var len: u32 = @min(iovecs.len, data.len);
1955 for (iovecs[0..len], data[0..len]) |*v, d| v.* = .{
1956 .buf = if (d.len == 0) "" else d.ptr, // TODO: does Windows allow ptr=undefined len=0 ?
1957 .len = d.len,
1958 };
1959 switch (splat) {
1960 0 => len -= 1,
1961 1 => {},
1962 else => {
1963 const pattern = data[data.len - 1];
1964 if (pattern.len == 1) {
1965 const memset_len = @min(splat_buffer.len, splat);
1966 const buf = splat_buffer[0..memset_len];
1967 @memset(buf, pattern[0]);
1968 iovecs[len - 1] = .{ .base = buf.ptr, .len = buf.len };
1969 var remaining_splat = splat - buf.len;
1970 while (remaining_splat > splat_buffer.len and len < iovecs.len) {
1971 iovecs[len] = .{ .base = &splat_buffer, .len = splat_buffer.len };
1972 remaining_splat -= splat_buffer.len;
1973 len += 1;
1974 }
1975 if (remaining_splat > 0 and len < iovecs.len) {
1976 iovecs[len] = .{ .base = &splat_buffer, .len = remaining_splat };
1977 len += 1;
1978 }
2015 }1979 }
2016 msg.iovlen = len;1980 },
2017 }1981 }
2018 },1982 var n: u32 = undefined;
1983 const rc = windows.ws2_32.WSASend(context, &iovecs, len, &n, 0, null, null);
1984 if (rc == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) {
1985 .WSAECONNABORTED => return error.ConnectionResetByPeer,
1986 .WSAECONNRESET => return error.ConnectionResetByPeer,
1987 .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space.
1988 .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2
1989 .WSAEINVAL => return error.SocketNotBound,
1990 .WSAEMSGSIZE => return error.MessageTooBig,
1991 .WSAENETDOWN => return error.NetworkSubsystemFailed,
1992 .WSAENETRESET => return error.ConnectionResetByPeer,
1993 .WSAENOBUFS => return error.SystemResources,
1994 .WSAENOTCONN => return error.SocketNotConnected,
1995 .WSAENOTSOCK => unreachable, // not a socket
1996 .WSAEOPNOTSUPP => unreachable, // only for message-oriented sockets
1997 .WSAESHUTDOWN => unreachable, // cannot send on a socket after write shutdown
1998 .WSAEWOULDBLOCK => return error.WouldBlock,
1999 .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function
2000 .WSA_IO_PENDING => unreachable, // not using overlapped I/O
2001 .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O
2002 else => |err| return windows.unexpectedWSAError(err),
2003 };
2004 return n;
2019 }2005 }
2020 const flags = posix.MSG.NOSIGNAL;
2021 return std.posix.sendmsg(sock_fd, &msg, flags);
2022 }
20232006
2024 fn windows_writeFile(2007 fn posix_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
2025 context: *anyopaque,2008 const fw: *std.fs.File.Writer = @alignCast(@ptrCast(context));
2026 in_file: std.fs.File,2009 const impl: *PosixImpl = @fieldParentPtr("fw", fw);
2027 in_offset: u64,2010 comptime assert(native_os != .windows);
2028 in_len: std.io.Writer.FileLen,2011 var splat_buffer: [256]u8 = undefined;
2029 headers_and_trailers: []const []const u8,2012 var iovecs: [max_buffers_len]std.posix.iovec_const = undefined;
2030 headers_len: usize,2013 var len: usize = @min(iovecs.len, data.len);
2031 ) std.io.Writer.FileError!usize {2014 for (iovecs[0..len], data[0..len]) |*v, d| v.* = .{
2032 const len_int = switch (in_len) {2015 .base = if (d.len == 0) "" else d.ptr, // OS sadly checks ptr addr before length.
2033 .zero => return windows_writeSplat(context, headers_and_trailers, 1),2016 .len = d.len,
2034 .entire_file => std.math.maxInt(usize),2017 };
2035 else => in_len.int(),2018 var msg: posix.msghdr_const = .{
2036 };2019 .name = null,
2037 if (headers_len > 0) return windows_writeSplat(context, headers_and_trailers[0..headers_len], 1);2020 .namelen = 0,
2038 var file_contents_buffer: [4096]u8 = undefined;2021 .iov = &iovecs,
2039 const read_buffer = file_contents_buffer[0..@min(file_contents_buffer.len, len_int)];2022 .iovlen = len,
2040 const n = try windows.ReadFile(in_file.handle, read_buffer, in_offset);2023 .control = null,
2041 return windows_writeSplat(context, &.{read_buffer[0..n]}, 1);2024 .controllen = 0,
2042 }2025 .flags = 0,
2026 };
2027 switch (splat) {
2028 0 => msg.iovlen = len - 1,
2029 1 => {},
2030 else => {
2031 const pattern = data[data.len - 1];
2032 if (pattern.len == 1) {
2033 const memset_len = @min(splat_buffer.len, splat);
2034 const buf = splat_buffer[0..memset_len];
2035 @memset(buf, pattern[0]);
2036 iovecs[len - 1] = .{ .base = buf.ptr, .len = buf.len };
2037 var remaining_splat = splat - buf.len;
2038 while (remaining_splat > splat_buffer.len and len < iovecs.len) {
2039 iovecs[len] = .{ .base = &splat_buffer, .len = splat_buffer.len };
2040 remaining_splat -= splat_buffer.len;
2041 len += 1;
2042 }
2043 if (remaining_splat > 0 and len < iovecs.len) {
2044 iovecs[len] = .{ .base = &splat_buffer, .len = remaining_splat };
2045 len += 1;
2046 }
2047 msg.iovlen = len;
2048 }
2049 },
2050 }
2051 const flags = posix.MSG.NOSIGNAL;
2052 return std.posix.sendmsg(fw.file.handle, &msg, flags) catch |err| {
2053 impl.err = err;
2054 return error.WriteFailed;
2055 };
2056 }
20432057
2044 const max_buffers_len = 8;2058 fn windows_writeFile(
2059 context: *anyopaque,
2060 in_file: std.fs.File,
2061 in_offset: u64,
2062 in_len: std.io.Writer.FileLen,
2063 headers_and_trailers: []const []const u8,
2064 headers_len: usize,
2065 ) std.io.Writer.FileError!usize {
2066 const len_int = switch (in_len) {
2067 .zero => return windows_writeSplat(context, headers_and_trailers, 1),
2068 .entire_file => std.math.maxInt(usize),
2069 else => in_len.int(),
2070 };
2071 if (headers_len > 0) return windows_writeSplat(context, headers_and_trailers[0..headers_len], 1);
2072 var file_contents_buffer: [4096]u8 = undefined;
2073 const read_buffer = file_contents_buffer[0..@min(file_contents_buffer.len, len_int)];
2074 const n = try windows.ReadFile(in_file.handle, read_buffer, in_offset);
2075 return windows_writeSplat(context, &.{read_buffer[0..n]}, 1);
2076 }
2077 };
20452078
2046 fn handleToOpaque(handle: Handle) ?*anyopaque {2079 pub fn reader(stream: Stream) Reader {
2047 return switch (@typeInfo(Handle)) {2080 return switch (native_os) {
2048 .pointer => @ptrCast(handle),2081 .windows => .{ .impl = stream },
2049 .int => @ptrFromInt(@as(u32, @bitCast(handle))),2082 else => .{ .impl = .{
2050 else => @compileError("unhandled"),2083 .fr = std.fs.File.reader(.{ .handle = stream.handle }),
2084 .err = {},
2085 } },
2051 };2086 };
2052 }2087 }
20532088
2054 fn opaqueToHandle(userdata: ?*anyopaque) Handle {2089 pub fn writer(stream: Stream) Writer {
2055 return switch (@typeInfo(Handle)) {2090 return switch (native_os) {
2056 .pointer => @ptrCast(userdata),2091 .windows => .{ .impl = stream },
2057 .int => @intCast(@intFromPtr(userdata)),2092 else => .{ .impl = .{
2058 else => @compileError("unhandled"),2093 .fw = std.fs.File.writer(.{ .handle = stream.handle }),
2094 .err = {},
2095 } },
2059 };2096 };
2060 }2097 }
2098
2099 const max_buffers_len = 8;
2061};2100};
20622101
2063pub const Server = struct {2102pub const Server = struct {
lib/std/process.zig+6-6
...@@ -1895,7 +1895,7 @@ pub fn createEnvironFromMap(...@@ -1895,7 +1895,7 @@ pub fn createEnvironFromMap(
1895 var i: usize = 0;1895 var i: usize = 0;
18961896
1897 if (zig_progress_action == .add) {1897 if (zig_progress_action == .add) {
1898 envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});1898 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
1899 i += 1;1899 i += 1;
1900 }1900 }
19011901
...@@ -1906,16 +1906,16 @@ pub fn createEnvironFromMap(...@@ -1906,16 +1906,16 @@ pub fn createEnvironFromMap(
1906 .add => unreachable,1906 .add => unreachable,
1907 .delete => continue,1907 .delete => continue,
1908 .edit => {1908 .edit => {
1909 envp_buf[i] = try std.fmt.allocPrintZ(arena, "{s}={d}", .{1909 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={d}", .{
1910 pair.key_ptr.*, options.zig_progress_fd.?,1910 pair.key_ptr.*, options.zig_progress_fd.?,
1911 });1911 }, 0);
1912 i += 1;1912 i += 1;
1913 continue;1913 continue;
1914 },1914 },
1915 .nothing => {},1915 .nothing => {},
1916 };1916 };
19171917
1918 envp_buf[i] = try std.fmt.allocPrintZ(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* });1918 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* }, 0);
1919 i += 1;1919 i += 1;
1920 }1920 }
1921 }1921 }
...@@ -1965,7 +1965,7 @@ pub fn createEnvironFromExisting(...@@ -1965,7 +1965,7 @@ pub fn createEnvironFromExisting(
1965 var existing_index: usize = 0;1965 var existing_index: usize = 0;
19661966
1967 if (zig_progress_action == .add) {1967 if (zig_progress_action == .add) {
1968 envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});1968 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
1969 i += 1;1969 i += 1;
1970 }1970 }
19711971
...@@ -1974,7 +1974,7 @@ pub fn createEnvironFromExisting(...@@ -1974,7 +1974,7 @@ pub fn createEnvironFromExisting(
1974 .add => unreachable,1974 .add => unreachable,
1975 .delete => continue,1975 .delete => continue,
1976 .edit => {1976 .edit => {
1977 envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});1977 envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
1978 i += 1;1978 i += 1;
1979 continue;1979 continue;
1980 },1980 },
lib/std/process/Child.zig+7-7
...@@ -1003,18 +1003,18 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {...@@ -1003,18 +1003,18 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
1003}1003}
10041004
1005fn writeIntFd(fd: i32, value: ErrInt) !void {1005fn writeIntFd(fd: i32, value: ErrInt) !void {
1006 const file: File = .{ .handle = fd };1006 var fw = std.fs.File.writer(.{ .handle = fd });
1007 var buffer: [8]u8 = undefined;1007 var buffer: [8]u8 = undefined;
1008 std.mem.writeInt(u64, &buffer, @intCast(value), .little);1008 var bw = fw.interface().buffered(&buffer);
1009 file.writeAll(&buffer) catch return error.SystemResorces;1009 bw.writeInt(u64, value, .little) catch return error.SystemResources;
1010}1010}
10111011
1012fn readIntFd(fd: i32) !ErrInt {1012fn readIntFd(fd: i32) !ErrInt {
1013 const file: File = .{ .handle = fd };1013 var fr = std.fs.File.reader(.{ .handle = fd });
1014 var buffer: [8]u8 = undefined;1014 var buffer: [8]u8 = undefined;
1015 const n = file.readAll(&buffer) catch return error.SystemResources;1015 var br: std.io.BufferedReader = undefined;
1016 if (n != buffer.len) return error.SystemResources;1016 br.init(fr.interface(), &buffer);
1017 return @intCast(std.mem.readInt(u64, &buffer, .little));1017 return @intCast(br.takeInt(u64, .little) catch return error.SystemResources);
1018}1018}
10191019
1020const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);1020const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
lib/std/zig/ErrorBundle.zig+2-2
...@@ -163,7 +163,7 @@ pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {...@@ -163,7 +163,7 @@ pub fn renderToStdErr(eb: ErrorBundle, options: RenderOptions) void {
163 renderToWriter(eb, options, bw) catch return;163 renderToWriter(eb, options, bw) catch return;
164}164}
165165
166pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {166pub fn renderToWriter(eb: ErrorBundle, options: RenderOptions, bw: *std.io.BufferedWriter) (std.io.Writer.Error || std.posix.UnexpectedError)!void {
167 if (eb.extra.len == 0) return;167 if (eb.extra.len == 0) return;
168 for (eb.getMessages()) |err_msg| {168 for (eb.getMessages()) |err_msg| {
169 try renderErrorMessageToWriter(eb, options, err_msg, bw, "error", .red, 0);169 try renderErrorMessageToWriter(eb, options, err_msg, bw, "error", .red, 0);
...@@ -186,7 +186,7 @@ fn renderErrorMessageToWriter(...@@ -186,7 +186,7 @@ fn renderErrorMessageToWriter(
186 kind: []const u8,186 kind: []const u8,
187 color: std.io.tty.Color,187 color: std.io.tty.Color,
188 indent: usize,188 indent: usize,
189) std.io.Writer.Error!void {189) (std.io.Writer.Error || std.posix.UnexpectedError)!void {
190 const ttyconf = options.ttyconf;190 const ttyconf = options.ttyconf;
191 const err_msg = eb.getErrorMessage(err_msg_index);191 const err_msg = eb.getErrorMessage(err_msg_index);
192 const prefix_start = bw.count;192 const prefix_start = bw.count;
src/Package/Fetch.zig+1-4
...@@ -1367,10 +1367,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U...@@ -1367,10 +1367,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
1367 const index_prog_node = f.prog_node.start("Index pack", 0);1367 const index_prog_node = f.prog_node.start("Index pack", 0);
1368 defer index_prog_node.end();1368 defer index_prog_node.end();
1369 var buffer: [4096]u8 = undefined;1369 var buffer: [4096]u8 = undefined;
1370 var index_buffered_writer: std.io.BufferedWriter = .{1370 var index_buffered_writer: std.io.BufferedWriter = index_file.writer().buffered(&buffer);
1371 .unbuffered_writer = index_file.writer(),
1372 .buffer = &buffer,
1373 };
1374 try git.indexPack(gpa, object_format, pack_file, &index_buffered_writer);1371 try git.indexPack(gpa, object_format, pack_file, &index_buffered_writer);
1375 try index_buffered_writer.flush();1372 try index_buffered_writer.flush();
1376 try index_file.sync();1373 try index_file.sync();
src/dev.zig+4
...@@ -78,6 +78,7 @@ pub const Env = enum {...@@ -78,6 +78,7 @@ pub const Env = enum {
78 .ast_gen,78 .ast_gen,
79 .sema,79 .sema,
80 .legalize,80 .legalize,
81 .c_compiler,
81 .llvm_backend,82 .llvm_backend,
82 .c_backend,83 .c_backend,
83 .wasm_backend,84 .wasm_backend,
...@@ -127,6 +128,7 @@ pub const Env = enum {...@@ -127,6 +128,7 @@ pub const Env = enum {
127 .clang_command,128 .clang_command,
128 .cc_command,129 .cc_command,
129 .translate_c_command,130 .translate_c_command,
131 .c_compiler,
130 => true,132 => true,
131 else => false,133 else => false,
132 },134 },
...@@ -248,6 +250,8 @@ pub const Feature = enum {...@@ -248,6 +250,8 @@ pub const Feature = enum {
248 sema,250 sema,
249 legalize,251 legalize,
250252
253 c_compiler,
254
251 llvm_backend,255 llvm_backend,
252 c_backend,256 c_backend,
253 wasm_backend,257 wasm_backend,
src/link/Elf/Atom.zig+14-17
...@@ -1388,10 +1388,7 @@ const x86_64 = struct {...@@ -1388,10 +1388,7 @@ const x86_64 = struct {
1388 .{ .imm = .s(-129) },1388 .{ .imm = .s(-129) },
1389 }, t) catch return false;1389 }, t) catch return false;
1390 var buf: [std.atomic.cache_line]u8 = undefined;1390 var buf: [std.atomic.cache_line]u8 = undefined;
1391 var bw: std.io.BufferedWriter = .{1391 var bw = std.io.Writer.null.buffered(&buf);
1392 .unbuffered_writer = .null,
1393 .buffer = &buf,
1394 };
1395 inst.encode(&bw, .{}) catch return false;1392 inst.encode(&bw, .{}) catch return false;
1396 return true;1393 return true;
1397 },1394 },
...@@ -1599,7 +1596,7 @@ const aarch64 = struct {...@@ -1599,7 +1596,7 @@ const aarch64 = struct {
1599 const diags = &elf_file.base.comp.link_diags;1596 const diags = &elf_file.base.comp.link_diags;
1600 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1597 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1601 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1598 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1602 const code = (try bw.writableSlice(4))[0..4];1599 const code = try bw.writableArray(4);
1603 const file_ptr = atom.file(elf_file).?;1600 const file_ptr = atom.file(elf_file).?;
16041601
1605 const P, const A, const S, const GOT, const G, const TP, const DTP = args;1602 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
...@@ -1626,7 +1623,7 @@ const aarch64 = struct {...@@ -1626,7 +1623,7 @@ const aarch64 = struct {
1626 const S_ = th.targetAddress(target_index, elf_file);1623 const S_ = th.targetAddress(target_index, elf_file);
1627 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;1624 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
1628 };1625 };
1629 aarch64_util.writeBranchImm(disp, (try bw.writableSlice(4))[0..4]);1626 aarch64_util.writeBranchImm(disp, code);
1630 },1627 },
16311628
1632 .PREL32 => {1629 .PREL32 => {
...@@ -1897,26 +1894,26 @@ const riscv = struct {...@@ -1897,26 +1894,26 @@ const riscv = struct {
18971894
1898 .HI20 => {1895 .HI20 => {
1899 const value: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);1896 const value: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);
1900 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], value);1897 riscv_util.writeInstU(try bw.writableArray(4), value);
1901 },1898 },
19021899
1903 .GOT_HI20 => {1900 .GOT_HI20 => {
1904 assert(target.flags.has_got);1901 assert(target.flags.has_got);
1905 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A - P) orelse return error.Overflow);1902 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A - P) orelse return error.Overflow);
1906 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], disp);1903 riscv_util.writeInstU(try bw.writableArray(4), disp);
1907 },1904 },
19081905
1909 .CALL_PLT => {1906 .CALL_PLT => {
1910 // TODO: relax1907 // TODO: relax
1911 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);1908 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);
1912 const code = (try bw.writableSlice(8))[0..8];1909 const code = try bw.writableArray(8);
1913 riscv_util.writeInstU(code[0..4], disp); // auipc1910 riscv_util.writeInstU(code[0..4], disp); // auipc
1914 riscv_util.writeInstI(code[4..8], disp); // jalr1911 riscv_util.writeInstI(code[4..8], disp); // jalr
1915 },1912 },
19161913
1917 .PCREL_HI20 => {1914 .PCREL_HI20 => {
1918 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);1915 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);
1919 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], disp);1916 riscv_util.writeInstU(try bw.writableArray(4), disp);
1920 },1917 },
19211918
1922 .PCREL_LO12_I,1919 .PCREL_LO12_I,
...@@ -1954,8 +1951,8 @@ const riscv = struct {...@@ -1954,8 +1951,8 @@ const riscv = struct {
1954 };1951 };
1955 relocs_log.debug(" [{x} => {x}]", .{ P_, disp + P_ });1952 relocs_log.debug(" [{x} => {x}]", .{ P_, disp + P_ });
1956 switch (r_type) {1953 switch (r_type) {
1957 .PCREL_LO12_I => riscv_util.writeInstI((try bw.writableSlice(4))[0..4], @bitCast(disp)),1954 .PCREL_LO12_I => riscv_util.writeInstI(try bw.writableArray(4), @bitCast(disp)),
1958 .PCREL_LO12_S => riscv_util.writeInstS((try bw.writableSlice(4))[0..4], @bitCast(disp)),1955 .PCREL_LO12_S => riscv_util.writeInstS(try bw.writableArray(4), @bitCast(disp)),
1959 else => unreachable,1956 else => unreachable,
1960 }1957 }
1961 },1958 },
...@@ -1965,8 +1962,8 @@ const riscv = struct {...@@ -1965,8 +1962,8 @@ const riscv = struct {
1965 => {1962 => {
1966 const disp: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);1963 const disp: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);
1967 switch (r_type) {1964 switch (r_type) {
1968 .LO12_I => riscv_util.writeInstI((try bw.writableSlice(4))[0..4], disp),1965 .LO12_I => riscv_util.writeInstI(try bw.writableArray(4), disp),
1969 .LO12_S => riscv_util.writeInstS((try bw.writableSlice(4))[0..4], disp),1966 .LO12_S => riscv_util.writeInstS(try bw.writableArray(4), disp),
1970 else => unreachable,1967 else => unreachable,
1971 }1968 }
1972 },1969 },
...@@ -1974,7 +1971,7 @@ const riscv = struct {...@@ -1974,7 +1971,7 @@ const riscv = struct {
1974 .TPREL_HI20 => {1971 .TPREL_HI20 => {
1975 const target_addr: u32 = @intCast(target.address(.{}, elf_file));1972 const target_addr: u32 = @intCast(target.address(.{}, elf_file));
1976 const val: i32 = @intCast(S + A - target_addr);1973 const val: i32 = @intCast(S + A - target_addr);
1977 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], @bitCast(val));1974 riscv_util.writeInstU(try bw.writableArray(4), @bitCast(val));
1978 },1975 },
19791976
1980 .TPREL_LO12_I,1977 .TPREL_LO12_I,
...@@ -1983,8 +1980,8 @@ const riscv = struct {...@@ -1983,8 +1980,8 @@ const riscv = struct {
1983 const target_addr: u32 = @intCast(target.address(.{}, elf_file));1980 const target_addr: u32 = @intCast(target.address(.{}, elf_file));
1984 const val: i32 = @intCast(S + A - target_addr);1981 const val: i32 = @intCast(S + A - target_addr);
1985 switch (r_type) {1982 switch (r_type) {
1986 .TPREL_LO12_I => riscv_util.writeInstI((try bw.writableSlice(4))[0..4], @bitCast(val)),1983 .TPREL_LO12_I => riscv_util.writeInstI(try bw.writableArray(4), @bitCast(val)),
1987 .TPREL_LO12_S => riscv_util.writeInstS((try bw.writableSlice(4))[0..4], @bitCast(val)),1984 .TPREL_LO12_S => riscv_util.writeInstS(try bw.writableArray(4), @bitCast(val)),
1988 else => unreachable,1985 else => unreachable,
1989 }1986 }
1990 },1987 },
src/link/MachO/dyld_info/Trie.zig+1-4
...@@ -185,10 +185,7 @@ const FinalizeNodeResult = struct {...@@ -185,10 +185,7 @@ const FinalizeNodeResult = struct {
185/// Updates offset of this node in the output byte stream.185/// Updates offset of this node in the output byte stream.
186fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {186fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {
187 var buf: [1024]u8 = undefined;187 var buf: [1024]u8 = undefined;
188 var bw: std.io.BufferedWriter = .{188 var bw = std.io.Writer.null.buffered(&buf);
189 .unbuffered_writer = .null,
190 .buffer = &buf,
191 };
192 const slice = self.nodes.slice();189 const slice = self.nodes.slice();
193190
194 var node_size: u32 = 0;191 var node_size: u32 = 0;
src/link/riscv.zig+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1pub fn writeSetSub6(comptime op: enum { set, sub }, addend: anytype, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {1pub fn writeSetSub6(comptime op: enum { set, sub }, addend: anytype, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {
2 const mask: u8 = 0b11_000000;2 const mask: u8 = 0b11_000000;
3 const actual: i8 = @truncate(addend);3 const actual: i8 = @truncate(addend);
4 const old_value = (try bw.writableSlice(1))[0];4 const old_value = (try bw.writableArray(1))[0];
5 const new_value = (old_value & mask) | (@as(u8, switch (op) {5 const new_value = (old_value & mask) | (@as(u8, switch (op) {
6 .set => @bitCast(actual),6 .set => @bitCast(actual),
7 .sub => @bitCast(@as(i8, @bitCast(old_value)) -| actual),7 .sub => @bitCast(@as(i8, @bitCast(old_value)) -| actual),
...@@ -14,7 +14,7 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io....@@ -14,7 +14,7 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io.
14 .set => try overwriteUleb(@intCast(addend), bw),14 .set => try overwriteUleb(@intCast(addend), bw),
15 .sub => {15 .sub => {
16 var br: std.io.BufferedReader = undefined;16 var br: std.io.BufferedReader = undefined;
17 br.initFixed(try bw.writableSlice(1));17 br.initFixed(try bw.writableArray(1));
18 const old_value = try br.takeLeb128(u64);18 const old_value = try br.takeLeb128(u64);
19 try overwriteUleb(old_value -% @as(u64, @intCast(addend)), bw);19 try overwriteUleb(old_value -% @as(u64, @intCast(addend)), bw);
20 },20 },
...@@ -24,7 +24,7 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io....@@ -24,7 +24,7 @@ pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io.
24fn overwriteUleb(new_value: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {24fn overwriteUleb(new_value: u64, bw: *std.io.BufferedWriter) std.io.Writer.Error!void {
25 var value: u64 = new_value;25 var value: u64 = new_value;
26 while (true) {26 while (true) {
27 const byte = (try bw.writableSlice(1))[0];27 const byte = (try bw.writableArray(1))[0];
28 try bw.writeByte((byte & 0x80) | @as(u7, @truncate(value)));28 try bw.writeByte((byte & 0x80) | @as(u7, @truncate(value)));
29 if (byte & 0x80 == 0) break;29 if (byte & 0x80 == 0) break;
30 value >>= 7;30 value >>= 7;
src/main.zig+13-2
...@@ -1808,6 +1808,7 @@ fn buildOutputType(...@@ -1808,6 +1808,7 @@ fn buildOutputType(
1808 } else manifest_file = arg;1808 } else manifest_file = arg;
1809 },1809 },
1810 .assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm => {1810 .assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm => {
1811 dev.check(.c_compiler);
1811 try create_module.c_source_files.append(arena, .{1812 try create_module.c_source_files.append(arena, .{
1812 // Populated after module creation.1813 // Populated after module creation.
1813 .owner = undefined,1814 .owner = undefined,
...@@ -1818,6 +1819,7 @@ fn buildOutputType(...@@ -1818,6 +1819,7 @@ fn buildOutputType(
1818 });1819 });
1819 },1820 },
1820 .rc => {1821 .rc => {
1822 dev.check(.win32_resource);
1821 try create_module.rc_source_files.append(arena, .{1823 try create_module.rc_source_files.append(arena, .{
1822 // Populated after module creation.1824 // Populated after module creation.
1823 .owner = undefined,1825 .owner = undefined,
...@@ -3303,6 +3305,7 @@ fn buildOutputType(...@@ -3303,6 +3305,7 @@ fn buildOutputType(
3303 defer thread_pool.deinit();3305 defer thread_pool.deinit();
33043306
3305 for (create_module.c_source_files.items) |*src| {3307 for (create_module.c_source_files.items) |*src| {
3308 dev.check(.c_compiler);
3306 if (!mem.eql(u8, src.src_path, "-")) continue;3309 if (!mem.eql(u8, src.src_path, "-")) continue;
33073310
3308 const ext = src.ext orelse3311 const ext = src.ext orelse
...@@ -5008,7 +5011,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5008,7 +5011,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5008 var http_client: if (dev.env.supports(.fetch_command)) std.http.Client else struct {5011 var http_client: if (dev.env.supports(.fetch_command)) std.http.Client else struct {
5009 allocator: Allocator,5012 allocator: Allocator,
5010 fn deinit(_: @This()) void {}5013 fn deinit(_: @This()) void {}
5011 } = .{ .allocator = gpa };5014 } = .{
5015 .allocator = gpa,
5016 .read_buffer_size = 0x4000,
5017 .write_buffer_size = 0x4000,
5018 };
5012 defer http_client.deinit();5019 defer http_client.deinit();
50135020
5014 var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{};5021 var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{};
...@@ -6815,7 +6822,11 @@ fn cmdFetch(...@@ -6815,7 +6822,11 @@ fn cmdFetch(
6815 try thread_pool.init(.{ .allocator = gpa });6822 try thread_pool.init(.{ .allocator = gpa });
6816 defer thread_pool.deinit();6823 defer thread_pool.deinit();
68176824
6818 var http_client: std.http.Client = .{ .allocator = gpa };6825 var http_client: std.http.Client = .{
6826 .allocator = gpa,
6827 .read_buffer_size = 0x4000,
6828 .write_buffer_size = 0x4000,
6829 };
6819 defer http_client.deinit();6830 defer http_client.deinit();
68206831
6821 try http_client.initDefaultProxies(arena);6832 try http_client.initDefaultProxies(arena);