| ... | @@ -146,6 +146,40 @@ pub fn formatType( | ... | @@ -146,6 +146,40 @@ pub fn formatType( |
| 146 | builtin.TypeId.Promise => { | 146 | builtin.TypeId.Promise => { |
| 147 | return format(context, Errors, output, "promise@{x}", @ptrToInt(value)); | 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 | builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) { | 183 | builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) { |
| 150 | builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) { | 184 | builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) { |
| 151 | builtin.TypeId.Array => |info| { | 185 | builtin.TypeId.Array => |info| { |
| ... | @@ -155,25 +189,7 @@ pub fn formatType( | ... | @@ -155,25 +189,7 @@ pub fn formatType( |
| 155 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); | 189 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 156 | }, | 190 | }, |
| 157 | builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { | 191 | builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { |
| 158 | const has_cust_fmt = comptime cf: { | 192 | return formatType(value.*, fmt, context, Errors, output); |
| 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)); | | |
| 177 | }, | 193 | }, |
| 178 | else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), | 194 | else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), |
| 179 | }, | 195 | }, |
| ... | @@ -911,14 +927,12 @@ test "fmt.format" { | ... | @@ -911,14 +927,12 @@ test "fmt.format" { |
| 911 | try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024)); | 927 | try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024)); |
| 912 | try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024)); | 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 | const Struct = struct { | 930 | const Struct = struct { |
| 916 | unused: u8, | 931 | field: u8, |
| 917 | }; | 932 | }; |
| 918 | var buf1: [32]u8 = undefined; | 933 | const value = Struct{ .field = 42 }; |
| 919 | const value = Struct{ .unused = 42 }; | 934 | try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", value); |
| 920 | const result = try bufPrint(buf1[0..], "pointer: {}\n", &value); | 935 | try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", &value); |
| 921 | assert(mem.startsWith(u8, result, "pointer: Struct@")); | | |
| 922 | } | 936 | } |
| 923 | { | 937 | { |
| 924 | var buf1: [32]u8 = undefined; | 938 | var buf1: [32]u8 = undefined; |
| ... | @@ -941,6 +955,7 @@ test "fmt.format" { | ... | @@ -941,6 +955,7 @@ test "fmt.format" { |
| 941 | { | 955 | { |
| 942 | // This fails on release due to a minor rounding difference. | 956 | // This fails on release due to a minor rounding difference. |
| 943 | // --release-fast outputs 9.999960000000001e-40 vs. the expected. | 957 | // --release-fast outputs 9.999960000000001e-40 vs. the expected. |
| | 958 | // TODO fix this, it should be the same in Debug and ReleaseFast |
| 944 | if (builtin.mode == builtin.Mode.Debug) { | 959 | if (builtin.mode == builtin.Mode.Debug) { |
| 945 | var buf1: [32]u8 = undefined; | 960 | var buf1: [32]u8 = undefined; |
| 946 | const value: f64 = 9.999960e-40; | 961 | const value: f64 = 9.999960e-40; |
| ... | @@ -1133,23 +1148,23 @@ test "fmt.format" { | ... | @@ -1133,23 +1148,23 @@ test "fmt.format" { |
| 1133 | y: f32, | 1148 | y: f32, |
| 1134 | | 1149 | |
| 1135 | pub fn format( | 1150 | pub fn format( |
| 1136 | self: *SelfType, | 1151 | self: SelfType, |
| 1137 | comptime fmt: []const u8, | 1152 | comptime fmt: []const u8, |
| 1138 | context: var, | 1153 | context: var, |
| 1139 | comptime Errors: type, | 1154 | comptime Errors: type, |
| 1140 | output: fn (@typeOf(context), []const u8) Errors!void, | 1155 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 1141 | ) Errors!void { | 1156 | ) Errors!void { |
| 1142 | if (fmt.len > 0) { | 1157 | switch (fmt.len) { |
| 1143 | if (fmt.len > 1) unreachable; | 1158 | 0 => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y), |
| 1144 | switch (fmt[0]) { | 1159 | 1 => switch (fmt[0]) { |
| 1145 | //point format | 1160 | //point format |
| 1146 | 'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y), | 1161 | 'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y), |
| 1147 | //dimension format | 1162 | //dimension format |
| 1148 | 'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y), | 1163 | 'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y), |
| 1149 | else => unreachable, | 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,6 +1175,10 @@ test "fmt.format" { |
| 1160 | }; | 1175 | }; |
| 1161 | try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value); | 1176 | try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value); |
| 1162 | try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", &value); | 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 | |