1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
//! Handlers that control how errors and attachments are formatted and
//! displayed.
//!
//! Handlers determine how context objects and attachments are formatted when
//! displaying or debugging error reports. The rootcause library provides
//! several built-in handlers that cover common use cases.
//!
//! # What Are Handlers?
//!
//! Handlers are types that implement the [`ContextHandler`] and/or
//! [`AttachmentHandler`] traits. They define how to format your error contexts
//! and attachments, including:
//! - How to display an error context (via [`Display`](core::fmt::Display))
//! - How to debug-format an error context (via [`Debug`](core::fmt::Debug))
//! - How to navigate to the error's source (via
//! [`Error::source`](core::error::Error::source))
//! - How to format attachments when they appear in reports
//! - Formatting preferences (inline vs appendix, display vs debug)
//!
//! # Formatting Behavior
//!
//! Handlers can control two aspects of formatting:
//!
//! ## 1. Formatting Function Selection
//!
//! The [`ContextHandler::preferred_formatting_style`] and
//! [`AttachmentHandler::preferred_formatting_style`] methods allow handlers to
//! specify whether they prefer [`Display`](core::fmt::Display) or
//! [`Debug`](core::fmt::Debug) formatting when shown in a report. The default
//! behavior is to always use `Display` formatting, regardless of how the report
//! itself is being formatted.
//!
//! All built-in handlers ([`Error`], [`Display`], [`struct@Debug`], [`Any`])
//! use this default behavior, which means they use their `display` method even
//! when the report is being debug-formatted with `{:?}`.
//!
//! ## 2. Attachment Placement
//!
//! For attachments, handlers can also specify placement preferences via
//! [`AttachmentFormattingStyle`]:
//! - **Inline**: Rendered directly in the error chain
//! - **InlineWithHeader**: Rendered inline but with a header (for multi-line
//! content)
//! - **Appendix**: Rendered in a separate appendix section
//! - **Opaque**: Not shown, but counted in a summary
//! - **Hidden**: Not shown at all
//!
//! # Built-in Handlers
//!
//! ## [`Error`]
//!
//! For types implementing [`std::error::Error`](core::error::Error). Delegates
//! to the type's `Display`, `Debug`, and `source` implementations. This is the
//! default handler for error types.
//!
//! ## [`Display`]
//!
//! For types implementing [`Display`](core::fmt::Display) and
//! [`Debug`](core::fmt::Debug). Useful for custom context types that aren't
//! errors. Always returns `None` for `source`.
//!
//! ## [`struct@Debug`]
//!
//! For types implementing [`Debug`](core::fmt::Debug). Uses debug formatting
//! for the `debug` method and shows "Context of type `TypeName`" for the
//! `display` method. Useful for types that don't implement `Display`.
//!
//! ## [`Any`]
//!
//! For any type. Shows "An object of type TypeName" for both `display` and
//! `debug`. Used when no other formatting is available.
//!
//! # When Handlers Are Selected
//!
//! Handlers are typically selected automatically by the
//! [`report!`](crate::report!) macro based on the traits implemented by your
//! context type. You can also specify a handler explicitly using
//! [`Report::new_custom`](crate::Report::new_custom).
//!
//! # Examples
//!
//! ```
//! use std::io;
//!
//! use rootcause::prelude::*;
//!
//! // Error handler (automatic for std::error::Error types)
//! let io_err: io::Error = io::Error::new(io::ErrorKind::NotFound, "file.txt");
//! let report: Report<io::Error> = report!(io_err);
//!
//! // Display handler (automatic for Display + Debug types)
//! let msg: String = "Configuration invalid".to_string();
//! let report2: Report<String> = report!(msg);
//! ```
pub use ;
/// Handler for types implementing [`std::error::Error`](core::error::Error).
///
/// This handler delegates to the error type's existing implementations of
/// [`Error::source`](core::error::Error::source),
/// [`Display`](core::fmt::Display), and [`Debug`](core::fmt::Debug). This is
/// the default handler for any type that implements the `Error` trait.
///
/// # When to Use
///
/// This handler is automatically selected by the [`report!`](crate::report!)
/// macro when you create a report from a type implementing `std::error::Error`.
/// You rarely need to specify it explicitly.
///
/// # Example
///
/// ```
/// use std::io;
///
/// use rootcause::prelude::*;
///
/// let error: io::Error = io::Error::new(io::ErrorKind::NotFound, "config.toml");
/// let report: Report<io::Error> = report!(error);
///
/// // The Error handler is used automatically, delegating to io::Error's Display
/// assert!(format!("{}", report).contains("config.toml"));
/// ```
;
/// Handler for types implementing [`Display`](core::fmt::Display) and
/// [`Debug`](core::fmt::Debug).
///
/// This handler delegates to the type's `Display` and `Debug` implementations
/// for formatting. This is suitable for custom context types that aren't errors
/// but can be meaningfully displayed. The [`source`](ContextHandler::source)
/// method always returns `None` since these types don't have error sources.
///
/// # When to Use
///
/// This handler is automatically selected for types that implement `Display`
/// and `Debug` but not `std::error::Error`. This is ideal for custom context
/// types like configuration objects, request parameters, or descriptive
/// messages.
///
/// # Examples
///
/// ```
/// use rootcause::prelude::*;
///
/// // String types use the Display handler
/// let report: Report = report!("Operation failed");
/// let output = format!("{}", report);
/// assert!(output.contains("Operation failed"));
///
/// // Custom types with Display also use this handler
/// #[derive(Debug)]
/// struct Config {
/// path: String,
/// timeout: u32,
/// }
///
/// impl std::fmt::Display for Config {
/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// write!(f, "Config[path={}, timeout={}]", self.path, self.timeout)
/// }
/// }
///
/// let config = Config {
/// path: "settings.toml".to_string(),
/// timeout: 30,
/// };
/// let report: Report<Config> = report!(config);
/// assert!(format!("{}", report).contains("settings.toml"));
/// ```
;
/// Handler for types implementing [`Debug`](core::fmt::Debug).
///
/// This handler uses the type's `Debug` implementation for the `debug` method,
/// but shows a generic message like "Context of type `TypeName`" for the
/// `display` method. This is useful for types that have debug information but
/// don't implement `Display`.
///
/// # When to Use
///
/// This handler is automatically selected for types that implement `Debug` but
/// not `Display`. This is useful for internal data structures or types where
/// displaying the full debug output as the primary message would be too
/// verbose.
///
/// # Formatting Behavior
///
/// - **`display` method**: Shows "Context of type `TypeName`"
/// - **`debug` method**: Uses the type's `Debug` implementation
/// - **`source` method**: Always returns `None`
/// - **Preferred formatting**: Same as requested formatting of the report.
///
/// # Example
///
/// ```
/// use rootcause::prelude::*;
///
/// #[derive(Debug)]
/// struct InternalState {
/// connection_count: usize,
/// buffer: Vec<u8>,
/// }
///
/// let state = InternalState {
/// connection_count: 42,
/// buffer: vec![1, 2, 3],
/// };
///
/// let report: Report<InternalState> = report!(state);
///
/// // Display formatting shows a generic message with the type name
/// let display_output = format!("{}", report);
/// assert!(display_output.contains("InternalState"));
/// assert!(!display_output.contains("connection_count")); // Details not shown
///
/// // Debug formatting also uses the handler's Display method (the default behavior)
/// let debug_output = format!("{:?}", report);
/// assert!(debug_output.contains("InternalState"));
/// ```
;
/// Handler for any type, regardless of implemented traits.
///
/// This is the most generic handler, working with any type without requiring
/// `Display`, `Debug`, or `Error` implementations. Both `Display` and `Debug`
/// output show "An object of type TypeName" using
/// [`type_name`](core::any::type_name).
///
/// # When to Use
///
/// This handler is a fallback for types that don't implement any formatting
/// traits. It's automatically selected when no more specific handler applies,
/// or can be used explicitly when you want to hide the details of a type.
///
/// # Formatting Behavior
///
/// - **Display output**: "An object of type TypeName"
/// - **Debug output**: "An object of type TypeName"
/// - **Source**: Always returns `None`
///
/// # Example
///
/// ```
/// use rootcause::{handlers, prelude::*};
///
/// struct Opaque {
/// secret: String,
/// }
///
/// let data = Opaque {
/// secret: "password123".to_string(),
/// };
///
/// // Use the Any handler explicitly to hide internal details
/// let report: Report<Opaque, markers::Mutable, markers::SendSync> =
/// Report::new_custom::<handlers::Any>(data);
///
/// // Only shows the type name, not the secret
/// let output = format!("{}", report);
/// assert!(output.contains("Opaque"));
/// assert!(!output.contains("password123"));
/// ```
;