authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-21 16:32:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:27-07:00
logd62f22cc4d2f17db0877cd9316bf8be9470d04a5
treebc97e5ae7485bf5f50350a1068019aae4db9b0db
parent6a0f2227e8b40e3456d3c85c72f68f483b239af3

link: port to `std.io.BufferedReader` API changes


5 files changed, 103 insertions(+), 52 deletions(-)

lib/std/io/BufferedReader.zig+52-22
...@@ -484,11 +484,13 @@ fn peekDelimiterInclusiveUnlessEnd(br: *BufferedReader, delimiter: u8) Delimiter...@@ -484,11 +484,13 @@ fn peekDelimiterInclusiveUnlessEnd(br: *BufferedReader, delimiter: u8) Delimiter
484/// found. Does not write the delimiter itself.484/// found. Does not write the delimiter itself.
485///485///
486/// Returns number of bytes streamed.486/// Returns number of bytes streamed.
487pub fn streamReadDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter: u8) Reader.Error!usize {487pub fn streamToDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter: u8) Reader.RwError!usize {
488 _ = br;488 const amount, const to = try br.streamToAny(bw, delimiter, .unlimited);
489 _ = bw;489 return switch (to) {
490 _ = delimiter;490 .delimiter => amount,
491 @panic("TODO");491 .limit => unreachable,
492 .end => error.EndOfStream,
493 };
492}494}
493495
494/// Appends to `bw` contents by reading from the stream until `delimiter` is found.496/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
...@@ -497,18 +499,19 @@ pub fn streamReadDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter:...@@ -497,18 +499,19 @@ pub fn streamReadDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter:
497/// Succeeds if stream ends before delimiter found.499/// Succeeds if stream ends before delimiter found.
498///500///
499/// Returns number of bytes streamed. The end is not signaled to the writer.501/// Returns number of bytes streamed. The end is not signaled to the writer.
500pub fn streamReadDelimiterExclusive(502pub fn streamToDelimiterOrEnd(
501 br: *BufferedReader,503 br: *BufferedReader,
502 bw: *BufferedWriter,504 bw: *BufferedWriter,
503 delimiter: u8,505 delimiter: u8,
504) Reader.ShortError!usize {506) Reader.RwAllError!usize {
505 _ = br;507 const amount, const to = try br.streamToAny(bw, delimiter, .unlimited);
506 _ = bw;508 return switch (to) {
507 _ = delimiter;509 .delimiter, .end => amount,
508 @panic("TODO");510 .limit => unreachable,
511 };
509}512}
510513
511pub const StreamDelimiterLimitedError = Reader.ShortError || error{514pub const StreamDelimiterLimitedError = Reader.RwAllError || error{
512 /// Stream ended before the delimiter was found.515 /// Stream ended before the delimiter was found.
513 EndOfStream,516 EndOfStream,
514 /// The delimiter was not found within the limit.517 /// The delimiter was not found within the limit.
...@@ -517,19 +520,46 @@ pub const StreamDelimiterLimitedError = Reader.ShortError || error{...@@ -517,19 +520,46 @@ pub const StreamDelimiterLimitedError = Reader.ShortError || error{
517520
518/// Appends to `bw` contents by reading from the stream until `delimiter` is found.521/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
519/// Does not write the delimiter itself.522/// Does not write the delimiter itself.
520//523///
521/// Returns number of bytes streamed.524/// Returns number of bytes streamed.
522pub fn streamReadDelimiterLimited(525pub fn streamToDelimiterOrLimit(
523 br: *BufferedReader,526 br: *BufferedReader,
524 bw: *BufferedWriter,527 bw: *BufferedWriter,
525 delimiter: u8,528 delimiter: u8,
526 limit: Reader.Limit,529 limit: Reader.Limit,
527) StreamDelimiterLimitedError!usize {530) StreamDelimiterLimitedError!usize {
528 _ = br;531 const amount, const to = try br.streamToAny(bw, delimiter, limit);
529 _ = bw;532 return switch (to) {
530 _ = delimiter;533 .delimiter => amount,
531 _ = limit;534 .limit => error.StreamTooLong,
532 @panic("TODO");535 .end => error.EndOfStream,
536 };
537}
538
539fn streamToAny(
540 br: *BufferedReader,
541 bw: *BufferedWriter,
542 delimiter: ?u8,
543 limit: Reader.Limit,
544) Reader.RwAllError!struct { usize, enum { delimiter, limit, end } } {
545 var amount: usize = 0;
546 var remaining = limit;
547 while (remaining.nonzero()) {
548 const available = remaining.slice(br.peekGreedy(1) catch |err| switch (err) {
549 error.ReadFailed => |e| return e,
550 error.EndOfStream => return .{ amount, .end },
551 });
552 if (delimiter) |d| if (std.mem.indexOfScalar(u8, available, d)) |delimiter_index| {
553 try bw.writeAll(available[0..delimiter_index]);
554 br.toss(delimiter_index + 1);
555 return .{ amount + delimiter_index, .delimiter };
556 };
557 try bw.writeAll(available);
558 br.toss(available.len);
559 amount += available.len;
560 remaining = remaining.subtract(available.len).?;
561 }
562 return .{ amount, .limit };
533}563}
534564
535/// Reads from the stream until specified byte is found, discarding all data,565/// Reads from the stream until specified byte is found, discarding all data,
...@@ -824,15 +854,15 @@ test peekDelimiterExclusive {...@@ -824,15 +854,15 @@ test peekDelimiterExclusive {
824 return error.Unimplemented;854 return error.Unimplemented;
825}855}
826856
827test streamReadDelimiter {857test streamToDelimiter {
828 return error.Unimplemented;858 return error.Unimplemented;
829}859}
830860
831test streamReadDelimiterExclusive {861test streamToDelimiterOrEnd {
832 return error.Unimplemented;862 return error.Unimplemented;
833}863}
834864
835test streamReadDelimiterLimited {865test streamToDelimiterOrLimit {
836 return error.Unimplemented;866 return error.Unimplemented;
837}867}
838868
src/Compilation.zig+14-11
...@@ -1000,11 +1000,14 @@ pub const CObject = struct {...@@ -1000,11 +1000,14 @@ pub const CObject = struct {
1000 defer file.close();1000 defer file.close();
1001 file.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;1001 file.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
10021002
1003 var line = std.ArrayList(u8).init(eb.gpa);1003 var buffer: [1 << 10]u8 = undefined;
1004 defer line.deinit();1004 var fr = file.reader();
1005 file.reader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;1005 var br = fr.interface().buffered(&buffer);
10061006 var bw: std.io.BufferedWriter = undefined;
1007 break :source_line try eb.addString(line.items);1007 bw.initFixed(&buffer);
1008 break :source_line try eb.addString(
1009 buffer[0 .. br.streamToDelimiterOrEnd(&bw, '\n') catch break :source_line 0],
1010 );
1008 };1011 };
10091012
1010 return .{1013 return .{
...@@ -3781,7 +3784,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3781,7 +3784,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3781 if (!refs.contains(anal_unit)) continue;3784 if (!refs.contains(anal_unit)) continue;
3782 }3785 }
37833786
3784 std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{3787 std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{f}'", .{
3785 error_msg.msg,3788 error_msg.msg,
3786 zcu.fmtAnalUnit(anal_unit),3789 zcu.fmtAnalUnit(anal_unit),
3787 });3790 });
...@@ -3941,12 +3944,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3941,12 +3944,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3941 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.3944 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
3942 // However, we haven't reported any such error.3945 // However, we haven't reported any such error.
3943 // This is a compiler bug.3946 // This is a compiler bug.
3944 var stderr = std.debug.lockStdErr2(&.{});3947 var stderr_bw = std.debug.lockStderrWriter(&.{});
3945 defer std.debug.unlockStdErr();3948 defer std.debug.unlockStderrWriter();
3946 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");3949 try stderr_bw.writeAll("referenced transitive analysis errors, but none actually emitted\n");
3947 try stderr.print("{} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});3950 try stderr_bw.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
3948 while (ref) |r| {3951 while (ref) |r| {
3949 try stderr.print("referenced by: {}{s}\n", .{3952 try stderr_bw.print("referenced by: {f}{s}\n", .{
3950 zcu.fmtAnalUnit(r.referencer),3953 zcu.fmtAnalUnit(r.referencer),
3951 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",3954 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
3952 });3955 });
src/Zcu/PerThread.zig+2-2
...@@ -268,7 +268,7 @@ pub fn updateFile(...@@ -268,7 +268,7 @@ pub fn updateFile(
268 file.zir = try AstGen.generate(gpa, file.tree.?);268 file.zir = try AstGen.generate(gpa, file.tree.?);
269 Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {269 Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {
270 error.OutOfMemory => |e| return e,270 error.OutOfMemory => |e| return e,
271 else => log.warn("unable to write cached ZIR code for {} to {}{s}: {s}", .{271 else => log.warn("unable to write cached ZIR code for {f} to {f}{s}: {s}", .{
272 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),272 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
273 }),273 }),
274 };274 };
...@@ -276,7 +276,7 @@ pub fn updateFile(...@@ -276,7 +276,7 @@ pub fn updateFile(
276 .zon => {276 .zon => {
277 file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});277 file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});
278 Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {278 Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {
279 log.warn("unable to write cached ZOIR code for {} to {}{s}: {s}", .{279 log.warn("unable to write cached ZOIR code for {f} to {f}{s}: {s}", .{
280 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),280 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
281 });281 });
282 };282 };
src/link.zig+33-15
...@@ -1023,15 +1023,24 @@ pub const File = struct {...@@ -1023,15 +1023,24 @@ pub const File = struct {
1023 };1023 };
1024 }1024 }
10251025
1026 fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: fs.File) anyerror!void {1026 fn loadGnuLdScript(
1027 base: *File,
1028 path: Path,
1029 parent_query: UnresolvedInput.Query,
1030 file: fs.File,
1031 ) anyerror!void {
1027 const diags = &base.comp.link_diags;1032 const diags = &base.comp.link_diags;
1028 const gpa = base.comp.gpa;1033 const gpa = base.comp.gpa;
1029 const stat = try file.stat();1034 const stat = try file.stat();
1030 const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig;1035 const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig;
1031 const buf = try gpa.alloc(u8, size);1036 const buf = try gpa.alloc(u8, size);
1032 defer gpa.free(buf);1037 defer gpa.free(buf);
1033 const n = try file.preadAll(buf, 0);1038 var fr = file.reader();
1034 if (buf.len != n) return error.UnexpectedEndOfFile;1039 var br = fr.interface().unbuffered();
1040 br.readSlice(buf) catch |err| switch (err) {
1041 error.ReadFailed => if (fr.err) |_| unreachable else |e| return e,
1042 error.EndOfStream => return error.UnexpectedEndOfFile,
1043 };
1035 var ld_script = try LdScript.parse(gpa, diags, path, buf);1044 var ld_script = try LdScript.parse(gpa, diags, path, buf);
1036 defer ld_script.deinit(gpa);1045 defer ld_script.deinit(gpa);
1037 for (ld_script.args) |arg| {1046 for (ld_script.args) |arg| {
...@@ -2092,24 +2101,33 @@ fn resolvePathInputLib(...@@ -2092,24 +2101,33 @@ fn resolvePathInputLib(
2092 };2101 };
2093 errdefer file.close();2102 errdefer file.close();
2094 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));2103 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));
2095 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f'}': {s}", .{2104 var fr = file.reader();
2096 test_path, @errorName(err),2105 var br = fr.interface().unbuffered();
2097 });2106 ok: {
2098 const buf = ld_script_bytes.items[0..n];2107 br.readSlice(ld_script_bytes.items) catch |err| switch (err) {
2099 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {2108 error.ReadFailed => fatal("failed to read '{f'}': {s}", .{
2100 // Appears to be an ELF or archive file.2109 test_path,
2101 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);2110 @errorName(if (fr.err) |_| unreachable else |e| e),
2111 }),
2112 error.EndOfStream => break :ok,
2113 };
2114 if (mem.startsWith(u8, ld_script_bytes.items, std.elf.MAGIC) or
2115 mem.startsWith(u8, ld_script_bytes.items, std.elf.ARMAG))
2116 {
2117 // Appears to be an ELF or archive file.
2118 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2119 }
2102 }2120 }
2103 const stat = file.stat() catch |err|2121 const stat = file.stat() catch |err|
2104 fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) });2122 fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) });
2105 const size = std.math.cast(u32, stat.size) orelse2123 const size = std.math.cast(u32, stat.size) orelse
2106 fatal("{f}: linker script too big", .{test_path});2124 fatal("{f}: linker script too big", .{test_path});
2107 try ld_script_bytes.resize(gpa, size);2125 try ld_script_bytes.resize(gpa, size);
2108 const buf2 = ld_script_bytes.items[n..];2126 br.readSlice(ld_script_bytes.items[@intCast(fr.pos)..]) catch |err| switch (err) {
2109 const n2 = file.preadAll(buf2, n) catch |err|2127 error.ReadFailed => if (fr.err) |_| unreachable else |e| fatal("failed to read {f}: {s}", .{ test_path, @errorName(e) }),
2110 fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) });2128 error.EndOfStream => fatal("failed to read {f}: unexpected end of file", .{test_path}),
2111 if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path});2129 };
2112 var diags = Diags.init(gpa);2130 var diags: Diags = .init(gpa);
2113 defer diags.deinit();2131 defer diags.deinit();
2114 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);2132 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);
2115 if (diags.hasErrors()) {2133 if (diags.hasErrors()) {
src/main.zig+2-2
...@@ -3511,7 +3511,7 @@ fn buildOutputType(...@@ -3511,7 +3511,7 @@ fn buildOutputType(
3511 if (t.arch == target.cpu.arch and t.os == target.os.tag) {3511 if (t.arch == target.cpu.arch and t.os == target.os.tag) {
3512 // If there's a `glibc_min`, there's also an `os_ver`.3512 // If there's a `glibc_min`, there's also an `os_ver`.
3513 if (t.glibc_min) |glibc_min| {3513 if (t.glibc_min) |glibc_min| {
3514 std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}.{d}.{d}", .{3514 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}.{d}.{d}", .{
3515 @tagName(t.arch),3515 @tagName(t.arch),
3516 @tagName(t.os),3516 @tagName(t.os),
3517 t.os_ver.?,3517 t.os_ver.?,
...@@ -3520,7 +3520,7 @@ fn buildOutputType(...@@ -3520,7 +3520,7 @@ fn buildOutputType(
3520 glibc_min.minor,3520 glibc_min.minor,
3521 });3521 });
3522 } else if (t.os_ver) |os_ver| {3522 } else if (t.os_ver) |os_ver| {
3523 std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}", .{3523 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}", .{
3524 @tagName(t.arch),3524 @tagName(t.arch),
3525 @tagName(t.os),3525 @tagName(t.os),
3526 os_ver,3526 os_ver,