chj_util/
partialbacktrace.rs1use std::fmt::Write;
5
6use backtrace::Backtrace;
7
8
9pub struct PartialBacktrace {
10 bt: Backtrace
11}
12
13fn cut_hex(mut s: String) -> String {
16 let err = |s, _msg| -> String {
17 s
20 };
21 let mut cs = s.char_indices().rev();
22 while let Some((_, c)) = cs.next() {
23 if ! c.is_ascii_hexdigit() {
24 if c != 'h' { return err(s, "expecting 'h' left of hex digits") }
25 if let Some((_, c)) = cs.next() {
26 if c != ':' { return err(s, "expecting ':' left of 'h'") }
27 if let Some((pos, c)) = cs.next() {
28 if c != ':' { return err(s, "expecting ':' left of 'h'") }
29 s.truncate(pos);
30 return s
31 } else {
32 return err(s, "premature end left of ':'")
33 }
34 } else {
35 return err(s, "expecting :: left of 'h'")
36 }
37 }
38 }
39 return err(s, "string ends early left of hex digits")
40}
41
42impl PartialBacktrace {
43 pub fn new() -> Self {
44 Self { bt: Backtrace::new() }
45 }
46
47 pub fn part_to_string(&self, skip: usize, end_file: &str) -> String {
51 let mut bt_str = String::new();
52 let frames = &self.bt.frames()[skip..];
53 let mut frameno = 0; 'outer: for frame in frames.iter() {
55 let mut subframeno = 0;
56 for sym in frame.symbols() {
57 if let Some(path) = sym.filename() {
61 let p = path.to_string_lossy();
62 if p.ends_with(end_file) {
63 break 'outer;
64 }
65 let name = sym.name().map(|s| cut_hex(s.to_string()))
66 .unwrap_or_else(|| " XX missing name ".into());
67 if subframeno == 0 {
68 write!(&mut bt_str, "{frameno:4}").unwrap();
69 } else {
70 bt_str.push_str(" ");
71 }
72 let indent_at = " at ";
73 write!(&mut bt_str, ": {name}\n\
74 {indent_at}{p}").unwrap();
75 if let Some(line) = sym.lineno() {
76 write!(&mut bt_str, ":{line}").unwrap();
77 if let Some(col) = sym.colno() {
78 write!(&mut bt_str, ":{col}").unwrap();
79 }
80 }
81 bt_str.push('\n');
82 subframeno += 1;
83 }
84 }
85 frameno += 1;
86 }
87 writeln!(&mut bt_str, " ({frameno}..{} skipped)",
88 frames.len() - 1).unwrap();
89 bt_str
90 }
91}