| author | |
| committer | |
| log | 716b4489be09bc34ac5470658722924460d36a5d |
| tree | 2da6dcad7747358a0df9c08580b7474076749b21 |
| parent | e60adb97d06f85adef7a0e2a2f320e04d0dce052 |
16 files changed, 350 insertions(+), 398 deletions(-)
lib/compiler/build_runner.zig+64-60| ... | @@ -378,13 +378,16 @@ pub fn main() !void { | ... | @@ -378,13 +378,16 @@ pub fn main() !void { |
| 378 | 378 | ||
| 379 | validateSystemLibraryOptions(builder); | 379 | validateSystemLibraryOptions(builder); |
| 380 | 380 | ||
| 381 | const stdout_writer = io.getStdOut().writer(); | 381 | var stdout_writer: std.io.BufferedWriter = .{ |
| 382 | .buffer = &stdout_buffer, | ||
| 383 | .unbuffered_writer = std.io.getStdOut().writer(), | ||
| 384 | }; | ||
| 382 | 385 | ||
| 383 | if (help_menu) | 386 | if (help_menu) |
| 384 | return usage(builder, stdout_writer); | 387 | return usage(builder, &stdout_writer); |
| 385 | 388 | ||
| 386 | if (steps_menu) | 389 | if (steps_menu) |
| 387 | return steps(builder, stdout_writer); | 390 | return steps(builder, &stdout_writer); |
| 388 | 391 | ||
| 389 | var run: Run = .{ | 392 | var run: Run = .{ |
| 390 | .max_rss = max_rss, | 393 | .max_rss = max_rss, |
| ... | @@ -696,24 +699,23 @@ fn runStepNames( | ... | @@ -696,24 +699,23 @@ fn runStepNames( |
| 696 | const ttyconf = run.ttyconf; | 699 | const ttyconf = run.ttyconf; |
| 697 | 700 | ||
| 698 | if (run.summary != .none) { | 701 | if (run.summary != .none) { |
| 699 | std.debug.lockStdErr(); | 702 | var bw = std.debug.lockStdErr2(); |
| 700 | defer std.debug.unlockStdErr(); | 703 | defer std.debug.unlockStdErr(); |
| 701 | const stderr = run.stderr; | ||
| 702 | 704 | ||
| 703 | const total_count = success_count + failure_count + pending_count + skipped_count; | 705 | const total_count = success_count + failure_count + pending_count + skipped_count; |
| 704 | ttyconf.setColor(stderr, .cyan) catch {}; | 706 | ttyconf.setColor(&bw, .cyan) catch {}; |
| 705 | stderr.writeAll("Build Summary:") catch {}; | 707 | bw.writeAll("Build Summary:") catch {}; |
| 706 | ttyconf.setColor(stderr, .reset) catch {}; | 708 | ttyconf.setColor(&bw, .reset) catch {}; |
| 707 | stderr.writer().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; | 709 | bw.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {}; |
| 708 | if (skipped_count > 0) stderr.writer().print("; {d} skipped", .{skipped_count}) catch {}; | 710 | if (skipped_count > 0) bw.print("; {d} skipped", .{skipped_count}) catch {}; |
| 709 | if (failure_count > 0) stderr.writer().print("; {d} failed", .{failure_count}) catch {}; | 711 | if (failure_count > 0) bw.print("; {d} failed", .{failure_count}) catch {}; |
| 710 | 712 | ||
| 711 | if (test_count > 0) stderr.writer().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; | 713 | if (test_count > 0) bw.print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {}; |
| 712 | if (test_skip_count > 0) stderr.writer().print("; {d} skipped", .{test_skip_count}) catch {}; | 714 | if (test_skip_count > 0) bw.print("; {d} skipped", .{test_skip_count}) catch {}; |
| 713 | if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {}; | 715 | if (test_fail_count > 0) bw.print("; {d} failed", .{test_fail_count}) catch {}; |
| 714 | if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {}; | 716 | if (test_leak_count > 0) bw.print("; {d} leaked", .{test_leak_count}) catch {}; |
| 715 | 717 | ||
| 716 | stderr.writeAll("\n") catch {}; | 718 | bw.writeAll("\n") catch {}; |
| 717 | 719 | ||
| 718 | // Print a fancy tree with build results. | 720 | // Print a fancy tree with build results. |
| 719 | var step_stack_copy = try step_stack.clone(gpa); | 721 | var step_stack_copy = try step_stack.clone(gpa); |
| ... | @@ -722,7 +724,7 @@ fn runStepNames( | ... | @@ -722,7 +724,7 @@ fn runStepNames( |
| 722 | var print_node: PrintNode = .{ .parent = null }; | 724 | var print_node: PrintNode = .{ .parent = null }; |
| 723 | if (step_names.len == 0) { | 725 | if (step_names.len == 0) { |
| 724 | print_node.last = true; | 726 | print_node.last = true; |
| 725 | printTreeStep(b, b.default_step, run, stderr, ttyconf, &print_node, &step_stack_copy) catch {}; | 727 | printTreeStep(b, b.default_step, run, &bw, ttyconf, &print_node, &step_stack_copy) catch {}; |
| 726 | } else { | 728 | } else { |
| 727 | const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { | 729 | const last_index = if (run.summary == .all) b.top_level_steps.count() else blk: { |
| 728 | var i: usize = step_names.len; | 730 | var i: usize = step_names.len; |
| ... | @@ -741,7 +743,7 @@ fn runStepNames( | ... | @@ -741,7 +743,7 @@ fn runStepNames( |
| 741 | for (step_names, 0..) |step_name, i| { | 743 | for (step_names, 0..) |step_name, i| { |
| 742 | const tls = b.top_level_steps.get(step_name).?; | 744 | const tls = b.top_level_steps.get(step_name).?; |
| 743 | print_node.last = i + 1 == last_index; | 745 | print_node.last = i + 1 == last_index; |
| 744 | printTreeStep(b, &tls.step, run, stderr, ttyconf, &print_node, &step_stack_copy) catch {}; | 746 | printTreeStep(b, &tls.step, run, &bw, ttyconf, &print_node, &step_stack_copy) catch {}; |
| 745 | } | 747 | } |
| 746 | } | 748 | } |
| 747 | } | 749 | } |
| ... | @@ -775,7 +777,7 @@ const PrintNode = struct { | ... | @@ -775,7 +777,7 @@ const PrintNode = struct { |
| 775 | last: bool = false, | 777 | last: bool = false, |
| 776 | }; | 778 | }; |
| 777 | 779 | ||
| 778 | fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void { | 780 | fn printPrefix(node: *PrintNode, stderr: *std.io.BufferedWriter, ttyconf: std.io.tty.Config) !void { |
| 779 | const parent = node.parent orelse return; | 781 | const parent = node.parent orelse return; |
| 780 | if (parent.parent == null) return; | 782 | if (parent.parent == null) return; |
| 781 | try printPrefix(parent, stderr, ttyconf); | 783 | try printPrefix(parent, stderr, ttyconf); |
| ... | @@ -789,7 +791,7 @@ fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void | ... | @@ -789,7 +791,7 @@ fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void |
| 789 | } | 791 | } |
| 790 | } | 792 | } |
| 791 | 793 | ||
| 792 | fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { | 794 | fn printChildNodePrefix(stderr: *std.io.BufferedWriter, ttyconf: std.io.tty.Config) !void { |
| 793 | try stderr.writeAll(switch (ttyconf) { | 795 | try stderr.writeAll(switch (ttyconf) { |
| 794 | .no_color, .windows_api => "+- ", | 796 | .no_color, .windows_api => "+- ", |
| 795 | .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ | 797 | .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ |
| ... | @@ -798,7 +800,7 @@ fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { | ... | @@ -798,7 +800,7 @@ fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { |
| 798 | 800 | ||
| 799 | fn printStepStatus( | 801 | fn printStepStatus( |
| 800 | s: *Step, | 802 | s: *Step, |
| 801 | stderr: File, | 803 | stderr: *std.io.BufferedWriter, |
| 802 | ttyconf: std.io.tty.Config, | 804 | ttyconf: std.io.tty.Config, |
| 803 | run: *const Run, | 805 | run: *const Run, |
| 804 | ) !void { | 806 | ) !void { |
| ... | @@ -820,10 +822,10 @@ fn printStepStatus( | ... | @@ -820,10 +822,10 @@ fn printStepStatus( |
| 820 | try stderr.writeAll(" cached"); | 822 | try stderr.writeAll(" cached"); |
| 821 | } else if (s.test_results.test_count > 0) { | 823 | } else if (s.test_results.test_count > 0) { |
| 822 | const pass_count = s.test_results.passCount(); | 824 | const pass_count = s.test_results.passCount(); |
| 823 | try stderr.writer().print(" {d} passed", .{pass_count}); | 825 | try stderr.print(" {d} passed", .{pass_count}); |
| 824 | if (s.test_results.skip_count > 0) { | 826 | if (s.test_results.skip_count > 0) { |
| 825 | try ttyconf.setColor(stderr, .yellow); | 827 | try ttyconf.setColor(stderr, .yellow); |
| 826 | try stderr.writer().print(" {d} skipped", .{s.test_results.skip_count}); | 828 | try stderr.print(" {d} skipped", .{s.test_results.skip_count}); |
| 827 | } | 829 | } |
| 828 | } else { | 830 | } else { |
| 829 | try stderr.writeAll(" success"); | 831 | try stderr.writeAll(" success"); |
| ... | @@ -832,15 +834,15 @@ fn printStepStatus( | ... | @@ -832,15 +834,15 @@ fn printStepStatus( |
| 832 | if (s.result_duration_ns) |ns| { | 834 | if (s.result_duration_ns) |ns| { |
| 833 | try ttyconf.setColor(stderr, .dim); | 835 | try ttyconf.setColor(stderr, .dim); |
| 834 | if (ns >= std.time.ns_per_min) { | 836 | if (ns >= std.time.ns_per_min) { |
| 835 | try stderr.writer().print(" {d}m", .{ns / std.time.ns_per_min}); | 837 | try stderr.print(" {d}m", .{ns / std.time.ns_per_min}); |
| 836 | } else if (ns >= std.time.ns_per_s) { | 838 | } else if (ns >= std.time.ns_per_s) { |
| 837 | try stderr.writer().print(" {d}s", .{ns / std.time.ns_per_s}); | 839 | try stderr.print(" {d}s", .{ns / std.time.ns_per_s}); |
| 838 | } else if (ns >= std.time.ns_per_ms) { | 840 | } else if (ns >= std.time.ns_per_ms) { |
| 839 | try stderr.writer().print(" {d}ms", .{ns / std.time.ns_per_ms}); | 841 | try stderr.print(" {d}ms", .{ns / std.time.ns_per_ms}); |
| 840 | } else if (ns >= std.time.ns_per_us) { | 842 | } else if (ns >= std.time.ns_per_us) { |
| 841 | try stderr.writer().print(" {d}us", .{ns / std.time.ns_per_us}); | 843 | try stderr.print(" {d}us", .{ns / std.time.ns_per_us}); |
| 842 | } else { | 844 | } else { |
| 843 | try stderr.writer().print(" {d}ns", .{ns}); | 845 | try stderr.print(" {d}ns", .{ns}); |
| 844 | } | 846 | } |
| 845 | try ttyconf.setColor(stderr, .reset); | 847 | try ttyconf.setColor(stderr, .reset); |
| 846 | } | 848 | } |
| ... | @@ -848,13 +850,13 @@ fn printStepStatus( | ... | @@ -848,13 +850,13 @@ fn printStepStatus( |
| 848 | const rss = s.result_peak_rss; | 850 | const rss = s.result_peak_rss; |
| 849 | try ttyconf.setColor(stderr, .dim); | 851 | try ttyconf.setColor(stderr, .dim); |
| 850 | if (rss >= 1000_000_000) { | 852 | if (rss >= 1000_000_000) { |
| 851 | try stderr.writer().print(" MaxRSS:{d}G", .{rss / 1000_000_000}); | 853 | try stderr.print(" MaxRSS:{d}G", .{rss / 1000_000_000}); |
| 852 | } else if (rss >= 1000_000) { | 854 | } else if (rss >= 1000_000) { |
| 853 | try stderr.writer().print(" MaxRSS:{d}M", .{rss / 1000_000}); | 855 | try stderr.print(" MaxRSS:{d}M", .{rss / 1000_000}); |
| 854 | } else if (rss >= 1000) { | 856 | } else if (rss >= 1000) { |
| 855 | try stderr.writer().print(" MaxRSS:{d}K", .{rss / 1000}); | 857 | try stderr.print(" MaxRSS:{d}K", .{rss / 1000}); |
| 856 | } else { | 858 | } else { |
| 857 | try stderr.writer().print(" MaxRSS:{d}B", .{rss}); | 859 | try stderr.print(" MaxRSS:{d}B", .{rss}); |
| 858 | } | 860 | } |
| 859 | try ttyconf.setColor(stderr, .reset); | 861 | try ttyconf.setColor(stderr, .reset); |
| 860 | } | 862 | } |
| ... | @@ -866,7 +868,7 @@ fn printStepStatus( | ... | @@ -866,7 +868,7 @@ fn printStepStatus( |
| 866 | if (skip == .skipped_oom) { | 868 | if (skip == .skipped_oom) { |
| 867 | try stderr.writeAll(" (not enough memory)"); | 869 | try stderr.writeAll(" (not enough memory)"); |
| 868 | try ttyconf.setColor(stderr, .dim); | 870 | try ttyconf.setColor(stderr, .dim); |
| 869 | try stderr.writer().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); | 871 | try stderr.print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); |
| 870 | try ttyconf.setColor(stderr, .yellow); | 872 | try ttyconf.setColor(stderr, .yellow); |
| 871 | } | 873 | } |
| 872 | try stderr.writeAll("\n"); | 874 | try stderr.writeAll("\n"); |
| ... | @@ -878,23 +880,23 @@ fn printStepStatus( | ... | @@ -878,23 +880,23 @@ fn printStepStatus( |
| 878 | 880 | ||
| 879 | fn printStepFailure( | 881 | fn printStepFailure( |
| 880 | s: *Step, | 882 | s: *Step, |
| 881 | stderr: File, | 883 | stderr: *std.io.BufferedWriter, |
| 882 | ttyconf: std.io.tty.Config, | 884 | ttyconf: std.io.tty.Config, |
| 883 | ) !void { | 885 | ) !void { |
| 884 | if (s.result_error_bundle.errorMessageCount() > 0) { | 886 | if (s.result_error_bundle.errorMessageCount() > 0) { |
| 885 | try ttyconf.setColor(stderr, .red); | 887 | try ttyconf.setColor(stderr, .red); |
| 886 | try stderr.writer().print(" {d} errors\n", .{ | 888 | try stderr.print(" {d} errors\n", .{ |
| 887 | s.result_error_bundle.errorMessageCount(), | 889 | s.result_error_bundle.errorMessageCount(), |
| 888 | }); | 890 | }); |
| 889 | try ttyconf.setColor(stderr, .reset); | 891 | try ttyconf.setColor(stderr, .reset); |
| 890 | } else if (!s.test_results.isSuccess()) { | 892 | } else if (!s.test_results.isSuccess()) { |
| 891 | try stderr.writer().print(" {d}/{d} passed", .{ | 893 | try stderr.print(" {d}/{d} passed", .{ |
| 892 | s.test_results.passCount(), s.test_results.test_count, | 894 | s.test_results.passCount(), s.test_results.test_count, |
| 893 | }); | 895 | }); |
| 894 | if (s.test_results.fail_count > 0) { | 896 | if (s.test_results.fail_count > 0) { |
| 895 | try stderr.writeAll(", "); | 897 | try stderr.writeAll(", "); |
| 896 | try ttyconf.setColor(stderr, .red); | 898 | try ttyconf.setColor(stderr, .red); |
| 897 | try stderr.writer().print("{d} failed", .{ | 899 | try stderr.print("{d} failed", .{ |
| 898 | s.test_results.fail_count, | 900 | s.test_results.fail_count, |
| 899 | }); | 901 | }); |
| 900 | try ttyconf.setColor(stderr, .reset); | 902 | try ttyconf.setColor(stderr, .reset); |
| ... | @@ -902,7 +904,7 @@ fn printStepFailure( | ... | @@ -902,7 +904,7 @@ fn printStepFailure( |
| 902 | if (s.test_results.skip_count > 0) { | 904 | if (s.test_results.skip_count > 0) { |
| 903 | try stderr.writeAll(", "); | 905 | try stderr.writeAll(", "); |
| 904 | try ttyconf.setColor(stderr, .yellow); | 906 | try ttyconf.setColor(stderr, .yellow); |
| 905 | try stderr.writer().print("{d} skipped", .{ | 907 | try stderr.print("{d} skipped", .{ |
| 906 | s.test_results.skip_count, | 908 | s.test_results.skip_count, |
| 907 | }); | 909 | }); |
| 908 | try ttyconf.setColor(stderr, .reset); | 910 | try ttyconf.setColor(stderr, .reset); |
| ... | @@ -910,7 +912,7 @@ fn printStepFailure( | ... | @@ -910,7 +912,7 @@ fn printStepFailure( |
| 910 | if (s.test_results.leak_count > 0) { | 912 | if (s.test_results.leak_count > 0) { |
| 911 | try stderr.writeAll(", "); | 913 | try stderr.writeAll(", "); |
| 912 | try ttyconf.setColor(stderr, .red); | 914 | try ttyconf.setColor(stderr, .red); |
| 913 | try stderr.writer().print("{d} leaked", .{ | 915 | try stderr.print("{d} leaked", .{ |
| 914 | s.test_results.leak_count, | 916 | s.test_results.leak_count, |
| 915 | }); | 917 | }); |
| 916 | try ttyconf.setColor(stderr, .reset); | 918 | try ttyconf.setColor(stderr, .reset); |
| ... | @@ -932,7 +934,7 @@ fn printTreeStep( | ... | @@ -932,7 +934,7 @@ fn printTreeStep( |
| 932 | b: *std.Build, | 934 | b: *std.Build, |
| 933 | s: *Step, | 935 | s: *Step, |
| 934 | run: *const Run, | 936 | run: *const Run, |
| 935 | stderr: File, | 937 | stderr: *std.io.BufferedWriter, |
| 936 | ttyconf: std.io.tty.Config, | 938 | ttyconf: std.io.tty.Config, |
| 937 | parent_node: *PrintNode, | 939 | parent_node: *PrintNode, |
| 938 | step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), | 940 | step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), |
| ... | @@ -992,7 +994,7 @@ fn printTreeStep( | ... | @@ -992,7 +994,7 @@ fn printTreeStep( |
| 992 | if (s.dependencies.items.len == 0) { | 994 | if (s.dependencies.items.len == 0) { |
| 993 | try stderr.writeAll(" (reused)\n"); | 995 | try stderr.writeAll(" (reused)\n"); |
| 994 | } else { | 996 | } else { |
| 995 | try stderr.writer().print(" (+{d} more reused dependencies)\n", .{ | 997 | try stderr.print(" (+{d} more reused dependencies)\n", .{ |
| 996 | s.dependencies.items.len, | 998 | s.dependencies.items.len, |
| 997 | }); | 999 | }); |
| 998 | } | 1000 | } |
| ... | @@ -1129,11 +1131,11 @@ fn workerMakeOneStep( | ... | @@ -1129,11 +1131,11 @@ fn workerMakeOneStep( |
| 1129 | const show_stderr = s.result_stderr.len > 0; | 1131 | const show_stderr = s.result_stderr.len > 0; |
| 1130 | 1132 | ||
| 1131 | if (show_error_msgs or show_compile_errors or show_stderr) { | 1133 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 1132 | std.debug.lockStdErr(); | 1134 | var bw = std.debug.lockStdErr2(); |
| 1133 | defer std.debug.unlockStdErr(); | 1135 | defer std.debug.unlockStdErr(); |
| 1134 | 1136 | ||
| 1135 | const gpa = b.allocator; | 1137 | const gpa = b.allocator; |
| 1136 | printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, run.stderr, run.prominent_compile_errors) catch {}; | 1138 | printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, &bw, run.prominent_compile_errors) catch {}; |
| 1137 | } | 1139 | } |
| 1138 | 1140 | ||
| 1139 | handle_result: { | 1141 | handle_result: { |
| ... | @@ -1190,7 +1192,7 @@ pub fn printErrorMessages( | ... | @@ -1190,7 +1192,7 @@ pub fn printErrorMessages( |
| 1190 | gpa: Allocator, | 1192 | gpa: Allocator, |
| 1191 | failing_step: *Step, | 1193 | failing_step: *Step, |
| 1192 | options: std.zig.ErrorBundle.RenderOptions, | 1194 | options: std.zig.ErrorBundle.RenderOptions, |
| 1193 | stderr: File, | 1195 | stderr: *std.io.BufferedWriter, |
| 1194 | prominent_compile_errors: bool, | 1196 | prominent_compile_errors: bool, |
| 1195 | ) !void { | 1197 | ) !void { |
| 1196 | // Provide context for where these error messages are coming from by | 1198 | // Provide context for where these error messages are coming from by |
| ... | @@ -1209,7 +1211,7 @@ pub fn printErrorMessages( | ... | @@ -1209,7 +1211,7 @@ pub fn printErrorMessages( |
| 1209 | var indent: usize = 0; | 1211 | var indent: usize = 0; |
| 1210 | while (step_stack.pop()) |s| : (indent += 1) { | 1212 | while (step_stack.pop()) |s| : (indent += 1) { |
| 1211 | if (indent > 0) { | 1213 | if (indent > 0) { |
| 1212 | try stderr.writer().writeByteNTimes(' ', (indent - 1) * 3); | 1214 | try stderr.splatByteAll(' ', (indent - 1) * 3); |
| 1213 | try printChildNodePrefix(stderr, ttyconf); | 1215 | try printChildNodePrefix(stderr, ttyconf); |
| 1214 | } | 1216 | } |
| 1215 | 1217 | ||
| ... | @@ -1231,7 +1233,7 @@ pub fn printErrorMessages( | ... | @@ -1231,7 +1233,7 @@ pub fn printErrorMessages( |
| 1231 | } | 1233 | } |
| 1232 | 1234 | ||
| 1233 | if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) { | 1235 | if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) { |
| 1234 | try failing_step.result_error_bundle.renderToWriter(options, stderr.writer()); | 1236 | try failing_step.result_error_bundle.renderToWriter(options, stderr); |
| 1235 | } | 1237 | } |
| 1236 | 1238 | ||
| 1237 | for (failing_step.result_error_msgs.items) |msg| { | 1239 | for (failing_step.result_error_msgs.items) |msg| { |
| ... | @@ -1243,27 +1245,29 @@ pub fn printErrorMessages( | ... | @@ -1243,27 +1245,29 @@ pub fn printErrorMessages( |
| 1243 | } | 1245 | } |
| 1244 | } | 1246 | } |
| 1245 | 1247 | ||
| 1246 | fn steps(builder: *std.Build, out_stream: anytype) !void { | 1248 | fn steps(builder: *std.Build, bw: *std.io.BufferedWriter) !void { |
| 1247 | const allocator = builder.allocator; | 1249 | const allocator = builder.allocator; |
| 1248 | for (builder.top_level_steps.values()) |top_level_step| { | 1250 | for (builder.top_level_steps.values()) |top_level_step| { |
| 1249 | const name = if (&top_level_step.step == builder.default_step) | 1251 | const name = if (&top_level_step.step == builder.default_step) |
| 1250 | try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name}) | 1252 | try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name}) |
| 1251 | else | 1253 | else |
| 1252 | top_level_step.step.name; | 1254 | top_level_step.step.name; |
| 1253 | try out_stream.print(" {s:<28} {s}\n", .{ name, top_level_step.description }); | 1255 | try bw.print(" {s:<28} {s}\n", .{ name, top_level_step.description }); |
| 1254 | } | 1256 | } |
| 1255 | } | 1257 | } |
| 1256 | 1258 | ||
| 1257 | fn usage(b: *std.Build, out_stream: anytype) !void { | 1259 | var stdout_buffer: [256]u8 = undefined; |
| 1258 | try out_stream.print( | 1260 | |
| 1261 | fn usage(b: *std.Build, bw: *std.io.BufferedWriter) !void { | ||
| 1262 | try bw.print( | ||
| 1259 | \\Usage: {s} build [steps] [options] | 1263 | \\Usage: {s} build [steps] [options] |
| 1260 | \\ | 1264 | \\ |
| 1261 | \\Steps: | 1265 | \\Steps: |
| 1262 | \\ | 1266 | \\ |
| 1263 | , .{b.graph.zig_exe}); | 1267 | , .{b.graph.zig_exe}); |
| 1264 | try steps(b, out_stream); | 1268 | try steps(b, bw); |
| 1265 | 1269 | ||
| 1266 | try out_stream.writeAll( | 1270 | try bw.writeAll( |
| 1267 | \\ | 1271 | \\ |
| 1268 | \\General Options: | 1272 | \\General Options: |
| 1269 | \\ -p, --prefix [path] Where to install files (default: zig-out) | 1273 | \\ -p, --prefix [path] Where to install files (default: zig-out) |
| ... | @@ -1319,25 +1323,25 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1319,25 +1323,25 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1319 | 1323 | ||
| 1320 | const arena = b.allocator; | 1324 | const arena = b.allocator; |
| 1321 | if (b.available_options_list.items.len == 0) { | 1325 | if (b.available_options_list.items.len == 0) { |
| 1322 | try out_stream.print(" (none)\n", .{}); | 1326 | try bw.print(" (none)\n", .{}); |
| 1323 | } else { | 1327 | } else { |
| 1324 | for (b.available_options_list.items) |option| { | 1328 | for (b.available_options_list.items) |option| { |
| 1325 | const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ | 1329 | const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ |
| 1326 | option.name, | 1330 | option.name, |
| 1327 | @tagName(option.type_id), | 1331 | @tagName(option.type_id), |
| 1328 | }); | 1332 | }); |
| 1329 | try out_stream.print("{s:<30} {s}\n", .{ name, option.description }); | 1333 | try bw.print("{s:<30} {s}\n", .{ name, option.description }); |
| 1330 | if (option.enum_options) |enum_options| { | 1334 | if (option.enum_options) |enum_options| { |
| 1331 | const padding = " " ** 33; | 1335 | const padding = " " ** 33; |
| 1332 | try out_stream.writeAll(padding ++ "Supported Values:\n"); | 1336 | try bw.writeAll(padding ++ "Supported Values:\n"); |
| 1333 | for (enum_options) |enum_option| { | 1337 | for (enum_options) |enum_option| { |
| 1334 | try out_stream.print(padding ++ " {s}\n", .{enum_option}); | 1338 | try bw.print(padding ++ " {s}\n", .{enum_option}); |
| 1335 | } | 1339 | } |
| 1336 | } | 1340 | } |
| 1337 | } | 1341 | } |
| 1338 | } | 1342 | } |
| 1339 | 1343 | ||
| 1340 | try out_stream.writeAll( | 1344 | try bw.writeAll( |
| 1341 | \\ | 1345 | \\ |
| 1342 | \\System Integration Options: | 1346 | \\System Integration Options: |
| 1343 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers | 1347 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers |
| ... | @@ -1352,7 +1356,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1352,7 +1356,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1352 | \\ | 1356 | \\ |
| 1353 | ); | 1357 | ); |
| 1354 | if (b.graph.system_library_options.entries.len == 0) { | 1358 | if (b.graph.system_library_options.entries.len == 0) { |
| 1355 | try out_stream.writeAll(" (none) -\n"); | 1359 | try bw.writeAll(" (none) -\n"); |
| 1356 | } else { | 1360 | } else { |
| 1357 | for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { | 1361 | for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { |
| 1358 | const status = switch (v) { | 1362 | const status = switch (v) { |
| ... | @@ -1360,11 +1364,11 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1360,11 +1364,11 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1360 | .declared_disabled => "no", | 1364 | .declared_disabled => "no", |
| 1361 | .user_enabled, .user_disabled => unreachable, // already emitted error | 1365 | .user_enabled, .user_disabled => unreachable, // already emitted error |
| 1362 | }; | 1366 | }; |
| 1363 | try out_stream.print(" {s:<43} {s}\n", .{ k, status }); | 1367 | try bw.print(" {s:<43} {s}\n", .{ k, status }); |
| 1364 | } | 1368 | } |
| 1365 | } | 1369 | } |
| 1366 | 1370 | ||
| 1367 | try out_stream.writeAll( | 1371 | try bw.writeAll( |
| 1368 | \\ | 1372 | \\ |
| 1369 | \\Advanced Options: | 1373 | \\Advanced Options: |
| 1370 | \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error | 1374 | \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error |
lib/std/Build/Fuzz.zig+4-6| ... | @@ -112,7 +112,6 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog | ... | @@ -112,7 +112,6 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog |
| 112 | 112 | ||
| 113 | fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void { | 113 | fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void { |
| 114 | const gpa = run.step.owner.allocator; | 114 | const gpa = run.step.owner.allocator; |
| 115 | const stderr = std.io.getStdErr(); | ||
| 116 | 115 | ||
| 117 | const compile = run.producer.?; | 116 | const compile = run.producer.?; |
| 118 | const prog_node = parent_prog_node.start(compile.step.name, 0); | 117 | const prog_node = parent_prog_node.start(compile.step.name, 0); |
| ... | @@ -125,9 +124,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par | ... | @@ -125,9 +124,9 @@ fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, par |
| 125 | const show_stderr = compile.step.result_stderr.len > 0; | 124 | const show_stderr = compile.step.result_stderr.len > 0; |
| 126 | 125 | ||
| 127 | if (show_error_msgs or show_compile_errors or show_stderr) { | 126 | if (show_error_msgs or show_compile_errors or show_stderr) { |
| 128 | std.debug.lockStdErr(); | 127 | var bw = std.debug.lockStdErr2(); |
| 129 | defer std.debug.unlockStdErr(); | 128 | defer std.debug.unlockStdErr(); |
| 130 | build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, stderr, false) catch {}; | 129 | build_runner.printErrorMessages(gpa, &compile.step, .{ .ttyconf = ttyconf }, &bw, false) catch {}; |
| 131 | } | 130 | } |
| 132 | 131 | ||
| 133 | const rebuilt_bin_path = result catch |err| switch (err) { | 132 | const rebuilt_bin_path = result catch |err| switch (err) { |
| ... | @@ -152,10 +151,9 @@ fn fuzzWorkerRun( | ... | @@ -152,10 +151,9 @@ fn fuzzWorkerRun( |
| 152 | 151 | ||
| 153 | 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) { |
| 154 | error.MakeFailed => { | 153 | error.MakeFailed => { |
| 155 | const stderr = std.io.getStdErr(); | 154 | var bw = std.debug.lockStdErr2(); |
| 156 | std.debug.lockStdErr(); | ||
| 157 | defer std.debug.unlockStdErr(); | 155 | defer std.debug.unlockStdErr(); |
| 158 | build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, stderr, false) catch {}; | 156 | build_runner.printErrorMessages(gpa, &run.step, .{ .ttyconf = ttyconf }, &bw, false) catch {}; |
| 159 | return; | 157 | return; |
| 160 | }, | 158 | }, |
| 161 | else => { | 159 | else => { |
lib/std/Build/Step/CheckObject.zig+9-8| ... | @@ -1393,7 +1393,8 @@ const MachODumper = struct { | ... | @@ -1393,7 +1393,8 @@ const MachODumper = struct { |
| 1393 | }, | 1393 | }, |
| 1394 | macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => { | 1394 | macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => { |
| 1395 | name_buf.clearRetainingCapacity(); | 1395 | name_buf.clearRetainingCapacity(); |
| 1396 | try reader.readUntilDelimiterArrayList(&name_buf, 0, std.math.maxInt(u32)); | 1396 | if (true) @panic("TODO fix this"); |
| 1397 | //try reader.readUntilDelimiterArrayList(&name_buf, 0, std.math.maxInt(u32)); | ||
| 1397 | try name_buf.append(0); | 1398 | try name_buf.append(0); |
| 1398 | }, | 1399 | }, |
| 1399 | macho.BIND_OPCODE_SET_ADDEND_SLEB => { | 1400 | macho.BIND_OPCODE_SET_ADDEND_SLEB => { |
| ... | @@ -2430,10 +2431,11 @@ const WasmDumper = struct { | ... | @@ -2430,10 +2431,11 @@ const WasmDumper = struct { |
| 2430 | return error.UnsupportedWasmVersion; | 2431 | return error.UnsupportedWasmVersion; |
| 2431 | } | 2432 | } |
| 2432 | 2433 | ||
| 2433 | var output = std.ArrayList(u8).init(gpa); | 2434 | var output: std.io.AllocatingWriter = undefined; |
| 2435 | const bw = output.init(gpa); | ||
| 2434 | defer output.deinit(); | 2436 | defer output.deinit(); |
| 2435 | parseAndDumpInner(step, check, bytes, &fbs, &output) catch |err| switch (err) { | 2437 | parseAndDumpInner(step, check, bytes, &fbs, bw) catch |err| switch (err) { |
| 2436 | error.EndOfStream => try output.appendSlice("\n<UnexpectedEndOfStream>"), | 2438 | error.EndOfStream => try bw.writeAll("\n<UnexpectedEndOfStream>"), |
| 2437 | else => |e| return e, | 2439 | else => |e| return e, |
| 2438 | }; | 2440 | }; |
| 2439 | return output.toOwnedSlice(); | 2441 | return output.toOwnedSlice(); |
| ... | @@ -2443,11 +2445,10 @@ const WasmDumper = struct { | ... | @@ -2443,11 +2445,10 @@ const WasmDumper = struct { |
| 2443 | step: *Step, | 2445 | step: *Step, |
| 2444 | check: Check, | 2446 | check: Check, |
| 2445 | bytes: []const u8, | 2447 | bytes: []const u8, |
| 2446 | fbs: *std.io.FixedBufferStream([]const u8), | 2448 | fbs: *std.io.FixedBufferStream, |
| 2447 | output: *std.ArrayList(u8), | 2449 | bw: *std.io.BufferedWriter, |
| 2448 | ) !void { | 2450 | ) !void { |
| 2449 | const reader = fbs.reader(); | 2451 | const reader = fbs.reader(); |
| 2450 | const writer = output.writer(); | ||
| 2451 | 2452 | ||
| 2452 | switch (check.kind) { | 2453 | switch (check.kind) { |
| 2453 | .headers => { | 2454 | .headers => { |
| ... | @@ -2457,7 +2458,7 @@ const WasmDumper = struct { | ... | @@ -2457,7 +2458,7 @@ const WasmDumper = struct { |
| 2457 | }; | 2458 | }; |
| 2458 | 2459 | ||
| 2459 | const section_length = try std.leb.readUleb128(u32, reader); | 2460 | const section_length = try std.leb.readUleb128(u32, reader); |
| 2460 | try parseAndDumpSection(step, section, bytes[fbs.pos..][0..section_length], writer); | 2461 | try parseAndDumpSection(step, section, bytes[fbs.pos..][0..section_length], bw); |
| 2461 | fbs.pos += section_length; | 2462 | fbs.pos += section_length; |
| 2462 | } else |_| {} // reached end of stream | 2463 | } else |_| {} // reached end of stream |
| 2463 | }, | 2464 | }, |
lib/std/Build/Step/Compile.zig+6-6| ... | @@ -2040,17 +2040,17 @@ fn checkCompileErrors(compile: *Compile) !void { | ... | @@ -2040,17 +2040,17 @@ fn checkCompileErrors(compile: *Compile) !void { |
| 2040 | .exact => |expect_lines| { | 2040 | .exact => |expect_lines| { |
| 2041 | for (expect_lines) |expect_line| { | 2041 | for (expect_lines) |expect_line| { |
| 2042 | const actual_line = actual_line_it.next() orelse { | 2042 | const actual_line = actual_line_it.next() orelse { |
| 2043 | try expected_generated.appendSlice(expect_line); | 2043 | try expected_generated.appendSlice(arena, expect_line); |
| 2044 | try expected_generated.append('\n'); | 2044 | try expected_generated.append(arena, '\n'); |
| 2045 | continue; | 2045 | continue; |
| 2046 | }; | 2046 | }; |
| 2047 | if (matchCompileError(actual_line, expect_line)) { | 2047 | if (matchCompileError(actual_line, expect_line)) { |
| 2048 | try expected_generated.appendSlice(actual_line); | 2048 | try expected_generated.appendSlice(arena, actual_line); |
| 2049 | try expected_generated.append('\n'); | 2049 | try expected_generated.append(arena, '\n'); |
| 2050 | continue; | 2050 | continue; |
| 2051 | } | 2051 | } |
| 2052 | try expected_generated.appendSlice(expect_line); | 2052 | try expected_generated.appendSlice(arena, expect_line); |
| 2053 | try expected_generated.append('\n'); | 2053 | try expected_generated.append(arena, '\n'); |
| 2054 | } | 2054 | } |
| 2055 | 2055 | ||
| 2056 | if (mem.eql(u8, expected_generated.items, actual_errors)) return; | 2056 | if (mem.eql(u8, expected_generated.items, actual_errors)) return; |
lib/std/Build/Step/ConfigHeader.zig+5-5| ... | @@ -599,14 +599,14 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) ! | ... | @@ -599,14 +599,14 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) ! |
| 599 | try output.appendSlice(if (b) " 1\n" else " 0\n"); | 599 | try output.appendSlice(if (b) " 1\n" else " 0\n"); |
| 600 | }, | 600 | }, |
| 601 | .int => |i| { | 601 | .int => |i| { |
| 602 | try output.writer().print("%define {s} {d}\n", .{ name, i }); | 602 | try output.print("%define {s} {d}\n", .{ name, i }); |
| 603 | }, | 603 | }, |
| 604 | .ident => |ident| { | 604 | .ident => |ident| { |
| 605 | try output.writer().print("%define {s} {s}\n", .{ name, ident }); | 605 | try output.print("%define {s} {s}\n", .{ name, ident }); |
| 606 | }, | 606 | }, |
| 607 | .string => |string| { | 607 | .string => |string| { |
| 608 | // TODO: use nasm-specific escaping instead of zig string literals | 608 | // TODO: use nasm-specific escaping instead of zig string literals |
| 609 | try output.writer().print("%define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) }); | 609 | try output.print("%define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) }); |
| 610 | }, | 610 | }, |
| 611 | } | 611 | } |
| 612 | } | 612 | } |
| ... | @@ -707,7 +707,7 @@ fn expand_variables_cmake( | ... | @@ -707,7 +707,7 @@ fn expand_variables_cmake( |
| 707 | try result.append(if (b) '1' else '0'); | 707 | try result.append(if (b) '1' else '0'); |
| 708 | }, | 708 | }, |
| 709 | .int => |i| { | 709 | .int => |i| { |
| 710 | try result.writer().print("{d}", .{i}); | 710 | try result.print("{d}", .{i}); |
| 711 | }, | 711 | }, |
| 712 | .ident, .string => |s| { | 712 | .ident, .string => |s| { |
| 713 | try result.appendSlice(s); | 713 | try result.appendSlice(s); |
| ... | @@ -764,7 +764,7 @@ fn expand_variables_cmake( | ... | @@ -764,7 +764,7 @@ fn expand_variables_cmake( |
| 764 | try result.append(if (b) '1' else '0'); | 764 | try result.append(if (b) '1' else '0'); |
| 765 | }, | 765 | }, |
| 766 | .int => |i| { | 766 | .int => |i| { |
| 767 | try result.writer().print("{d}", .{i}); | 767 | try result.print("{d}", .{i}); |
| 768 | }, | 768 | }, |
| 769 | .ident, .string => |s| { | 769 | .ident, .string => |s| { |
| 770 | try result.appendSlice(s); | 770 | try result.appendSlice(s); |
lib/std/Uri.zig+4-3| ... | @@ -445,13 +445,14 @@ test remove_dot_segments { | ... | @@ -445,13 +445,14 @@ test remove_dot_segments { |
| 445 | 445 | ||
| 446 | /// 5.2.3. Merge Paths | 446 | /// 5.2.3. Merge Paths |
| 447 | fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component { | 447 | fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component { |
| 448 | var aux = std.io.fixedBufferStream(aux_buf.*); | 448 | var aux: std.io.BufferedWriter = undefined; |
| 449 | aux.initFixed(aux_buf.*); | ||
| 449 | if (!base.isEmpty()) { | 450 | if (!base.isEmpty()) { |
| 450 | try aux.writer().print("{path}", .{base}); | 451 | aux.print("{fpath}", .{base}) catch |err| return @errorCast(err); |
| 451 | aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse | 452 | aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse |
| 452 | return remove_dot_segments(new); | 453 | return remove_dot_segments(new); |
| 453 | } | 454 | } |
| 454 | try aux.writer().print("/{s}", .{new}); | 455 | aux.print("/{s}", .{new}) catch |err| return @errorCast(err); |
| 455 | const merged_path = remove_dot_segments(aux.getWritten()); | 456 | const merged_path = remove_dot_segments(aux.getWritten()); |
| 456 | aux_buf.* = aux_buf.*[merged_path.percent_encoded.len..]; | 457 | aux_buf.* = aux_buf.*[merged_path.percent_encoded.len..]; |
| 457 | return merged_path; | 458 | return merged_path; |
lib/std/array_list.zig+15-1| ... | @@ -338,6 +338,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty | ... | @@ -338,6 +338,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?mem.Alignment) ty |
| 338 | @memcpy(self.items[old_len..][0..items.len], items); | 338 | @memcpy(self.items[old_len..][0..items.len], items); |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | pub fn print(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void { | ||
| 342 | var unmanaged = self.moveToUnmanaged(); | ||
| 343 | try unmanaged.print(self.allocator, fmt, args); | ||
| 344 | self.* = unmanaged.toManaged(self.allocator); | ||
| 345 | } | ||
| 346 | |||
| 341 | /// Append a value to the list `n` times. | 347 | /// Append a value to the list `n` times. |
| 342 | /// Allocates more memory as necessary. | 348 | /// Allocates more memory as necessary. |
| 343 | /// Invalidates element pointers if additional memory is needed. | 349 | /// Invalidates element pointers if additional memory is needed. |
| ... | @@ -902,7 +908,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig | ... | @@ -902,7 +908,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig |
| 902 | var aw: std.io.AllocatingWriter = undefined; | 908 | var aw: std.io.AllocatingWriter = undefined; |
| 903 | const bw = aw.fromArrayList(gpa, self); | 909 | const bw = aw.fromArrayList(gpa, self); |
| 904 | defer self.* = aw.toArrayList(); | 910 | defer self.* = aw.toArrayList(); |
| 905 | bw.print(fmt, args) catch return error.OutOfMemory; | 911 | return @errorCast(bw.print(fmt, args)); |
| 912 | } | ||
| 913 | |||
| 914 | pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void { | ||
| 915 | comptime assert(T == u8); | ||
| 916 | var bw: std.io.BufferedWriter = undefined; | ||
| 917 | bw.initFixed(self.unusedCapacitySlice()); | ||
| 918 | bw.print(fmt, args) catch unreachable; | ||
| 919 | self.items.len += bw.end; | ||
| 906 | } | 920 | } |
| 907 | 921 | ||
| 908 | /// Append a value to the list `n` times. | 922 | /// Append a value to the list `n` times. |
lib/std/http/Server.zig+64-14| ... | @@ -421,9 +421,9 @@ pub const Request = struct { | ... | @@ -421,9 +421,9 @@ pub const Request = struct { |
| 421 | try request.server.connection.stream.writeAll(h.items); | 421 | try request.server.connection.stream.writeAll(h.items); |
| 422 | return; | 422 | return; |
| 423 | } | 423 | } |
| 424 | h.fixedWriter().print("{s} {d} {s}\r\n", .{ | 424 | h.printAssumeCapacity("{s} {d} {s}\r\n", .{ |
| 425 | @tagName(options.version), @intFromEnum(options.status), phrase, | 425 | @tagName(options.version), @intFromEnum(options.status), phrase, |
| 426 | }) catch unreachable; | 426 | }); |
| 427 | 427 | ||
| 428 | switch (options.version) { | 428 | switch (options.version) { |
| 429 | .@"HTTP/1.0" => if (keep_alive) h.appendSliceAssumeCapacity("connection: keep-alive\r\n"), | 429 | .@"HTTP/1.0" => if (keep_alive) h.appendSliceAssumeCapacity("connection: keep-alive\r\n"), |
| ... | @@ -434,7 +434,7 @@ pub const Request = struct { | ... | @@ -434,7 +434,7 @@ pub const Request = struct { |
| 434 | .none => {}, | 434 | .none => {}, |
| 435 | .chunked => h.appendSliceAssumeCapacity("transfer-encoding: chunked\r\n"), | 435 | .chunked => h.appendSliceAssumeCapacity("transfer-encoding: chunked\r\n"), |
| 436 | } else { | 436 | } else { |
| 437 | h.fixedWriter().print("content-length: {d}\r\n", .{content.len}) catch unreachable; | 437 | h.printAssumeCapacity("content-length: {d}\r\n", .{content.len}); |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | var chunk_header_buffer: [18]u8 = undefined; | 440 | var chunk_header_buffer: [18]u8 = undefined; |
| ... | @@ -573,9 +573,9 @@ pub const Request = struct { | ... | @@ -573,9 +573,9 @@ pub const Request = struct { |
| 573 | h.appendSliceAssumeCapacity("content-length: 0\r\n\r\n"); | 573 | h.appendSliceAssumeCapacity("content-length: 0\r\n\r\n"); |
| 574 | break :eb true; | 574 | break :eb true; |
| 575 | } else eb: { | 575 | } else eb: { |
| 576 | h.fixedWriter().print("{s} {d} {s}\r\n", .{ | 576 | h.printAssumeCapacity("{s} {d} {s}\r\n", .{ |
| 577 | @tagName(o.version), @intFromEnum(o.status), phrase, | 577 | @tagName(o.version), @intFromEnum(o.status), phrase, |
| 578 | }) catch unreachable; | 578 | }); |
| 579 | 579 | ||
| 580 | switch (o.version) { | 580 | switch (o.version) { |
| 581 | .@"HTTP/1.0" => if (keep_alive) h.appendSliceAssumeCapacity("connection: keep-alive\r\n"), | 581 | .@"HTTP/1.0" => if (keep_alive) h.appendSliceAssumeCapacity("connection: keep-alive\r\n"), |
| ... | @@ -586,7 +586,7 @@ pub const Request = struct { | ... | @@ -586,7 +586,7 @@ pub const Request = struct { |
| 586 | .chunked => h.appendSliceAssumeCapacity("transfer-encoding: chunked\r\n"), | 586 | .chunked => h.appendSliceAssumeCapacity("transfer-encoding: chunked\r\n"), |
| 587 | .none => {}, | 587 | .none => {}, |
| 588 | } else if (options.content_length) |len| { | 588 | } else if (options.content_length) |len| { |
| 589 | h.fixedWriter().print("content-length: {d}\r\n", .{len}) catch unreachable; | 589 | h.printAssumeCapacity("content-length: {d}\r\n", .{len}); |
| 590 | } else { | 590 | } else { |
| 591 | h.appendSliceAssumeCapacity("transfer-encoding: chunked\r\n"); | 591 | h.appendSliceAssumeCapacity("transfer-encoding: chunked\r\n"); |
| 592 | } | 592 | } |
| ... | @@ -889,12 +889,34 @@ pub const Response = struct { | ... | @@ -889,12 +889,34 @@ pub const Response = struct { |
| 889 | /// when the end of stream occurs by calling `end`. | 889 | /// when the end of stream occurs by calling `end`. |
| 890 | pub fn write(r: *Response, bytes: []const u8) WriteError!usize { | 890 | pub fn write(r: *Response, bytes: []const u8) WriteError!usize { |
| 891 | switch (r.transfer_encoding) { | 891 | switch (r.transfer_encoding) { |
| 892 | .content_length, .none => return write_cl(r, bytes), | 892 | .content_length, .none => return @errorCast(cl_writeSplat(r, &.{bytes}, 1)), |
| 893 | .chunked => return write_chunked(r, bytes), | 893 | .chunked => return @errorCast(chunked_writeSplat(r, &.{bytes}, 1)), |
| 894 | } | 894 | } |
| 895 | } | 895 | } |
| 896 | 896 | ||
| 897 | fn write_cl(context: *const anyopaque, bytes: []const u8) WriteError!usize { | 897 | fn cl_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize { |
| 898 | _ = splat; | ||
| 899 | return cl_write(context, data[0]); // TODO: try to send all the data | ||
| 900 | } | ||
| 901 | |||
| 902 | fn cl_writeFile( | ||
| 903 | context: *anyopaque, | ||
| 904 | file: std.fs.File, | ||
| 905 | offset: u64, | ||
| 906 | len: std.io.Writer.VTable.FileLen, | ||
| 907 | headers_and_trailers: []const []const u8, | ||
| 908 | headers_len: usize, | ||
| 909 | ) anyerror!usize { | ||
| 910 | _ = context; | ||
| 911 | _ = file; | ||
| 912 | _ = offset; | ||
| 913 | _ = len; | ||
| 914 | _ = headers_and_trailers; | ||
| 915 | _ = headers_len; | ||
| 916 | return error.Unimplemented; | ||
| 917 | } | ||
| 918 | |||
| 919 | fn cl_write(context: *anyopaque, bytes: []const u8) WriteError!usize { | ||
| 898 | const r: *Response = @constCast(@alignCast(@ptrCast(context))); | 920 | const r: *Response = @constCast(@alignCast(@ptrCast(context))); |
| 899 | 921 | ||
| 900 | var trash: u64 = std.math.maxInt(u64); | 922 | var trash: u64 = std.math.maxInt(u64); |
| ... | @@ -944,7 +966,29 @@ pub const Response = struct { | ... | @@ -944,7 +966,29 @@ pub const Response = struct { |
| 944 | return bytes.len; | 966 | return bytes.len; |
| 945 | } | 967 | } |
| 946 | 968 | ||
| 947 | fn write_chunked(context: *const anyopaque, bytes: []const u8) WriteError!usize { | 969 | fn chunked_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize { |
| 970 | _ = splat; | ||
| 971 | return chunked_write(context, data[0]); // TODO: try to send all the data | ||
| 972 | } | ||
| 973 | |||
| 974 | fn chunked_writeFile( | ||
| 975 | context: *anyopaque, | ||
| 976 | file: std.fs.File, | ||
| 977 | offset: u64, | ||
| 978 | len: std.io.Writer.VTable.FileLen, | ||
| 979 | headers_and_trailers: []const []const u8, | ||
| 980 | headers_len: usize, | ||
| 981 | ) anyerror!usize { | ||
| 982 | _ = context; | ||
| 983 | _ = file; | ||
| 984 | _ = offset; | ||
| 985 | _ = len; | ||
| 986 | _ = headers_and_trailers; | ||
| 987 | _ = headers_len; | ||
| 988 | return error.Unimplemented; | ||
| 989 | } | ||
| 990 | |||
| 991 | fn chunked_write(context: *anyopaque, bytes: []const u8) WriteError!usize { | ||
| 948 | const r: *Response = @constCast(@alignCast(@ptrCast(context))); | 992 | const r: *Response = @constCast(@alignCast(@ptrCast(context))); |
| 949 | assert(r.transfer_encoding == .chunked); | 993 | assert(r.transfer_encoding == .chunked); |
| 950 | 994 | ||
| ... | @@ -1115,11 +1159,17 @@ pub const Response = struct { | ... | @@ -1115,11 +1159,17 @@ pub const Response = struct { |
| 1115 | r.chunk_len = 0; | 1159 | r.chunk_len = 0; |
| 1116 | } | 1160 | } |
| 1117 | 1161 | ||
| 1118 | pub fn writer(r: *Response) std.io.AnyWriter { | 1162 | pub fn writer(r: *Response) std.io.Writer { |
| 1119 | return .{ | 1163 | return .{ |
| 1120 | .writeFn = switch (r.transfer_encoding) { | 1164 | .vtable = switch (r.transfer_encoding) { |
| 1121 | .none, .content_length => write_cl, | 1165 | .none, .content_length => &.{ |
| 1122 | .chunked => write_chunked, | 1166 | .writeSplat = cl_writeSplat, |
| 1167 | .writeFile = cl_writeFile, | ||
| 1168 | }, | ||
| 1169 | .chunked => &.{ | ||
| 1170 | .writeSplat = chunked_writeSplat, | ||
| 1171 | .writeFile = chunked_writeFile, | ||
| 1172 | }, | ||
| 1123 | }, | 1173 | }, |
| 1124 | .context = r, | 1174 | .context = r, |
| 1125 | }; | 1175 | }; |
lib/std/io.zig-13| ... | @@ -123,19 +123,6 @@ pub fn GenericReader( | ... | @@ -123,19 +123,6 @@ pub fn GenericReader( |
| 123 | return @errorCast(self.any().readAllAlloc(allocator, max_size)); | 123 | return @errorCast(self.any().readAllAlloc(allocator, max_size)); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | pub inline fn readUntilDelimiterArrayList( | ||
| 127 | self: Self, | ||
| 128 | array_list: *std.ArrayList(u8), | ||
| 129 | delimiter: u8, | ||
| 130 | max_size: usize, | ||
| 131 | ) (NoEofError || Allocator.Error || error{StreamTooLong})!void { | ||
| 132 | return @errorCast(self.any().readUntilDelimiterArrayList( | ||
| 133 | array_list, | ||
| 134 | delimiter, | ||
| 135 | max_size, | ||
| 136 | )); | ||
| 137 | } | ||
| 138 | |||
| 139 | pub inline fn readUntilDelimiterAlloc( | 126 | pub inline fn readUntilDelimiterAlloc( |
| 140 | self: Self, | 127 | self: Self, |
| 141 | allocator: Allocator, | 128 | allocator: Allocator, |
lib/std/io/AllocatingWriter.zig+2| ... | @@ -17,6 +17,8 @@ const assert = std.debug.assert; | ... | @@ -17,6 +17,8 @@ const assert = std.debug.assert; |
| 17 | /// returning a slice that includes both. | 17 | /// returning a slice that includes both. |
| 18 | written: []u8, | 18 | written: []u8, |
| 19 | allocator: std.mem.Allocator, | 19 | allocator: std.mem.Allocator, |
| 20 | /// When using this API, it is not necessary to call | ||
| 21 | /// `std.io.BufferedWriter.flush`. | ||
| 20 | buffered_writer: std.io.BufferedWriter, | 22 | buffered_writer: std.io.BufferedWriter, |
| 21 | 23 | ||
| 22 | const vtable: std.io.Writer.VTable = .{ | 24 | const vtable: std.io.Writer.VTable = .{ |
lib/std/io/BufferedWriter.zig+3-3| ... | @@ -33,7 +33,7 @@ pub fn writer(bw: *BufferedWriter) Writer { | ... | @@ -33,7 +33,7 @@ pub fn writer(bw: *BufferedWriter) Writer { |
| 33 | return .{ | 33 | return .{ |
| 34 | .context = bw, | 34 | .context = bw, |
| 35 | .vtable = &.{ | 35 | .vtable = &.{ |
| 36 | .write = passthru_writeSplat, | 36 | .writeSplat = passthru_writeSplat, |
| 37 | .writeFile = passthru_writeFile, | 37 | .writeFile = passthru_writeFile, |
| 38 | }, | 38 | }, |
| 39 | }; | 39 | }; |
| ... | @@ -1003,7 +1003,7 @@ pub fn printFloat( | ... | @@ -1003,7 +1003,7 @@ pub fn printFloat( |
| 1003 | 'x' => { | 1003 | 'x' => { |
| 1004 | var sub_bw: BufferedWriter = undefined; | 1004 | var sub_bw: BufferedWriter = undefined; |
| 1005 | sub_bw.initFixed(&buf); | 1005 | sub_bw.initFixed(&buf); |
| 1006 | sub_bw.printFloatHexadecimal(value, options) catch unreachable; | 1006 | sub_bw.printFloatHexadecimal(value, options.precision) catch unreachable; |
| 1007 | return alignBufferOptions(bw, sub_bw.getWritten(), options); | 1007 | return alignBufferOptions(bw, sub_bw.getWritten(), options); |
| 1008 | }, | 1008 | }, |
| 1009 | else => invalidFmtError(fmt, value), | 1009 | else => invalidFmtError(fmt, value), |
| ... | @@ -1103,7 +1103,7 @@ pub fn printFloatHexadecimal(bw: *BufferedWriter, value: anytype, opt_precision: | ... | @@ -1103,7 +1103,7 @@ pub fn printFloatHexadecimal(bw: *BufferedWriter, value: anytype, opt_precision: |
| 1103 | // Add trailing zeros if explicitly requested. | 1103 | // Add trailing zeros if explicitly requested. |
| 1104 | if (opt_precision) |precision| if (precision > 0) { | 1104 | if (opt_precision) |precision| if (precision > 0) { |
| 1105 | if (precision > trimmed.len) | 1105 | if (precision > trimmed.len) |
| 1106 | try bw.writeByteNTimes('0', precision - trimmed.len); | 1106 | try bw.splatByteAll('0', precision - trimmed.len); |
| 1107 | }; | 1107 | }; |
| 1108 | try bw.writeAll("p"); | 1108 | try bw.writeAll("p"); |
| 1109 | try printIntOptions(bw, exponent - exponent_bias, 10, .lower, .{}); | 1109 | try printIntOptions(bw, exponent - exponent_bias, 10, .lower, .{}); |
lib/std/io/Reader.zig+4-98| ... | @@ -93,108 +93,14 @@ pub fn readAllAlloc(self: Self, allocator: mem.Allocator, max_size: usize) anyer | ... | @@ -93,108 +93,14 @@ pub fn readAllAlloc(self: Self, allocator: mem.Allocator, max_size: usize) anyer |
| 93 | return try array_list.toOwnedSlice(); | 93 | return try array_list.toOwnedSlice(); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead. | 96 | /// Appends to `bw` contents by reading from the stream until `delimiter` is found. |
| 97 | /// Replaces the `std.ArrayList` contents by reading from the stream until `delimiter` is found. | ||
| 98 | /// Does not include the delimiter in the result. | ||
| 99 | /// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the | ||
| 100 | /// `std.ArrayList` is populated with `max_size` bytes from the stream. | ||
| 101 | pub fn readUntilDelimiterArrayList( | ||
| 102 | self: Self, | ||
| 103 | array_list: *std.ArrayList(u8), | ||
| 104 | delimiter: u8, | ||
| 105 | max_size: usize, | ||
| 106 | ) anyerror!void { | ||
| 107 | array_list.shrinkRetainingCapacity(0); | ||
| 108 | try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size); | ||
| 109 | } | ||
| 110 | |||
| 111 | /// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead. | ||
| 112 | /// Allocates enough memory to read until `delimiter`. If the allocated | ||
| 113 | /// memory would be greater than `max_size`, returns `error.StreamTooLong`. | ||
| 114 | /// Caller owns returned memory. | ||
| 115 | /// If this function returns an error, the contents from the stream read so far are lost. | ||
| 116 | pub fn readUntilDelimiterAlloc( | ||
| 117 | self: Self, | ||
| 118 | allocator: mem.Allocator, | ||
| 119 | delimiter: u8, | ||
| 120 | max_size: usize, | ||
| 121 | ) anyerror![]u8 { | ||
| 122 | var array_list = std.ArrayList(u8).init(allocator); | ||
| 123 | defer array_list.deinit(); | ||
| 124 | try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size); | ||
| 125 | return try array_list.toOwnedSlice(); | ||
| 126 | } | ||
| 127 | |||
| 128 | /// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead. | ||
| 129 | /// Reads from the stream until specified byte is found. If the buffer is not | ||
| 130 | /// large enough to hold the entire contents, `error.StreamTooLong` is returned. | ||
| 131 | /// If end-of-stream is found, `error.EndOfStream` is returned. | ||
| 132 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The | ||
| 133 | /// delimiter byte is written to the output buffer but is not included | ||
| 134 | /// in the returned slice. | ||
| 135 | pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) anyerror![]u8 { | ||
| 136 | var fbs = std.io.fixedBufferStream(buf); | ||
| 137 | try self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len); | ||
| 138 | const output = fbs.getWritten(); | ||
| 139 | buf[output.len] = delimiter; // emulating old behaviour | ||
| 140 | return output; | ||
| 141 | } | ||
| 142 | |||
| 143 | /// Deprecated: use `streamUntilDelimiter` with ArrayList's (or any other's) writer instead. | ||
| 144 | /// Allocates enough memory to read until `delimiter` or end-of-stream. | ||
| 145 | /// If the allocated memory would be greater than `max_size`, returns | ||
| 146 | /// `error.StreamTooLong`. If end-of-stream is found, returns the rest | ||
| 147 | /// of the stream. If this function is called again after that, returns | ||
| 148 | /// null. | ||
| 149 | /// Caller owns returned memory. | ||
| 150 | /// If this function returns an error, the contents from the stream read so far are lost. | ||
| 151 | pub fn readUntilDelimiterOrEofAlloc( | ||
| 152 | self: Self, | ||
| 153 | allocator: mem.Allocator, | ||
| 154 | delimiter: u8, | ||
| 155 | max_size: usize, | ||
| 156 | ) anyerror!?[]u8 { | ||
| 157 | var array_list = std.ArrayList(u8).init(allocator); | ||
| 158 | defer array_list.deinit(); | ||
| 159 | self.streamUntilDelimiter(array_list.writer(), delimiter, max_size) catch |err| switch (err) { | ||
| 160 | error.EndOfStream => if (array_list.items.len == 0) { | ||
| 161 | return null; | ||
| 162 | }, | ||
| 163 | else => |e| return e, | ||
| 164 | }; | ||
| 165 | return try array_list.toOwnedSlice(); | ||
| 166 | } | ||
| 167 | |||
| 168 | /// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead. | ||
| 169 | /// Reads from the stream until specified byte is found. If the buffer is not | ||
| 170 | /// large enough to hold the entire contents, `error.StreamTooLong` is returned. | ||
| 171 | /// If end-of-stream is found, returns the rest of the stream. If this | ||
| 172 | /// function is called again after that, returns null. | ||
| 173 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The | ||
| 174 | /// delimiter byte is written to the output buffer but is not included | ||
| 175 | /// in the returned slice. | ||
| 176 | pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) anyerror!?[]u8 { | ||
| 177 | var fbs = std.io.fixedBufferStream(buf); | ||
| 178 | self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len) catch |err| switch (err) { | ||
| 179 | error.EndOfStream => if (fbs.getWritten().len == 0) { | ||
| 180 | return null; | ||
| 181 | }, | ||
| 182 | |||
| 183 | else => |e| return e, | ||
| 184 | }; | ||
| 185 | const output = fbs.getWritten(); | ||
| 186 | buf[output.len] = delimiter; // emulating old behaviour | ||
| 187 | return output; | ||
| 188 | } | ||
| 189 | |||
| 190 | /// Appends to the `writer` contents by reading from the stream until `delimiter` is found. | ||
| 191 | /// Does not write the delimiter itself. | 97 | /// Does not write the delimiter itself. |
| 192 | /// If `optional_max_size` is not null and amount of written bytes exceeds `optional_max_size`, | 98 | /// If `optional_max_size` is not null and amount of written bytes exceeds `optional_max_size`, |
| 193 | /// returns `error.StreamTooLong` and finishes appending. | 99 | /// returns `error.StreamTooLong` and finishes appending. |
| 194 | /// If `optional_max_size` is null, appending is unbounded. | 100 | /// If `optional_max_size` is null, appending is unbounded. |
| 195 | pub fn streamUntilDelimiter( | 101 | pub fn streamUntilDelimiter( |
| 196 | self: Self, | 102 | self: Self, |
| 197 | writer: anytype, | 103 | bw: *std.io.BufferedWriter, |
| 198 | delimiter: u8, | 104 | delimiter: u8, |
| 199 | optional_max_size: ?usize, | 105 | optional_max_size: ?usize, |
| 200 | ) anyerror!void { | 106 | ) anyerror!void { |
| ... | @@ -202,14 +108,14 @@ pub fn streamUntilDelimiter( | ... | @@ -202,14 +108,14 @@ pub fn streamUntilDelimiter( |
| 202 | for (0..max_size) |_| { | 108 | for (0..max_size) |_| { |
| 203 | const byte: u8 = try self.readByte(); | 109 | const byte: u8 = try self.readByte(); |
| 204 | if (byte == delimiter) return; | 110 | if (byte == delimiter) return; |
| 205 | try writer.writeByte(byte); | 111 | try bw.writeByte(byte); |
| 206 | } | 112 | } |
| 207 | return error.StreamTooLong; | 113 | return error.StreamTooLong; |
| 208 | } else { | 114 | } else { |
| 209 | while (true) { | 115 | while (true) { |
| 210 | const byte: u8 = try self.readByte(); | 116 | const byte: u8 = try self.readByte(); |
| 211 | if (byte == delimiter) return; | 117 | if (byte == delimiter) return; |
| 212 | try writer.writeByte(byte); | 118 | try bw.writeByte(byte); |
| 213 | } | 119 | } |
| 214 | // Can not throw `error.StreamTooLong` since there are no boundary. | 120 | // Can not throw `error.StreamTooLong` since there are no boundary. |
| 215 | } | 121 | } |
lib/std/tar/writer.zig+156-167| ... | @@ -2,187 +2,176 @@ const std = @import("std"); | ... | @@ -2,187 +2,176 @@ const std = @import("std"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 3 | const testing = std.testing; |
| 4 | 4 | ||
| 5 | /// Creates tar Writer which will write tar content to the `underlying_writer`. | 5 | pub const Writer = struct { |
| 6 | /// Use setRoot to nest all following entries under single root. If file don't | 6 | const block_size = @sizeOf(Header); |
| 7 | /// fit into posix header (name+prefix: 100+155 bytes) gnu extented header will | 7 | const empty_block: [block_size]u8 = [_]u8{0} ** block_size; |
| 8 | /// be used for long names. Options enables setting file premission mode and | 8 | |
| 9 | /// mtime. Default is to use current time for mtime and 0o664 for file mode. | 9 | /// Options for writing file/dir/link. If left empty 0o664 is used for |
| 10 | pub fn writer(underlying_writer: anytype) Writer(@TypeOf(underlying_writer)) { | 10 | /// file mode and current time for mtime. |
| 11 | return .{ .underlying_writer = underlying_writer }; | 11 | pub const Options = struct { |
| 12 | } | 12 | /// File system permission mode. |
| 13 | 13 | mode: u32 = 0, | |
| 14 | pub fn Writer(comptime WriterType: type) type { | 14 | /// File system modification time. |
| 15 | return struct { | 15 | mtime: u64 = 0, |
| 16 | const block_size = @sizeOf(Header); | 16 | }; |
| 17 | const empty_block: [block_size]u8 = [_]u8{0} ** block_size; | 17 | const Self = @This(); |
| 18 | |||
| 19 | /// Options for writing file/dir/link. If left empty 0o664 is used for | ||
| 20 | /// file mode and current time for mtime. | ||
| 21 | pub const Options = struct { | ||
| 22 | /// File system permission mode. | ||
| 23 | mode: u32 = 0, | ||
| 24 | /// File system modification time. | ||
| 25 | mtime: u64 = 0, | ||
| 26 | }; | ||
| 27 | const Self = @This(); | ||
| 28 | 18 | ||
| 29 | underlying_writer: WriterType, | 19 | underlying_writer: *std.io.BufferedWriter, |
| 30 | prefix: []const u8 = "", | 20 | prefix: []const u8 = "", |
| 31 | mtime_now: u64 = 0, | 21 | mtime_now: u64 = 0, |
| 32 | 22 | ||
| 33 | /// Sets prefix for all other write* method paths. | 23 | /// Sets prefix for all other write* method paths. |
| 34 | pub fn setRoot(self: *Self, root: []const u8) !void { | 24 | pub fn setRoot(self: *Self, root: []const u8) !void { |
| 35 | if (root.len > 0) | 25 | if (root.len > 0) |
| 36 | try self.writeDir(root, .{}); | 26 | try self.writeDir(root, .{}); |
| 37 | 27 | ||
| 38 | self.prefix = root; | 28 | self.prefix = root; |
| 39 | } | 29 | } |
| 40 | 30 | ||
| 41 | /// Writes directory. | 31 | /// Writes directory. |
| 42 | pub fn writeDir(self: *Self, sub_path: []const u8, opt: Options) !void { | 32 | pub fn writeDir(self: *Self, sub_path: []const u8, opt: Options) !void { |
| 43 | try self.writeHeader(.directory, sub_path, "", 0, opt); | 33 | try self.writeHeader(.directory, sub_path, "", 0, opt); |
| 44 | } | 34 | } |
| 45 | 35 | ||
| 46 | /// Writes file system file. | 36 | /// Writes file system file. |
| 47 | pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void { | 37 | pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void { |
| 48 | const stat = try file.stat(); | 38 | const stat = try file.stat(); |
| 49 | const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s)); | 39 | const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s)); |
| 50 | 40 | ||
| 51 | var header = Header{}; | 41 | var header = Header{}; |
| 52 | try self.setPath(&header, sub_path); | 42 | try self.setPath(&header, sub_path); |
| 53 | try header.setSize(stat.size); | 43 | try header.setSize(stat.size); |
| 54 | try header.setMtime(mtime); | 44 | try header.setMtime(mtime); |
| 55 | try header.write(self.underlying_writer); | 45 | try header.write(self.underlying_writer); |
| 56 | 46 | ||
| 57 | try self.underlying_writer.writeFile(file); | 47 | try self.underlying_writer.writeFileAll(file, .{ .len = .init(stat.size) }); |
| 58 | try self.writePadding(stat.size); | 48 | try self.writePadding(stat.size); |
| 59 | } | 49 | } |
| 60 | 50 | ||
| 61 | /// Writes file reading file content from `reader`. Number of bytes in | 51 | /// Writes file reading file content from `reader`. Number of bytes in |
| 62 | /// reader must be equal to `size`. | 52 | /// reader must be equal to `size`. |
| 63 | pub fn writeFileStream(self: *Self, sub_path: []const u8, size: usize, reader: anytype, opt: Options) !void { | 53 | pub fn writeFileStream(self: *Self, sub_path: []const u8, size: usize, reader: anytype, opt: Options) !void { |
| 64 | try self.writeHeader(.regular, sub_path, "", @intCast(size), opt); | 54 | try self.writeHeader(.regular, sub_path, "", @intCast(size), opt); |
| 65 | 55 | ||
| 66 | var counting_reader = std.io.countingReader(reader); | 56 | var counting_reader = std.io.countingReader(reader); |
| 67 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); | 57 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); |
| 68 | try fifo.pump(counting_reader.reader(), self.underlying_writer); | 58 | try fifo.pump(counting_reader.reader(), self.underlying_writer); |
| 69 | if (counting_reader.bytes_read != size) return error.WrongReaderSize; | 59 | if (counting_reader.bytes_read != size) return error.WrongReaderSize; |
| 70 | try self.writePadding(size); | 60 | try self.writePadding(size); |
| 71 | } | 61 | } |
| 72 | 62 | ||
| 73 | /// Writes file using bytes buffer `content` for size and file content. | 63 | /// Writes file using bytes buffer `content` for size and file content. |
| 74 | pub fn writeFileBytes(self: *Self, sub_path: []const u8, content: []const u8, opt: Options) !void { | 64 | pub fn writeFileBytes(self: *Self, sub_path: []const u8, content: []const u8, opt: Options) !void { |
| 75 | try self.writeHeader(.regular, sub_path, "", @intCast(content.len), opt); | 65 | try self.writeHeader(.regular, sub_path, "", @intCast(content.len), opt); |
| 76 | try self.underlying_writer.writeAll(content); | 66 | try self.underlying_writer.writeAll(content); |
| 77 | try self.writePadding(content.len); | 67 | try self.writePadding(content.len); |
| 78 | } | 68 | } |
| 79 | 69 | ||
| 80 | /// Writes symlink. | 70 | /// Writes symlink. |
| 81 | pub fn writeLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void { | 71 | pub fn writeLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void { |
| 82 | try self.writeHeader(.symbolic_link, sub_path, link_name, 0, opt); | 72 | try self.writeHeader(.symbolic_link, sub_path, link_name, 0, opt); |
| 83 | } | 73 | } |
| 84 | 74 | ||
| 85 | /// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and | 75 | /// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and |
| 86 | /// default for entry mode . | 76 | /// default for entry mode . |
| 87 | pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void { | 77 | pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void { |
| 88 | switch (entry.kind) { | 78 | switch (entry.kind) { |
| 89 | .directory => { | 79 | .directory => { |
| 90 | try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) }); | 80 | try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) }); |
| 91 | }, | 81 | }, |
| 92 | .file => { | 82 | .file => { |
| 93 | var file = try entry.dir.openFile(entry.basename, .{}); | 83 | var file = try entry.dir.openFile(entry.basename, .{}); |
| 94 | defer file.close(); | 84 | defer file.close(); |
| 95 | try self.writeFile(entry.path, file); | 85 | try self.writeFile(entry.path, file); |
| 96 | }, | 86 | }, |
| 97 | .sym_link => { | 87 | .sym_link => { |
| 98 | var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; | 88 | var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; |
| 99 | const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer); | 89 | const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer); |
| 100 | try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) }); | 90 | try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) }); |
| 101 | }, | 91 | }, |
| 102 | else => { | 92 | else => { |
| 103 | return error.UnsupportedWalkerEntryKind; | 93 | return error.UnsupportedWalkerEntryKind; |
| 104 | }, | 94 | }, |
| 105 | } | ||
| 106 | } | 95 | } |
| 96 | } | ||
| 107 | 97 | ||
| 108 | fn writeHeader( | 98 | fn writeHeader( |
| 109 | self: *Self, | 99 | self: *Self, |
| 110 | typeflag: Header.FileType, | 100 | typeflag: Header.FileType, |
| 111 | sub_path: []const u8, | 101 | sub_path: []const u8, |
| 112 | link_name: []const u8, | 102 | link_name: []const u8, |
| 113 | size: u64, | 103 | size: u64, |
| 114 | opt: Options, | 104 | opt: Options, |
| 115 | ) !void { | 105 | ) !void { |
| 116 | var header = Header.init(typeflag); | 106 | var header = Header.init(typeflag); |
| 117 | try self.setPath(&header, sub_path); | 107 | try self.setPath(&header, sub_path); |
| 118 | try header.setSize(size); | 108 | try header.setSize(size); |
| 119 | try header.setMtime(if (opt.mtime != 0) opt.mtime else self.mtimeNow()); | 109 | try header.setMtime(if (opt.mtime != 0) opt.mtime else self.mtimeNow()); |
| 120 | if (opt.mode != 0) | 110 | if (opt.mode != 0) |
| 121 | try header.setMode(opt.mode); | 111 | try header.setMode(opt.mode); |
| 122 | if (typeflag == .symbolic_link) | 112 | if (typeflag == .symbolic_link) |
| 123 | header.setLinkname(link_name) catch |err| switch (err) { | 113 | header.setLinkname(link_name) catch |err| switch (err) { |
| 124 | error.NameTooLong => try self.writeExtendedHeader(.gnu_long_link, &.{link_name}), | 114 | error.NameTooLong => try self.writeExtendedHeader(.gnu_long_link, &.{link_name}), |
| 125 | else => return err, | 115 | else => return err, |
| 126 | }; | 116 | }; |
| 127 | try header.write(self.underlying_writer); | 117 | try header.write(self.underlying_writer); |
| 128 | } | 118 | } |
| 129 | 119 | ||
| 130 | fn mtimeNow(self: *Self) u64 { | 120 | fn mtimeNow(self: *Self) u64 { |
| 131 | if (self.mtime_now == 0) | 121 | if (self.mtime_now == 0) |
| 132 | self.mtime_now = @intCast(std.time.timestamp()); | 122 | self.mtime_now = @intCast(std.time.timestamp()); |
| 133 | return self.mtime_now; | 123 | return self.mtime_now; |
| 134 | } | 124 | } |
| 135 | 125 | ||
| 136 | fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 { | 126 | fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 { |
| 137 | const stat = try entry.dir.statFile(entry.basename); | 127 | const stat = try entry.dir.statFile(entry.basename); |
| 138 | return @intCast(@divFloor(stat.mtime, std.time.ns_per_s)); | 128 | return @intCast(@divFloor(stat.mtime, std.time.ns_per_s)); |
| 139 | } | 129 | } |
| 140 | 130 | ||
| 141 | /// Writes path in posix header, if don't fit (in name+prefix; 100+155 | 131 | /// Writes path in posix header, if don't fit (in name+prefix; 100+155 |
| 142 | /// bytes) writes it in gnu extended header. | 132 | /// bytes) writes it in gnu extended header. |
| 143 | fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void { | 133 | fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void { |
| 144 | header.setPath(self.prefix, sub_path) catch |err| switch (err) { | 134 | header.setPath(self.prefix, sub_path) catch |err| switch (err) { |
| 145 | error.NameTooLong => { | 135 | error.NameTooLong => { |
| 146 | // write extended header | 136 | // write extended header |
| 147 | const buffers: []const []const u8 = if (self.prefix.len == 0) | 137 | const buffers: []const []const u8 = if (self.prefix.len == 0) |
| 148 | &.{sub_path} | 138 | &.{sub_path} |
| 149 | else | 139 | else |
| 150 | &.{ self.prefix, "/", sub_path }; | 140 | &.{ self.prefix, "/", sub_path }; |
| 151 | try self.writeExtendedHeader(.gnu_long_name, buffers); | 141 | try self.writeExtendedHeader(.gnu_long_name, buffers); |
| 152 | }, | 142 | }, |
| 153 | else => return err, | 143 | else => return err, |
| 154 | }; | 144 | }; |
| 155 | } | 145 | } |
| 156 | 146 | ||
| 157 | /// Writes gnu extended header: gnu_long_name or gnu_long_link. | 147 | /// Writes gnu extended header: gnu_long_name or gnu_long_link. |
| 158 | fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void { | 148 | fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void { |
| 159 | var len: usize = 0; | 149 | var len: usize = 0; |
| 160 | for (buffers) |buf| | 150 | for (buffers) |buf| |
| 161 | len += buf.len; | 151 | len += buf.len; |
| 162 | 152 | ||
| 163 | var header = Header.init(typeflag); | 153 | var header = Header.init(typeflag); |
| 164 | try header.setSize(len); | 154 | try header.setSize(len); |
| 165 | try header.write(self.underlying_writer); | 155 | try header.write(self.underlying_writer); |
| 166 | for (buffers) |buf| | 156 | for (buffers) |buf| |
| 167 | try self.underlying_writer.writeAll(buf); | 157 | try self.underlying_writer.writeAll(buf); |
| 168 | try self.writePadding(len); | 158 | try self.writePadding(len); |
| 169 | } | 159 | } |
| 170 | 160 | ||
| 171 | fn writePadding(self: *Self, bytes: u64) !void { | 161 | fn writePadding(self: *Self, bytes: u64) !void { |
| 172 | const pos: usize = @intCast(bytes % block_size); | 162 | const pos: usize = @intCast(bytes % block_size); |
| 173 | if (pos == 0) return; | 163 | if (pos == 0) return; |
| 174 | try self.underlying_writer.writeAll(empty_block[pos..]); | 164 | try self.underlying_writer.writeAll(empty_block[pos..]); |
| 175 | } | 165 | } |
| 176 | 166 | ||
| 177 | /// Tar should finish with two zero blocks, but 'reasonable system must | 167 | /// Tar should finish with two zero blocks, but 'reasonable system must |
| 178 | /// not assume that such a block exists when reading an archive' (from | 168 | /// not assume that such a block exists when reading an archive' (from |
| 179 | /// reference). In practice it is safe to skip this finish. | 169 | /// reference). In practice it is safe to skip this finish. |
| 180 | pub fn finish(self: *Self) !void { | 170 | pub fn finish(self: *Self) !void { |
| 181 | try self.underlying_writer.writeAll(&empty_block); | 171 | try self.underlying_writer.writeAll(&empty_block); |
| 182 | try self.underlying_writer.writeAll(&empty_block); | 172 | try self.underlying_writer.writeAll(&empty_block); |
| 183 | } | 173 | } |
| 184 | }; | 174 | }; |
| 185 | } | ||
| 186 | 175 | ||
| 187 | /// A struct that is exactly 512 bytes and matches tar file format. This is | 176 | /// A struct that is exactly 512 bytes and matches tar file format. This is |
| 188 | /// intended to be used for outputting tar files; for parsing there is | 177 | /// intended to be used for outputting tar files; for parsing there is |
| ... | @@ -431,14 +420,14 @@ test "write files" { | ... | @@ -431,14 +420,14 @@ test "write files" { |
| 431 | { | 420 | { |
| 432 | const root = "root"; | 421 | const root = "root"; |
| 433 | 422 | ||
| 434 | var output = std.ArrayList(u8).init(testing.allocator); | 423 | var output: std.io.AllocatingWriter = undefined; |
| 424 | var wrt: Writer = .{ .underlying_writer = output.init(testing.allocator) }; | ||
| 435 | defer output.deinit(); | 425 | defer output.deinit(); |
| 436 | var wrt = writer(output.writer()); | ||
| 437 | try wrt.setRoot(root); | 426 | try wrt.setRoot(root); |
| 438 | for (files) |file| | 427 | for (files) |file| |
| 439 | try wrt.writeFileBytes(file.path, file.content, .{}); | 428 | try wrt.writeFileBytes(file.path, file.content, .{}); |
| 440 | 429 | ||
| 441 | var input = std.io.fixedBufferStream(output.items); | 430 | var input: std.io.FixedBufferStream = .{ .buffer = output.getWritten() }; |
| 442 | var iter = std.tar.iterator( | 431 | var iter = std.tar.iterator( |
| 443 | input.reader(), | 432 | input.reader(), |
| 444 | .{ .file_name_buffer = &file_name_buffer, .link_name_buffer = &link_name_buffer }, | 433 | .{ .file_name_buffer = &file_name_buffer, .link_name_buffer = &link_name_buffer }, |
| ... | @@ -467,15 +456,15 @@ test "write files" { | ... | @@ -467,15 +456,15 @@ test "write files" { |
| 467 | } | 456 | } |
| 468 | // without root | 457 | // without root |
| 469 | { | 458 | { |
| 470 | var output = std.ArrayList(u8).init(testing.allocator); | 459 | var output: std.io.AllocatingWriter = undefined; |
| 460 | var wrt: Writer = .{ .underlying_writer = output.init(testing.allocator) }; | ||
| 471 | defer output.deinit(); | 461 | defer output.deinit(); |
| 472 | var wrt = writer(output.writer()); | ||
| 473 | for (files) |file| { | 462 | for (files) |file| { |
| 474 | var content = std.io.fixedBufferStream(file.content); | 463 | var content = std.io.fixedBufferStream(file.content); |
| 475 | try wrt.writeFileStream(file.path, file.content.len, content.reader(), .{}); | 464 | try wrt.writeFileStream(file.path, file.content.len, content.reader(), .{}); |
| 476 | } | 465 | } |
| 477 | 466 | ||
| 478 | var input = std.io.fixedBufferStream(output.items); | 467 | var input: std.io.FixedBufferStream = .{ .buffer = output.getWritten() }; |
| 479 | var iter = std.tar.iterator( | 468 | var iter = std.tar.iterator( |
| 480 | input.reader(), | 469 | input.reader(), |
| 481 | .{ .file_name_buffer = &file_name_buffer, .link_name_buffer = &link_name_buffer }, | 470 | .{ .file_name_buffer = &file_name_buffer, .link_name_buffer = &link_name_buffer }, |
lib/std/zig.zig+4-4| ... | @@ -635,7 +635,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -635,7 +635,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 635 | var help_text = std.ArrayList(u8).init(allocator); | 635 | var help_text = std.ArrayList(u8).init(allocator); |
| 636 | defer help_text.deinit(); | 636 | defer help_text.deinit(); |
| 637 | for (diags.arch.?.allCpuModels()) |cpu| { | 637 | for (diags.arch.?.allCpuModels()) |cpu| { |
| 638 | help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help; | 638 | help_text.print(" {s}\n", .{cpu.name}) catch break :help; |
| 639 | } | 639 | } |
| 640 | std.log.info("available CPUs for architecture '{s}':\n{s}", .{ | 640 | std.log.info("available CPUs for architecture '{s}':\n{s}", .{ |
| 641 | @tagName(diags.arch.?), help_text.items, | 641 | @tagName(diags.arch.?), help_text.items, |
| ... | @@ -648,7 +648,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -648,7 +648,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 648 | var help_text = std.ArrayList(u8).init(allocator); | 648 | var help_text = std.ArrayList(u8).init(allocator); |
| 649 | defer help_text.deinit(); | 649 | defer help_text.deinit(); |
| 650 | for (diags.arch.?.allFeaturesList()) |feature| { | 650 | for (diags.arch.?.allFeaturesList()) |feature| { |
| 651 | help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help; | 651 | help_text.print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help; |
| 652 | } | 652 | } |
| 653 | std.log.info("available CPU features for architecture '{s}':\n{s}", .{ | 653 | std.log.info("available CPU features for architecture '{s}':\n{s}", .{ |
| 654 | @tagName(diags.arch.?), help_text.items, | 654 | @tagName(diags.arch.?), help_text.items, |
| ... | @@ -661,7 +661,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -661,7 +661,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 661 | var help_text = std.ArrayList(u8).init(allocator); | 661 | var help_text = std.ArrayList(u8).init(allocator); |
| 662 | defer help_text.deinit(); | 662 | defer help_text.deinit(); |
| 663 | inline for (@typeInfo(std.Target.ObjectFormat).@"enum".fields) |field| { | 663 | inline for (@typeInfo(std.Target.ObjectFormat).@"enum".fields) |field| { |
| 664 | help_text.writer().print(" {s}\n", .{field.name}) catch break :help; | 664 | help_text.print(" {s}\n", .{field.name}) catch break :help; |
| 665 | } | 665 | } |
| 666 | std.log.info("available object formats:\n{s}", .{help_text.items}); | 666 | std.log.info("available object formats:\n{s}", .{help_text.items}); |
| 667 | } | 667 | } |
| ... | @@ -672,7 +672,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -672,7 +672,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 672 | var help_text = std.ArrayList(u8).init(allocator); | 672 | var help_text = std.ArrayList(u8).init(allocator); |
| 673 | defer help_text.deinit(); | 673 | defer help_text.deinit(); |
| 674 | inline for (@typeInfo(std.Target.Cpu.Arch).@"enum".fields) |field| { | 674 | inline for (@typeInfo(std.Target.Cpu.Arch).@"enum".fields) |field| { |
| 675 | help_text.writer().print(" {s}\n", .{field.name}) catch break :help; | 675 | help_text.print(" {s}\n", .{field.name}) catch break :help; |
| 676 | } | 676 | } |
| 677 | std.log.info("available architectures:\n{s} native\n", .{help_text.items}); | 677 | std.log.info("available architectures:\n{s} native\n", .{help_text.items}); |
| 678 | } | 678 | } |
lib/std/zig/ErrorBundle.zig+8-8| ... | @@ -194,11 +194,11 @@ fn renderErrorMessageToWriter( | ... | @@ -194,11 +194,11 @@ fn renderErrorMessageToWriter( |
| 194 | ) anyerror!void { | 194 | ) anyerror!void { |
| 195 | const ttyconf = options.ttyconf; | 195 | const ttyconf = options.ttyconf; |
| 196 | var counting_writer: std.io.CountingWriter = .{ .child_writer = bw.writer() }; | 196 | var counting_writer: std.io.CountingWriter = .{ .child_writer = bw.writer() }; |
| 197 | const counting_bw = counting_writer.unbufferedWriter(); | 197 | var counting_bw = counting_writer.unbufferedWriter(); |
| 198 | const err_msg = eb.getErrorMessage(err_msg_index); | 198 | const err_msg = eb.getErrorMessage(err_msg_index); |
| 199 | if (err_msg.src_loc != .none) { | 199 | if (err_msg.src_loc != .none) { |
| 200 | const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); | 200 | const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc)); |
| 201 | try counting_bw.writeByteNTimes(' ', indent); | 201 | try counting_bw.splatByteAll(' ', indent); |
| 202 | try ttyconf.setColor(bw, .bold); | 202 | try ttyconf.setColor(bw, .bold); |
| 203 | try counting_bw.print("{s}:{d}:{d}: ", .{ | 203 | try counting_bw.print("{s}:{d}:{d}: ", .{ |
| 204 | eb.nullTerminatedString(src.data.src_path), | 204 | eb.nullTerminatedString(src.data.src_path), |
| ... | @@ -210,7 +210,7 @@ fn renderErrorMessageToWriter( | ... | @@ -210,7 +210,7 @@ fn renderErrorMessageToWriter( |
| 210 | try counting_bw.writeAll(": "); | 210 | try counting_bw.writeAll(": "); |
| 211 | // This is the length of the part before the error message: | 211 | // This is the length of the part before the error message: |
| 212 | // e.g. "file.zig:4:5: error: " | 212 | // e.g. "file.zig:4:5: error: " |
| 213 | const prefix_len: usize = @intCast(counting_bw.context.bytes_written); | 213 | const prefix_len: usize = @intCast(counting_writer.bytes_written); |
| 214 | try ttyconf.setColor(bw, .reset); | 214 | try ttyconf.setColor(bw, .reset); |
| 215 | try ttyconf.setColor(bw, .bold); | 215 | try ttyconf.setColor(bw, .bold); |
| 216 | if (err_msg.count == 1) { | 216 | if (err_msg.count == 1) { |
| ... | @@ -233,11 +233,11 @@ fn renderErrorMessageToWriter( | ... | @@ -233,11 +233,11 @@ fn renderErrorMessageToWriter( |
| 233 | const before_caret = src.data.span_main - src.data.span_start; | 233 | const before_caret = src.data.span_main - src.data.span_start; |
| 234 | // -1 since span.main includes the caret | 234 | // -1 since span.main includes the caret |
| 235 | const after_caret = src.data.span_end -| src.data.span_main -| 1; | 235 | const after_caret = src.data.span_end -| src.data.span_main -| 1; |
| 236 | try bw.writeByteNTimes(' ', src.data.column - before_caret); | 236 | try bw.splatByteAll(' ', src.data.column - before_caret); |
| 237 | try ttyconf.setColor(bw, .green); | 237 | try ttyconf.setColor(bw, .green); |
| 238 | try bw.writeByteNTimes('~', before_caret); | 238 | try bw.splatByteAll('~', before_caret); |
| 239 | try bw.writeByte('^'); | 239 | try bw.writeByte('^'); |
| 240 | try bw.writeByteNTimes('~', after_caret); | 240 | try bw.splatByteAll('~', after_caret); |
| 241 | try bw.writeByte('\n'); | 241 | try bw.writeByte('\n'); |
| 242 | try ttyconf.setColor(bw, .reset); | 242 | try ttyconf.setColor(bw, .reset); |
| 243 | } | 243 | } |
| ... | @@ -277,7 +277,7 @@ fn renderErrorMessageToWriter( | ... | @@ -277,7 +277,7 @@ fn renderErrorMessageToWriter( |
| 277 | } | 277 | } |
| 278 | } else { | 278 | } else { |
| 279 | try ttyconf.setColor(bw, color); | 279 | try ttyconf.setColor(bw, color); |
| 280 | try bw.writeByteNTimes(' ', indent); | 280 | try bw.splatByteAll(' ', indent); |
| 281 | try bw.writeAll(kind); | 281 | try bw.writeAll(kind); |
| 282 | try bw.writeAll(": "); | 282 | try bw.writeAll(": "); |
| 283 | try ttyconf.setColor(bw, .reset); | 283 | try ttyconf.setColor(bw, .reset); |
| ... | @@ -306,7 +306,7 @@ fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, bw: *std.io.BufferedWriter, | ... | @@ -306,7 +306,7 @@ fn writeMsg(eb: ErrorBundle, err_msg: ErrorMessage, bw: *std.io.BufferedWriter, |
| 306 | try bw.writeAll(line); | 306 | try bw.writeAll(line); |
| 307 | if (lines.index == null) break; | 307 | if (lines.index == null) break; |
| 308 | try bw.writeByte('\n'); | 308 | try bw.writeByte('\n'); |
| 309 | try bw.writeByteNTimes(' ', indent); | 309 | try bw.splatByteAll(' ', indent); |
| 310 | } | 310 | } |
| 311 | } | 311 | } |
| 312 | 312 |
lib/std/zig/LibCInstallation.zig+2-2| ... | @@ -370,7 +370,7 @@ fn findNativeIncludeDirWindows( | ... | @@ -370,7 +370,7 @@ fn findNativeIncludeDirWindows( |
| 370 | 370 | ||
| 371 | for (installs) |install| { | 371 | for (installs) |install| { |
| 372 | result_buf.shrinkAndFree(0); | 372 | result_buf.shrinkAndFree(0); |
| 373 | try result_buf.writer().print("{s}\\Include\\{s}\\ucrt", .{ install.path, install.version }); | 373 | try result_buf.print("{s}\\Include\\{s}\\ucrt", .{ install.path, install.version }); |
| 374 | 374 | ||
| 375 | var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { | 375 | var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { |
| 376 | error.FileNotFound, | 376 | error.FileNotFound, |
| ... | @@ -417,7 +417,7 @@ fn findNativeCrtDirWindows( | ... | @@ -417,7 +417,7 @@ fn findNativeCrtDirWindows( |
| 417 | 417 | ||
| 418 | for (installs) |install| { | 418 | for (installs) |install| { |
| 419 | result_buf.shrinkAndFree(0); | 419 | result_buf.shrinkAndFree(0); |
| 420 | try result_buf.writer().print("{s}\\Lib\\{s}\\ucrt\\{s}", .{ install.path, install.version, arch_sub_dir }); | 420 | try result_buf.print("{s}\\Lib\\{s}\\ucrt\\{s}", .{ install.path, install.version, arch_sub_dir }); |
| 421 | 421 | ||
| 422 | var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { | 422 | var dir = fs.cwd().openDir(result_buf.items, .{}) catch |err| switch (err) { |
| 423 | error.FileNotFound, | 423 | error.FileNotFound, |