/// An adjacency list representation of an execution tree. /// /// This tree provides a convenient intermediate representation for formatting /// [`Trace`] as a tree. pub(super) struct Tree { /// The roots of the trees. /// /// There should only be one root, but the code is robust to multiple roots.
roots: HashSet<Symbol>,
/// The adjacency list of symbols in the execution tree(s).
edges: HashMap<Symbol, HashSet<Symbol>>,
}
impl Tree { /// Constructs a [`Tree`] from [`Trace`] pub(super) fn from_trace(trace: Trace) -> Self { letmut roots: HashSet<Symbol> = HashSet::default(); letmut edges: HashMap<Symbol, HashSet<Symbol>> = HashMap::default();
for trace in trace.backtraces { let trace = to_symboltrace(trace);
/// Produces the sub-symbols of a given symbol. fn consequences(&self, frame: &Symbol) -> Option<impl ExactSizeIterator<Item = &Symbol>> {
Some(self.edges.get(frame)?.iter())
}
/// Format this [`Tree`] as a textual tree. fn display<W: fmt::Write>(
&self,
f: &mut W,
root: &Symbol,
is_last: bool,
prefix: &str,
) -> fmt::Result { let root_fmt = format!("{}", root);
let current; let next;
if is_last {
current = format!("{prefix}└╼\u{a0}{root_fmt}");
next = format!("{}\u{a0}\u{a0}\u{a0}", prefix);
} else {
current = format!("{prefix}├╼\u{a0}{root_fmt}");
next = format!("{}│\u{a0}\u{a0}", prefix);
}
iflet Some(consequences) = self.consequences(root) { let len = consequences.len(); for (i, consequence) in consequences.enumerate() { let is_last = i == len - 1;
writeln!(f)?; self.display(f, consequence, is_last, &next)?;
}
}
Ok(())
}
}
impl fmt::Display for Tree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for root in &self.roots { self.display(f, root, true, " ")?;
}
Ok(())
}
}
/// Resolve a sequence of [`backtrace::BacktraceFrame`]s into a sequence of /// [`Symbol`]s. fn to_symboltrace(backtrace: Backtrace) -> SymbolTrace { // Resolve the backtrace frames to symbols. let backtrace: Backtrace = { letmut backtrace = backtrace::Backtrace::from(backtrace);
backtrace.resolve();
backtrace.into()
};
// Accumulate the symbols in descending order into `symboltrace`. letmut symboltrace: SymbolTrace = vec![]; letmut state = DefaultHasher::new(); for frame in backtrace.into_iter().rev() { for symbol in frame.symbols().iter().rev() { let symbol = Symbol {
symbol: symbol.clone(),
parent_hash: state.finish(),
};
symbol.hash(&mut state);
symboltrace.push(symbol);
}
}
symboltrace
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-23)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.