Skip to main content

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}