| ... | ... | @@ -146,6 +146,40 @@ pub fn formatType( |
| 146 | 146 | builtin.TypeId.Promise => { |
| 147 | 147 | return format(context, Errors, output, "promise@{x}", @ptrToInt(value)); |
| 148 | 148 | }, |
| 149 | builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { |
| 150 | const has_cust_fmt = comptime cf: { |
| 151 | const info = @typeInfo(T); |
| 152 | const defs = switch (info) { |
| 153 | builtin.TypeId.Struct => |s| s.defs, |
| 154 | builtin.TypeId.Union => |u| u.defs, |
| 155 | builtin.TypeId.Enum => |e| e.defs, |
| 156 | else => unreachable, |
| 157 | }; |
| 158 | |
| 159 | for (defs) |def| { |
| 160 | if (mem.eql(u8, def.name, "format")) { |
| 161 | break :cf true; |
| 162 | } |
| 163 | } |
| 164 | break :cf false; |
| 165 | }; |
| 166 | |
| 167 | if (has_cust_fmt) return value.format(fmt, context, Errors, output); |
| 168 | try output(context, @typeName(T)); |
| 169 | comptime var field_i = 0; |
| 170 | inline while (field_i < @memberCount(T)) : (field_i += 1) { |
| 171 | if (field_i == 0) { |
| 172 | try output(context, "{ ."); |
| 173 | } else { |
| 174 | try output(context, ", ."); |
| 175 | } |
| 176 | try output(context, @memberName(T, field_i)); |
| 177 | try output(context, " = "); |
| 178 | try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output); |
| 179 | } |
| 180 | try output(context, " }"); |
| 181 | return; |
| 182 | }, |
| 149 | 183 | builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) { |
| 150 | 184 | builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) { |
| 151 | 185 | builtin.TypeId.Array => |info| { |
| ... | ... | @@ -155,25 +189,7 @@ pub fn formatType( |
| 155 | 189 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 156 | 190 | }, |
| 157 | 191 | builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { |
| 158 | | const has_cust_fmt = comptime cf: { |
| 159 | | const info = @typeInfo(T.Child); |
| 160 | | const defs = switch (info) { |
| 161 | | builtin.TypeId.Struct => |s| s.defs, |
| 162 | | builtin.TypeId.Union => |u| u.defs, |
| 163 | | builtin.TypeId.Enum => |e| e.defs, |
| 164 | | else => unreachable, |
| 165 | | }; |
| 166 | | |
| 167 | | for (defs) |def| { |
| 168 | | if (mem.eql(u8, def.name, "format")) { |
| 169 | | break :cf true; |
| 170 | | } |
| 171 | | } |
| 172 | | break :cf false; |
| 173 | | }; |
| 174 | | |
| 175 | | if (has_cust_fmt) return value.format(fmt, context, Errors, output); |
| 176 | | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 192 | return formatType(value.*, fmt, context, Errors, output); |
| 177 | 193 | }, |
| 178 | 194 | else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), |
| 179 | 195 | }, |
| ... | ... | @@ -911,14 +927,12 @@ test "fmt.format" { |
| 911 | 927 | try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024)); |
| 912 | 928 | try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024)); |
| 913 | 929 | { |
| 914 | | // Dummy field because of https://github.com/ziglang/zig/issues/557. |
| 915 | 930 | const Struct = struct { |
| 916 | | unused: u8, |
| 931 | field: u8, |
| 917 | 932 | }; |
| 918 | | var buf1: [32]u8 = undefined; |
| 919 | | const value = Struct{ .unused = 42 }; |
| 920 | | const result = try bufPrint(buf1[0..], "pointer: {}\n", &value); |
| 921 | | assert(mem.startsWith(u8, result, "pointer: Struct@")); |
| 933 | const value = Struct{ .field = 42 }; |
| 934 | try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", value); |
| 935 | try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", &value); |
| 922 | 936 | } |
| 923 | 937 | { |
| 924 | 938 | var buf1: [32]u8 = undefined; |
| ... | ... | @@ -941,6 +955,7 @@ test "fmt.format" { |
| 941 | 955 | { |
| 942 | 956 | // This fails on release due to a minor rounding difference. |
| 943 | 957 | // --release-fast outputs 9.999960000000001e-40 vs. the expected. |
| 958 | // TODO fix this, it should be the same in Debug and ReleaseFast |
| 944 | 959 | if (builtin.mode == builtin.Mode.Debug) { |
| 945 | 960 | var buf1: [32]u8 = undefined; |
| 946 | 961 | const value: f64 = 9.999960e-40; |
| ... | ... | @@ -1133,23 +1148,23 @@ test "fmt.format" { |
| 1133 | 1148 | y: f32, |
| 1134 | 1149 | |
| 1135 | 1150 | pub fn format( |
| 1136 | | self: *SelfType, |
| 1151 | self: SelfType, |
| 1137 | 1152 | comptime fmt: []const u8, |
| 1138 | 1153 | context: var, |
| 1139 | 1154 | comptime Errors: type, |
| 1140 | 1155 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 1141 | 1156 | ) Errors!void { |
| 1142 | | if (fmt.len > 0) { |
| 1143 | | if (fmt.len > 1) unreachable; |
| 1144 | | switch (fmt[0]) { |
| 1157 | switch (fmt.len) { |
| 1158 | 0 => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y), |
| 1159 | 1 => switch (fmt[0]) { |
| 1145 | 1160 | //point format |
| 1146 | 1161 | 'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y), |
| 1147 | 1162 | //dimension format |
| 1148 | 1163 | 'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y), |
| 1149 | 1164 | else => unreachable, |
| 1150 | | } |
| 1165 | }, |
| 1166 | else => unreachable, |
| 1151 | 1167 | } |
| 1152 | | return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y); |
| 1153 | 1168 | } |
| 1154 | 1169 | }; |
| 1155 | 1170 | |
| ... | ... | @@ -1160,6 +1175,10 @@ test "fmt.format" { |
| 1160 | 1175 | }; |
| 1161 | 1176 | try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value); |
| 1162 | 1177 | try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", &value); |
| 1178 | |
| 1179 | // same thing but not passing a pointer |
| 1180 | try testFmt("point: (10.200,2.220)\n", "point: {}\n", value); |
| 1181 | try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value); |
| 1163 | 1182 | } |
| 1164 | 1183 | } |
| 1165 | 1184 | |