From 93ac76594a6ee88e0851bca904a2bbfb0c6509d7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 9 Jul 2025 15:31:02 -0700 Subject: [PATCH] std: fmt.format to io.Writer.print allows reverting format -> deprecatedFormat, plus I think this is a nicer place for the function. --- lib/std/crypto/ml_kem.zig | 14 +-- lib/std/fmt.zig | 198 +------------------------------- lib/std/io/DeprecatedWriter.zig | 2 +- lib/std/io/Writer.zig | 188 +++++++++++++++++++++++++++++- lib/std/json/stringify.zig | 6 +- lib/std/os/uefi.zig | 2 +- lib/std/zig/render.zig | 4 +- lib/std/zon/stringify.zig | 12 +- src/link/tapi/parse.zig | 8 +- 9 files changed, 215 insertions(+), 219 deletions(-) diff --git a/lib/std/crypto/ml_kem.zig b/lib/std/crypto/ml_kem.zig index 4c19095523..ce3edf9eb5 100644 --- a/lib/std/crypto/ml_kem.zig +++ b/lib/std/crypto/ml_kem.zig @@ -1737,11 +1737,11 @@ test "NIST KAT test" { var f = sha2.Sha256.init(.{}); const fw = f.writer(); var g = NistDRBG.init(seed); - try std.fmt.deprecatedFormat(fw, "# {s}\n\n", .{mode.name}); + try std.fmt.format(fw, "# {s}\n\n", .{mode.name}); for (0..100) |i| { g.fill(&seed); - try std.fmt.deprecatedFormat(fw, "count = {}\n", .{i}); - try std.fmt.deprecatedFormat(fw, "seed = {X}\n", .{&seed}); + try std.fmt.format(fw, "count = {}\n", .{i}); + try std.fmt.format(fw, "seed = {X}\n", .{&seed}); var g2 = NistDRBG.init(seed); // This is not equivalent to g2.fill(kseed[:]). As the reference @@ -1756,10 +1756,10 @@ test "NIST KAT test" { const e = kp.public_key.encaps(eseed); const ss2 = try kp.secret_key.decaps(&e.ciphertext); try testing.expectEqual(ss2, e.shared_secret); - try std.fmt.deprecatedFormat(fw, "pk = {X}\n", .{&kp.public_key.toBytes()}); - try std.fmt.deprecatedFormat(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()}); - try std.fmt.deprecatedFormat(fw, "ct = {X}\n", .{&e.ciphertext}); - try std.fmt.deprecatedFormat(fw, "ss = {X}\n\n", .{&e.shared_secret}); + try std.fmt.format(fw, "pk = {X}\n", .{&kp.public_key.toBytes()}); + try std.fmt.format(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()}); + try std.fmt.format(fw, "ct = {X}\n", .{&e.ciphertext}); + try std.fmt.format(fw, "ss = {X}\n\n", .{&e.shared_secret}); } var out: [32]u8 = undefined; diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index c9a203679e..0c51d56e30 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -78,197 +78,10 @@ pub const Number = struct { }; }; -/// Renders fmt string with args, calling `writer` with slices of bytes. -/// If `writer` returns an error, the error is returned from `format` and -/// `writer` is not called again. -/// -/// The format string must be comptime-known and may contain placeholders following -/// this format: -/// `{[argument][specifier]:[fill][alignment][width].[precision]}` -/// -/// Above, each word including its surrounding [ and ] is a parameter which you have to replace with something: -/// -/// - *argument* is either the numeric index or the field name of the argument that should be inserted -/// - when using a field name, you are required to enclose the field name (an identifier) in square -/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...} -/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below) -/// - *fill* is a single byte which is used to pad formatted numbers. -/// - *alignment* is one of the three bytes '<', '^', or '>' to make numbers -/// left, center, or right-aligned, respectively. -/// - Not all specifiers support alignment. -/// - Alignment is not Unicode-aware; appropriate only when used with raw bytes or ASCII. -/// - *width* is the total width of the field in bytes. This only applies to number formatting. -/// - *precision* specifies how many decimals a formatted number should have. -/// -/// Note that most of the parameters are optional and may be omitted. Also you -/// can leave out separators like `:` and `.` when all parameters after the -/// separator are omitted. -/// -/// Only exception is the *fill* parameter. If a non-zero *fill* character is -/// required at the same time as *width* is specified, one has to specify -/// *alignment* as well, as otherwise the digit following `:` is interpreted as -/// *width*, not *fill*. -/// -/// The *specifier* has several options for types: -/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes -/// - `s`: -/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination -/// - for slices of u8, print the entire slice as a string without zero-termination -/// - `t`: -/// - for enums and tagged unions: prints the tag name -/// - for error sets: prints the error name -/// - `b64`: output string as standard base64 -/// - `e`: output floating point value in scientific notation -/// - `d`: output numeric value in decimal notation -/// - `b`: output integer value in binary notation -/// - `o`: output integer value in octal notation -/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max. -/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max. -/// - `D`: output nanoseconds as duration -/// - `B`: output bytes in SI units (decimal) -/// - `Bi`: output bytes in IEC units (binary) -/// - `?`: output optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value. -/// - `!`: output error union value as either the unwrapped value, or the formatted error value; may be followed by a format specifier for the underlying value. -/// - `*`: output the address of the value instead of the value itself. -/// - `any`: output a value of any type using its default format. -/// - `f`: delegates to a method on the type named "format" with the signature `fn (*Writer, args: anytype) Writer.Error!void`. -/// -/// A user type may be a `struct`, `vector`, `union` or `enum` type. -/// -/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`. -pub fn format(w: *Writer, comptime fmt: []const u8, args: anytype) Writer.Error!void { - const ArgsType = @TypeOf(args); - const args_type_info = @typeInfo(ArgsType); - if (args_type_info != .@"struct") { - @compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType)); - } - - const fields_info = args_type_info.@"struct".fields; - if (fields_info.len > max_format_args) { - @compileError("32 arguments max are supported per format call"); - } - - @setEvalBranchQuota(fmt.len * 1000); - comptime var arg_state: ArgState = .{ .args_len = fields_info.len }; - comptime var i = 0; - comptime var literal: []const u8 = ""; - inline while (true) { - const start_index = i; - - inline while (i < fmt.len) : (i += 1) { - switch (fmt[i]) { - '{', '}' => break, - else => {}, - } - } - - comptime var end_index = i; - comptime var unescape_brace = false; - - // Handle {{ and }}, those are un-escaped as single braces - if (i + 1 < fmt.len and fmt[i + 1] == fmt[i]) { - unescape_brace = true; - // Make the first brace part of the literal... - end_index += 1; - // ...and skip both - i += 2; - } - - literal = literal ++ fmt[start_index..end_index]; - - // We've already skipped the other brace, restart the loop - if (unescape_brace) continue; - - // Write out the literal - if (literal.len != 0) { - try w.writeAll(literal); - literal = ""; - } - - if (i >= fmt.len) break; - - if (fmt[i] == '}') { - @compileError("missing opening {"); - } - - // Get past the { - comptime assert(fmt[i] == '{'); - i += 1; - - const fmt_begin = i; - // Find the closing brace - inline while (i < fmt.len and fmt[i] != '}') : (i += 1) {} - const fmt_end = i; - - if (i >= fmt.len) { - @compileError("missing closing }"); - } - - // Get past the } - comptime assert(fmt[i] == '}'); - i += 1; - - const placeholder_array = fmt[fmt_begin..fmt_end].*; - const placeholder = comptime Placeholder.parse(&placeholder_array); - const arg_pos = comptime switch (placeholder.arg) { - .none => null, - .number => |pos| pos, - .named => |arg_name| meta.fieldIndex(ArgsType, arg_name) orelse - @compileError("no argument with name '" ++ arg_name ++ "'"), - }; - - const width = switch (placeholder.width) { - .none => null, - .number => |v| v, - .named => |arg_name| blk: { - const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse - @compileError("no argument with name '" ++ arg_name ++ "'"); - _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments"); - break :blk @field(args, arg_name); - }, - }; - - const precision = switch (placeholder.precision) { - .none => null, - .number => |v| v, - .named => |arg_name| blk: { - const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse - @compileError("no argument with name '" ++ arg_name ++ "'"); - _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments"); - break :blk @field(args, arg_name); - }, - }; - - const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse - @compileError("too few arguments"); - - try w.printValue( - placeholder.specifier_arg, - .{ - .fill = placeholder.fill, - .alignment = placeholder.alignment, - .width = width, - .precision = precision, - }, - @field(args, fields_info[arg_to_print].name), - std.options.fmt_max_depth, - ); - } - - if (comptime arg_state.hasUnusedArgs()) { - const missing_count = arg_state.args_len - @popCount(arg_state.used_args); - switch (missing_count) { - 0 => unreachable, - 1 => @compileError("unused argument in '" ++ fmt ++ "'"), - else => @compileError(comptimePrint("{d}", .{missing_count}) ++ " unused arguments in '" ++ fmt ++ "'"), - } - } -} - -/// Deprecated in favor of `format`. -pub fn deprecatedFormat(writer: anytype, comptime fmt: []const u8, args: anytype) !void { +/// Deprecated in favor of `Writer.print`. +pub fn format(writer: anytype, comptime fmt: []const u8, args: anytype) !void { var adapter = writer.adaptToNewApi(); - return format(&adapter.new_interface, fmt, args) catch |err| switch (err) { + return adapter.new_interface.print(fmt, args) catch |err| switch (err) { error.WriteFailed => return adapter.err.?, }; } @@ -418,7 +231,6 @@ pub const Parser = struct { }; pub const ArgSetType = u32; -const max_format_args = @typeInfo(ArgSetType).int.bits; pub const ArgState = struct { next_arg: usize = 0, @@ -1524,8 +1336,8 @@ test "recursive format function" { pub fn format(self: R, writer: *Writer) Writer.Error!void { return switch (self) { - .Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}), - .Branch => |b| std.fmt.format(writer, "Branch({f}, {f})", .{ b.left, b.right }), + .Leaf => |n| writer.print("Leaf({})", .{n}), + .Branch => |b| writer.print("Branch({f}, {f})", .{ b.left, b.right }), }; } }; diff --git a/lib/std/io/DeprecatedWriter.zig b/lib/std/io/DeprecatedWriter.zig index 34d72c7efe..391b985357 100644 --- a/lib/std/io/DeprecatedWriter.zig +++ b/lib/std/io/DeprecatedWriter.zig @@ -21,7 +21,7 @@ pub fn writeAll(self: Self, bytes: []const u8) anyerror!void { } pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void { - return std.fmt.deprecatedFormat(self, format, args); + return std.fmt.format(self, format, args); } pub fn writeByte(self: Self, byte: u8) anyerror!void { diff --git a/lib/std/io/Writer.zig b/lib/std/io/Writer.zig index 4280d0b93e..54868f9945 100644 --- a/lib/std/io/Writer.zig +++ b/lib/std/io/Writer.zig @@ -519,8 +519,192 @@ pub fn writeAllPreserve(w: *Writer, preserve_length: usize, bytes: []const u8) E while (index < bytes.len) index += try w.writePreserve(preserve_length, bytes[index..]); } -pub fn print(w: *Writer, comptime format: []const u8, args: anytype) Error!void { - try std.fmt.format(w, format, args); +/// Renders fmt string with args, calling `writer` with slices of bytes. +/// If `writer` returns an error, the error is returned from `format` and +/// `writer` is not called again. +/// +/// The format string must be comptime-known and may contain placeholders following +/// this format: +/// `{[argument][specifier]:[fill][alignment][width].[precision]}` +/// +/// Above, each word including its surrounding [ and ] is a parameter which you have to replace with something: +/// +/// - *argument* is either the numeric index or the field name of the argument that should be inserted +/// - when using a field name, you are required to enclose the field name (an identifier) in square +/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...} +/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below) +/// - *fill* is a single byte which is used to pad formatted numbers. +/// - *alignment* is one of the three bytes '<', '^', or '>' to make numbers +/// left, center, or right-aligned, respectively. +/// - Not all specifiers support alignment. +/// - Alignment is not Unicode-aware; appropriate only when used with raw bytes or ASCII. +/// - *width* is the total width of the field in bytes. This only applies to number formatting. +/// - *precision* specifies how many decimals a formatted number should have. +/// +/// Note that most of the parameters are optional and may be omitted. Also you +/// can leave out separators like `:` and `.` when all parameters after the +/// separator are omitted. +/// +/// Only exception is the *fill* parameter. If a non-zero *fill* character is +/// required at the same time as *width* is specified, one has to specify +/// *alignment* as well, as otherwise the digit following `:` is interpreted as +/// *width*, not *fill*. +/// +/// The *specifier* has several options for types: +/// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes +/// - `s`: +/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination +/// - for slices of u8, print the entire slice as a string without zero-termination +/// - `t`: +/// - for enums and tagged unions: prints the tag name +/// - for error sets: prints the error name +/// - `b64`: output string as standard base64 +/// - `e`: output floating point value in scientific notation +/// - `d`: output numeric value in decimal notation +/// - `b`: output integer value in binary notation +/// - `o`: output integer value in octal notation +/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max. +/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max. +/// - `D`: output nanoseconds as duration +/// - `B`: output bytes in SI units (decimal) +/// - `Bi`: output bytes in IEC units (binary) +/// - `?`: output optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value. +/// - `!`: output error union value as either the unwrapped value, or the formatted error value; may be followed by a format specifier for the underlying value. +/// - `*`: output the address of the value instead of the value itself. +/// - `any`: output a value of any type using its default format. +/// - `f`: delegates to a method on the type named "format" with the signature `fn (*Writer, args: anytype) Writer.Error!void`. +/// +/// A user type may be a `struct`, `vector`, `union` or `enum` type. +/// +/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`. +pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void { + const ArgsType = @TypeOf(args); + const args_type_info = @typeInfo(ArgsType); + if (args_type_info != .@"struct") { + @compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType)); + } + + const fields_info = args_type_info.@"struct".fields; + const max_format_args = @typeInfo(std.fmt.ArgSetType).int.bits; + if (fields_info.len > max_format_args) { + @compileError("32 arguments max are supported per format call"); + } + + @setEvalBranchQuota(fmt.len * 1000); + comptime var arg_state: std.fmt.ArgState = .{ .args_len = fields_info.len }; + comptime var i = 0; + comptime var literal: []const u8 = ""; + inline while (true) { + const start_index = i; + + inline while (i < fmt.len) : (i += 1) { + switch (fmt[i]) { + '{', '}' => break, + else => {}, + } + } + + comptime var end_index = i; + comptime var unescape_brace = false; + + // Handle {{ and }}, those are un-escaped as single braces + if (i + 1 < fmt.len and fmt[i + 1] == fmt[i]) { + unescape_brace = true; + // Make the first brace part of the literal... + end_index += 1; + // ...and skip both + i += 2; + } + + literal = literal ++ fmt[start_index..end_index]; + + // We've already skipped the other brace, restart the loop + if (unescape_brace) continue; + + // Write out the literal + if (literal.len != 0) { + try w.writeAll(literal); + literal = ""; + } + + if (i >= fmt.len) break; + + if (fmt[i] == '}') { + @compileError("missing opening {"); + } + + // Get past the { + comptime assert(fmt[i] == '{'); + i += 1; + + const fmt_begin = i; + // Find the closing brace + inline while (i < fmt.len and fmt[i] != '}') : (i += 1) {} + const fmt_end = i; + + if (i >= fmt.len) { + @compileError("missing closing }"); + } + + // Get past the } + comptime assert(fmt[i] == '}'); + i += 1; + + const placeholder_array = fmt[fmt_begin..fmt_end].*; + const placeholder = comptime std.fmt.Placeholder.parse(&placeholder_array); + const arg_pos = comptime switch (placeholder.arg) { + .none => null, + .number => |pos| pos, + .named => |arg_name| std.meta.fieldIndex(ArgsType, arg_name) orelse + @compileError("no argument with name '" ++ arg_name ++ "'"), + }; + + const width = switch (placeholder.width) { + .none => null, + .number => |v| v, + .named => |arg_name| blk: { + const arg_i = comptime std.meta.fieldIndex(ArgsType, arg_name) orelse + @compileError("no argument with name '" ++ arg_name ++ "'"); + _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments"); + break :blk @field(args, arg_name); + }, + }; + + const precision = switch (placeholder.precision) { + .none => null, + .number => |v| v, + .named => |arg_name| blk: { + const arg_i = comptime std.meta.fieldIndex(ArgsType, arg_name) orelse + @compileError("no argument with name '" ++ arg_name ++ "'"); + _ = comptime arg_state.nextArg(arg_i) orelse @compileError("too few arguments"); + break :blk @field(args, arg_name); + }, + }; + + const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse + @compileError("too few arguments"); + + try w.printValue( + placeholder.specifier_arg, + .{ + .fill = placeholder.fill, + .alignment = placeholder.alignment, + .width = width, + .precision = precision, + }, + @field(args, fields_info[arg_to_print].name), + std.options.fmt_max_depth, + ); + } + + if (comptime arg_state.hasUnusedArgs()) { + const missing_count = arg_state.args_len - @popCount(arg_state.used_args); + switch (missing_count) { + 0 => unreachable, + 1 => @compileError("unused argument in '" ++ fmt ++ "'"), + else => @compileError(std.fmt.comptimePrint("{d}", .{missing_count}) ++ " unused arguments in '" ++ fmt ++ "'"), + } + } } /// Calls `drain` as many times as necessary such that `byte` is transferred. diff --git a/lib/std/json/stringify.zig b/lib/std/json/stringify.zig index b3c208756c..aa49573695 100644 --- a/lib/std/json/stringify.zig +++ b/lib/std/json/stringify.zig @@ -689,7 +689,7 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void { // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. try out_stream.writeAll("\\u"); //try w.printInt("x", .{ .width = 4, .fill = '0' }, codepoint); - try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{codepoint}); + try std.fmt.format(out_stream, "{x:0>4}", .{codepoint}); } else { assert(codepoint <= 0x10FFFF); // To escape an extended character that is not in the Basic Multilingual Plane, @@ -698,10 +698,10 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void { const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00; try out_stream.writeAll("\\u"); //try w.printInt("x", .{ .width = 4, .fill = '0' }, high); - try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{high}); + try std.fmt.format(out_stream, "{x:0>4}", .{high}); try out_stream.writeAll("\\u"); //try w.printInt("x", .{ .width = 4, .fill = '0' }, low); - try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{low}); + try std.fmt.format(out_stream, "{x:0>4}", .{low}); } } diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 804dc414ce..6526f590fa 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -65,7 +65,7 @@ pub const Guid = extern struct { const time_mid = @byteSwap(self.time_mid); const time_high_and_version = @byteSwap(self.time_high_and_version); - return std.fmt.format(writer, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{ + return writer.print("{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{ std.mem.asBytes(&time_low), std.mem.asBytes(&time_mid), std.mem.asBytes(&time_high_and_version), diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 597820df25..56ab032771 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -2872,7 +2872,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void { .success => |codepoint| { if (codepoint <= 0x7f) { const buf = [1]u8{@as(u8, @intCast(codepoint))}; - try std.fmt.deprecatedFormat(writer, "{f}", .{std.zig.fmtString(&buf)}); + try std.fmt.format(writer, "{f}", .{std.zig.fmtString(&buf)}); } else { try writer.writeAll(escape_sequence); } @@ -2884,7 +2884,7 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void { }, 0x00...('\\' - 1), ('\\' + 1)...0x7f => { const buf = [1]u8{byte}; - try std.fmt.deprecatedFormat(writer, "{f}", .{std.zig.fmtString(&buf)}); + try std.fmt.format(writer, "{f}", .{std.zig.fmtString(&buf)}); pos += 1; }, 0x80...0xff => { diff --git a/lib/std/zon/stringify.zig b/lib/std/zon/stringify.zig index 2b4fc642df..1a38dc7579 100644 --- a/lib/std/zon/stringify.zig +++ b/lib/std/zon/stringify.zig @@ -501,7 +501,7 @@ pub fn Serializer(Writer: type) type { try self.int(val); }, .float, .comptime_float => try self.float(val), - .bool, .null => try std.fmt.deprecatedFormat(self.writer, "{}", .{val}), + .bool, .null => try std.fmt.format(self.writer, "{}", .{val}), .enum_literal => try self.ident(@tagName(val)), .@"enum" => try self.ident(@tagName(val)), .pointer => |pointer| { @@ -616,7 +616,7 @@ pub fn Serializer(Writer: type) type { /// Serialize an integer. pub fn int(self: *Self, val: anytype) Writer.Error!void { //try self.writer.printInt(val, 10, .lower, .{}); - try std.fmt.deprecatedFormat(self.writer, "{d}", .{val}); + try std.fmt.format(self.writer, "{d}", .{val}); } /// Serialize a float. @@ -631,12 +631,12 @@ pub fn Serializer(Writer: type) type { } else if (std.math.isNegativeZero(val)) { return self.writer.writeAll("-0.0"); } else { - try std.fmt.deprecatedFormat(self.writer, "{d}", .{val}); + try std.fmt.format(self.writer, "{d}", .{val}); }, .comptime_float => if (val == 0) { return self.writer.writeAll("0"); } else { - try std.fmt.deprecatedFormat(self.writer, "{d}", .{val}); + try std.fmt.format(self.writer, "{d}", .{val}); }, else => comptime unreachable, } @@ -659,7 +659,7 @@ pub fn Serializer(Writer: type) type { var buf: [8]u8 = undefined; const len = std.unicode.utf8Encode(val, &buf) catch return error.InvalidCodepoint; const str = buf[0..len]; - try std.fmt.deprecatedFormat(self.writer, "'{f}'", .{std.zig.fmtChar(str)}); + try std.fmt.format(self.writer, "'{f}'", .{std.zig.fmtChar(str)}); } /// Like `value`, but always serializes `val` as a tuple. @@ -717,7 +717,7 @@ pub fn Serializer(Writer: type) type { /// Like `value`, but always serializes `val` as a string. pub fn string(self: *Self, val: []const u8) Writer.Error!void { - try std.fmt.deprecatedFormat(self.writer, "\"{f}\"", .{std.zig.fmtString(val)}); + try std.fmt.format(self.writer, "\"{f}\"", .{std.zig.fmtString(val)}); } /// Options for formatting multiline strings. diff --git a/src/link/tapi/parse.zig b/src/link/tapi/parse.zig index 73174e6d8f..0f418dea30 100644 --- a/src/link/tapi/parse.zig +++ b/src/link/tapi/parse.zig @@ -83,15 +83,15 @@ pub const Node = struct { pub fn format(self: *const Doc, writer: *std.io.Writer) std.io.Writer.Error!void { if (self.directive) |id| { - try std.fmt.format(writer, "{{ ", .{}); + try writer.print("{{ ", .{}); const directive = self.base.tree.getRaw(id, id); - try std.fmt.format(writer, ".directive = {s}, ", .{directive}); + try writer.print(".directive = {s}, ", .{directive}); } if (self.value) |node| { - try std.fmt.format(writer, "{}", .{node}); + try writer.print("{}", .{node}); } if (self.directive != null) { - try std.fmt.format(writer, " }}", .{}); + try writer.print(" }}", .{}); } } };