rune/shared/
mod.rs
1mod assert_send;
2mod caller;
3mod consts;
4mod fixed_vec;
5mod gen;
6
7pub(crate) use self::assert_send::AssertSend;
8pub(crate) use self::caller::Caller;
9pub(crate) use self::consts::Consts;
10pub(crate) use self::fixed_vec::FixedVec;
11pub(crate) use self::gen::Gen;
12
13#[cfg(all(debug_assertions, feature = "std"))]
15mod r#impl {
16 use core::fmt::{self, Write};
17 use core::sync::atomic::{AtomicU8, Ordering};
18
19 use std::env;
20 use std::thread::panicking;
21
22 pub(crate) use std::backtrace::Backtrace;
23
24 pub(crate) enum RuneAssert {
25 Panic,
27 Trace,
29 Error,
31 }
32
33 impl RuneAssert {
34 #[allow(unused)]
36 pub(crate) fn is_panic(&self) -> bool {
37 matches!(self, Self::Panic)
38 }
39
40 #[allow(unused)]
42 pub(crate) fn is_trace(&self) -> bool {
43 matches!(self, Self::Trace)
44 }
45 }
46
47 const VAR: &str = "RUNE_ASSERT";
48
49 static ENABLED: AtomicU8 = AtomicU8::new(0);
50
51 pub(crate) fn rune_assert() -> RuneAssert {
52 let mut value = ENABLED.load(Ordering::Relaxed);
53
54 if value == 0 {
55 value = match env::var(VAR).as_deref() {
56 Ok("panic") => 1,
57 Ok("trace") => 2,
58 _ => 3,
59 };
60
61 ENABLED.store(value, Ordering::Relaxed);
62 }
63
64 match value {
65 1 if !panicking() => RuneAssert::Panic,
66 2 if !panicking() => RuneAssert::Trace,
67 _ => RuneAssert::Error,
68 }
69 }
70
71 pub(crate) struct CaptureAt {
72 at: &'static str,
73 done: usize,
74 string: rust_alloc::string::String,
75 }
76
77 impl CaptureAt {
78 pub(crate) fn new(at: &'static str) -> Self {
79 Self {
80 at,
81 done: 0,
82 string: rust_alloc::string::String::default(),
83 }
84 }
85
86 pub(crate) fn as_str(&self) -> Option<&str> {
87 if self.done > 0 {
88 Some(&self.string[self.done..])
89 } else {
90 None
91 }
92 }
93 }
94
95 impl Write for CaptureAt {
96 #[inline]
97 fn write_str(&mut self, mut s: &str) -> fmt::Result {
98 if self.done > 0 {
99 return Ok(());
100 }
101
102 while let Some(n) = s.find('\n') {
103 self.string.push_str(&s[..n]);
104
105 if let Some(n) = self.string.find("at ") {
106 let at = &self.string[n + 3..];
107
108 if at.contains(self.at) {
109 self.done = n + 3;
110 return Ok(());
111 }
112 }
113
114 self.string.clear();
115 s = &s[n + 1..];
116 }
117
118 self.string.push_str(s);
119 Ok(())
120 }
121 }
122
123 macro_rules! _rune_diagnose {
124 ($($tt:tt)*) => {
125 if $crate::shared::rune_assert().is_panic() {
126 panic!($($tt)*);
127 } else {
128 tracing::trace!($($tt)*);
129 }
130 };
131 }
132
133 macro_rules! _rune_trace {
134 ($at:expr, $tok:expr) => {{
135 if $crate::shared::rune_assert().is_trace() {
136 use std::backtrace::Backtrace;
137 use std::fmt::Write as _;
138
139 let bt = Backtrace::force_capture();
140 let mut at = $crate::shared::CaptureAt::new($at);
141
142 write!(at, "{bt}").with_span($tok.span)?;
143
144 if let Some(_line) = at.as_str() {
145 tracing::trace!("{_line}: {:?}", $tok);
146 }
147 }
148 }};
149 }
150
151 #[doc(inline)]
156 pub(crate) use _rune_diagnose as rune_diagnose;
157
158 #[doc(inline)]
162 pub(crate) use _rune_trace as rune_trace;
163}
164
165#[cfg(not(all(debug_assertions, feature = "std")))]
166mod r#impl {
167 use core::fmt;
168
169 macro_rules! _rune_diagnose {
170 ($($tt:tt)*) => {
171 tracing::trace!($($tt)*);
172 };
173 }
174
175 macro_rules! _rune_trace {
176 ($at:expr, $tok:expr) => {{
177 _ = $at;
178 _ = $tok;
179 }};
180 }
181
182 pub(crate) struct Backtrace;
183
184 impl Backtrace {
185 #[inline(always)]
186 pub(crate) fn capture() -> Self {
187 Self
188 }
189 }
190
191 impl fmt::Display for Backtrace {
192 #[inline(always)]
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 write!(
195 f,
196 "backtrace not available, missing cfg(all(debug_assertions, feature = \"std\"))"
197 )
198 }
199 }
200
201 #[doc(inline)]
206 pub(crate) use _rune_diagnose as rune_diagnose;
207
208 #[doc(inline)]
212 pub(crate) use _rune_trace as rune_trace;
213}
214
215pub(crate) use self::r#impl::*;