diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-07-05 10:43:14 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-07-07 22:43:53 -0700 |
| commit | 5378fdb153bc76990105e3640e7725e434e8cdee (patch) | |
| tree | 9791e08538c10c521f5634ed79e3b369fcd004df | |
| parent | 4ccc6f2b5777afd06f0fddbea4e0e0d0c92b007d (diff) | |
| download | zig-5378fdb153bc76990105e3640e7725e434e8cdee.tar.gz zig-5378fdb153bc76990105e3640e7725e434e8cdee.zip | |
std.fmt: fully remove format string from format methods
Introduces `std.fmt.alt` which is a helper for calling alternate format
methods besides one named "format".
43 files changed, 295 insertions, 363 deletions
diff --git a/lib/compiler/resinator/res.zig b/lib/compiler/resinator/res.zig index 266efbaa69..0f441bd17b 100644 --- a/lib/compiler/resinator/res.zig +++ b/lib/compiler/resinator/res.zig @@ -164,8 +164,7 @@ pub const Language = packed struct(u16) { return @bitCast(self); } - pub fn format(language: Language, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(language: Language, w: *std.io.Writer) std.io.Writer.Error!void { const language_id = language.asInt(); const language_name = language_name: { if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| { @@ -440,8 +439,7 @@ pub const NameOrOrdinal = union(enum) { } } - pub fn format(self: NameOrOrdinal, w: *std.io.Writer, comptime fmt: []const u8) !void { - comptime assert(fmt.len == 0); + pub fn format(self: NameOrOrdinal, w: *std.io.Writer) !void { switch (self) { .name => |name| { try w.print("{s}", .{std.unicode.fmtUtf16Le(name)}); diff --git a/lib/std/Build/Cache/Directory.zig b/lib/std/Build/Cache/Directory.zig index cc6b930c23..14a5e8a24d 100644 --- a/lib/std/Build/Cache/Directory.zig +++ b/lib/std/Build/Cache/Directory.zig @@ -56,8 +56,7 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void { self.* = undefined; } -pub fn format(self: Directory, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); +pub fn format(self: Directory, writer: *std.io.Writer) std.io.Writer.Error!void { if (self.path) |p| { try writer.writeAll(p); try writer.writeAll(fs.path.sep_str); diff --git a/lib/std/Build/Cache/Path.zig b/lib/std/Build/Cache/Path.zig index 55af4fdbfa..a0a58067fc 100644 --- a/lib/std/Build/Cache/Path.zig +++ b/lib/std/Build/Cache/Path.zig @@ -147,25 +147,35 @@ pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 { return std.fmt.allocPrintSentinel(allocator, "{f}", .{p}, 0); } -pub fn format(self: Path, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - if (f.len == 1) { - // Quote-escape the string. - const zigEscape = switch (f[0]) { - 'q' => std.zig.stringEscape, - '\'' => std.zig.charEscape, - else => @compileError("unsupported format string: " ++ f), - }; - if (self.root_dir.path) |p| { - try zigEscape(p, writer); - if (self.sub_path.len > 0) try zigEscape(fs.path.sep_str, writer); - } - if (self.sub_path.len > 0) { - try zigEscape(self.sub_path, writer); - } - return; +pub fn fmtEscapeString(path: Path) std.fmt.Formatter(Path, formatEscapeString) { + return .{ .data = path }; +} + +pub fn formatEscapeString(path: Path, writer: *std.io.Writer) std.io.Writer.Error!void { + if (path.root_dir.path) |p| { + try std.zig.stringEscape(p, writer); + if (path.sub_path.len > 0) try std.zig.stringEscape(fs.path.sep_str, writer); + } + if (path.sub_path.len > 0) { + try std.zig.stringEscape(path.sub_path, writer); } - if (f.len > 0) - std.fmt.invalidFmtError(f, self); +} + +pub fn fmtEscapeChar(path: Path) std.fmt.Formatter(Path, formatEscapeChar) { + return .{ .data = path }; +} + +pub fn formatEscapeChar(path: Path, writer: *std.io.Writer) std.io.Writer.Error!void { + if (path.root_dir.path) |p| { + try std.zig.charEscape(p, writer); + if (path.sub_path.len > 0) try std.zig.charEscape(fs.path.sep_str, writer); + } + if (path.sub_path.len > 0) { + try std.zig.charEscape(path.sub_path, writer); + } +} + +pub fn format(self: Path, writer: *std.io.Writer) std.io.Writer.Error!void { if (std.fs.path.isAbsolute(self.sub_path)) { try writer.writeAll(self.sub_path); return; diff --git a/lib/std/SemanticVersion.zig b/lib/std/SemanticVersion.zig index 50b146d74f..52b5908693 100644 --- a/lib/std/SemanticVersion.zig +++ b/lib/std/SemanticVersion.zig @@ -150,8 +150,7 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize { }; } -pub fn format(self: Version, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self); +pub fn format(self: Version, w: *std.io.Writer) std.io.Writer.Error!void { try w.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch }); if (self.pre) |pre| try w.print("-{s}", .{pre}); if (self.build) |build| try w.print("+{s}", .{build}); diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index b1dc845eb5..611d6581c3 100644 --- a/lib/std/Uri.zig +++ b/lib/std/Uri.zig @@ -1,6 +1,10 @@ //! Uniform Resource Identifier (URI) parsing roughly adhering to <https://tools.ietf.org/html/rfc3986>. //! Does not do perfect grammar and character class checking, but should be robust against URIs in the wild. +const std = @import("std.zig"); +const testing = std.testing; +const Uri = @This(); + scheme: []const u8, user: ?Component = null, password: ?Component = null, @@ -34,21 +38,14 @@ pub const Component = union(enum) { return switch (component) { .raw => |raw| raw, .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| - try std.fmt.allocPrint(arena, "{fraw}", .{component}) + try std.fmt.allocPrint(arena, "{f}", .{std.fmt.alt(component, .formatRaw)}) else percent_encoded, }; } - pub fn format(component: Component, w: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void { - if (fmt_str.len == 0) { - try w.print("std.Uri.Component{{ .{s} = \"{f}\" }}", .{ - @tagName(component), - std.zig.fmtString(switch (component) { - .raw, .percent_encoded => |string| string, - }), - }); - } else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) { + pub fn formatRaw(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try w.writeAll(raw), .percent_encoded => |percent_encoded| { var start: usize = 0; @@ -67,28 +64,56 @@ pub const Component = union(enum) { } try w.writeAll(percent_encoded[start..]); }, - } else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) { + } + } + + pub fn formatEscaped(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try percentEncode(w, raw, isUnreserved), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), - } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) { + } + } + + pub fn formatUser(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try percentEncode(w, raw, isUserChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), - } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) { + } + } + + pub fn formatPassword(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try percentEncode(w, raw, isPasswordChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), - } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) { + } + } + + pub fn formatHost(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try percentEncode(w, raw, isHostChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), - } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) { + } + } + + pub fn formatPath(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try percentEncode(w, raw, isPathChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), - } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) { + } + } + + pub fn formatQuery(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try percentEncode(w, raw, isQueryChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), - } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) { + } + } + + pub fn formatFragment(component: Component, w: *std.io.Writer) std.io.Writer.Error!void { + switch (component) { .raw => |raw| try percentEncode(w, raw, isFragmentChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), - } else @compileError("invalid format string '" ++ fmt_str ++ "'"); + } } pub fn percentEncode(w: *std.io.Writer, raw: []const u8, comptime isValidChar: fn (u8) bool) std.io.Writer.Error!void { @@ -215,82 +240,77 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { return uri; } -pub const WriteToStreamOptions = struct { - /// When true, include the scheme part of the URI. - scheme: bool = false, - - /// When true, include the user and password part of the URI. Ignored if `authority` is false. - authentication: bool = false, - - /// When true, include the authority part of the URI. - authority: bool = false, - - /// When true, include the path part of the URI. - path: bool = false, - - /// When true, include the query part of the URI. Ignored when `path` is false. - query: bool = false, - - /// When true, include the fragment part of the URI. Ignored when `path` is false. - fragment: bool = false, - - /// When true, include the port part of the URI. Ignored when `port` is null. - port: bool = true, -}; - -pub fn writeToStream(uri: Uri, writer: *std.io.Writer, options: WriteToStreamOptions) std.io.Writer.Error!void { - if (options.scheme) { +pub fn writeToStream(uri: *const Uri, writer: *std.io.Writer, flags: Format.Flags) std.io.Writer.Error!void { + if (flags.scheme) { try writer.print("{s}:", .{uri.scheme}); - if (options.authority and uri.host != null) { + if (flags.authority and uri.host != null) { try writer.writeAll("//"); } } - if (options.authority) { - if (options.authentication and uri.host != null) { + if (flags.authority) { + if (flags.authentication and uri.host != null) { if (uri.user) |user| { - try writer.print("{fuser}", .{user}); + try user.formatUser(writer); if (uri.password) |password| { - try writer.print(":{fpassword}", .{password}); + try writer.writeByte(':'); + try password.formatPassword(writer); } try writer.writeByte('@'); } } if (uri.host) |host| { - try writer.print("{fhost}", .{host}); - if (options.port) { + try host.formatHost(writer); + if (flags.port) { if (uri.port) |port| try writer.print(":{d}", .{port}); } } } - if (options.path) { - try writer.print("{fpath}", .{ - if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path, - }); - if (options.query) { - if (uri.query) |query| try writer.print("?{fquery}", .{query}); + if (flags.path) { + const uri_path: Component = if (uri.path.isEmpty()) .{ .percent_encoded = "/" } else uri.path; + try uri_path.formatPath(writer); + if (flags.query) { + if (uri.query) |query| { + try writer.writeByte('?'); + try query.formatQuery(writer); + } } - if (options.fragment) { - if (uri.fragment) |fragment| try writer.print("#{ffragment}", .{fragment}); + if (flags.fragment) { + if (uri.fragment) |fragment| { + try writer.writeByte('#'); + try fragment.formatFragment(writer); + } } } } -pub fn format(uri: Uri, writer: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void { - const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0; - const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0; - const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0; - const path = comptime std.mem.indexOfScalar(u8, fmt_str, '/') != null or fmt_str.len == 0; - const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0; - const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0; +pub const Format = struct { + uri: *const Uri, + flags: Flags = .{}, + + pub const Flags = struct { + /// When true, include the scheme part of the URI. + scheme: bool = false, + /// When true, include the user and password part of the URI. Ignored if `authority` is false. + authentication: bool = false, + /// When true, include the authority part of the URI. + authority: bool = false, + /// When true, include the path part of the URI. + path: bool = false, + /// When true, include the query part of the URI. Ignored when `path` is false. + query: bool = false, + /// When true, include the fragment part of the URI. Ignored when `path` is false. + fragment: bool = false, + /// When true, include the port part of the URI. Ignored when `port` is null. + port: bool = true, + }; + + pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { + return writeToStream(f.uri, writer, f.flags); + } +}; - return writeToStream(uri, writer, .{ - .scheme = scheme, - .authentication = authentication, - .authority = authority, - .path = path, - .query = query, - .fragment = fragment, - }); +pub fn fmt(uri: *const Uri, flags: Format.Flags) std.fmt.Formatter(Format, Format.default) { + return .{ .data = .{ .uri = uri, .flags = flags } }; } /// Parses the URI or returns an error. @@ -427,14 +447,13 @@ test remove_dot_segments { /// 5.2.3. Merge Paths fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component { - var aux = std.io.fixedBufferStream(aux_buf.*); + var aux: std.io.Writer = .fixed(aux_buf.*); if (!base.isEmpty()) { - try aux.writer().print("{fpath}", .{base}); - aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse - return remove_dot_segments(new); + base.formatPath(&aux) catch return error.NoSpaceLeft; + aux.end = std.mem.lastIndexOfScalar(u8, aux.buffered(), '/') orelse return remove_dot_segments(new); } - try aux.writer().print("/{s}", .{new}); - const merged_path = remove_dot_segments(aux.getWritten()); + aux.print("/{s}", .{new}) catch return error.NoSpaceLeft; + const merged_path = remove_dot_segments(aux.buffered()); aux_buf.* = aux_buf.*[merged_path.percent_encoded.len..]; return merged_path; } @@ -794,8 +813,11 @@ test "Special test" { test "URI percent encoding" { try std.testing.expectFmt( "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad", - "{f%}", - .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }}, + "{f}", + .{std.fmt.alt( + @as(Component, .{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }), + .formatEscaped, + )}, ); } @@ -804,7 +826,10 @@ test "URI percent decoding" { const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad"; var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*; - try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }}); + try std.testing.expectFmt(expected, "{f}", .{std.fmt.alt( + @as(Component, .{ .percent_encoded = &input }), + .formatRaw, + )}); var output: [expected.len]u8 = undefined; try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); @@ -816,7 +841,10 @@ test "URI percent decoding" { const expected = "/abc%"; var input = expected.*; - try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }}); + try std.testing.expectFmt(expected, "{f}", .{std.fmt.alt( + @as(Component, .{ .percent_encoded = &input }), + .formatRaw, + )}); var output: [expected.len]u8 = undefined; try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); @@ -830,7 +858,9 @@ test "URI query encoding" { const parsed = try Uri.parse(address); // format the URI to percent encode it - try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{f/?}", .{parsed}); + try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{f}", .{ + parsed.fmt(.{ .path = true, .query = true }), + }); } test "format" { @@ -844,7 +874,9 @@ test "format" { .query = null, .fragment = null, }; - try std.testing.expectFmt("file:/foo/bar/baz", "{f;/?#}", .{uri}); + try std.testing.expectFmt("file:/foo/bar/baz", "{f}", .{ + uri.fmt(.{ .scheme = true, .path = true, .query = true, .fragment = true }), + }); } test "URI malformed input" { @@ -852,7 +884,3 @@ test "URI malformed input" { try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://]@[")); try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://lo]s\x85hc@[/8\x10?0Q")); } - -const std = @import("std.zig"); -const testing = std.testing; -const Uri = @This(); diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 03b4db10bb..a69a74e93d 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -34,9 +34,7 @@ pub const StackTrace = struct { index: usize, instruction_addresses: []usize, - pub fn format(self: StackTrace, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - if (fmt.len != 0) unreachable; - + pub fn format(self: StackTrace, writer: *std.io.Writer) std.io.Writer.Error!void { // TODO: re-evaluate whether to use format() methods at all. // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly // where it tries to call detectTTYConfig here. diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 17daacfdd5..b5938fcd8f 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -24,6 +24,8 @@ pub const Alignment = enum { right, }; +pub const Case = enum { lower, upper }; + const default_alignment = .right; const default_fill_char = ' '; @@ -84,13 +86,7 @@ pub const Options = struct { /// - `!`: 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. -/// -/// If a formatted user type contains a function of the type -/// ``` -/// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.Options, writer: anytype) !void -/// ``` -/// with `?` being the type formatted, this function will be called instead of the default implementation. -/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type. +/// - `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. /// @@ -406,8 +402,6 @@ pub const ArgState = struct { } }; -pub const Case = enum { lower, upper }; - /// Asserts the rendered integer value fits in `buffer`. /// Returns the end index within `buffer`. pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize { @@ -425,26 +419,49 @@ pub fn digits2(value: u8) [2]u8 { } } -pub const ParseIntError = error{ - /// The result cannot fit in the type specified. - Overflow, - /// The input was empty or contained an invalid character. - InvalidCharacter, -}; +/// Deprecated in favor of `Alt`. +pub const Formatter = Alt; -pub fn Formatter( +/// Creates a type suitable for instantiating and passing to a "{f}" placeholder. +pub fn Alt( comptime Data: type, comptime formatFn: fn (data: Data, writer: *Writer) Writer.Error!void, ) type { return struct { data: Data, - pub fn format(self: @This(), writer: *Writer, comptime fmt: []const u8) Writer.Error!void { - comptime assert(fmt.len == 0); + pub inline fn format(self: @This(), writer: *Writer) Writer.Error!void { try formatFn(self.data, writer); } }; } +/// Helper for calling alternate format methods besides one named "format". +pub fn alt( + context: anytype, + comptime func_name: @TypeOf(.enum_literal), +) Formatter(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) { + return .{ .data = context }; +} + +test alt { + const Example = struct { + number: u8, + + pub fn other(ex: @This(), w: *Writer) Writer.Error!void { + try w.writeByte(ex.number); + } + }; + const ex: Example = .{ .number = 'a' }; + try expectFmt("a", "{f}", .{alt(ex, .other)}); +} + +pub const ParseIntError = error{ + /// The result cannot fit in the type specified. + Overflow, + /// The input was empty or contained an invalid character. + InvalidCharacter, +}; + /// Parses the string `buf` as signed or unsigned representation in the /// specified base of an integral value of type `T`. /// @@ -1005,7 +1022,7 @@ test "slice" { const S2 = struct { x: u8, - pub fn format(s: @This(), writer: *Writer, comptime _: []const u8) Writer.Error!void { + pub fn format(s: @This(), writer: *Writer) Writer.Error!void { try writer.print("S2({})", .{s.x}); } }; @@ -1249,35 +1266,6 @@ test "float.libc.sanity" { try expectFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 1518338049))))}); } -test "custom" { - const Vec2 = struct { - const SelfType = @This(); - x: f32, - y: f32, - - pub fn format(self: SelfType, writer: *Writer, comptime fmt: []const u8) Writer.Error!void { - if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) { - return std.fmt.format(writer, "({d:.3},{d:.3})", .{ self.x, self.y }); - } else if (comptime std.mem.eql(u8, fmt, "d")) { - return std.fmt.format(writer, "{d:.3}x{d:.3}", .{ self.x, self.y }); - } else { - @compileError("unknown format character: '" ++ fmt ++ "'"); - } - } - }; - - var value: Vec2 = .{ - .x = 10.2, - .y = 2.22, - }; - try expectFmt("point: (10.200,2.220)\n", "point: {f}\n", .{&value}); - try expectFmt("dim: 10.200x2.220\n", "dim: {fd}\n", .{&value}); - - // same thing but not passing a pointer - try expectFmt("point: (10.200,2.220)\n", "point: {f}\n", .{value}); - try expectFmt("dim: 10.200x2.220\n", "dim: {fd}\n", .{value}); -} - test "union" { const TU = union(enum) { float: f32, @@ -1516,7 +1504,7 @@ test "recursive format function" { Leaf: i32, Branch: struct { left: *const R, right: *const R }, - pub fn format(self: R, writer: *Writer, comptime _: []const u8) Writer.Error!void { + 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 }), diff --git a/lib/std/http.zig b/lib/std/http.zig index 67abe36aa1..5bf12a1876 100644 --- a/lib/std/http.zig +++ b/lib/std/http.zig @@ -42,8 +42,7 @@ pub const Method = enum(u64) { return x; } - pub fn format(self: Method, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: Method, w: *std.io.Writer) std.io.Writer.Error!void { const bytes: []const u8 = @ptrCast(&@intFromEnum(self)); const str = std.mem.sliceTo(bytes, 0); try w.writeAll(str); diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig index 8f4dfe308e..b68f3291ab 100644 --- a/lib/std/http/Client.zig +++ b/lib/std/http/Client.zig @@ -832,7 +832,7 @@ pub const Request = struct { } fn sendAdapted(req: *Request, connection: *Connection, w: *std.io.Writer) !void { - try req.method.format(w, ""); + try req.method.format(w); try w.writeByte(' '); if (req.method == .CONNECT) { @@ -1290,26 +1290,32 @@ pub const basic_authorization = struct { } pub fn valueLengthFromUri(uri: Uri) usize { - var stream = std.io.countingWriter(std.io.null_writer); - try stream.writer().print("{fuser}", .{uri.user orelse Uri.Component.empty}); - const user_len = stream.bytes_written; - stream.bytes_written = 0; - try stream.writer().print("{fpassword}", .{uri.password orelse Uri.Component.empty}); - const password_len = stream.bytes_written; + const user: Uri.Component = uri.user orelse .empty; + const password: Uri.Component = uri.password orelse .empty; + + var w: std.io.Writer = .discarding(&.{}); + user.formatUser(&w) catch unreachable; // discarding + const user_len = w.count; + + w.count = 0; + password.formatPassword(&w) catch unreachable; // discarding + const password_len = w.count; + return valueLength(@intCast(user_len), @intCast(password_len)); } pub fn value(uri: Uri, out: []u8) []u8 { + const user: Uri.Component = uri.user orelse .empty; + const password: Uri.Component = uri.password orelse .empty; + var buf: [max_user_len + ":".len + max_password_len]u8 = undefined; - var stream = std.io.fixedBufferStream(&buf); - stream.writer().print("{fuser}", .{uri.user orelse Uri.Component.empty}) catch - unreachable; - assert(stream.pos <= max_user_len); - stream.writer().print(":{fpassword}", .{uri.password orelse Uri.Component.empty}) catch - unreachable; + var w: std.io.Writer = .fixed(&buf); + user.formatUser(&w) catch unreachable; // fixed + assert(w.count <= max_user_len); + password.formatPassword(&w) catch unreachable; // fixed @memcpy(out[0..prefix.len], prefix); - const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], stream.getWritten()); + const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], w.buffered()); return out[0 .. prefix.len + base64.len]; } }; diff --git a/lib/std/io/Writer.zig b/lib/std/io/Writer.zig index 8a2a579584..29376db2e5 100644 --- a/lib/std/io/Writer.zig +++ b/lib/std/io/Writer.zig @@ -804,8 +804,11 @@ pub fn printValue( ) Error!void { const T = @TypeOf(value); - if (comptime std.mem.eql(u8, fmt, "*")) return w.printAddress(value); - if (fmt.len > 0 and fmt[0] == 'f') return value.format(w, fmt[1..]); + if (fmt.len == 1) switch (fmt[0]) { + '*' => return w.printAddress(value), + 'f' => return value.format(w), + else => {}, + }; const is_any = comptime std.mem.eql(u8, fmt, ANY); if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) { @@ -1568,12 +1571,8 @@ test "printValue max_depth" { x: f32, y: f32, - pub fn format(self: SelfType, w: *Writer, comptime fmt: []const u8) Error!void { - if (fmt.len == 0) { - return w.print("({d:.3},{d:.3})", .{ self.x, self.y }); - } else { - @compileError("unknown format string: '" ++ fmt ++ "'"); - } + pub fn format(self: SelfType, w: *Writer) Error!void { + return w.print("({d:.3},{d:.3})", .{ self.x, self.y }); } }; const E = enum { diff --git a/lib/std/json/fmt.zig b/lib/std/json/fmt.zig index dc1a6b43e8..c526dce1da 100644 --- a/lib/std/json/fmt.zig +++ b/lib/std/json/fmt.zig @@ -15,8 +15,7 @@ pub fn Formatter(comptime T: type) type { value: T, options: StringifyOptions, - pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: @This(), writer: *std.io.Writer) std.io.Writer.Error!void { try stringify(self.value, self.options, writer); } }; diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 3e6d66321f..000b578dc0 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -2317,46 +2317,40 @@ pub const Const = struct { return .{ normalized_res.reconstruct(if (self.positive) .positive else .negative), exactness }; } - /// To allow `std.fmt.format` to work with this type. /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, /// this function will fail to print the string, printing "(BigInt)" instead of a number. /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. /// See `toString` and `toStringAlloc` for a way to print big integers without failure. - pub fn format(self: Const, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime var base = 10; - comptime var case: std.fmt.Case = .lower; - - if (fmt.len == 0 or comptime mem.eql(u8, fmt, "d")) { - base = 10; - case = .lower; - } else if (comptime mem.eql(u8, fmt, "b")) { - base = 2; - case = .lower; - } else if (comptime mem.eql(u8, fmt, "x")) { - base = 16; - case = .lower; - } else if (comptime mem.eql(u8, fmt, "X")) { - base = 16; - case = .upper; - } else { - std.fmt.invalidFmtError(fmt, self); - } - + pub fn print(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void { const available_len = 64; if (self.limbs.len > available_len) return w.writeAll("(BigInt)"); - var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined; + var limbs: [calcToStringLimbsBufferLen(available_len, 10)]Limb = undefined; const biggest: Const = .{ .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len), .positive = false, }; - var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined; + var buf: [biggest.sizeInBaseUpperBound(2)]u8 = undefined; const len = self.toString(&buf, base, case, &limbs); return w.writeAll(buf[0..len]); } + const Format = struct { + int: Const, + base: u8, + case: std.fmt.Case, + + pub fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void { + return print(f.int, w, f.base, f.case); + } + }; + + pub fn fmt(self: Const, base: u8, case: std.fmt.Case) std.fmt.Formatter(Format, Format.default) { + return .{ .data = .{ .int = self, .base = base, .case = case } }; + } + /// Converts self to a string in the requested base. /// Caller owns returned memory. /// Asserts that `base` is in the range [2, 36]. @@ -2924,12 +2918,16 @@ pub const Managed = struct { } /// To allow `std.fmt.format` to work with `Managed`. + pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { + return self.toConst().format(w, f); + } + /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, /// this function will fail to print the string, printing "(BigInt)" instead of a number. /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. /// See `toString` and `toStringAlloc` for a way to print big integers without failure. - pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - return self.toConst().format(w, f); + pub fn fmt(self: Managed, base: u8, case: std.fmt.Case) std.fmt.Formatter(Const.Format, Const.Format.default) { + return .{ .data = .{ .int = self.toConst(), .base = base, .case = case } }; } /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| == diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 0f688b359d..58f5a01a05 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -3813,14 +3813,8 @@ test "(BigInt) positive" { try a.pow(&a, 64 * @sizeOf(Limb) * 8); try b.sub(&a, &c); - const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0); - defer testing.allocator.free(a_fmt); - - const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0); - defer testing.allocator.free(b_fmt); - - try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); - try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)")); + try testing.expectFmt("(BigInt)", "{f}", .{a.fmt(10, .lower)}); + try testing.expectFmt("1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190335", "{f}", .{b.fmt(10, .lower)}); } test "(BigInt) negative" { @@ -3838,10 +3832,10 @@ test "(BigInt) negative" { a.negate(); try b.add(&a, &c); - const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0); + const a_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{a.fmt(10, .lower)}); defer testing.allocator.free(a_fmt); - const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0); + const b_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{b.fmt(10, .lower)}); defer testing.allocator.free(b_fmt); try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); diff --git a/lib/std/net.zig b/lib/std/net.zig index cfaad090ab..36d6062ef8 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -161,11 +161,10 @@ pub const Address = extern union { } } - pub fn format(self: Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: Address, w: *std.io.Writer) std.io.Writer.Error!void { switch (self.any.family) { - posix.AF.INET => try self.in.format(w, fmt), - posix.AF.INET6 => try self.in6.format(w, fmt), + posix.AF.INET => try self.in.format(w), + posix.AF.INET6 => try self.in6.format(w), posix.AF.UNIX => { if (!has_unix_sockets) unreachable; try w.writeAll(std.mem.sliceTo(&self.un.path, 0)); @@ -341,8 +340,7 @@ pub const Ip4Address = extern struct { self.sa.port = mem.nativeToBig(u16, port); } - pub fn format(self: Ip4Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: Ip4Address, w: *std.io.Writer) std.io.Writer.Error!void { const bytes: *const [4]u8 = @ptrCast(&self.sa.addr); try w.print("{d}.{d}.{d}.{d}:{d}", .{ bytes[0], bytes[1], bytes[2], bytes[3], self.getPort() }); } @@ -633,8 +631,7 @@ pub const Ip6Address = extern struct { self.sa.port = mem.nativeToBig(u16, port); } - pub fn format(self: Ip6Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: Ip6Address, w: *std.io.Writer) std.io.Writer.Error!void { const port = mem.bigToNative(u16, self.sa.port); if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) { try w.print("[::ffff:{d}.{d}.{d}.{d}]:{d}", .{ diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 33822e0070..804dc414ce 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -60,9 +60,7 @@ pub const Guid = extern struct { node: [6]u8, /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format - pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); - + pub fn format(self: @This(), writer: *std.io.Writer) std.io.Writer.Error!void { const time_low = @byteSwap(self.time_low); const time_mid = @byteSwap(self.time_mid); const time_high_and_version = @byteSwap(self.time_high_and_version); diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 292d8367fc..4691b96933 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -1796,8 +1796,7 @@ pub const Linkage = enum(u4) { extern_weak = 7, external = 0, - pub fn format(self: Linkage, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: Linkage, w: *Writer) Writer.Error!void { if (self != .external) try w.print(" {s}", .{@tagName(self)}); } @@ -1814,8 +1813,7 @@ pub const Preemption = enum { dso_local, implicit_dso_local, - pub fn format(self: Preemption, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: Preemption, w: *Writer) Writer.Error!void { if (self == .dso_local) try w.print(" {s}", .{@tagName(self)}); } }; @@ -1833,8 +1831,7 @@ pub const Visibility = enum(u2) { }; } - pub fn format(self: Visibility, writer: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: Visibility, writer: *Writer) Writer.Error!void { if (self != .default) try writer.print(" {s}", .{@tagName(self)}); } }; @@ -1844,8 +1841,7 @@ pub const DllStorageClass = enum(u2) { dllimport = 1, dllexport = 2, - pub fn format(self: DllStorageClass, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: DllStorageClass, w: *Writer) Writer.Error!void { if (self != .default) try w.print(" {s}", .{@tagName(self)}); } }; @@ -1871,8 +1867,7 @@ pub const UnnamedAddr = enum(u2) { unnamed_addr = 1, local_unnamed_addr = 2, - pub fn format(self: UnnamedAddr, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: UnnamedAddr, w: *Writer) Writer.Error!void { if (self != .default) try w.print(" {s}", .{@tagName(self)}); } }; @@ -1975,8 +1970,7 @@ pub const ExternallyInitialized = enum { default, externally_initialized, - pub fn format(self: ExternallyInitialized, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: ExternallyInitialized, w: *Writer) Writer.Error!void { if (self != .default) try w.print(" {s}", .{@tagName(self)}); } }; @@ -2074,8 +2068,7 @@ pub const CallConv = enum(u10) { pub const default = CallConv.ccc; - pub fn format(self: CallConv, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: CallConv, w: *Writer) Writer.Error!void { switch (self) { default => {}, .fastcc, @@ -7969,8 +7962,7 @@ pub const Metadata = enum(u32) { AllCallsDescribed: bool = false, Unused: u2 = 0, - pub fn format(self: DIFlags, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: DIFlags, w: *Writer) Writer.Error!void { var need_pipe = false; inline for (@typeInfo(DIFlags).@"struct".fields) |field| { switch (@typeInfo(field.type)) { @@ -8027,8 +8019,7 @@ pub const Metadata = enum(u32) { ObjCDirect: bool = false, Unused: u20 = 0, - pub fn format(self: DISPFlags, w: *Writer, comptime f: []const u8) Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: DISPFlags, w: *Writer) Writer.Error!void { var need_pipe = false; inline for (@typeInfo(DISPFlags).@"struct".fields) |field| { switch (@typeInfo(field.type)) { diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig index cc54f682de..7cd991f509 100644 --- a/lib/std/zon/parse.zig +++ b/lib/std/zon/parse.zig @@ -226,8 +226,7 @@ pub const Diagnostics = struct { return .{ .diag = self }; } - pub fn format(self: *const @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: *const @This(), w: *std.io.Writer) std.io.Writer.Error!void { var errors = self.iterateErrors(); while (errors.next()) |err| { const loc = err.getLocation(self); diff --git a/lib/ubsan_rt.zig b/lib/ubsan_rt.zig index cc58e424f9..cfb9ea2d99 100644 --- a/lib/ubsan_rt.zig +++ b/lib/ubsan_rt.zig @@ -119,9 +119,7 @@ const Value = extern struct { } } - pub fn format(value: Value, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); - + pub fn format(value: Value, writer: *std.io.Writer) std.io.Writer.Error!void { // Work around x86_64 backend limitation. if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .windows) { try writer.writeAll("(unknown)"); diff --git a/src/Air.zig b/src/Air.zig index ecb74ecadb..de02ea8cf2 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -957,8 +957,7 @@ pub const Inst = struct { return index.unwrap().target; } - pub fn format(index: Index, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(index: Index, w: *std.io.Writer) std.io.Writer.Error!void { try w.writeByte('%'); switch (index.unwrap()) { .ref => {}, diff --git a/src/Air/Liveness.zig b/src/Air/Liveness.zig index 8aa37e3c45..e369428636 100644 --- a/src/Air/Liveness.zig +++ b/src/Air/Liveness.zig @@ -2036,8 +2036,7 @@ fn fmtInstSet(set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void)) FmtIns const FmtInstSet = struct { set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void), - pub fn format(val: FmtInstSet, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(val: FmtInstSet, w: *std.io.Writer) std.io.Writer.Error!void { if (val.set.count() == 0) { try w.writeAll("[no instructions]"); return; @@ -2057,8 +2056,7 @@ fn fmtInstList(list: []const Air.Inst.Index) FmtInstList { const FmtInstList = struct { list: []const Air.Inst.Index, - pub fn format(val: FmtInstList, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(val: FmtInstList, w: *std.io.Writer) std.io.Writer.Error!void { if (val.list.len == 0) { try w.writeAll("[no instructions]"); return; diff --git a/src/Compilation.zig b/src/Compilation.zig index 9ee4f61df1..85184ab913 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -399,8 +399,7 @@ pub const Path = struct { const Formatter = struct { p: Path, comp: *Compilation, - pub fn format(f: Formatter, w: *std.io.Writer, comptime unused_fmt: []const u8) std.io.Writer.Error!void { - comptime assert(unused_fmt.len == 0); + pub fn format(f: Formatter, w: *std.io.Writer) std.io.Writer.Error!void { const root_path: []const u8 = switch (f.p.root) { .zig_lib => f.comp.dirs.zig_lib.path orelse ".", .global_cache => f.comp.dirs.global_cache.path orelse ".", diff --git a/src/Package/Fetch/git.zig b/src/Package/Fetch/git.zig index e9a5714201..8dfcbb2453 100644 --- a/src/Package/Fetch/git.zig +++ b/src/Package/Fetch/git.zig @@ -119,8 +119,7 @@ pub const Oid = union(Format) { } else error.InvalidOid; } - pub fn format(oid: Oid, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(oid: Oid, writer: *std.io.Writer) std.io.Writer.Error!void { try writer.print("{x}", .{oid.slice()}); } diff --git a/src/Sema.zig b/src/Sema.zig index 1306223076..8686d2ba47 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9448,8 +9448,7 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool { fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void { const CallingConventionsSupportingVarArgsList = struct { arch: std.Target.Cpu.Arch, - pub fn format(ctx: @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(ctx: @This(), w: *std.io.Writer) std.io.Writer.Error!void { var first = true; for (calling_conventions_supporting_var_args) |cc_inner| { for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| { @@ -9894,8 +9893,7 @@ fn finishFunc( .bad_arch => |allowed_archs| { const ArchListFormatter = struct { archs: []const std.Target.Cpu.Arch, - pub fn format(formatter: @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(formatter: @This(), w: *std.io.Writer) std.io.Writer.Error!void { for (formatter.archs, 0..) |arch, i| { if (i != 0) try w.writeAll(", "); diff --git a/src/Type.zig b/src/Type.zig index 3b73846693..a199811c8e 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -121,9 +121,8 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool { return a.toIntern() == b.toIntern(); } -pub fn format(ty: Type, writer: *std.io.Writer, comptime unused_fmt_string: []const u8) !void { +pub fn format(ty: Type, writer: *std.io.Writer) !void { _ = ty; - _ = unused_fmt_string; _ = writer; @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); } diff --git a/src/Value.zig b/src/Value.zig index 00cda7d363..aed97c8754 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -15,10 +15,9 @@ const Value = @This(); ip_index: InternPool.Index, -pub fn format(val: Value, writer: *std.io.Writer, comptime fmt: []const u8) !void { +pub fn format(val: Value, writer: *std.io.Writer) !void { _ = val; _ = writer; - _ = fmt; @compileError("do not use format values directly; use either fmtDebug or fmtValue"); } diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 19a3078f03..f0fdc3a98a 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -566,8 +566,7 @@ const InstTracking = struct { } } - pub fn format(inst_tracking: InstTracking, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(inst_tracking: InstTracking, writer: *std.io.Writer) std.io.Writer.Error!void { if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try writer.print("|{}| ", .{inst_tracking.long}); try writer.print("{}", .{inst_tracking.short}); } diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig index e436da680b..43ccf00058 100644 --- a/src/arch/riscv64/Mir.zig +++ b/src/arch/riscv64/Mir.zig @@ -92,8 +92,7 @@ pub const Inst = struct { }, }; - pub fn format(inst: Inst, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - assert(fmt.len == 0); + pub fn format(inst: Inst, writer: *std.io.Writer) std.io.Writer.Error!void { try writer.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) }); } }; diff --git a/src/arch/riscv64/bits.zig b/src/arch/riscv64/bits.zig index 5264364da4..2f79da7116 100644 --- a/src/arch/riscv64/bits.zig +++ b/src/arch/riscv64/bits.zig @@ -249,24 +249,6 @@ pub const FrameIndex = enum(u32) { spill_frame, /// Other indices are used for local variable stack slots _, - - pub const named_count = @typeInfo(FrameIndex).@"enum".fields.len; - - pub fn isNamed(fi: FrameIndex) bool { - return @intFromEnum(fi) < named_count; - } - - pub fn format(fi: FrameIndex, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - try writer.writeAll("FrameIndex"); - if (fi.isNamed()) { - try writer.writeByte('.'); - try writer.writeAll(@tagName(fi)); - } else { - try writer.writeByte('('); - try writer.printInt(fmt, .{}, @intFromEnum(fi)); - try writer.writeByte(')'); - } - } }; /// A linker symbol not yet allocated in VM. diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 2d7ed94094..177d6b7b49 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -525,7 +525,7 @@ pub const MCValue = union(enum) { }; } - pub fn format(mcv: MCValue, bw: *Writer, comptime _: []const u8) Writer.Error!void { + pub fn format(mcv: MCValue, bw: *Writer) Writer.Error!void { switch (mcv) { .none, .unreach, .dead, .undef => try bw.print("({s})", .{@tagName(mcv)}), .immediate => |pl| try bw.print("0x{x}", .{pl}), @@ -812,7 +812,7 @@ const InstTracking = struct { } } - pub fn format(tracking: InstTracking, bw: *Writer, comptime _: []const u8) Writer.Error!void { + pub fn format(tracking: InstTracking, bw: *Writer) Writer.Error!void { if (!std.meta.eql(tracking.long, tracking.short)) try bw.print("|{f}| ", .{tracking.long}); try bw.print("{f}", .{tracking.short}); } diff --git a/src/arch/x86_64/Encoding.zig b/src/arch/x86_64/Encoding.zig index ce46eb39d6..6956b25a3f 100644 --- a/src/arch/x86_64/Encoding.zig +++ b/src/arch/x86_64/Encoding.zig @@ -158,8 +158,7 @@ pub fn modRmExt(encoding: Encoding) u3 { }; } -pub fn format(encoding: Encoding, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); +pub fn format(encoding: Encoding, writer: *std.io.Writer) std.io.Writer.Error!void { var opc = encoding.opcode(); if (encoding.data.mode.isVex()) { try writer.writeAll("VEX."); diff --git a/src/arch/x86_64/bits.zig b/src/arch/x86_64/bits.zig index ac9bb9a0d5..2e9b1f7f21 100644 --- a/src/arch/x86_64/bits.zig +++ b/src/arch/x86_64/bits.zig @@ -721,24 +721,6 @@ pub const FrameIndex = enum(u32) { call_frame, // Other indices are used for local variable stack slots _, - - pub const named_count = @typeInfo(FrameIndex).@"enum".fields.len; - - pub fn isNamed(fi: FrameIndex) bool { - return @intFromEnum(fi) < named_count; - } - - pub fn format(fi: FrameIndex, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - try writer.writeAll("FrameIndex"); - if (fi.isNamed()) { - try writer.writeByte('.'); - try writer.writeAll(@tagName(fi)); - } else { - try writer.writeByte('('); - try writer.printInt(fmt, .{}, @intFromEnum(fi)); - try writer.writeByte(')'); - } - } }; pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; @@ -839,8 +821,7 @@ pub const Memory = struct { }; } - pub fn format(s: Size, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(s: Size, writer: *std.io.Writer) std.io.Writer.Error!void { if (s == .none) return; try writer.writeAll(@tagName(s)); switch (s) { @@ -905,8 +886,7 @@ pub const Immediate = union(enum) { return .{ .signed = x }; } - pub fn format(imm: Immediate, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(imm: Immediate, writer: *std.io.Writer) std.io.Writer.Error!void { switch (imm) { inline else => |int| try writer.print("{d}", .{int}), .nav => |nav_off| try writer.print("Nav({d}) + {d}", .{ @intFromEnum(nav_off.nav), nav_off.off }), diff --git a/src/arch/x86_64/encoder.zig b/src/arch/x86_64/encoder.zig index 6e63761ec2..59938990f6 100644 --- a/src/arch/x86_64/encoder.zig +++ b/src/arch/x86_64/encoder.zig @@ -353,8 +353,7 @@ pub const Instruction = struct { return inst; } - pub fn format(inst: Instruction, w: *Writer, comptime unused_format_string: []const u8) Writer.Error!void { - comptime assert(unused_format_string.len == 0); + pub fn format(inst: Instruction, w: *Writer) Writer.Error!void { switch (inst.prefix) { .none, .directive => {}, else => try w.print("{s} ", .{@tagName(inst.prefix)}), diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 72d454643e..26780fa940 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -2471,8 +2471,7 @@ const RenderCTypeTrailing = enum { no_space, maybe_space, - pub fn format(self: @This(), w: *Writer, comptime fmt: []const u8) Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: @This(), w: *Writer) Writer.Error!void { switch (self) { .no_space => {}, .maybe_space => try w.writeByte(' '), diff --git a/src/codegen/spirv/spec.zig b/src/codegen/spirv/spec.zig index 588815a413..82ec05ebba 100644 --- a/src/codegen/spirv/spec.zig +++ b/src/codegen/spirv/spec.zig @@ -19,8 +19,7 @@ pub const IdResult = enum(Word) { none, _, - pub fn format(self: IdResult, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: IdResult, writer: *std.io.Writer) std.io.Writer.Error!void { switch (self) { .none => try writer.writeAll("(none)"), else => try writer.print("%{d}", .{@intFromEnum(self)}), diff --git a/src/link/Elf.zig b/src/link/Elf.zig index eb168ae779..785f200928 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -4192,8 +4192,7 @@ pub const Ref = struct { return ref.index == other.index and ref.file == other.file; } - pub fn format(ref: Ref, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(ref: Ref, writer: *std.io.Writer) std.io.Writer.Error!void { try writer.print("ref({d},{d})", .{ ref.index, ref.file }); } }; diff --git a/src/link/Elf/Archive.zig b/src/link/Elf/Archive.zig index 952fcd74da..2243dc4781 100644 --- a/src/link/Elf/Archive.zig +++ b/src/link/Elf/Archive.zig @@ -260,8 +260,7 @@ pub const ArStrtab = struct { try writer.writeAll(ar.buffer.items); } - pub fn format(ar: ArStrtab, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(ar: ArStrtab, writer: *std.io.Writer) std.io.Writer.Error!void { try writer.print("{f}", .{std.ascii.hexEscape(ar.buffer.items, .lower)}); } }; diff --git a/src/link/Elf/gc.zig b/src/link/Elf/gc.zig index 977c9e8c7a..61eb2098da 100644 --- a/src/link/Elf/gc.zig +++ b/src/link/Elf/gc.zig @@ -185,8 +185,7 @@ const Level = struct { self.value += 1; } - pub fn format(self: *const @This(), w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: *const @This(), w: *std.io.Writer) std.io.Writer.Error!void { try w.splatByteAll(' ', self.value); } }; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index cfcd1d6f74..734b4b6a04 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -4472,8 +4472,7 @@ pub const Ref = struct { }; } - pub fn format(ref: Ref, bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void { - comptime assert(unused_fmt_string.len == 0); + pub fn format(ref: Ref, bw: *Writer) Writer.Error!void { try bw.print("%{d} in file({d})", .{ ref.index, ref.file }); } }; diff --git a/src/link/MachO/UnwindInfo.zig b/src/link/MachO/UnwindInfo.zig index 85afb6e4ad..a0ffdfe06a 100644 --- a/src/link/MachO/UnwindInfo.zig +++ b/src/link/MachO/UnwindInfo.zig @@ -455,8 +455,7 @@ pub const Encoding = extern struct { return enc.enc == other.enc; } - pub fn format(enc: Encoding, w: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void { - comptime assert(unused_fmt_string.len == 0); + pub fn format(enc: Encoding, w: *Writer) Writer.Error!void { try w.print("0x{x:0>8}", .{enc.enc}); } }; diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index 17bd302d82..79ff4e1707 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -196,9 +196,8 @@ const Level = struct { self.value += 1; } - pub fn format(self: *const @This(), bw: *Writer, comptime unused_fmt_string: []const u8) Writer.Error!void { - _ = unused_fmt_string; - try bw.splatByteAll(' ', self.value); + pub fn format(self: *const @This(), w: *Writer) Writer.Error!void { + try w.splatByteAll(' ', self.value); } }; diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index d7c8b687e9..74c30c0c18 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2126,8 +2126,7 @@ pub const FunctionType = extern struct { wasm: *const Wasm, ft: FunctionType, - pub fn format(self: Formatter, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: Formatter, writer: *std.io.Writer) std.io.Writer.Error!void { const params = self.ft.params.slice(self.wasm); const returns = self.ft.returns.slice(self.wasm); @@ -2906,8 +2905,7 @@ pub const Feature = packed struct(u8) { @"=", }; - pub fn format(feature: Feature, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(feature: Feature, writer: *std.io.Writer) std.io.Writer.Error!void { try writer.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) }); } diff --git a/src/link/table_section.zig b/src/link/table_section.zig index 65d4a67287..72cfe96c5a 100644 --- a/src/link/table_section.zig +++ b/src/link/table_section.zig @@ -39,8 +39,7 @@ pub fn TableSection(comptime Entry: type) type { return self.entries.items.len; } - pub fn format(self: Self, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - comptime assert(f.len == 0); + pub fn format(self: Self, writer: *std.io.Writer) std.io.Writer.Error!void { try writer.writeAll("TableSection:\n"); for (self.entries.items, 0..) |entry, i| { try writer.print(" {d} => {}\n", .{ i, entry }); diff --git a/src/link/tapi/parse.zig b/src/link/tapi/parse.zig index 28ef2642a9..73174e6d8f 100644 --- a/src/link/tapi/parse.zig +++ b/src/link/tapi/parse.zig @@ -57,9 +57,9 @@ pub const Node = struct { } } - pub fn format(self: *const Node, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { + pub fn format(self: *const Node, writer: *std.io.Writer) std.io.Writer.Error!void { switch (self.tag) { - inline else => |tag| return @as(*tag.Type(), @fieldParentPtr("base", self)).format(writer, fmt), + inline else => |tag| return @as(*tag.Type(), @fieldParentPtr("base", self)).format(writer), } } @@ -81,8 +81,7 @@ pub const Node = struct { } } - pub fn format(self: *const Doc, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: *const Doc, writer: *std.io.Writer) std.io.Writer.Error!void { if (self.directive) |id| { try std.fmt.format(writer, "{{ ", .{}); const directive = self.base.tree.getRaw(id, id); @@ -122,8 +121,7 @@ pub const Node = struct { self.values.deinit(allocator); } - pub fn format(self: *const Map, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: *const Map, writer: *std.io.Writer) std.io.Writer.Error!void { try std.fmt.format(writer, "{{ ", .{}); for (self.values.items) |entry| { const key = self.base.tree.getRaw(entry.key, entry.key); @@ -155,8 +153,7 @@ pub const Node = struct { self.values.deinit(allocator); } - pub fn format(self: *const List, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: *const List, writer: *std.io.Writer) std.io.Writer.Error!void { try std.fmt.format(writer, "[ ", .{}); for (self.values.items) |node| { try std.fmt.format(writer, "{}, ", .{node}); @@ -180,8 +177,7 @@ pub const Node = struct { self.string_value.deinit(allocator); } - pub fn format(self: *const Value, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime assert(fmt.len == 0); + pub fn format(self: *const Value, writer: *std.io.Writer) std.io.Writer.Error!void { const raw = self.base.tree.getRaw(self.base.start, self.base.end); return std.fmt.format(writer, "{s}", .{raw}); } |
