http_type/panic/impl.rs
1use crate::*;
2
3/// Implementation of methods for the `PanicData` struct.
4impl PanicData {
5 /// Creates a new `PanicData` instance from its constituent parts.
6 ///
7 /// # Arguments
8 ///
9 /// - `Option<String>` - The panic message.
10 /// - `Option<String>` - The source code location of the panic.
11 /// - `Option<String>` - The panic payload.
12 ///
13 /// # Returns
14 ///
15 /// - `PanicData` - A new panic instance.
16 #[inline(always)]
17 pub(crate) fn new(
18 message: Option<String>,
19 location: Option<String>,
20 payload: Option<String>,
21 ) -> Self {
22 Self {
23 message,
24 location,
25 payload,
26 }
27 }
28
29 /// Attempts to extract a string from a dynamic `&dyn Any` panic payload.
30 ///
31 /// This function handles payloads that are either `&str` or `String`.
32 ///
33 /// # Arguments
34 ///
35 /// - `&dyn Any` - The payload from a object.
36 ///
37 /// # Returns
38 ///
39 /// - `Option<String>` - The extracted message, or None if the payload is not a string type.
40 #[inline(always)]
41 fn try_extract_panic_message(panic_payload: &dyn Any) -> Option<String> {
42 if let Some(s) = panic_payload.downcast_ref::<&str>() {
43 Some(s.to_string())
44 } else {
45 panic_payload.downcast_ref::<String>().cloned()
46 }
47 }
48
49 /// Creates a `PanicData` instance from a `tokio::task::JoinError`.
50 ///
51 /// This is used to handle panics that occur within spawned asynchronous tasks,
52 /// extracting the panic message from the `JoinError`.
53 ///
54 /// # Arguments
55 ///
56 /// - `JoinError` - The error from a panicked task.
57 ///
58 /// # Returns
59 ///
60 /// - `PanicData` - A new panic instance with message from error.
61 pub fn from_join_error(join_error: JoinError) -> Self {
62 let default_message: String = join_error.to_string();
63 let mut message: Option<String> = if let Ok(panic_join_error) = join_error.try_into_panic()
64 {
65 Self::try_extract_panic_message(&panic_join_error)
66 } else {
67 None
68 };
69 if (message.is_none() || message.clone().unwrap_or_default().is_empty())
70 && !default_message.is_empty()
71 {
72 message = Some(default_message);
73 }
74 let panic: PanicData = PanicData::new(message, None, None);
75 panic
76 }
77}