authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-04 11:06:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-04 11:06:55-04:00
log11e7e03139596f16b1ee1b1d96b035ec9f94ab48
treea9b00c4f3b41c73227d1c506fa2ef374af56b8ce
parent96164ce61377b36bcaf0c4087ca9b1ab822b9457
parent940a8544486d24e69162b9ed1dcf1495ba0c4bd3

Merge branch 'zig-custom-format' of https://github.com/tgschultz/zig into tgschultz-zig-custom-format

I removed the code that checks for type signature and type. A function named `format` is enough for zig to give it a try.

2 files changed, 243 insertions(+), 209 deletions(-)

std/fmt/index.zig+242-208
...@@ -16,27 +16,12 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),...@@ -16,27 +16,12 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
16 Start,16 Start,
17 OpenBrace,17 OpenBrace,
18 CloseBrace,18 CloseBrace,
19 Integer,19 FormatString,
20 IntegerWidth,
21 Float,
22 FloatWidth,
23 FloatScientific,
24 FloatScientificWidth,
25 Character,
26 Buf,
27 BufWidth,
28 Bytes,
29 BytesBase,
30 BytesWidth,
31 };20 };
3221
33 comptime var start_index = 0;22 comptime var start_index = 0;
34 comptime var state = State.Start;23 comptime var state = State.Start;
35 comptime var next_arg = 0;24 comptime var next_arg = 0;
36 comptime var radix = 0;
37 comptime var uppercase = false;
38 comptime var width = 0;
39 comptime var width_start = 0;
4025
41 inline for (fmt) |c, i| {26 inline for (fmt) |c, i| {
42 switch (state) {27 switch (state) {
...@@ -45,8 +30,10 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),...@@ -45,8 +30,10 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
45 if (start_index < i) {30 if (start_index < i) {
46 try output(context, fmt[start_index..i]);31 try output(context, fmt[start_index..i]);
47 }32 }
33 start_index = i;
48 state = State.OpenBrace;34 state = State.OpenBrace;
49 },35 },
36
50 '}' => {37 '}' => {
51 if (start_index < i) {38 if (start_index < i) {
52 try output(context, fmt[start_index..i]);39 try output(context, fmt[start_index..i]);
...@@ -61,57 +48,14 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),...@@ -61,57 +48,14 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
61 start_index = i;48 start_index = i;
62 },49 },
63 '}' => {50 '}' => {
64 try formatValue(args[next_arg], context, Errors, output);51 try formatType(args[next_arg], fmt[0..0], context, Errors, output);
65 next_arg += 1;52 next_arg += 1;
66 state = State.Start;53 state = State.Start;
67 start_index = i + 1;54 start_index = i + 1;
68 },55 },
69 'd' => {56 else => {
70 radix = 10;57 state = State.FormatString;
71 uppercase = false;
72 width = 0;
73 state = State.Integer;
74 },
75 'x' => {
76 radix = 16;
77 uppercase = false;
78 width = 0;
79 state = State.Integer;
80 },
81 'X' => {
82 radix = 16;
83 uppercase = true;
84 width = 0;
85 state = State.Integer;
86 },
87 'c' => {
88 state = State.Character;
89 },
90 's' => {
91 state = State.Buf;
92 },
93 'e' => {
94 state = State.FloatScientific;
95 },
96 '.' => {
97 state = State.Float;
98 },
99 'B' => {
100 width = 0;
101 radix = 1000;
102 state = State.Bytes;
103 },
104 else => @compileError("Unknown format character: " ++ []u8{c}),
105 },
106 State.Buf => switch (c) {
107 '}' => {
108 return output(context, args[next_arg]);
109 },
110 '0'...'9' => {
111 width_start = i;
112 state = State.BufWidth;
113 },58 },
114 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
115 },59 },
116 State.CloseBrace => switch (c) {60 State.CloseBrace => switch (c) {
117 '}' => {61 '}' => {
...@@ -120,138 +64,15 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),...@@ -120,138 +64,15 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
120 },64 },
121 else => @compileError("Single '}' encountered in format string"),65 else => @compileError("Single '}' encountered in format string"),
122 },66 },
123 State.Integer => switch (c) {67 State.FormatString => switch (c) {
124 '}' => {
125 try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);
126 next_arg += 1;
127 state = State.Start;
128 start_index = i + 1;
129 },
130 '0'...'9' => {
131 width_start = i;
132 state = State.IntegerWidth;
133 },
134 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
135 },
136 State.IntegerWidth => switch (c) {
137 '}' => {68 '}' => {
138 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);69 const s = start_index + 1;
139 try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);70 try formatType(args[next_arg], fmt[s..i], context, Errors, output);
140 next_arg += 1;71 next_arg += 1;
141 state = State.Start;72 state = State.Start;
142 start_index = i + 1;73 start_index = i + 1;
143 },74 },
144 '0'...'9' => {},75 else => {},
145 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
146 },
147 State.FloatScientific => switch (c) {
148 '}' => {
149 try formatFloatScientific(args[next_arg], null, context, Errors, output);
150 next_arg += 1;
151 state = State.Start;
152 start_index = i + 1;
153 },
154 '0'...'9' => {
155 width_start = i;
156 state = State.FloatScientificWidth;
157 },
158 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
159 },
160 State.FloatScientificWidth => switch (c) {
161 '}' => {
162 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
163 try formatFloatScientific(args[next_arg], width, context, Errors, output);
164 next_arg += 1;
165 state = State.Start;
166 start_index = i + 1;
167 },
168 '0'...'9' => {},
169 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
170 },
171 State.Float => switch (c) {
172 '}' => {
173 try formatFloatDecimal(args[next_arg], null, context, Errors, output);
174 next_arg += 1;
175 state = State.Start;
176 start_index = i + 1;
177 },
178 '0'...'9' => {
179 width_start = i;
180 state = State.FloatWidth;
181 },
182 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
183 },
184 State.FloatWidth => switch (c) {
185 '}' => {
186 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
187 try formatFloatDecimal(args[next_arg], width, context, Errors, output);
188 next_arg += 1;
189 state = State.Start;
190 start_index = i + 1;
191 },
192 '0'...'9' => {},
193 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
194 },
195 State.BufWidth => switch (c) {
196 '}' => {
197 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
198 try formatBuf(args[next_arg], width, context, Errors, output);
199 next_arg += 1;
200 state = State.Start;
201 start_index = i + 1;
202 },
203 '0'...'9' => {},
204 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
205 },
206 State.Character => switch (c) {
207 '}' => {
208 try formatAsciiChar(args[next_arg], context, Errors, output);
209 next_arg += 1;
210 state = State.Start;
211 start_index = i + 1;
212 },
213 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
214 },
215 State.Bytes => switch (c) {
216 '}' => {
217 try formatBytes(args[next_arg], 0, radix, context, Errors, output);
218 next_arg += 1;
219 state = State.Start;
220 start_index = i + 1;
221 },
222 'i' => {
223 radix = 1024;
224 state = State.BytesBase;
225 },
226 '0'...'9' => {
227 width_start = i;
228 state = State.BytesWidth;
229 },
230 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
231 },
232 State.BytesBase => switch (c) {
233 '}' => {
234 try formatBytes(args[next_arg], 0, radix, context, Errors, output);
235 next_arg += 1;
236 state = State.Start;
237 start_index = i + 1;
238 },
239 '0'...'9' => {
240 width_start = i;
241 state = State.BytesWidth;
242 },
243 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
244 },
245 State.BytesWidth => switch (c) {
246 '}' => {
247 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
248 try formatBytes(args[next_arg], width, radix, context, Errors, output);
249 next_arg += 1;
250 state = State.Start;
251 start_index = i + 1;
252 },
253 '0'...'9' => {},
254 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
255 },76 },
256 }77 }
257 }78 }
...@@ -268,14 +89,17 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),...@@ -268,14 +89,17 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
268 }89 }
269}90}
27091
271pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {92pub fn formatType(
93 value: var,
94 comptime fmt: []const u8,
95 context: var,
96 comptime Errors: type,
97 output: fn (@typeOf(context), []const u8) Errors!void,
98) Errors!void {
272 const T = @typeOf(value);99 const T = @typeOf(value);
273 switch (@typeId(T)) {100 switch (@typeId(T)) {
274 builtin.TypeId.Int => {101 builtin.TypeId.Int, builtin.TypeId.Float => {
275 return formatInt(value, 10, false, 0, context, Errors, output);102 return formatValue(value, fmt, context, Errors, output);
276 },
277 builtin.TypeId.Float => {
278 return formatFloatScientific(value, null, context, Errors, output);
279 },103 },
280 builtin.TypeId.Void => {104 builtin.TypeId.Void => {
281 return output(context, "void");105 return output(context, "void");
...@@ -285,16 +109,16 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (...@@ -285,16 +109,16 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
285 },109 },
286 builtin.TypeId.Nullable => {110 builtin.TypeId.Nullable => {
287 if (value) |payload| {111 if (value) |payload| {
288 return formatValue(payload, context, Errors, output);112 return formatType(payload, fmt, context, Errors, output);
289 } else {113 } else {
290 return output(context, "null");114 return output(context, "null");
291 }115 }
292 },116 },
293 builtin.TypeId.ErrorUnion => {117 builtin.TypeId.ErrorUnion => {
294 if (value) |payload| {118 if (value) |payload| {
295 return formatValue(payload, context, Errors, output);119 return formatType(payload, fmt, context, Errors, output);
296 } else |err| {120 } else |err| {
297 return formatValue(err, context, Errors, output);121 return formatType(err, fmt, context, Errors, output);
298 }122 }
299 },123 },
300 builtin.TypeId.ErrorSet => {124 builtin.TypeId.ErrorSet => {
...@@ -302,10 +126,34 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (...@@ -302,10 +126,34 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
302 return output(context, @errorName(value));126 return output(context, @errorName(value));
303 },127 },
304 builtin.TypeId.Pointer => {128 builtin.TypeId.Pointer => {
305 if (@typeId(T.Child) == builtin.TypeId.Array and T.Child.Child == u8) {129 switch (@typeId(T.Child)) {
306 return output(context, (value.*)[0..]);130 builtin.TypeId.Array => {
307 } else {131 if (T.Child.Child == u8) {
308 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));132 return formatText(value, fmt, context, Errors, output);
133 }
134 },
135 builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
136 const has_cust_fmt = comptime cf: {
137 const info = @typeInfo(T.Child);
138 const defs = switch (info) {
139 builtin.TypeId.Struct => |s| s.defs,
140 builtin.TypeId.Union => |u| u.defs,
141 builtin.TypeId.Enum => |e| e.defs,
142 else => unreachable,
143 };
144
145 for (defs) |def| {
146 if (mem.eql(u8, def.name, "format")) {
147 break :cf true;
148 }
149 }
150 break :cf false;
151 };
152
153 if (has_cust_fmt) return value.format(fmt, context, Errors, output);
154 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
155 },
156 else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
309 }157 }
310 },158 },
311 else => if (@canImplicitCast([]const u8, value)) {159 else => if (@canImplicitCast([]const u8, value)) {
...@@ -317,11 +165,129 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (...@@ -317,11 +165,129 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
317 }165 }
318}166}
319167
320pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {168fn formatValue(
169 value: var,
170 comptime fmt: []const u8,
171 context: var,
172 comptime Errors: type,
173 output: fn (@typeOf(context), []const u8) Errors!void,
174) Errors!void {
175 if (fmt.len > 0) {
176 if (fmt[0] == 'B') {
177 comptime var width: ?usize = null;
178 if (fmt.len > 1) {
179 if (fmt[1] == 'i') {
180 if (fmt.len > 2) width = comptime (parseUnsigned(usize, fmt[2..], 10) catch unreachable);
181 return formatBytes(value, width, 1024, context, Errors, output);
182 }
183 width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
184 }
185 return formatBytes(value, width, 1000, context, Errors, output);
186 }
187 }
188
189 comptime var T = @typeOf(value);
190 switch (@typeId(T)) {
191 builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
192 builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
193 else => unreachable,
194 }
195}
196
197pub fn formatIntValue(
198 value: var,
199 comptime fmt: []const u8,
200 context: var,
201 comptime Errors: type,
202 output: fn (@typeOf(context), []const u8) Errors!void,
203) Errors!void {
204 comptime var radix = 10;
205 comptime var uppercase = false;
206 comptime var width = 0;
207 if (fmt.len > 0) {
208 switch (fmt[0]) {
209 'c' => {
210 if (@typeOf(value) == u8) {
211 if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});
212 return formatAsciiChar(value, context, Errors, output);
213 }
214 },
215 'd' => {
216 radix = 10;
217 uppercase = false;
218 width = 0;
219 },
220 'x' => {
221 radix = 16;
222 uppercase = false;
223 width = 0;
224 },
225 'X' => {
226 radix = 16;
227 uppercase = true;
228 width = 0;
229 },
230 else => @compileError("Unknown format character: " ++ []u8{fmt[0]}),
231 }
232 if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
233 }
234 return formatInt(value, radix, uppercase, width, context, Errors, output);
235}
236
237fn formatFloatValue(
238 value: var,
239 comptime fmt: []const u8,
240 context: var,
241 comptime Errors: type,
242 output: fn (@typeOf(context), []const u8) Errors!void,
243) Errors!void {
244 comptime var width: ?usize = null;
245 comptime var float_fmt = 'e';
246 if (fmt.len > 0) {
247 float_fmt = fmt[0];
248 if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
249 }
250
251 switch (float_fmt) {
252 'e' => try formatFloatScientific(value, width, context, Errors, output),
253 '.' => try formatFloatDecimal(value, width, context, Errors, output),
254 else => @compileError("Unknown format character: " ++ []u8{float_fmt}),
255 }
256}
257
258pub fn formatText(
259 bytes: []const u8,
260 comptime fmt: []const u8,
261 context: var,
262 comptime Errors: type,
263 output: fn (@typeOf(context), []const u8) Errors!void,
264) Errors!void {
265 if (fmt.len > 0) {
266 if (fmt[0] == 's') {
267 comptime var width = 0;
268 if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
269 return formatBuf(bytes, width, context, Errors, output);
270 } else @compileError("Unknown format character: " ++ []u8{fmt[0]});
271 }
272 return output(context, bytes);
273}
274
275pub fn formatAsciiChar(
276 c: u8,
277 context: var,
278 comptime Errors: type,
279 output: fn (@typeOf(context), []const u8) Errors!void,
280) Errors!void {
321 return output(context, (&c)[0..1]);281 return output(context, (&c)[0..1]);
322}282}
323283
324pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {284pub fn formatBuf(
285 buf: []const u8,
286 width: usize,
287 context: var,
288 comptime Errors: type,
289 output: fn (@typeOf(context), []const u8) Errors!void,
290) Errors!void {
325 try output(context, buf);291 try output(context, buf);
326292
327 var leftover_padding = if (width > buf.len) (width - buf.len) else return;293 var leftover_padding = if (width > buf.len) (width - buf.len) else return;
...@@ -334,7 +300,13 @@ pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: t...@@ -334,7 +300,13 @@ pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: t
334// Print a float in scientific notation to the specified precision. Null uses full precision.300// Print a float in scientific notation to the specified precision. Null uses full precision.
335// It should be the case that every full precision, printed value can be re-parsed back to the301// It should be the case that every full precision, printed value can be re-parsed back to the
336// same type unambiguously.302// same type unambiguously.
337pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {303pub fn formatFloatScientific(
304 value: var,
305 maybe_precision: ?usize,
306 context: var,
307 comptime Errors: type,
308 output: fn (@typeOf(context), []const u8) Errors!void,
309) Errors!void {
338 var x = f64(value);310 var x = f64(value);
339311
340 // Errol doesn't handle these special cases.312 // Errol doesn't handle these special cases.
...@@ -423,7 +395,13 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var,...@@ -423,7 +395,13 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var,
423395
424// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.396// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
425// By default floats are printed at full precision (no rounding).397// By default floats are printed at full precision (no rounding).
426pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {398pub fn formatFloatDecimal(
399 value: var,
400 maybe_precision: ?usize,
401 context: var,
402 comptime Errors: type,
403 output: fn (@typeOf(context), []const u8) Errors!void,
404) Errors!void {
427 var x = f64(value);405 var x = f64(value);
428406
429 // Errol doesn't handle these special cases.407 // Errol doesn't handle these special cases.
...@@ -613,7 +591,15 @@ pub fn formatInt(...@@ -613,7 +591,15 @@ pub fn formatInt(
613 }591 }
614}592}
615593
616fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {594fn formatIntSigned(
595 value: var,
596 base: u8,
597 uppercase: bool,
598 width: usize,
599 context: var,
600 comptime Errors: type,
601 output: fn (@typeOf(context), []const u8) Errors!void,
602) Errors!void {
617 const uint = @IntType(false, @typeOf(value).bit_count);603 const uint = @IntType(false, @typeOf(value).bit_count);
618 if (value < 0) {604 if (value < 0) {
619 const minus_sign: u8 = '-';605 const minus_sign: u8 = '-';
...@@ -632,7 +618,15 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context:...@@ -632,7 +618,15 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context:
632 }618 }
633}619}
634620
635fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {621fn formatIntUnsigned(
622 value: var,
623 base: u8,
624 uppercase: bool,
625 width: usize,
626 context: var,
627 comptime Errors: type,
628 output: fn (@typeOf(context), []const u8) Errors!void,
629) Errors!void {
636 // max_int_digits accounts for the minus sign. when printing an unsigned630 // max_int_digits accounts for the minus sign. when printing an unsigned
637 // number we don't need to do that.631 // number we don't need to do that.
638 var buf: [max_int_digits - 1]u8 = undefined;632 var buf: [max_int_digits - 1]u8 = undefined;
...@@ -831,6 +825,10 @@ test "fmt.format" {...@@ -831,6 +825,10 @@ test "fmt.format" {
831 const value: u3 = 0b101;825 const value: u3 = 0b101;
832 try testFmt("u3: 5\n", "u3: {}\n", value);826 try testFmt("u3: 5\n", "u3: {}\n", value);
833 }827 }
828 {
829 const value: u8 = 'a';
830 try testFmt("u8: a\n", "u8: {c}\n", value);
831 }
834 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));832 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
835 try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));833 try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));
836 {834 {
...@@ -1048,6 +1046,42 @@ test "fmt.format" {...@@ -1048,6 +1046,42 @@ test "fmt.format" {
1048 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1046 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1049 assert(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));1047 assert(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
1050 }1048 }
1049 //custom type format
1050 {
1051 const Vec2 = struct {
1052 const SelfType = this;
1053 x: f32,
1054 y: f32,
1055
1056 pub fn format(
1057 self: *SelfType,
1058 comptime fmt: []const u8,
1059 context: var,
1060 comptime Errors: type,
1061 output: fn (@typeOf(context), []const u8) Errors!void,
1062 ) Errors!void {
1063 if (fmt.len > 0) {
1064 if (fmt.len > 1) unreachable;
1065 switch (fmt[0]) {
1066 //point format
1067 'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),
1068 //dimension format
1069 'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y),
1070 else => unreachable,
1071 }
1072 }
1073 return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y);
1074 }
1075 };
1076
1077 var buf1: [32]u8 = undefined;
1078 var value = Vec2{
1079 .x = 10.2,
1080 .y = 2.22,
1081 };
1082 try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value);
1083 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", &value);
1084 }
1051}1085}
10521086
1053fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {1087fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {
std/os/time.zig+1-1
...@@ -266,7 +266,7 @@ test "os.time.timestamp" {...@@ -266,7 +266,7 @@ test "os.time.timestamp" {
266266
267test "os.time.Timer" {267test "os.time.Timer" {
268 const ns_per_ms = (ns_per_s / ms_per_s);268 const ns_per_ms = (ns_per_s / ms_per_s);
269 const margin = ns_per_ms * 50;269 const margin = ns_per_ms * 150;
270270
271 var timer = try Timer.start();271 var timer = try Timer.start();
272 sleep(0, 10 * ns_per_ms);272 sleep(0, 10 * ns_per_ms);