oopsie_core/
diagnostic.rs1use alloc::boxed::Box;
4use alloc::sync::Arc;
5
6use crate::{Backtrace, ErrorCode, HelpText, SpanTrace};
7
8pub trait Diagnostic: core::error::Error {
14 #[inline]
16 fn oopsie_backtrace(&self) -> Option<&Backtrace> {
17 None
18 }
19
20 #[inline]
22 fn oopsie_spantrace(&self) -> Option<&SpanTrace> {
23 None
24 }
25
26 #[inline]
28 fn oopsie_location(&self) -> Option<&'static core::panic::Location<'static>> {
29 None
30 }
31
32 #[inline]
34 fn oopsie_error_code(&self) -> Option<ErrorCode> {
35 None
36 }
37
38 #[inline]
40 fn oopsie_help_text(&self) -> Option<HelpText> {
41 None
42 }
43
44 #[inline]
51 fn oopsie_exit_code(&self) -> Option<core::num::NonZeroU8> {
52 None
53 }
54}
55
56impl<T: Diagnostic> Diagnostic for Box<T> {
57 #[inline]
58 fn oopsie_backtrace(&self) -> Option<&Backtrace> {
59 (**self).oopsie_backtrace()
60 }
61
62 #[inline]
63 fn oopsie_spantrace(&self) -> Option<&SpanTrace> {
64 (**self).oopsie_spantrace()
65 }
66
67 #[inline]
68 fn oopsie_location(&self) -> Option<&'static core::panic::Location<'static>> {
69 (**self).oopsie_location()
70 }
71
72 #[inline]
73 fn oopsie_error_code(&self) -> Option<ErrorCode> {
74 (**self).oopsie_error_code()
75 }
76
77 #[inline]
78 fn oopsie_help_text(&self) -> Option<HelpText> {
79 (**self).oopsie_help_text()
80 }
81
82 #[inline]
83 fn oopsie_exit_code(&self) -> Option<core::num::NonZeroU8> {
84 (**self).oopsie_exit_code()
85 }
86}
87
88impl<T: Diagnostic> Diagnostic for Arc<T> {
92 #[inline]
93 fn oopsie_backtrace(&self) -> Option<&Backtrace> {
94 (**self).oopsie_backtrace()
95 }
96
97 #[inline]
98 fn oopsie_spantrace(&self) -> Option<&SpanTrace> {
99 (**self).oopsie_spantrace()
100 }
101
102 #[inline]
103 fn oopsie_location(&self) -> Option<&'static core::panic::Location<'static>> {
104 (**self).oopsie_location()
105 }
106
107 #[inline]
108 fn oopsie_error_code(&self) -> Option<ErrorCode> {
109 (**self).oopsie_error_code()
110 }
111
112 #[inline]
113 fn oopsie_help_text(&self) -> Option<HelpText> {
114 (**self).oopsie_help_text()
115 }
116
117 #[inline]
118 fn oopsie_exit_code(&self) -> Option<core::num::NonZeroU8> {
119 (**self).oopsie_exit_code()
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use crate::Capturable;
127 use std::fmt;
128
129 #[derive(Debug)]
130 struct Src {
131 backtrace: Backtrace,
132 spantrace: SpanTrace,
133 }
134
135 impl fmt::Display for Src {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 f.write_str("src")
138 }
139 }
140
141 impl std::error::Error for Src {}
142
143 impl Diagnostic for Src {
144 fn oopsie_backtrace(&self) -> Option<&Backtrace> {
145 Some(&self.backtrace)
146 }
147
148 fn oopsie_spantrace(&self) -> Option<&SpanTrace> {
149 Some(&self.spantrace)
150 }
151 }
152
153 #[test]
154 fn box_delegates_diagnostic_accessors() {
155 let src = Src {
156 backtrace: Backtrace::capture(),
157 spantrace: SpanTrace::capture(),
158 };
159 let boxed = Box::new(src);
160 assert!(boxed.oopsie_backtrace().is_some());
161 assert!(boxed.oopsie_spantrace().is_some());
162 }
163
164 #[test]
165 fn box_diagnostic_extraction_reuses_source_frames() {
166 use crate::{RustBacktrace, with_rust_backtrace_override};
167
168 with_rust_backtrace_override(RustBacktrace::Enabled, || {
169 let src = Src {
170 backtrace: Backtrace::capture(),
171 spantrace: SpanTrace::capture(),
172 };
173 let expected_frames = src.backtrace.frames().len();
174 assert!(
175 expected_frames > 0,
176 "backtrace must be enabled for this test to be probative"
177 );
178 let boxed = Box::new(src);
179 let extracted = <(Backtrace, SpanTrace) as Capturable>::capture_or_extract(&boxed);
180 assert_eq!(extracted.0.frames().len(), expected_frames);
181 });
182 }
183
184 #[test]
185 fn arc_delegates_diagnostic_accessors() {
186 let src = Src {
187 backtrace: Backtrace::capture(),
188 spantrace: SpanTrace::capture(),
189 };
190 let arced = Arc::new(src);
191 assert!(arced.oopsie_backtrace().is_some());
192 assert!(arced.oopsie_spantrace().is_some());
193 }
194
195 #[test]
196 fn arc_diagnostic_extraction_reuses_source_frames() {
197 use crate::{RustBacktrace, with_rust_backtrace_override};
198
199 with_rust_backtrace_override(RustBacktrace::Enabled, || {
200 let src = Src {
201 backtrace: Backtrace::capture(),
202 spantrace: SpanTrace::capture(),
203 };
204 let expected_frames = src.backtrace.frames().len();
205 assert!(
206 expected_frames > 0,
207 "backtrace must be enabled for this test to be probative"
208 );
209 let arced = Arc::new(src);
210 let extracted = <(Backtrace, SpanTrace) as Capturable>::capture_or_extract(&arced);
211 assert_eq!(extracted.0.frames().len(), expected_frames);
212 });
213 }
214}