authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-24 16:20:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-24 17:01:19-07:00
log92505a7de7f720acc74906a053cd89a33174eb1f
tree679a88feade1d36d53a073ac2d149173a0fae580
parent9dda196eea5fc5f299eb87feb93a8d7e756ba2fa

std: move fmt.bufPrint to mem.print


2 files changed, 166 insertions(+), 118 deletions(-)

lib/std/fmt.zig+113-114
...@@ -6,8 +6,6 @@ const std = @import("std.zig");...@@ -6,8 +6,6 @@ const std = @import("std.zig");
6const math = std.math;6const math = std.math;
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const mem = std.mem;8const mem = std.mem;
9const meta = std.meta;
10const lossyCast = math.lossyCast;
11const expectFmt = std.testing.expectFmt;9const expectFmt = std.testing.expectFmt;
12const testing = std.testing;10const testing = std.testing;
13const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
...@@ -254,6 +252,13 @@ pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Opt...@@ -254,6 +252,13 @@ pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Opt
254 return w.end;252 return w.end;
255}253}
256254
255test printInt {
256 const x: i32 = -3;
257 var buffer: [64]u8 = undefined;
258 const s = buffer[0..printInt(&buffer, x, 10, .lower, .{})];
259 try testing.expectEqualStrings("-3", s);
260}
261
257/// Converts values in the range [0, 100) to a base 10 string.262/// Converts values in the range [0, 100) to a base 10 string.
258pub fn digits2(value: u8) [2]u8 {263pub fn digits2(value: u8) [2]u8 {
259 if (builtin.mode == .ReleaseSmall) {264 if (builtin.mode == .ReleaseSmall) {
...@@ -332,63 +337,63 @@ pub fn parseIntWithGenericCharacter(...@@ -332,63 +337,63 @@ pub fn parseIntWithGenericCharacter(
332}337}
333338
334test parseInt {339test parseInt {
335 try std.testing.expectEqual(-10, try parseInt(i32, "-10", 10));340 try testing.expectEqual(-10, try parseInt(i32, "-10", 10));
336 try std.testing.expectEqual(10, try parseInt(i32, "+10", 10));341 try testing.expectEqual(10, try parseInt(i32, "+10", 10));
337 try std.testing.expectEqual(10, try parseInt(u32, "+10", 10));342 try testing.expectEqual(10, try parseInt(u32, "+10", 10));
338 try std.testing.expectError(error.Overflow, parseInt(u32, "-10", 10));343 try testing.expectError(error.Overflow, parseInt(u32, "-10", 10));
339 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, " 10", 10));344 try testing.expectError(error.InvalidCharacter, parseInt(u32, " 10", 10));
340 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "10 ", 10));345 try testing.expectError(error.InvalidCharacter, parseInt(u32, "10 ", 10));
341 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "_10_", 10));346 try testing.expectError(error.InvalidCharacter, parseInt(u32, "_10_", 10));
342 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10_", 10));347 try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10_", 10));
343 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x10_", 10));348 try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x10_", 10));
344 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10", 10));349 try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x_10", 10));
345 try std.testing.expectEqual(255, try parseInt(u8, "255", 10));350 try testing.expectEqual(255, try parseInt(u8, "255", 10));
346 try std.testing.expectError(error.Overflow, parseInt(u8, "256", 10));351 try testing.expectError(error.Overflow, parseInt(u8, "256", 10));
347352
348 // +0 and -0 should work for unsigned353 // +0 and -0 should work for unsigned
349 try std.testing.expectEqual(0, try parseInt(u8, "-0", 10));354 try testing.expectEqual(0, try parseInt(u8, "-0", 10));
350 try std.testing.expectEqual(0, try parseInt(u8, "+0", 10));355 try testing.expectEqual(0, try parseInt(u8, "+0", 10));
351356
352 // ensure minInt is parsed correctly357 // ensure minInt is parsed correctly
353 try std.testing.expectEqual(math.minInt(i1), try parseInt(i1, "-1", 10));358 try testing.expectEqual(math.minInt(i1), try parseInt(i1, "-1", 10));
354 try std.testing.expectEqual(math.minInt(i8), try parseInt(i8, "-128", 10));359 try testing.expectEqual(math.minInt(i8), try parseInt(i8, "-128", 10));
355 try std.testing.expectEqual(math.minInt(i43), try parseInt(i43, "-4398046511104", 10));360 try testing.expectEqual(math.minInt(i43), try parseInt(i43, "-4398046511104", 10));
356361
357 // empty string or bare +- is invalid362 // empty string or bare +- is invalid
358 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "", 10));363 try testing.expectError(error.InvalidCharacter, parseInt(u32, "", 10));
359 try std.testing.expectError(error.InvalidCharacter, parseInt(i32, "", 10));364 try testing.expectError(error.InvalidCharacter, parseInt(i32, "", 10));
360 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "+", 10));365 try testing.expectError(error.InvalidCharacter, parseInt(u32, "+", 10));
361 try std.testing.expectError(error.InvalidCharacter, parseInt(i32, "+", 10));366 try testing.expectError(error.InvalidCharacter, parseInt(i32, "+", 10));
362 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "-", 10));367 try testing.expectError(error.InvalidCharacter, parseInt(u32, "-", 10));
363 try std.testing.expectError(error.InvalidCharacter, parseInt(i32, "-", 10));368 try testing.expectError(error.InvalidCharacter, parseInt(i32, "-", 10));
364369
365 // autodectect the base370 // autodectect the base
366 try std.testing.expectEqual(111, try parseInt(i32, "111", 0));371 try testing.expectEqual(111, try parseInt(i32, "111", 0));
367 try std.testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));372 try testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));
368 try std.testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));373 try testing.expectEqual(111, try parseInt(i32, "1_1_1", 0));
369 try std.testing.expectEqual(7, try parseInt(i32, "+0b111", 0));374 try testing.expectEqual(7, try parseInt(i32, "+0b111", 0));
370 try std.testing.expectEqual(7, try parseInt(i32, "+0B111", 0));375 try testing.expectEqual(7, try parseInt(i32, "+0B111", 0));
371 try std.testing.expectEqual(7, try parseInt(i32, "+0b1_11", 0));376 try testing.expectEqual(7, try parseInt(i32, "+0b1_11", 0));
372 try std.testing.expectEqual(73, try parseInt(i32, "+0o111", 0));377 try testing.expectEqual(73, try parseInt(i32, "+0o111", 0));
373 try std.testing.expectEqual(73, try parseInt(i32, "+0O111", 0));378 try testing.expectEqual(73, try parseInt(i32, "+0O111", 0));
374 try std.testing.expectEqual(73, try parseInt(i32, "+0o11_1", 0));379 try testing.expectEqual(73, try parseInt(i32, "+0o11_1", 0));
375 try std.testing.expectEqual(273, try parseInt(i32, "+0x111", 0));380 try testing.expectEqual(273, try parseInt(i32, "+0x111", 0));
376 try std.testing.expectEqual(-7, try parseInt(i32, "-0b111", 0));381 try testing.expectEqual(-7, try parseInt(i32, "-0b111", 0));
377 try std.testing.expectEqual(-7, try parseInt(i32, "-0b11_1", 0));382 try testing.expectEqual(-7, try parseInt(i32, "-0b11_1", 0));
378 try std.testing.expectEqual(-73, try parseInt(i32, "-0o111", 0));383 try testing.expectEqual(-73, try parseInt(i32, "-0o111", 0));
379 try std.testing.expectEqual(-273, try parseInt(i32, "-0x111", 0));384 try testing.expectEqual(-273, try parseInt(i32, "-0x111", 0));
380 try std.testing.expectEqual(-273, try parseInt(i32, "-0X111", 0));385 try testing.expectEqual(-273, try parseInt(i32, "-0X111", 0));
381 try std.testing.expectEqual(-273, try parseInt(i32, "-0x1_11", 0));386 try testing.expectEqual(-273, try parseInt(i32, "-0x1_11", 0));
382387
383 // bare binary/octal/decimal prefix is invalid388 // bare binary/octal/decimal prefix is invalid
384 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0b", 0));389 try testing.expectError(error.InvalidCharacter, parseInt(u32, "0b", 0));
385 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0o", 0));390 try testing.expectError(error.InvalidCharacter, parseInt(u32, "0o", 0));
386 try std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x", 0));391 try testing.expectError(error.InvalidCharacter, parseInt(u32, "0x", 0));
387392
388 // edge cases which previously errored due to base overflowing T393 // edge cases which previously errored due to base overflowing T
389 try std.testing.expectEqual(@as(i2, -2), try std.fmt.parseInt(i2, "-10", 2));394 try testing.expectEqual(@as(i2, -2), try std.fmt.parseInt(i2, "-10", 2));
390 try std.testing.expectEqual(@as(i4, -8), try std.fmt.parseInt(i4, "-10", 8));395 try testing.expectEqual(@as(i4, -8), try std.fmt.parseInt(i4, "-10", 8));
391 try std.testing.expectEqual(@as(i5, -16), try std.fmt.parseInt(i5, "-10", 16));396 try testing.expectEqual(@as(i5, -16), try std.fmt.parseInt(i5, "-10", 16));
392}397}
393398
394fn parseIntWithSign(399fn parseIntWithSign(
...@@ -475,39 +480,39 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, base: u8) ParseIntError!...@@ -475,39 +480,39 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, base: u8) ParseIntError!
475}480}
476481
477test parseUnsigned {482test parseUnsigned {
478 try std.testing.expectEqual(50124, try parseUnsigned(u16, "050124", 10));483 try testing.expectEqual(50124, try parseUnsigned(u16, "050124", 10));
479 try std.testing.expectEqual(65535, try parseUnsigned(u16, "65535", 10));484 try testing.expectEqual(65535, try parseUnsigned(u16, "65535", 10));
480 try std.testing.expectEqual(65535, try parseUnsigned(u16, "65_535", 10));485 try testing.expectEqual(65535, try parseUnsigned(u16, "65_535", 10));
481 try std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));486 try testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
482487
483 try std.testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0ffffffffffffffff", 16));488 try testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0ffffffffffffffff", 16));
484 try std.testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0f_fff_fff_fff_fff_fff", 16));489 try testing.expectEqual(0xffffffffffffffff, try parseUnsigned(u64, "0f_fff_fff_fff_fff_fff", 16));
485 try std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));490 try testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
486491
487 try std.testing.expectEqual(0xDEADBEEF, try parseUnsigned(u32, "DeadBeef", 16));492 try testing.expectEqual(0xDEADBEEF, try parseUnsigned(u32, "DeadBeef", 16));
488493
489 try std.testing.expectEqual(1, try parseUnsigned(u7, "1", 10));494 try testing.expectEqual(1, try parseUnsigned(u7, "1", 10));
490 try std.testing.expectEqual(8, try parseUnsigned(u7, "1000", 2));495 try testing.expectEqual(8, try parseUnsigned(u7, "1000", 2));
491496
492 try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));497 try testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
493 try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));498 try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
494499
495 try std.testing.expectEqual(1442151747, try parseUnsigned(u32, "NUMBER", 36));500 try testing.expectEqual(1442151747, try parseUnsigned(u32, "NUMBER", 36));
496501
497 // these numbers should fit even though the base itself doesn't fit in the destination type502 // these numbers should fit even though the base itself doesn't fit in the destination type
498 try std.testing.expectEqual(0, try parseUnsigned(u1, "0", 10));503 try testing.expectEqual(0, try parseUnsigned(u1, "0", 10));
499 try std.testing.expectEqual(1, try parseUnsigned(u1, "1", 10));504 try testing.expectEqual(1, try parseUnsigned(u1, "1", 10));
500 try std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));505 try testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
501 try std.testing.expectEqual(1, try parseUnsigned(u1, "001", 16));506 try testing.expectEqual(1, try parseUnsigned(u1, "001", 16));
502 try std.testing.expectEqual(3, try parseUnsigned(u2, "3", 16));507 try testing.expectEqual(3, try parseUnsigned(u2, "3", 16));
503 try std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));508 try testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
504509
505 // parseUnsigned does not expect a sign510 // parseUnsigned does not expect a sign
506 try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "+0", 10));511 try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "+0", 10));
507 try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "-0", 10));512 try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "-0", 10));
508513
509 // test empty string error514 // test empty string error
510 try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "", 10));515 try testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "", 10));
511}516}
512517
513/// Parses a number like '2G', '2Gi', or '2GiB'.518/// Parses a number like '2G', '2Gi', or '2GiB'.
...@@ -549,15 +554,15 @@ pub fn parseIntSizeSuffix(buf: []const u8, digit_base: u8) ParseIntError!usize {...@@ -549,15 +554,15 @@ pub fn parseIntSizeSuffix(buf: []const u8, digit_base: u8) ParseIntError!usize {
549}554}
550555
551test parseIntSizeSuffix {556test parseIntSizeSuffix {
552 try std.testing.expectEqual(2, try parseIntSizeSuffix("2", 10));557 try testing.expectEqual(2, try parseIntSizeSuffix("2", 10));
553 try std.testing.expectEqual(2, try parseIntSizeSuffix("2B", 10));558 try testing.expectEqual(2, try parseIntSizeSuffix("2B", 10));
554 try std.testing.expectEqual(2000, try parseIntSizeSuffix("2kB", 10));559 try testing.expectEqual(2000, try parseIntSizeSuffix("2kB", 10));
555 try std.testing.expectEqual(2000, try parseIntSizeSuffix("2k", 10));560 try testing.expectEqual(2000, try parseIntSizeSuffix("2k", 10));
556 try std.testing.expectEqual(2048, try parseIntSizeSuffix("2KiB", 10));561 try testing.expectEqual(2048, try parseIntSizeSuffix("2KiB", 10));
557 try std.testing.expectEqual(2048, try parseIntSizeSuffix("2Ki", 10));562 try testing.expectEqual(2048, try parseIntSizeSuffix("2Ki", 10));
558 try std.testing.expectEqual(10240, try parseIntSizeSuffix("aKiB", 16));563 try testing.expectEqual(10240, try parseIntSizeSuffix("aKiB", 16));
559 try std.testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("", 10));564 try testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("", 10));
560 try std.testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("2iB", 10));565 try testing.expectError(error.InvalidCharacter, parseIntSizeSuffix("2iB", 10));
561}566}
562567
563pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;568pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
...@@ -588,28 +593,22 @@ pub fn digitToChar(digit: u8, case: Case) u8 {...@@ -588,28 +593,22 @@ pub fn digitToChar(digit: u8, case: Case) u8 {
588 };593 };
589}594}
590595
591pub const BufPrintError = error{596/// Deprecated in favor of `mem.PrintError`.
592 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.597pub const BufPrintError = mem.PrintError;
593 NoSpaceLeft,
594};
595598
596/// Print a format string into `buf`. Returns a slice of the bytes printed.599/// Deprecated in favor of `mem.print`.
597pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {600pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 {
598 var w: Writer = .fixed(buf);601 return mem.print(buf, fmt, args);
599 w.print(fmt, args) catch |err| switch (err) {
600 error.WriteFailed => return error.NoSpaceLeft,
601 };
602 return w.buffered();
603}602}
604603
604/// Deprecated in favor of `mem.printSentinel`.
605pub fn bufPrintSentinel(605pub fn bufPrintSentinel(
606 buf: []u8,606 buf: []u8,
607 comptime fmt: []const u8,607 comptime fmt: []const u8,
608 args: anytype,608 args: anytype,
609 comptime sentinel: u8,609 comptime sentinel: u8,
610) BufPrintError![:sentinel]u8 {610) BufPrintError![:sentinel]u8 {
611 const result = try bufPrint(buf, fmt ++ [_]u8{sentinel}, args);611 return mem.printSentinel(buf, fmt, args, sentinel);
612 return result[0 .. result.len - 1 :sentinel];
613}612}
614613
615/// Count the characters needed for format.614/// Count the characters needed for format.
...@@ -640,7 +639,7 @@ pub fn allocPrintSentinel(...@@ -640,7 +639,7 @@ pub fn allocPrintSentinel(
640pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {639pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 {
641 comptime {640 comptime {
642 var buf: [count(fmt, args):0]u8 = undefined;641 var buf: [count(fmt, args):0]u8 = undefined;
643 _ = bufPrint(&buf, fmt, args) catch unreachable;642 _ = mem.print(&buf, fmt, args) catch unreachable;
644 buf[buf.len] = 0;643 buf[buf.len] = 0;
645 const final = buf;644 const final = buf;
646 return &final;645 return &final;
...@@ -649,12 +648,12 @@ pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [cou...@@ -649,12 +648,12 @@ pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [cou
649648
650test comptimePrint {649test comptimePrint {
651 @setEvalBranchQuota(2000);650 @setEvalBranchQuota(2000);
652 try std.testing.expectEqual(*const [3:0]u8, @TypeOf(comptimePrint("{}", .{100})));651 try testing.expectEqual(*const [3:0]u8, @TypeOf(comptimePrint("{}", .{100})));
653 try std.testing.expectEqualSlices(u8, "100", comptimePrint("{}", .{100}));652 try testing.expectEqualSlices(u8, "100", comptimePrint("{}", .{100}));
654 try std.testing.expectEqualStrings("30", comptimePrint("{d}", .{30.0}));653 try testing.expectEqualStrings("30", comptimePrint("{d}", .{30.0}));
655 try std.testing.expectEqualStrings("30.0", comptimePrint("{d:3.1}", .{30.0}));654 try testing.expectEqualStrings("30.0", comptimePrint("{d:3.1}", .{30.0}));
656 try std.testing.expectEqualStrings("0.05", comptimePrint("{d}", .{0.05}));655 try testing.expectEqualStrings("0.05", comptimePrint("{d}", .{0.05}));
657 try std.testing.expectEqualStrings("5e-2", comptimePrint("{e}", .{0.05}));656 try testing.expectEqualStrings("5e-2", comptimePrint("{e}", .{0.05}));
658}657}
659658
660test "parse u64 digit too big" {659test "parse u64 digit too big" {
...@@ -667,7 +666,7 @@ test "parse u64 digit too big" {...@@ -667,7 +666,7 @@ test "parse u64 digit too big" {
667666
668test "parse unsigned comptime" {667test "parse unsigned comptime" {
669 comptime {668 comptime {
670 try std.testing.expectEqual(2, try parseUnsigned(usize, "2", 10));669 try testing.expectEqual(2, try parseUnsigned(usize, "2", 10));
671 }670 }
672}671}
673672
...@@ -772,15 +771,15 @@ test "buffer" {...@@ -772,15 +771,15 @@ test "buffer" {
772 var buf1: [32]u8 = undefined;771 var buf1: [32]u8 = undefined;
773 var w: Writer = .fixed(&buf1);772 var w: Writer = .fixed(&buf1);
774 try w.printValue("", .{}, 1234, std.options.fmt_max_depth);773 try w.printValue("", .{}, 1234, std.options.fmt_max_depth);
775 try std.testing.expectEqualStrings("1234", w.buffered());774 try testing.expectEqualStrings("1234", w.buffered());
776775
777 w = .fixed(&buf1);776 w = .fixed(&buf1);
778 try w.printValue("c", .{}, 'a', std.options.fmt_max_depth);777 try w.printValue("c", .{}, 'a', std.options.fmt_max_depth);
779 try std.testing.expectEqualStrings("a", w.buffered());778 try testing.expectEqualStrings("a", w.buffered());
780779
781 w = .fixed(&buf1);780 w = .fixed(&buf1);
782 try w.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);781 try w.printValue("b", .{}, 0b1100, std.options.fmt_max_depth);
783 try std.testing.expectEqualStrings("1100", w.buffered());782 try testing.expectEqualStrings("1100", w.buffered());
784 }783 }
785}784}
786785
...@@ -801,7 +800,7 @@ test "array" {...@@ -801,7 +800,7 @@ test "array" {
801800
802 var buf: [100]u8 = undefined;801 var buf: [100]u8 = undefined;
803 try expectFmt(802 try expectFmt(
804 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),803 try mem.print(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}),
805 "array: {*}\n",804 "array: {*}\n",
806 .{&value},805 .{&value},
807 );806 );
...@@ -1177,7 +1176,7 @@ test bytesToHex {...@@ -1177,7 +1176,7 @@ test bytesToHex {
1177 const input = "input slice";1176 const input = "input slice";
1178 const encoded = bytesToHex(input, .lower);1177 const encoded = bytesToHex(input, .lower);
1179 var decoded: [input.len]u8 = undefined;1178 var decoded: [input.len]u8 = undefined;
1180 try std.testing.expectEqualSlices(u8, input, try hexToBytes(&decoded, &encoded));1179 try testing.expectEqualSlices(u8, input, try hexToBytes(&decoded, &encoded));
1181}1180}
11821181
1183test hexToBytes {1182test hexToBytes {
...@@ -1189,9 +1188,9 @@ test hexToBytes {...@@ -1189,9 +1188,9 @@ test hexToBytes {
1189 try expectFmt(repeated, "{X}", .{try hexToBytes(&buf, repeated)});1188 try expectFmt(repeated, "{X}", .{try hexToBytes(&buf, repeated)});
1190 try expectFmt("ABCD", "{X}", .{try hexToBytes(&buf, "ABCD")});1189 try expectFmt("ABCD", "{X}", .{try hexToBytes(&buf, "ABCD")});
1191 try expectFmt("", "{X}", .{try hexToBytes(&buf, "")});1190 try expectFmt("", "{X}", .{try hexToBytes(&buf, "")});
1192 try std.testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));1191 try testing.expectError(error.InvalidCharacter, hexToBytes(&buf, "012Z"));
1193 try std.testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));1192 try testing.expectError(error.InvalidLength, hexToBytes(&buf, "AAA"));
1194 try std.testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));1193 try testing.expectError(error.NoSpaceLeft, hexToBytes(buf[0..1], "ABAB"));
1195}1194}
11961195
1197test "positional" {1196test "positional" {
...@@ -1226,12 +1225,12 @@ test "vector" {...@@ -1226,12 +1225,12 @@ test "vector" {
1226 const vop: @Vector(4, ?*const u64) = [_]?*const u64{ &x[0], null, null, &x[3] };1225 const vop: @Vector(4, ?*const u64) = [_]?*const u64{ &x[0], null, null, &x[3] };
12271226
1228 var expect_buffer: [@sizeOf(usize) * 2 * 4 + 64]u8 = undefined;1227 var expect_buffer: [@sizeOf(usize) * 2 * 4 + 64]u8 = undefined;
1229 try expectFmt(try bufPrint(1228 try expectFmt(try mem.print(
1230 &expect_buffer,1229 &expect_buffer,
1231 "{{ {}, {}, {}, {} }}",1230 "{{ {}, {}, {}, {} }}",
1232 .{ &x[0], &x[1], &x[2], &x[3] },1231 .{ &x[0], &x[1], &x[2], &x[3] },
1233 ), "{}", .{vp});1232 ), "{}", .{vp});
1234 try expectFmt(try bufPrint(1233 try expectFmt(try mem.print(
1235 &expect_buffer,1234 &expect_buffer,
1236 "{{ {?}, null, null, {?} }}",1235 "{{ {?}, null, null, {?} }}",
1237 .{ &x[0], &x[3] },1236 .{ &x[0], &x[3] },
...@@ -1348,18 +1347,18 @@ pub fn hex(x: anytype) [@typeInfo(@TypeOf(x)).int.bits / 4]u8 {...@@ -1348,18 +1347,18 @@ pub fn hex(x: anytype) [@typeInfo(@TypeOf(x)).int.bits / 4]u8 {
1348test hex {1347test hex {
1349 {1348 {
1350 const x = hex(@as(u32, 0xdeadbeef));1349 const x = hex(@as(u32, 0xdeadbeef));
1351 try std.testing.expect(x.len == 8);1350 try testing.expect(x.len == 8);
1352 try std.testing.expectEqualStrings("efbeadde", &x);1351 try testing.expectEqualStrings("efbeadde", &x);
1353 }1352 }
1354 {1353 {
1355 const s = "[" ++ hex(@as(u48, 0x12345678_abcd)) ++ "]";1354 const s = "[" ++ hex(@as(u48, 0x12345678_abcd)) ++ "]";
1356 try std.testing.expect(s.len == 14);1355 try testing.expect(s.len == 14);
1357 try std.testing.expectEqualStrings("[cdab78563412]", s);1356 try testing.expectEqualStrings("[cdab78563412]", s);
1358 }1357 }
1359 {1358 {
1360 const s = "[" ++ hex(@as(u64, 0x12345678_abcdef00)) ++ "]";1359 const s = "[" ++ hex(@as(u64, 0x12345678_abcdef00)) ++ "]";
1361 try std.testing.expect(s.len == 18);1360 try testing.expect(s.len == 18);
1362 try std.testing.expectEqualStrings("[00efcdab78563412]", s);1361 try testing.expectEqualStrings("[00efcdab78563412]", s);
1363 }1362 }
1364}1363}
13651364
lib/std/mem.zig+53-4
...@@ -1,12 +1,14 @@...@@ -1,12 +1,14 @@
1const std = @import("std.zig");1const mem = @This();
2
2const builtin = @import("builtin");3const builtin = @import("builtin");
4const native_endian = builtin.cpu.arch.endian();
5
6const std = @import("std.zig");
3const debug = std.debug;7const debug = std.debug;
4const assert = debug.assert;8const assert = debug.assert;
5const math = std.math;9const math = std.math;
6const mem = @This();
7const testing = std.testing;10const testing = std.testing;
8const Endian = std.builtin.Endian;11const Endian = std.lang.Endian;
9const native_endian = builtin.cpu.arch.endian();
1012
11/// The standard library currently thoroughly depends on byte size13/// The standard library currently thoroughly depends on byte size
12/// being 8 bits. (see the use of u8 throughout allocation code as14/// being 8 bits. (see the use of u8 throughout allocation code as
...@@ -5152,3 +5154,50 @@ test "read/write(Var)PackedInt" {...@@ -5152,3 +5154,50 @@ test "read/write(Var)PackedInt" {
5152 }5154 }
5153 }5155 }
5154}5156}
5157
5158pub const PrintError = error{
5159 /// As much as possible was written to the buffer, but it was too small to
5160 /// fit all the printed bytes.
5161 NoSpaceLeft,
5162};
5163
5164/// Render a formatted string into `buffer`. Returns a slice of `buffer`
5165/// starting at index 0 containing the result, or `error.NoSpaceLeft` if one or
5166/// more bytes were truncated.
5167///
5168/// See `std.Io.Writer.print`.
5169pub fn print(buffer: []u8, comptime format: []const u8, args: anytype) PrintError![]u8 {
5170 var w: std.Io.Writer = .fixed(buffer);
5171 w.print(format, args) catch |err| switch (err) {
5172 error.WriteFailed => return error.NoSpaceLeft,
5173 };
5174 return w.buffered();
5175}
5176
5177test print {
5178 const x: i32 = -1;
5179 const y: []const u8 = "hi";
5180 var buffer: [64]u8 = undefined;
5181 const s = try print(&buffer, "{d}={s}", .{ x, y });
5182 try testing.expectEqualStrings("-1=hi", s);
5183}
5184
5185/// Like `print` but returned slice has the provided sentinel.
5186pub fn printSentinel(
5187 buffer: []u8,
5188 comptime format: []const u8,
5189 args: anytype,
5190 comptime sentinel: u8,
5191) PrintError![:sentinel]u8 {
5192 const result = try print(buffer, format ++ [1]u8{sentinel}, args);
5193 return result[0 .. result.len - 1 :sentinel];
5194}
5195
5196test printSentinel {
5197 const x: i32 = -1;
5198 const y: []const u8 = "hi";
5199 var buffer: [64]u8 = undefined;
5200 const s = try printSentinel(&buffer, "{d}={s}", .{ x, y }, 0);
5201 try testing.expectEqualStrings("-1=hi", s);
5202 try testing.expectEqual(0, s[s.len]);
5203}