authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-15 21:04:00-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-16 17:20:02-07:00
log1a20b467ea3f480306317a6145d910d8c44a9b48
treea65bab55b8f1718a23ca09502d7442d249950e0e
parent680358767e30ac386e6727ffc9295820c598d6b9

std.zig: update to new I/O API


1 files changed, 25 insertions(+), 33 deletions(-)

lib/std/zig.zig+25-33
...@@ -2,6 +2,12 @@...@@ -2,6 +2,12 @@
2//! source lives here. These APIs are provided as-is and have absolutely no API2//! source lives here. These APIs are provided as-is and have absolutely no API
3//! guarantees whatsoever.3//! guarantees whatsoever.
44
5const std = @import("std.zig");
6const tokenizer = @import("zig/tokenizer.zig");
7const assert = std.debug.assert;
8const Allocator = std.mem.Allocator;
9const Writer = std.Io.Writer;
10
5pub const ErrorBundle = @import("zig/ErrorBundle.zig");11pub const ErrorBundle = @import("zig/ErrorBundle.zig");
6pub const Server = @import("zig/Server.zig");12pub const Server = @import("zig/Server.zig");
7pub const Client = @import("zig/Client.zig");13pub const Client = @import("zig/Client.zig");
...@@ -355,11 +361,6 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![...@@ -355,11 +361,6 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![
355 return buffer.toOwnedSlice();361 return buffer.toOwnedSlice();
356}362}
357363
358const std = @import("std.zig");
359const tokenizer = @import("zig/tokenizer.zig");
360const assert = std.debug.assert;
361const Allocator = std.mem.Allocator;
362
363/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.364/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed.
364///365///
365/// See also `fmtIdFlags`.366/// See also `fmtIdFlags`.
...@@ -425,7 +426,7 @@ pub const FormatId = struct {...@@ -425,7 +426,7 @@ pub const FormatId = struct {
425 };426 };
426427
427 /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.428 /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
428 fn render(ctx: FormatId, writer: *std.io.Writer) std.io.Writer.Error!void {429 fn render(ctx: FormatId, writer: *Writer) Writer.Error!void {
429 const bytes = ctx.bytes;430 const bytes = ctx.bytes;
430 if (isValidId(bytes) and431 if (isValidId(bytes) and
431 (ctx.flags.allow_primitive or !std.zig.isPrimitive(bytes)) and432 (ctx.flags.allow_primitive or !std.zig.isPrimitive(bytes)) and
...@@ -463,7 +464,7 @@ test fmtChar {...@@ -463,7 +464,7 @@ test fmtChar {
463}464}
464465
465/// Print the string as escaped contents of a double quoted string.466/// Print the string as escaped contents of a double quoted string.
466pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {467pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void {
467 for (bytes) |byte| switch (byte) {468 for (bytes) |byte| switch (byte) {
468 '\n' => try w.writeAll("\\n"),469 '\n' => try w.writeAll("\\n"),
469 '\r' => try w.writeAll("\\r"),470 '\r' => try w.writeAll("\\r"),
...@@ -480,7 +481,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo...@@ -480,7 +481,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo
480}481}
481482
482/// Print the string as escaped contents of a single-quoted string.483/// Print the string as escaped contents of a single-quoted string.
483pub fn charEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {484pub fn charEscape(bytes: []const u8, w: *Writer) Writer.Error!void {
484 for (bytes) |byte| switch (byte) {485 for (bytes) |byte| switch (byte) {
485 '\n' => try w.writeAll("\\n"),486 '\n' => try w.writeAll("\\n"),
486 '\r' => try w.writeAll("\\r"),487 '\r' => try w.writeAll("\\r"),
...@@ -529,20 +530,18 @@ test isUnderscore {...@@ -529,20 +530,18 @@ test isUnderscore {
529 try std.testing.expect(!isUnderscore("\\x5f"));530 try std.testing.expect(!isUnderscore("\\x5f"));
530}531}
531532
532pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: ?usize) ![:0]u8 {533pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: usize) ![:0]u8 {
533 const source_code = input.readToEndAllocOptions(534 var buffer: std.ArrayListAlignedUnmanaged(u8, .@"2") = .empty;
534 gpa,535 defer buffer.deinit(gpa);
535 max_src_size,536
536 size_hint,537 try buffer.ensureUnusedCapacity(gpa, size_hint);
537 .of(u8),538
538 0,539 input.readIntoArrayList(gpa, .limited(max_src_size), .@"2", &buffer) catch |err| switch (err) {
539 ) catch |err| switch (err) {
540 error.ConnectionResetByPeer => unreachable,540 error.ConnectionResetByPeer => unreachable,
541 error.ConnectionTimedOut => unreachable,541 error.ConnectionTimedOut => unreachable,
542 error.NotOpenForReading => unreachable,542 error.NotOpenForReading => unreachable,
543 else => |e| return e,543 else => |e| return e,
544 };544 };
545 errdefer gpa.free(source_code);
546545
547 // Detect unsupported file types with their Byte Order Mark546 // Detect unsupported file types with their Byte Order Mark
548 const unsupported_boms = [_][]const u8{547 const unsupported_boms = [_][]const u8{
...@@ -551,30 +550,23 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: ?...@@ -551,30 +550,23 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: ?
551 "\xfe\xff", // UTF-16 big endian550 "\xfe\xff", // UTF-16 big endian
552 };551 };
553 for (unsupported_boms) |bom| {552 for (unsupported_boms) |bom| {
554 if (std.mem.startsWith(u8, source_code, bom)) {553 if (std.mem.startsWith(u8, buffer.items, bom)) {
555 return error.UnsupportedEncoding;554 return error.UnsupportedEncoding;
556 }555 }
557 }556 }
558557
559 // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8558 // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8
560 if (std.mem.startsWith(u8, source_code, "\xff\xfe")) {559 if (std.mem.startsWith(u8, buffer.items, "\xff\xfe")) {
561 if (source_code.len % 2 != 0) return error.InvalidEncoding;560 if (buffer.items.len % 2 != 0) return error.InvalidEncoding;
562 // TODO: after wrangle-writer-buffering branch is merged,561 return std.unicode.utf16LeToUtf8AllocZ(gpa, @ptrCast(buffer.items)) catch |err| switch (err) {
563 // avoid this unnecessary allocation
564 const aligned_copy = try gpa.alloc(u16, source_code.len / 2);
565 defer gpa.free(aligned_copy);
566 @memcpy(std.mem.sliceAsBytes(aligned_copy), source_code);
567 const source_code_utf8 = std.unicode.utf16LeToUtf8AllocZ(gpa, aligned_copy) catch |err| switch (err) {
568 error.DanglingSurrogateHalf => error.UnsupportedEncoding,562 error.DanglingSurrogateHalf => error.UnsupportedEncoding,
569 error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding,563 error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding,
570 error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding,564 error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding,
571 else => |e| return e,565 else => |e| return e,
572 };566 };
573 gpa.free(source_code);
574 return source_code_utf8;
575 }567 }
576568
577 return source_code;569 return buffer.toOwnedSliceSentinel(gpa, 0);
578}570}
579571
580pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void {572pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void {
...@@ -621,7 +613,7 @@ pub fn parseTargetQueryOrReportFatalError(...@@ -621,7 +613,7 @@ pub fn parseTargetQueryOrReportFatalError(
621 var help_text = std.ArrayList(u8).init(allocator);613 var help_text = std.ArrayList(u8).init(allocator);
622 defer help_text.deinit();614 defer help_text.deinit();
623 for (diags.arch.?.allCpuModels()) |cpu| {615 for (diags.arch.?.allCpuModels()) |cpu| {
624 help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help;616 help_text.print(" {s}\n", .{cpu.name}) catch break :help;
625 }617 }
626 std.log.info("available CPUs for architecture '{s}':\n{s}", .{618 std.log.info("available CPUs for architecture '{s}':\n{s}", .{
627 @tagName(diags.arch.?), help_text.items,619 @tagName(diags.arch.?), help_text.items,
...@@ -634,7 +626,7 @@ pub fn parseTargetQueryOrReportFatalError(...@@ -634,7 +626,7 @@ pub fn parseTargetQueryOrReportFatalError(
634 var help_text = std.ArrayList(u8).init(allocator);626 var help_text = std.ArrayList(u8).init(allocator);
635 defer help_text.deinit();627 defer help_text.deinit();
636 for (diags.arch.?.allFeaturesList()) |feature| {628 for (diags.arch.?.allFeaturesList()) |feature| {
637 help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help;629 help_text.print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help;
638 }630 }
639 std.log.info("available CPU features for architecture '{s}':\n{s}", .{631 std.log.info("available CPU features for architecture '{s}':\n{s}", .{
640 @tagName(diags.arch.?), help_text.items,632 @tagName(diags.arch.?), help_text.items,
...@@ -647,7 +639,7 @@ pub fn parseTargetQueryOrReportFatalError(...@@ -647,7 +639,7 @@ pub fn parseTargetQueryOrReportFatalError(
647 var help_text = std.ArrayList(u8).init(allocator);639 var help_text = std.ArrayList(u8).init(allocator);
648 defer help_text.deinit();640 defer help_text.deinit();
649 inline for (@typeInfo(std.Target.ObjectFormat).@"enum".fields) |field| {641 inline for (@typeInfo(std.Target.ObjectFormat).@"enum".fields) |field| {
650 help_text.writer().print(" {s}\n", .{field.name}) catch break :help;642 help_text.print(" {s}\n", .{field.name}) catch break :help;
651 }643 }
652 std.log.info("available object formats:\n{s}", .{help_text.items});644 std.log.info("available object formats:\n{s}", .{help_text.items});
653 }645 }
...@@ -658,7 +650,7 @@ pub fn parseTargetQueryOrReportFatalError(...@@ -658,7 +650,7 @@ pub fn parseTargetQueryOrReportFatalError(
658 var help_text = std.ArrayList(u8).init(allocator);650 var help_text = std.ArrayList(u8).init(allocator);
659 defer help_text.deinit();651 defer help_text.deinit();
660 inline for (@typeInfo(std.Target.Cpu.Arch).@"enum".fields) |field| {652 inline for (@typeInfo(std.Target.Cpu.Arch).@"enum".fields) |field| {
661 help_text.writer().print(" {s}\n", .{field.name}) catch break :help;653 help_text.print(" {s}\n", .{field.name}) catch break :help;
662 }654 }
663 std.log.info("available architectures:\n{s} native\n", .{help_text.items});655 std.log.info("available architectures:\n{s} native\n", .{help_text.items});
664 }656 }