1//! A variant of `std.builtin.StackTrace` that stores its data within itself
2//! instead of being a pointer. This allows storing captured stack traces
3//! for later printing.
4
5data: [31]usize,
6index: usize,
7
8pub const empty: StoredTrace = .{
9 .data = .{0} ** 31,
10 .index = 0,
11};
12
13pub fn trace(stored: *StoredTrace) std.builtin.StackTrace {
14 return .{
15 .index = stored.index,
16 .instruction_addresses = &stored.data,
17 };
18}
19
20pub fn capture(begin: ?usize) StoredTrace {
21 var stored: StoredTrace = undefined;
22 var frame = stored.trace();
23 std.debug.captureStackTrace(begin orelse @returnAddress(), &frame);
24 stored.index = frame.index;
25 return stored;
26}
27
28pub fn from(stack_trace: ?*std.builtin.StackTrace) StoredTrace {
29 if (stack_trace) |stack| {
30 var data: [31]usize = undefined;
31 @memset(&data, 0);
32 const items = @min(stack.instruction_addresses.len, 31);
33 @memcpy(data[0..items], stack.instruction_addresses[0..items]);
34 return .{
35 .data = data,
36 .index = @min(items, stack.index),
37 };
38 } else {
39 return empty;
40 }
41}
42
43pub const BlankImpl = struct {
44 pub const empty: BlankImpl = .{};
45
46 pub fn trace(_: *BlankImpl) std.builtin.StackTrace {
47 @compileError("trace is not available with StoredTrace.BlankImpl");
48 }
49
50 pub fn capture(_: ?usize) @This() {
51 return .{};
52 }
53
54 pub fn from(_: ?*std.builtin.StackTrace) @This() {
55 return .{};
56 }
57};
58
59pub const DebugStoredTrace = if (builtin.mode == .Debug)
60 StoredTrace
61else
62 BlankImpl;
63
64pub const StoredTrace = @This();
65
66const std = @import("std");
67const builtin = @import("builtin");