1use std::{fmt, sync::OnceLock};
2
3#[derive(derive_more::Debug, derive_more::Display, Clone, Copy)]
5#[debug("{_0:?}")]
6pub struct Location(&'static std::panic::Location<'static>);
7
8#[derive(Clone)]
12pub struct Meta {
13 location: Option<Location>,
14}
15
16impl fmt::Display for Meta {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 if let Some(location) = self.location.as_ref() {
19 write!(f, "{location}")?;
20 }
21 Ok(())
22 }
23}
24
25impl fmt::Debug for Meta {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 write!(f, "Meta")?;
28 if let Some(location) = self.location.as_ref() {
29 write!(f, "({location})")?;
30 }
31 Ok(())
32 }
33}
34
35#[track_caller]
37pub fn meta() -> Meta {
38 Meta::default()
39}
40
41impl Default for Meta {
42 #[track_caller]
43 fn default() -> Self {
44 Self {
45 location: location(),
46 }
47 }
48}
49
50impl Meta {
51 #[track_caller]
52 pub fn new() -> Self {
54 Self::default()
55 }
56
57 pub fn location(&self) -> Option<&Location> {
59 self.location.as_ref()
60 }
61}
62
63#[cfg(test)]
64static BACKTRACE_ENABLED: OnceLock<std::sync::RwLock<bool>> = OnceLock::new();
65
66#[cfg(not(test))]
67static BACKTRACE_ENABLED: OnceLock<bool> = OnceLock::new();
68
69#[doc(hidden)]
70pub fn backtrace_enabled() -> bool {
71 let from_env = || {
72 matches!(
73 std::env::var("RUST_BACKTRACE").as_deref(),
74 Ok("1") | Ok("full")
75 ) || matches!(std::env::var("RUST_ERROR_LOCATION").as_deref(), Ok("1"))
76 };
77 #[cfg(test)]
78 return *(BACKTRACE_ENABLED
79 .get_or_init(|| std::sync::RwLock::new(from_env()))
80 .read()
81 .unwrap());
82
83 #[cfg(not(test))]
84 return *(BACKTRACE_ENABLED.get_or_init(from_env));
85}
86
87#[doc(hidden)]
88#[cfg(test)]
89pub fn set_backtrace_enabled(value: bool) {
90 let mut inner = BACKTRACE_ENABLED
91 .get_or_init(Default::default)
92 .write()
93 .unwrap();
94 *inner = value;
95}
96
97#[track_caller]
98fn location() -> Option<Location> {
99 if backtrace_enabled() {
100 Some(Location(std::panic::Location::caller()))
101 } else {
102 None
103 }
104}