authorgravatar for 39384757+chadwain@users.noreply.github.comChadwain Holness <39384757+chadwain@users.noreply.github.com> 2024-02-03 16:47:55-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-03 21:47:55+00:00
log60308550978be821515323256af17e0b8a610b1c
tree20250d90d9eda8f0279fb751829cbc868d99d6d6
parent122387943bf1d00c85aba77f37c93072e43140c9
signaturebadge-check Signed by PGP key B5690EEEBB952194

std.fmt: fix formatting slices of structs with custom formatting

`hasMethod` doesn't make sense for pointers to more than one item.

2 files changed, 70 insertions(+), 1 deletions(-)

lib/std/fmt.zig+18
...@@ -2255,6 +2255,24 @@ test "slice" {...@@ -2255,6 +2255,24 @@ test "slice" {
2255 try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});2255 try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});
2256 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});2256 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
2257 }2257 }
2258 {
2259 const S1 = struct {
2260 x: u8,
2261 };
2262 const struct_slice: []const S1 = &[_]S1{ S1{ .x = 8 }, S1{ .x = 42 } };
2263 try expectFmt("slice: { fmt.test.slice.S1{ .x = 8 }, fmt.test.slice.S1{ .x = 42 } }", "slice: {any}", .{struct_slice});
2264 }
2265 {
2266 const S2 = struct {
2267 x: u8,
2268
2269 pub fn format(s: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
2270 try writer.print("S2({})", .{s.x});
2271 }
2272 };
2273 const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } };
2274 try expectFmt("slice: { S2(8), S2(42) }", "slice: {any}", .{struct_slice});
2275 }
2258}2276}
22592277
2260test "escape non-printable" {2278test "escape non-printable" {
lib/std/meta.zig+52-1
...@@ -1122,15 +1122,66 @@ pub inline fn hasFn(comptime T: type, comptime name: []const u8) bool {...@@ -1122,15 +1122,66 @@ pub inline fn hasFn(comptime T: type, comptime name: []const u8) bool {
1122 return @typeInfo(@TypeOf(@field(T, name))) == .Fn;1122 return @typeInfo(@TypeOf(@field(T, name))) == .Fn;
1123}1123}
11241124
1125test "hasFn" {
1126 const S1 = struct {
1127 pub fn foo() void {}
1128 };
1129
1130 try std.testing.expect(hasFn(S1, "foo"));
1131 try std.testing.expect(!hasFn(S1, "bar"));
1132 try std.testing.expect(!hasFn(*S1, "foo"));
1133
1134 const S2 = struct {
1135 foo: fn () void,
1136 };
1137
1138 try std.testing.expect(!hasFn(S2, "foo"));
1139}
1140
1125/// Returns true if a type has a `name` method; `false` otherwise.1141/// Returns true if a type has a `name` method; `false` otherwise.
1126/// Result is always comptime-known.1142/// Result is always comptime-known.
1127pub inline fn hasMethod(comptime T: type, comptime name: []const u8) bool {1143pub inline fn hasMethod(comptime T: type, comptime name: []const u8) bool {
1128 return switch (@typeInfo(T)) {1144 return switch (@typeInfo(T)) {
1129 .Pointer => |P| hasFn(P.child, name),1145 .Pointer => |P| switch (P.size) {
1146 .One => hasFn(P.child, name),
1147 .Many, .Slice, .C => false,
1148 },
1130 else => hasFn(T, name),1149 else => hasFn(T, name),
1131 };1150 };
1132}1151}
11331152
1153test "hasMethod" {
1154 try std.testing.expect(!hasMethod(u32, "foo"));
1155 try std.testing.expect(!hasMethod([]u32, "len"));
1156 try std.testing.expect(!hasMethod(struct { u32, u64 }, "len"));
1157
1158 const S1 = struct {
1159 pub fn foo() void {}
1160 };
1161
1162 try std.testing.expect(hasMethod(S1, "foo"));
1163 try std.testing.expect(hasMethod(*S1, "foo"));
1164
1165 try std.testing.expect(!hasMethod(S1, "bar"));
1166 try std.testing.expect(!hasMethod(*[1]S1, "foo"));
1167 try std.testing.expect(!hasMethod(*[10]S1, "foo"));
1168 try std.testing.expect(!hasMethod([]S1, "foo"));
1169
1170 const S2 = struct {
1171 foo: fn () void,
1172 };
1173
1174 try std.testing.expect(!hasMethod(S2, "foo"));
1175
1176 const U = union {
1177 pub fn foo() void {}
1178 };
1179
1180 try std.testing.expect(hasMethod(U, "foo"));
1181 try std.testing.expect(hasMethod(*U, "foo"));
1182 try std.testing.expect(!hasMethod(U, "bar"));
1183}
1184
1134/// True if every value of the type `T` has a unique bit pattern representing it.1185/// True if every value of the type `T` has a unique bit pattern representing it.
1135/// In other words, `T` has no unused bits and no padding.1186/// In other words, `T` has no unused bits and no padding.
1136/// Result is always comptime-known.1187/// Result is always comptime-known.