diff --git a/lib/docs/wasm/Walk.zig b/lib/docs/wasm/Walk.zig index 90df301f22..2c41e9c940 100644 --- a/lib/docs/wasm/Walk.zig +++ b/lib/docs/wasm/Walk.zig @@ -433,14 +433,18 @@ fn parse(file_name: []const u8, source: []u8) Oom!Ast { defer ast.deinit(gpa); const token_offsets = ast.tokens.items(.start); - var rendered_err: std.ArrayListUnmanaged(u8) = .{}; - defer rendered_err.deinit(gpa); + var rendered_err: std.Io.Writer.Allocating = .init(gpa); + defer rendered_err.deinit(); for (ast.errors) |err| { const err_offset = token_offsets[err.token] + ast.errorOffset(err); const err_loc = std.zig.findLineColumn(ast.source, err_offset); rendered_err.clearRetainingCapacity(); - try ast.renderError(err, rendered_err.writer(gpa)); - log.err("{s}:{d}:{d}: {s}", .{ file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.items }); + ast.renderError(err, &rendered_err.writer) catch |e| switch (e) { + error.WriteFailed => return error.OutOfMemory, + }; + log.err("{s}:{d}:{d}: {s}", .{ + file_name, err_loc.line + 1, err_loc.column + 1, rendered_err.getWritten(), + }); } return Ast.parse(gpa, "", .zig); } diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index 8543f0bce5..dd72607b3f 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -2481,6 +2481,12 @@ pub const Allocating = struct { return list.ensureUnusedCapacity(a.allocator, additional_count); } + pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void { + var list = a.toArrayList(); + defer a.setArrayList(list); + return list.ensureTotalCapacity(a.allocator, new_capacity); + } + pub fn toOwnedSlice(a: *Allocating) error{OutOfMemory}![]u8 { var list = a.toArrayList(); defer a.setArrayList(list); diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 6a64adc547..fa45af129c 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -530,18 +530,11 @@ test isUnderscore { try std.testing.expect(!isUnderscore("\\x5f")); } -pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: usize) ![:0]u8 { +pub fn readSourceFileToEndAlloc(gpa: Allocator, file_reader: *std.fs.File.Reader) ![:0]u8 { var buffer: std.ArrayListAlignedUnmanaged(u8, .@"2") = .empty; defer buffer.deinit(gpa); - try buffer.ensureUnusedCapacity(gpa, size_hint); - - input.readIntoArrayList(gpa, .limited(max_src_size), .@"2", &buffer) catch |err| switch (err) { - error.ConnectionResetByPeer => unreachable, - error.ConnectionTimedOut => unreachable, - error.NotOpenForReading => unreachable, - else => |e| return e, - }; + try file_reader.interface.appendRemaining(gpa, .@"2", &buffer, .limited(max_src_size)); // Detect unsupported file types with their Byte Order Mark const unsupported_boms = [_][]const u8{ diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 175403b295..52fc41a2c9 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -11278,10 +11278,14 @@ fn parseStrLit( offset: u32, ) InnerError!void { const raw_string = bytes[offset..]; - var buf_managed = buf.toManaged(astgen.gpa); - const result = std.zig.string_literal.parseWrite(buf_managed.writer(), raw_string); - buf.* = buf_managed.moveToUnmanaged(); - switch (try result) { + const result = r: { + var aw: std.io.Writer.Allocating = .fromArrayList(astgen.gpa, buf); + defer buf.* = aw.toArrayList(); + break :r std.zig.string_literal.parseWrite(&aw.writer, raw_string) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + }; + switch (result) { .success => return, .failure => |err| return astgen.failWithStrLitError(err, token, bytes, offset), } @@ -11324,17 +11328,18 @@ fn appendErrorNodeNotes( notes: []const u32, ) Allocator.Error!void { @branchHint(.cold); + const gpa = astgen.gpa; const string_bytes = &astgen.string_bytes; const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len); - try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args); + try string_bytes.print(gpa, format ++ "\x00", args); const notes_index: u32 = if (notes.len != 0) blk: { const notes_start = astgen.extra.items.len; - try astgen.extra.ensureTotalCapacity(astgen.gpa, notes_start + 1 + notes.len); + try astgen.extra.ensureTotalCapacity(gpa, notes_start + 1 + notes.len); astgen.extra.appendAssumeCapacity(@intCast(notes.len)); astgen.extra.appendSliceAssumeCapacity(notes); break :blk @intCast(notes_start); } else 0; - try astgen.compile_errors.append(astgen.gpa, .{ + try astgen.compile_errors.append(gpa, .{ .msg = msg, .node = node.toOptional(), .token = .none, @@ -11418,7 +11423,7 @@ fn appendErrorTokNotesOff( const gpa = astgen.gpa; const string_bytes = &astgen.string_bytes; const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len); - try string_bytes.writer(gpa).print(format ++ "\x00", args); + try string_bytes.print(gpa, format ++ "\x00", args); const notes_index: u32 = if (notes.len != 0) blk: { const notes_start = astgen.extra.items.len; try astgen.extra.ensureTotalCapacity(gpa, notes_start + 1 + notes.len); @@ -11454,7 +11459,7 @@ fn errNoteTokOff( @branchHint(.cold); const string_bytes = &astgen.string_bytes; const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len); - try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args); + try string_bytes.print(astgen.gpa, format ++ "\x00", args); return astgen.addExtra(Zir.Inst.CompileErrors.Item{ .msg = msg, .node = .none, @@ -11473,7 +11478,7 @@ fn errNoteNode( @branchHint(.cold); const string_bytes = &astgen.string_bytes; const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len); - try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args); + try string_bytes.print(astgen.gpa, format ++ "\x00", args); return astgen.addExtra(Zir.Inst.CompileErrors.Item{ .msg = msg, .node = node.toOptional(), @@ -13715,13 +13720,14 @@ fn emitDbgStmtForceCurrentIndex(gz: *GenZir, lc: LineColumn) !void { } }); } -fn lowerAstErrors(astgen: *AstGen) !void { +fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void { const gpa = astgen.gpa; const tree = astgen.tree; assert(tree.errors.len > 0); - var msg: std.ArrayListUnmanaged(u8) = .empty; - defer msg.deinit(gpa); + var msg: std.io.Writer.Allocating = .init(gpa); + defer msg.deinit(); + const msg_w = &msg.writer; var notes: std.ArrayListUnmanaged(u32) = .empty; defer notes.deinit(gpa); @@ -13749,26 +13755,26 @@ fn lowerAstErrors(astgen: *AstGen) !void { break :blk idx - tok_start; }; - const err: Ast.Error = .{ + const ast_err: Ast.Error = .{ .tag = Ast.Error.Tag.invalid_byte, .token = tok, .extra = .{ .offset = bad_off }, }; msg.clearRetainingCapacity(); - try tree.renderError(err, msg.writer(gpa)); - return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.items}, notes.items); + tree.renderError(ast_err, msg_w) catch return error.OutOfMemory; + return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.getWritten()}, notes.items); } var cur_err = tree.errors[0]; for (tree.errors[1..]) |err| { if (err.is_note) { - try tree.renderError(err, msg.writer(gpa)); - try notes.append(gpa, try astgen.errNoteTok(err.token, "{s}", .{msg.items})); + tree.renderError(err, msg_w) catch return error.OutOfMemory; + try notes.append(gpa, try astgen.errNoteTok(err.token, "{s}", .{msg.getWritten()})); } else { // Flush error const extra_offset = tree.errorOffset(cur_err); - try tree.renderError(cur_err, msg.writer(gpa)); - try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.items}, notes.items); + tree.renderError(cur_err, msg_w) catch return error.OutOfMemory; + try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items); notes.clearRetainingCapacity(); cur_err = err; @@ -13781,8 +13787,8 @@ fn lowerAstErrors(astgen: *AstGen) !void { // Flush error const extra_offset = tree.errorOffset(cur_err); - try tree.renderError(cur_err, msg.writer(gpa)); - try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.items}, notes.items); + tree.renderError(cur_err, msg_w) catch return error.OutOfMemory; + try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items); } const DeclarationName = union(enum) { diff --git a/src/Compilation.zig b/src/Compilation.zig index 8406134352..461528c939 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5328,7 +5328,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{}); defer out_zig_file.close(); - const formatted = try tree.render(comp.gpa); + const formatted = try tree.renderAlloc(comp.gpa); defer comp.gpa.free(formatted); try out_zig_file.writeAll(formatted); diff --git a/src/Package/Manifest.zig b/src/Package/Manifest.zig index 1d71b60fa3..f5a4a8c314 100644 --- a/src/Package/Manifest.zig +++ b/src/Package/Manifest.zig @@ -471,10 +471,14 @@ const Parse = struct { offset: u32, ) InnerError!void { const raw_string = bytes[offset..]; - var buf_managed = buf.toManaged(p.gpa); - const result = std.zig.string_literal.parseWrite(buf_managed.writer(), raw_string); - buf.* = buf_managed.moveToUnmanaged(); - switch (try result) { + const result = r: { + var aw: std.io.Writer.Allocating = .fromArrayList(p.gpa, buf); + defer buf.* = aw.toArrayList(); + break :r std.zig.string_literal.parseWrite(&aw.writer, raw_string) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + }; + switch (result) { .success => {}, .failure => |err| try p.appendStrLitError(err, token, bytes, offset), } diff --git a/src/fmt.zig b/src/fmt.zig index bbb02e0c34..88c0e3a06f 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -34,7 +34,7 @@ const Fmt = struct { color: Color, gpa: Allocator, arena: Allocator, - out_buffer: std.ArrayList(u8), + out_buffer: std.Io.Writer.Allocating, const SeenMap = std.AutoHashMap(fs.File.INode, void); }; @@ -102,7 +102,9 @@ pub fn run( } const stdin: fs.File = .stdin(); - const source_code = std.zig.readSourceFileToEndAlloc(gpa, stdin, null) catch |err| { + var stdio_buffer: [1024]u8 = undefined; + var file_reader: fs.File.Reader = stdin.reader(&stdio_buffer); + const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| { fatal("unable to read stdin: {}", .{err}); }; defer gpa.free(source_code); @@ -146,7 +148,7 @@ pub fn run( try std.zig.printAstErrorsToStderr(gpa, tree, "", color); process.exit(2); } - const formatted = try tree.render(gpa); + const formatted = try tree.renderAlloc(gpa); defer gpa.free(formatted); if (check_flag) { @@ -169,7 +171,7 @@ pub fn run( .check_ast = check_ast_flag, .force_zon = force_zon, .color = color, - .out_buffer = std.ArrayList(u8).init(gpa), + .out_buffer = .init(gpa), }; defer fmt.seen.deinit(); defer fmt.out_buffer.deinit(); @@ -230,6 +232,9 @@ const FmtError = error{ NetNameDeleted, InvalidArgument, ProcessNotFound, + ConnectionTimedOut, + NotOpenForReading, + StreamTooLong, } || fs.File.OpenError; fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { @@ -295,12 +300,15 @@ fn fmtPathFile( if (stat.kind == .directory) return error.IsDir; + var read_buffer: [1024]u8 = undefined; + var file_reader: fs.File.Reader = source_file.reader(&read_buffer); + file_reader.size = stat.size; + const gpa = fmt.gpa; - const source_code = try std.zig.readSourceFileToEndAlloc( - gpa, - source_file, - std.math.cast(usize, stat.size) orelse return error.FileTooBig, - ); + const source_code = std.zig.readSourceFileToEndAlloc(gpa, &file_reader) catch |err| switch (err) { + error.ReadFailed => return file_reader.err.?, + else => |e| return e, + }; defer gpa.free(source_code); source_file.close(); @@ -363,11 +371,13 @@ fn fmtPathFile( } // As a heuristic, we make enough capacity for the same as the input source. - fmt.out_buffer.shrinkRetainingCapacity(0); + fmt.out_buffer.clearRetainingCapacity(); try fmt.out_buffer.ensureTotalCapacity(source_code.len); - try tree.renderToArrayList(&fmt.out_buffer, .{}); - if (mem.eql(u8, fmt.out_buffer.items, source_code)) + tree.render(gpa, &fmt.out_buffer.writer, .{}) catch |err| switch (err) { + error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, + }; + if (mem.eql(u8, fmt.out_buffer.getWritten(), source_code)) return; if (check_mode) { @@ -378,7 +388,7 @@ fn fmtPathFile( var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode }); defer af.deinit(); - try af.file.writeAll(fmt.out_buffer.items); + try af.file.writeAll(fmt.out_buffer.getWritten()); try af.finish(); const stdout = std.fs.File.stdout().deprecatedWriter(); try stdout.print("{s}\n", .{file_path}); diff --git a/src/main.zig b/src/main.zig index 37b137ea94..019ae8bc7e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4550,7 +4550,7 @@ fn cmdTranslateC( error.SemanticAnalyzeFail => break :f .{ .error_bundle = errors }, }; defer tree.deinit(comp.gpa); - break :f .{ .success = try tree.render(arena) }; + break :f .{ .success = try tree.renderAlloc(arena) }; }, }; @@ -6058,7 +6058,8 @@ fn cmdAstCheck( }; } else fs.File.stdin(); defer if (zig_source_path != null) f.close(); - break :s std.zig.readSourceFileToEndAlloc(arena, f, null) catch |err| { + var file_reader: fs.File.Reader = f.reader(&stdio_buffer); + break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| { fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) }); }; }; @@ -6416,14 +6417,16 @@ fn cmdChangelist( var f = fs.cwd().openFile(old_source_path, .{}) catch |err| fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); defer f.close(); - break :source std.zig.readSourceFileToEndAlloc(arena, f, std.zig.max_src_size) catch |err| + var file_reader: fs.File.Reader = f.reader(&stdio_buffer); + break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) }); }; const new_source = source: { var f = fs.cwd().openFile(new_source_path, .{}) catch |err| fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) }); defer f.close(); - break :source std.zig.readSourceFileToEndAlloc(arena, f, std.zig.max_src_size) catch |err| + var file_reader: fs.File.Reader = f.reader(&stdio_buffer); + break :source std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) }); }; @@ -6946,7 +6949,7 @@ fn cmdFetch( ast.deinit(gpa); } - var fixups: Ast.Fixups = .{}; + var fixups: Ast.Render.Fixups = .{}; defer fixups.deinit(gpa); var saved_path_or_url = path_or_url; @@ -7047,12 +7050,13 @@ fn cmdFetch( try fixups.append_string_after_node.put(gpa, manifest.version_node, dependencies_text); } - var rendered = std.ArrayList(u8).init(gpa); - defer rendered.deinit(); - try ast.renderToArrayList(&rendered, fixups); + var aw: std.Io.Writer.Allocating = .init(gpa); + defer aw.deinit(); + try ast.render(gpa, &aw.writer, fixups); + const rendered = aw.getWritten(); - build_root.directory.handle.writeFile(.{ .sub_path = Package.Manifest.basename, .data = rendered.items }) catch |err| { - fatal("unable to write {s} file: {s}", .{ Package.Manifest.basename, @errorName(err) }); + build_root.directory.handle.writeFile(.{ .sub_path = Package.Manifest.basename, .data = rendered }) catch |err| { + fatal("unable to write {s} file: {t}", .{ Package.Manifest.basename, err }); }; return cleanExit(); diff --git a/tools/gen_spirv_spec.zig b/tools/gen_spirv_spec.zig index 8840a476c4..c8a3cf5ced 100644 --- a/tools/gen_spirv_spec.zig +++ b/tools/gen_spirv_spec.zig @@ -120,7 +120,7 @@ pub fn main() !void { error_bundle.renderToStdErr(color.renderOptions()); } - const formatted_output = try tree.render(allocator); + const formatted_output = try tree.renderAlloc(allocator); _ = try std.fs.File.stdout().write(formatted_output); }