authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-09-21 12:39:35+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-11-05 16:10:33+01:00
log2cce23062b95cf112ddbf4613c5a7e9ff60f0f88
tree5518b5e3fd5593c36439f2b58a134d2ecc776581
parent678ecc94ca8584e8fef9bfae4ed5fa97c62c58e1

Update the API and add add error-recovery path


1 files changed, 25 insertions(+), 11 deletions(-)

lib/std/fmt.zig+25-11
...@@ -557,8 +557,8 @@ pub fn formatIntValue(...@@ -557,8 +557,8 @@ pub fn formatIntValue(
557 @compileError("Cannot escape character with more than 8 bits");557 @compileError("Cannot escape character with more than 8 bits");
558 }558 }
559 } else if (comptime std.mem.eql(u8, fmt, "u")) {559 } else if (comptime std.mem.eql(u8, fmt, "u")) {
560 if (@TypeOf(int_value).bit_count <= 32) {560 if (@typeInfo(@TypeOf(int_value)).Int.bits <= 21) {
561 return formatUtf8Codepoint(@as(u32, int_value), options, context, Errors, output);561 return formatUnicodeCodepoint(@as(u21, int_value), options, writer);
562 } else {562 } else {
563 @compileError("Cannot print integer that is larger than 32 bits as an UTF-8 sequence");563 @compileError("Cannot print integer that is larger than 32 bits as an UTF-8 sequence");
564 }564 }
...@@ -648,16 +648,22 @@ pub fn formatAsciiChar(...@@ -648,16 +648,22 @@ pub fn formatAsciiChar(
648 return writer.writeAll(@as(*const [1]u8, &c));648 return writer.writeAll(@as(*const [1]u8, &c));
649}649}
650650
651pub fn formatUtf8Codepoint(651pub fn formatUnicodeCodepoint(
652 c: u32,652 c: u21,
653 options: FormatOptions,653 options: FormatOptions,
654 context: anytype,654 writer: anytype,
655 comptime Errors: type,655) !void {
656 output: fn (@TypeOf(context), []const u8) Errors!void,
657) Errors!void {
658 var buf: [4]u8 = undefined;656 var buf: [4]u8 = undefined;
659 const len = std.unicode.utf8Encode(c, buf[0..]) catch unreachable;657 // In case of error output the replacement char U+FFFD
660 return output(context, @as(*const [4]u8, &buf)[0..len]);658 const len = std.unicode.utf8Encode(@truncate(u21, c), &buf) catch |err| switch (err) {
659 error.Utf8CannotEncodeSurrogateHalf => {
660 return writer.writeAll(&[_]u8{ 0xef, 0xbf, 0xbd });
661 },
662 error.CodepointTooLarge => {
663 return writer.writeAll(&[_]u8{ 0xef, 0xbf, 0xbd });
664 },
665 };
666 return writer.writeAll(buf[0..len]);
661}667}
662668
663pub fn formatBuf(669pub fn formatBuf(
...@@ -1409,9 +1415,17 @@ test "int.specifier" {...@@ -1409,9 +1415,17 @@ test "int.specifier" {
1409 try testFmt("UTF-8: a\n", "UTF-8: {u}\n", .{value});1415 try testFmt("UTF-8: a\n", "UTF-8: {u}\n", .{value});
1410 }1416 }
1411 {1417 {
1412 const value: u32 = 0x1F310;1418 const value: u21 = 0x1F310;
1413 try testFmt("UTF-8: 🌐\n", "UTF-8: {u}\n", .{value});1419 try testFmt("UTF-8: 🌐\n", "UTF-8: {u}\n", .{value});
1414 }1420 }
1421 {
1422 const value: u21 = 0xD800;
1423 try testFmt("UTF-8: �\n", "UTF-8: {u}\n", .{value});
1424 }
1425 {
1426 const value: u21 = 0x110001;
1427 try testFmt("UTF-8: �\n", "UTF-8: {u}\n", .{value});
1428 }
1415}1429}
14161430
1417test "int.padded" {1431test "int.padded" {