authorgravatar for benjamin.feng@glassdoor.comBenjamin Feng <benjamin.feng@glassdoor.com> 2020-02-29 11:59:37-06:00
committergravatar for benjamin.feng@glassdoor.comBenjamin Feng <benjamin.feng@glassdoor.com> 2020-03-12 09:04:18-05:00
log278b9ec1aaabb8bcfbbf9c964012dc5bd2ad154a
tree58a9426d91f6e1e9bb48697d3ddd21a434ad32c3
parentae3fb6df007807a37fe448fdef2b8ee669b29a5a

Blind translation


1 files changed, 170 insertions(+), 206 deletions(-)

lib/std/fmtstream.zig+170-206
......@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
6969///
7070/// If a formatted user type contains a function of the type
7171/// ```
72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void
72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmtstream.FormatOptions, out_stream: var) !void
7373/// ```
7474/// with `?` being the type formatted, this function will be called instead of the default implementation.
7575/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
7676///
7777/// A user type may be a `struct`, `vector`, `union` or `enum` type.
7878pub fn format(
79 context: var,
80 comptime Errors: type,
81 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
79 out_stream: var,
8280 comptime fmt: []const u8,
8381 args: var,
84) Errors!void {
82) !void {
8583 const ArgSetType = u32;
8684 if (@typeInfo(@TypeOf(args)) != .Struct) {
8785 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
......@@ -138,7 +136,7 @@ pub fn format(
138136 .Start => switch (c) {
139137 '{' => {
140138 if (start_index < i) {
141 try output(context, fmt[start_index..i]);
139 try out_stream.writeAll(fmt[start_index..i]);
142140 }
143141
144142 start_index = i;
......@@ -150,7 +148,7 @@ pub fn format(
150148 },
151149 '}' => {
152150 if (start_index < i) {
153 try output(context, fmt[start_index..i]);
151 try out_stream.writeAll(fmt[start_index..i]);
154152 }
155153 state = .CloseBrace;
156154 },
......@@ -185,9 +183,7 @@ pub fn format(
185183 args[arg_to_print],
186184 fmt[0..0],
187185 options,
188 context,
189 Errors,
190 output,
186 out_stream,
191187 default_max_depth,
192188 );
193189
......@@ -218,9 +214,7 @@ pub fn format(
218214 args[arg_to_print],
219215 fmt[specifier_start..i],
220216 options,
221 context,
222 Errors,
223 output,
217 out_stream,
224218 default_max_depth,
225219 );
226220 state = .Start;
......@@ -265,9 +259,7 @@ pub fn format(
265259 args[arg_to_print],
266260 fmt[specifier_start..specifier_end],
267261 options,
268 context,
269 Errors,
270 output,
262 out_stream,
271263 default_max_depth,
272264 );
273265 state = .Start;
......@@ -293,9 +285,7 @@ pub fn format(
293285 args[arg_to_print],
294286 fmt[specifier_start..specifier_end],
295287 options,
296 context,
297 Errors,
298 output,
288 out_stream,
299289 default_max_depth,
300290 );
301291 state = .Start;
......@@ -316,7 +306,7 @@ pub fn format(
316306 }
317307 }
318308 if (start_index < fmt.len) {
319 try output(context, fmt[start_index..]);
309 try out_stream.writeAll(fmt[start_index..]);
320310 }
321311}
322312
......@@ -324,121 +314,119 @@ pub fn formatType(
324314 value: var,
325315 comptime fmt: []const u8,
326316 options: FormatOptions,
327 context: var,
328 comptime Errors: type,
329 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
317 out_stream: var,
330318 max_depth: usize,
331) Errors!void {
319) !void {
332320 if (comptime std.mem.eql(u8, fmt, "*")) {
333 try output(context, @typeName(@TypeOf(value).Child));
334 try output(context, "@");
335 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output);
321 try out_stream.writeAll(@typeName(@TypeOf(value).Child));
322 try out_stream.writeAll("@");
323 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
336324 return;
337325 }
338326
339327 const T = @TypeOf(value);
340328 switch (@typeInfo(T)) {
341329 .ComptimeInt, .Int, .Float => {
342 return formatValue(value, fmt, options, context, Errors, output);
330 return formatValue(value, fmt, options, out_stream);
343331 },
344332 .Void => {
345 return output(context, "void");
333 return out_stream.writeAll("void");
346334 },
347335 .Bool => {
348 return output(context, if (value) "true" else "false");
336 return out_stream.writeAll(if (value) "true" else "false");
349337 },
350338 .Optional => {
351339 if (value) |payload| {
352 return formatType(payload, fmt, options, context, Errors, output, max_depth);
340 return formatType(payload, fmt, options, out_stream, max_depth);
353341 } else {
354 return output(context, "null");
342 return out_stream.writeAll("null");
355343 }
356344 },
357345 .ErrorUnion => {
358346 if (value) |payload| {
359 return formatType(payload, fmt, options, context, Errors, output, max_depth);
347 return formatType(payload, fmt, options, out_stream, max_depth);
360348 } else |err| {
361 return formatType(err, fmt, options, context, Errors, output, max_depth);
349 return formatType(err, fmt, options, out_stream, max_depth);
362350 }
363351 },
364352 .ErrorSet => {
365 try output(context, "error.");
366 return output(context, @errorName(value));
353 try out_stream.writeAll("error.");
354 return out_stream.writeAll(@errorName(value));
367355 },
368356 .Enum => |enumInfo| {
369357 if (comptime std.meta.trait.hasFn("format")(T)) {
370 return value.format(fmt, options, context, Errors, output);
358 return value.format(fmt, options, out_stream);
371359 }
372360
373 try output(context, @typeName(T));
361 try out_stream.writeAll(@typeName(T));
374362 if (enumInfo.is_exhaustive) {
375 try output(context, ".");
376 try output(context, @tagName(value));
363 try out_stream.writeAll(".");
364 try out_stream.writeAll(@tagName(value));
377365 } else {
378366 // TODO: when @tagName works on exhaustive enums print known enum strings
379 try output(context, "(");
380 try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);
381 try output(context, ")");
367 try out_stream.writeAll("(");
368 try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
369 try out_stream.writeAll(")");
382370 }
383371 },
384372 .Union => {
385373 if (comptime std.meta.trait.hasFn("format")(T)) {
386 return value.format(fmt, options, context, Errors, output);
374 return value.format(fmt, options, out_stream);
387375 }
388376
389 try output(context, @typeName(T));
377 try out_stream.writeAll(@typeName(T));
390378 if (max_depth == 0) {
391 return output(context, "{ ... }");
379 return out_stream.writeAll("{ ... }");
392380 }
393381 const info = @typeInfo(T).Union;
394382 if (info.tag_type) |UnionTagType| {
395 try output(context, "{ .");
396 try output(context, @tagName(@as(UnionTagType, value)));
397 try output(context, " = ");
383 try out_stream.writeAll("{ .");
384 try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
385 try out_stream.writeAll(" = ");
398386 inline for (info.fields) |u_field| {
399387 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
400 try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1);
388 try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1);
401389 }
402390 }
403 try output(context, " }");
391 try out_stream.writeAll(" }");
404392 } else {
405 try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});
393 try format(out_stream, "@{x}", .{@ptrToInt(&value)});
406394 }
407395 },
408396 .Struct => |StructT| {
409397 if (comptime std.meta.trait.hasFn("format")(T)) {
410 return value.format(fmt, options, context, Errors, output);
398 return value.format(fmt, options, out_stream);
411399 }
412400
413 try output(context, @typeName(T));
401 try out_stream.writeAll(@typeName(T));
414402 if (max_depth == 0) {
415 return output(context, "{ ... }");
403 return out_stream.writeAll("{ ... }");
416404 }
417 try output(context, "{");
405 try out_stream.writeAll("{");
418406 inline for (StructT.fields) |f, i| {
419407 if (i == 0) {
420 try output(context, " .");
408 try out_stream.writeAll(" .");
421409 } else {
422 try output(context, ", .");
410 try out_stream.writeAll(", .");
423411 }
424 try output(context, f.name);
425 try output(context, " = ");
426 try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);
412 try out_stream.writeAll(f.name);
413 try out_stream.writeAll(" = ");
414 try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1);
427415 }
428 try output(context, " }");
416 try out_stream.writeAll(" }");
429417 },
430418 .Pointer => |ptr_info| switch (ptr_info.size) {
431419 .One => switch (@typeInfo(ptr_info.child)) {
432420 .Array => |info| {
433421 if (info.child == u8) {
434 return formatText(value, fmt, options, context, Errors, output);
422 return formatText(value, fmt, options, out_stream);
435423 }
436 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
424 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
437425 },
438426 .Enum, .Union, .Struct => {
439 return formatType(value.*, fmt, options, context, Errors, output, max_depth);
427 return formatType(value.*, fmt, options, out_stream, max_depth);
440428 },
441 else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
429 else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
442430 },
443431 .Many, .C => {
444432 if (ptr_info.sentinel) |sentinel| {
......@@ -446,19 +434,19 @@ pub fn formatType(
446434 }
447435 if (ptr_info.child == u8) {
448436 if (fmt.len > 0 and fmt[0] == 's') {
449 return formatText(mem.span(value), fmt, options, context, Errors, output);
437 return formatText(mem.span(value), fmt, options, out_stream);
450438 }
451439 }
452 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
440 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
453441 },
454442 .Slice => {
455443 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
456 return formatText(value, fmt, options, context, Errors, output);
444 return formatText(value, fmt, options, out_stream);
457445 }
458446 if (ptr_info.child == u8) {
459 return formatText(value, fmt, options, context, Errors, output);
447 return formatText(value, fmt, options, out_stream);
460448 }
461 return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
449 return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
462450 },
463451 },
464452 .Array => |info| {
......@@ -473,24 +461,24 @@ pub fn formatType(
473461 .sentinel = null,
474462 },
475463 });
476 return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth);
464 return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth);
477465 },
478466 .Vector => {
479467 const len = @typeInfo(T).Vector.len;
480 try output(context, "{ ");
468 try out_stream.writeAll("{ ");
481469 var i: usize = 0;
482470 while (i < len) : (i += 1) {
483 try formatValue(value[i], fmt, options, context, Errors, output);
471 try formatValue(value[i], fmt, options, out_stream);
484472 if (i < len - 1) {
485 try output(context, ", ");
473 try out_stream.writeAll(", ");
486474 }
487475 }
488 try output(context, " }");
476 try out_stream.writeAll(" }");
489477 },
490478 .Fn => {
491 return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
479 return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
492480 },
493 .Type => return output(context, @typeName(T)),
481 .Type => return out_stream.writeAll(@typeName(T)),
494482 .EnumLiteral => {
495483 const buffer = [_]u8{'.'} ++ @tagName(value);
496484 return formatType(buffer, fmt, options, context, Errors, output, max_depth);
......@@ -503,21 +491,19 @@ fn formatValue(
503491 value: var,
504492 comptime fmt: []const u8,
505493 options: FormatOptions,
506 context: var,
507 comptime Errors: type,
508 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
509) Errors!void {
494 out_stream: var,
495) !void {
510496 if (comptime std.mem.eql(u8, fmt, "B")) {
511 return formatBytes(value, options, 1000, context, Errors, output);
497 return formatBytes(value, options, 1000, out_stream);
512498 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
513 return formatBytes(value, options, 1024, context, Errors, output);
499 return formatBytes(value, options, 1024, out_stream);
514500 }
515501
516502 const T = @TypeOf(value);
517503 switch (@typeInfo(T)) {
518 .Float => return formatFloatValue(value, fmt, options, context, Errors, output),
519 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
520 .Bool => return output(context, if (value) "true" else "false"),
504 .Float => return formatFloatValue(value, fmt, options, out_stream),
505 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream),
506 .Bool => return out_stream.writeAll(if (value) "true" else "false"),
521507 else => comptime unreachable,
522508 }
523509}
......@@ -526,10 +512,8 @@ pub fn formatIntValue(
526512 value: var,
527513 comptime fmt: []const u8,
528514 options: FormatOptions,
529 context: var,
530 comptime Errors: type,
531 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
532) Errors!void {
515 out_stream: var,
516) !void {
533517 comptime var radix = 10;
534518 comptime var uppercase = false;
535519
......@@ -544,7 +528,7 @@ pub fn formatIntValue(
544528 uppercase = false;
545529 } else if (comptime std.mem.eql(u8, fmt, "c")) {
546530 if (@TypeOf(int_value).bit_count <= 8) {
547 return formatAsciiChar(@as(u8, int_value), options, context, Errors, output);
531 return formatAsciiChar(@as(u8, int_value), options, out_stream);
548532 } else {
549533 @compileError("Cannot print integer that is larger than 8 bits as a ascii");
550534 }
......@@ -561,21 +545,19 @@ pub fn formatIntValue(
561545 @compileError("Unknown format string: '" ++ fmt ++ "'");
562546 }
563547
564 return formatInt(int_value, radix, uppercase, options, context, Errors, output);
548 return formatInt(int_value, radix, uppercase, options, out_stream);
565549}
566550
567551fn formatFloatValue(
568552 value: var,
569553 comptime fmt: []const u8,
570554 options: FormatOptions,
571 context: var,
572 comptime Errors: type,
573 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
574) Errors!void {
555 out_stream: var,
556) !void {
575557 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
576 return formatFloatScientific(value, options, context, Errors, output);
558 return formatFloatScientific(value, options, out_stream);
577559 } else if (comptime std.mem.eql(u8, fmt, "d")) {
578 return formatFloatDecimal(value, options, context, Errors, output);
560 return formatFloatDecimal(value, options, out_stream);
579561 } else {
580562 @compileError("Unknown format string: '" ++ fmt ++ "'");
581563 }
......@@ -585,17 +567,15 @@ pub fn formatText(
585567 bytes: []const u8,
586568 comptime fmt: []const u8,
587569 options: FormatOptions,
588 context: var,
589 comptime Errors: type,
590 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
591) Errors!void {
570 out_stream: var,
571) !void {
592572 if (fmt.len == 0) {
593 return output(context, bytes);
573 return out_stream.writeAll(bytes);
594574 } else if (comptime std.mem.eql(u8, fmt, "s")) {
595 return formatBuf(bytes, options, context, Errors, output);
575 return formatBuf(bytes, options, out_stream);
596576 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
597577 for (bytes) |c| {
598 try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output);
578 try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream);
599579 }
600580 return;
601581 } else {
......@@ -606,27 +586,23 @@ pub fn formatText(
606586pub fn formatAsciiChar(
607587 c: u8,
608588 options: FormatOptions,
609 context: var,
610 comptime Errors: type,
611 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
612) Errors!void {
613 return output(context, @as(*const [1]u8, &c)[0..]);
589 out_stream: var,
590) !void {
591 return out_stream.writeAll(@as(*const [1]u8, &c)[0..]);
614592}
615593
616594pub fn formatBuf(
617595 buf: []const u8,
618596 options: FormatOptions,
619 context: var,
620 comptime Errors: type,
621 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
622) Errors!void {
623 try output(context, buf);
597 out_stream: var,
598) !void {
599 try out_stream.writeAll(buf);
624600
625601 const width = options.width orelse 0;
626602 var leftover_padding = if (width > buf.len) (width - buf.len) else return;
627603 const pad_byte: u8 = options.fill;
628604 while (leftover_padding > 0) : (leftover_padding -= 1) {
629 try output(context, @as(*const [1]u8, &pad_byte)[0..1]);
605 try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]);
630606 }
631607}
632608
......@@ -636,40 +612,38 @@ pub fn formatBuf(
636612pub fn formatFloatScientific(
637613 value: var,
638614 options: FormatOptions,
639 context: var,
640 comptime Errors: type,
641 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
642) Errors!void {
615 out_stream: var,
616) !void {
643617 var x = @floatCast(f64, value);
644618
645619 // Errol doesn't handle these special cases.
646620 if (math.signbit(x)) {
647 try output(context, "-");
621 try out_stream.writeAll("-");
648622 x = -x;
649623 }
650624
651625 if (math.isNan(x)) {
652 return output(context, "nan");
626 return out_stream.writeAll("nan");
653627 }
654628 if (math.isPositiveInf(x)) {
655 return output(context, "inf");
629 return out_stream.writeAll("inf");
656630 }
657631 if (x == 0.0) {
658 try output(context, "0");
632 try out_stream.writeAll("0");
659633
660634 if (options.precision) |precision| {
661635 if (precision != 0) {
662 try output(context, ".");
636 try out_stream.writeAll(".");
663637 var i: usize = 0;
664638 while (i < precision) : (i += 1) {
665 try output(context, "0");
639 try out_stream.writeAll("0");
666640 }
667641 }
668642 } else {
669 try output(context, ".0");
643 try out_stream.writeAll(".0");
670644 }
671645
672 try output(context, "e+00");
646 try out_stream.writeAll("e+00");
673647 return;
674648 }
675649
......@@ -679,50 +653,50 @@ pub fn formatFloatScientific(
679653 if (options.precision) |precision| {
680654 errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
681655
682 try output(context, float_decimal.digits[0..1]);
656 try out_stream.writeAll(float_decimal.digits[0..1]);
683657
684658 // {e0} case prints no `.`
685659 if (precision != 0) {
686 try output(context, ".");
660 try out_stream.writeAll(".");
687661
688662 var printed: usize = 0;
689663 if (float_decimal.digits.len > 1) {
690664 const num_digits = math.min(float_decimal.digits.len, precision + 1);
691 try output(context, float_decimal.digits[1..num_digits]);
665 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
692666 printed += num_digits - 1;
693667 }
694668
695669 while (printed < precision) : (printed += 1) {
696 try output(context, "0");
670 try out_stream.writeAll("0");
697671 }
698672 }
699673 } else {
700 try output(context, float_decimal.digits[0..1]);
701 try output(context, ".");
674 try out_stream.writeAll(float_decimal.digits[0..1]);
675 try out_stream.writeAll(".");
702676 if (float_decimal.digits.len > 1) {
703677 const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
704678
705 try output(context, float_decimal.digits[1..num_digits]);
679 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
706680 } else {
707 try output(context, "0");
681 try out_stream.writeAll("0");
708682 }
709683 }
710684
711 try output(context, "e");
685 try out_stream.writeAll("e");
712686 const exp = float_decimal.exp - 1;
713687
714688 if (exp >= 0) {
715 try output(context, "+");
689 try out_stream.writeAll("+");
716690 if (exp > -10 and exp < 10) {
717 try output(context, "0");
691 try out_stream.writeAll("0");
718692 }
719 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
693 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
720694 } else {
721 try output(context, "-");
695 try out_stream.writeAll("-");
722696 if (exp > -10 and exp < 10) {
723 try output(context, "0");
697 try out_stream.writeAll("0");
724698 }
725 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
699 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
726700 }
727701}
728702
......@@ -731,36 +705,34 @@ pub fn formatFloatScientific(
731705pub fn formatFloatDecimal(
732706 value: var,
733707 options: FormatOptions,
734 context: var,
735 comptime Errors: type,
736 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
737) Errors!void {
708 out_stream: var,
709) !void {
738710 var x = @as(f64, value);
739711
740712 // Errol doesn't handle these special cases.
741713 if (math.signbit(x)) {
742 try output(context, "-");
714 try out_stream.writeAll("-");
743715 x = -x;
744716 }
745717
746718 if (math.isNan(x)) {
747 return output(context, "nan");
719 return out_stream.writeAll("nan");
748720 }
749721 if (math.isPositiveInf(x)) {
750 return output(context, "inf");
722 return out_stream.writeAll("inf");
751723 }
752724 if (x == 0.0) {
753 try output(context, "0");
725 try out_stream.writeAll("0");
754726
755727 if (options.precision) |precision| {
756728 if (precision != 0) {
757 try output(context, ".");
729 try out_stream.writeAll(".");
758730 var i: usize = 0;
759731 while (i < precision) : (i += 1) {
760 try output(context, "0");
732 try out_stream.writeAll("0");
761733 }
762734 } else {
763 try output(context, ".0");
735 try out_stream.writeAll(".0");
764736 }
765737 }
766738
......@@ -782,14 +754,14 @@ pub fn formatFloatDecimal(
782754
783755 if (num_digits_whole > 0) {
784756 // We may have to zero pad, for instance 1e4 requires zero padding.
785 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
757 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
786758
787759 var i = num_digits_whole_no_pad;
788760 while (i < num_digits_whole) : (i += 1) {
789 try output(context, "0");
761 try out_stream.writeAll("0");
790762 }
791763 } else {
792 try output(context, "0");
764 try out_stream.writeAll("0");
793765 }
794766
795767 // {.0} special case doesn't want a trailing '.'
......@@ -797,7 +769,7 @@ pub fn formatFloatDecimal(
797769 return;
798770 }
799771
800 try output(context, ".");
772 try out_stream.writeAll(".");
801773
802774 // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
803775 var printed: usize = 0;
......@@ -809,7 +781,7 @@ pub fn formatFloatDecimal(
809781
810782 var i: usize = 0;
811783 while (i < zeros_to_print) : (i += 1) {
812 try output(context, "0");
784 try out_stream.writeAll("0");
813785 printed += 1;
814786 }
815787
......@@ -821,14 +793,14 @@ pub fn formatFloatDecimal(
821793 // Remaining fractional portion, zero-padding if insufficient.
822794 assert(precision >= printed);
823795 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
824 try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
796 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
825797 return;
826798 } else {
827 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
799 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
828800 printed += float_decimal.digits.len - num_digits_whole_no_pad;
829801
830802 while (printed < precision) : (printed += 1) {
831 try output(context, "0");
803 try out_stream.writeAll("0");
832804 }
833805 }
834806 } else {
......@@ -840,14 +812,14 @@ pub fn formatFloatDecimal(
840812
841813 if (num_digits_whole > 0) {
842814 // We may have to zero pad, for instance 1e4 requires zero padding.
843 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
815 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
844816
845817 var i = num_digits_whole_no_pad;
846818 while (i < num_digits_whole) : (i += 1) {
847 try output(context, "0");
819 try out_stream.writeAll("0");
848820 }
849821 } else {
850 try output(context, "0");
822 try out_stream.writeAll("0");
851823 }
852824
853825 // Omit `.` if no fractional portion
......@@ -855,7 +827,7 @@ pub fn formatFloatDecimal(
855827 return;
856828 }
857829
858 try output(context, ".");
830 try out_stream.writeAll(".");
859831
860832 // Zero-fill until we reach significant digits or run out of precision.
861833 if (float_decimal.exp < 0) {
......@@ -863,11 +835,11 @@ pub fn formatFloatDecimal(
863835
864836 var i: usize = 0;
865837 while (i < zero_digit_count) : (i += 1) {
866 try output(context, "0");
838 try out_stream.writeAll("0");
867839 }
868840 }
869841
870 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
842 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
871843 }
872844}
873845
......@@ -875,12 +847,10 @@ pub fn formatBytes(
875847 value: var,
876848 options: FormatOptions,
877849 comptime radix: usize,
878 context: var,
879 comptime Errors: type,
880 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
881) Errors!void {
850 out_stream: var,
851) !void {
882852 if (value == 0) {
883 return output(context, "0B");
853 return out_stream.writeAll("0B");
884854 }
885855
886856 const mags_si = " kMGTPEZY";
......@@ -897,10 +867,10 @@ pub fn formatBytes(
897867 else => unreachable,
898868 };
899869
900 try formatFloatDecimal(new_value, options, context, Errors, output);
870 try formatFloatDecimal(new_value, options, out_stream);
901871
902872 if (suffix == ' ') {
903 return output(context, "B");
873 return out_stream.writeAll("B");
904874 }
905875
906876 const buf = switch (radix) {
......@@ -908,7 +878,7 @@ pub fn formatBytes(
908878 1024 => &[_]u8{ suffix, 'i', 'B' },
909879 else => unreachable,
910880 };
911 return output(context, buf);
881 return out_stream.writeAll(buf);
912882}
913883
914884pub fn formatInt(
......@@ -916,10 +886,8 @@ pub fn formatInt(
916886 base: u8,
917887 uppercase: bool,
918888 options: FormatOptions,
919 context: var,
920 comptime Errors: type,
921 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
922) Errors!void {
889 out_stream: var,
890) !void {
923891 const int_value = if (@TypeOf(value) == comptime_int) blk: {
924892 const Int = math.IntFittingRange(value, value);
925893 break :blk @as(Int, value);
......@@ -927,9 +895,9 @@ pub fn formatInt(
927895 value;
928896
929897 if (@TypeOf(int_value).is_signed) {
930 return formatIntSigned(int_value, base, uppercase, options, context, Errors, output);
898 return formatIntSigned(int_value, base, uppercase, options, out_stream);
931899 } else {
932 return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output);
900 return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
933901 }
934902}
935903
......@@ -938,10 +906,8 @@ fn formatIntSigned(
938906 base: u8,
939907 uppercase: bool,
940908 options: FormatOptions,
941 context: var,
942 comptime Errors: type,
943 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
944) Errors!void {
909 out_stream: var,
910) !void {
945911 const new_options = FormatOptions{
946912 .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
947913 .precision = options.precision,
......@@ -950,15 +916,15 @@ fn formatIntSigned(
950916 const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
951917 const Uint = std.meta.IntType(false, bit_count);
952918 if (value < 0) {
953 try output(context, "-");
919 try out_stream.writeAll("-");
954920 const new_value = math.absCast(value);
955 return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
921 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
956922 } else if (options.width == null or options.width.? == 0) {
957 return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, context, Errors, output);
923 return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream);
958924 } else {
959 try output(context, "+");
925 try out_stream.writeAll("+");
960926 const new_value = @intCast(Uint, value);
961 return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);
927 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
962928 }
963929}
964930
......@@ -967,10 +933,8 @@ fn formatIntUnsigned(
967933 base: u8,
968934 uppercase: bool,
969935 options: FormatOptions,
970 context: var,
971 comptime Errors: type,
972 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
973) Errors!void {
936 out_stream: var,
937) !void {
974938 assert(base >= 2);
975939 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
976940 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
......@@ -994,16 +958,16 @@ fn formatIntUnsigned(
994958 const zero_byte: u8 = options.fill;
995959 var leftover_padding = padding - index;
996960 while (true) {
997 try output(context, @as(*const [1]u8, &zero_byte)[0..]);
961 try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]);
998962 leftover_padding -= 1;
999963 if (leftover_padding == 0) break;
1000964 }
1001965 mem.set(u8, buf[0..index], options.fill);
1002 return output(context, &buf);
966 return out_stream.writeAll(&buf);
1003967 } else {
1004968 const padded_buf = buf[index - padding ..];
1005969 mem.set(u8, padded_buf[0..padding], options.fill);
1006 return output(context, padded_buf);
970 return out_stream.writeAll(padded_buf);
1007971 }
1008972}
1009973
......@@ -1451,12 +1415,12 @@ test "custom" {
14511415 options: FormatOptions,
14521416 context: var,
14531417 comptime Errors: type,
1454 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1455 ) Errors!void {
1418 comptime output: fn (@TypeOf(context), []const u8) !void,
1419 ) !void {
14561420 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
1457 return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
1421 return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
14581422 } else if (comptime std.mem.eql(u8, fmt, "d")) {
1459 return std.fmt.format(context, Errors, output, "{d:.3}x{d:.3}", .{ self.x, self.y });
1423 return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
14601424 } else {
14611425 @compileError("Unknown format character: '" ++ fmt ++ "'");
14621426 }
......@@ -1658,10 +1622,10 @@ test "formatType max_depth" {
16581622 options: FormatOptions,
16591623 context: var,
16601624 comptime Errors: type,
1661 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1662 ) Errors!void {
1625 comptime output: fn (@TypeOf(context), []const u8) !void,
1626 ) !void {
16631627 if (fmt.len == 0) {
1664 return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
1628 return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
16651629 } else {
16661630 @compileError("Unknown format string: '" ++ fmt ++ "'");
16671631 }