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