diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 77b619a056..805fb7205f 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -244,10 +244,14 @@ pub fn dumpHexFallible(bytes: []const u8) !void { const stderr = std.io.getStdErr(); const ttyconf = std.io.tty.detectConfig(stderr); const writer = stderr.writer(); + try dumpHexInternal(bytes, ttyconf, writer); +} + +fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytype) !void { var chunks = mem.window(u8, bytes, 16, 16); while (chunks.next()) |window| { // 1. Print the address. - const address = (@intFromPtr(bytes.ptr) + 0x10 * (chunks.index orelse 0) / 16) - 0x10; + const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10; try ttyconf.setColor(writer, .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. @@ -292,6 +296,24 @@ pub fn dumpHexFallible(bytes: []const u8) !void { } } +test dumpHexInternal { + const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 }; + var output = std.ArrayList(u8).init(std.testing.allocator); + defer output.deinit(); + try dumpHexInternal(bytes, .no_color, output.writer()); + const expected = try std.fmt.allocPrint(std.testing.allocator, + \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ + \\{x:0>[2]} 01 12 13 ... + \\ + , .{ + @intFromPtr(bytes.ptr), + @intFromPtr(bytes.ptr) + 16, + @sizeOf(usize) * 2, + }); + defer std.testing.allocator.free(expected); + try std.testing.expectEqualStrings(expected, output.items); +} + /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpCurrentStackTrace(start_addr: ?usize) void {