Prints a hexadecimal view of the bytes, returning any error that occurs.
pub fn dumpHexFallible(t: Io.Terminal, bytes: []const u8) !void
pub fn dumpHexFallible(t: Io.Terminal, bytes: []const u8) !void {
const w = t.writer;
var chunks = mem.window(u8, bytes, 16, 16);
while (chunks.next()) |window| {
// 1. Print the address.
const address = (@intFromPtr(bytes.ptr) + 0x10 * @divCeil(chunks.index orelse bytes.len, 16) - 0x10);
try t.setColor(.dim);
// We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more.
// Also, make sure all lines are aligned by padding the address.
try w.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });
try t.setColor(.reset);
// 2. Print the bytes.
for (window, 0..) |byte, index| {
try w.print("{X:0>2} ", .{byte});
if (index == 7) try w.writeByte(' ');
}
try w.writeByte(' ');
if (window.len < 16) {
var missing_columns = (16 - window.len) * 3;
if (window.len < 8) missing_columns += 1;
try w.splatByteAll(' ', missing_columns);
}
// 3. Print the characters.
for (window) |byte| {
if (std.ascii.isPrint(byte)) {
try w.writeByte(byte);
} else {
// Related: https://github.com/ziglang/zig/issues/7600
if (t.mode == .windows_api) {
try w.writeByte('.');
continue;
}
// Let's print some common control codes as graphical Unicode symbols.
// We don't want to do this for all control codes because most control codes apart from
// the ones that Zig has escape sequences for are likely not very useful to print as symbols.
switch (byte) {
'\n' => try w.writeAll("␊"),
'\r' => try w.writeAll("␍"),
'\t' => try w.writeAll("␉"),
else => try w.writeByte('.'),
}
}
}
try w.writeByte('\n');
}
}