#[cfg(feature = "inspection")]
use std::cell::RefCell;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SourceLocation {
pub name: &'static str,
pub file: &'static str,
pub line: u32,
pub manifest_dir: &'static str,
}
#[cfg(feature = "inspection")]
thread_local! {
static STACK: RefCell<Vec<SourceLocation>> = const { RefCell::new(Vec::new()) };
}
#[doc(hidden)]
pub struct SourceScope {
#[cfg(feature = "inspection")]
depth: usize,
marker: std::marker::PhantomData<std::rc::Rc<()>>,
}
impl Drop for SourceScope {
fn drop(&mut self) {
#[cfg(feature = "inspection")]
STACK.with(|stack| stack.borrow_mut().truncate(self.depth));
}
}
#[doc(hidden)]
#[inline]
pub fn __source_scope(
name: &'static str,
file: &'static str,
line: u32,
manifest_dir: &'static str,
) -> SourceScope {
#[cfg(feature = "inspection")]
let depth = STACK.with(|stack| {
let mut stack = stack.borrow_mut();
let depth = stack.len();
stack.push(SourceLocation {
name,
file,
line,
manifest_dir,
});
depth
});
#[cfg(not(feature = "inspection"))]
let _ = (name, file, line, manifest_dir);
SourceScope {
#[cfg(feature = "inspection")]
depth,
marker: std::marker::PhantomData,
}
}
#[cfg(feature = "inspection")]
pub fn current_source_trace() -> std::rc::Rc<[SourceLocation]> {
STACK.with(|stack| std::rc::Rc::from(stack.borrow().as_slice()))
}
#[cfg(feature = "inspection")]
pub(crate) struct SourceContext(Vec<SourceLocation>);
#[cfg(feature = "inspection")]
impl Drop for SourceContext {
fn drop(&mut self) {
STACK.with(|stack| *stack.borrow_mut() = std::mem::take(&mut self.0));
}
}
#[cfg(feature = "inspection")]
pub(crate) fn restore_source_trace(trace: &[SourceLocation]) -> SourceContext {
SourceContext(STACK.with(|stack| stack.replace(trace.to_vec())))
}
#[cfg(all(test, feature = "inspection"))]
#[path = "tests/source_trace_tests.rs"]
mod tests;