| use std::any::Any; | |
| use crate::bridge::{Buffer, Decode, Encode}; | |
| /// Simplified version of panic payloads, ignoring | |
| /// types other than `&'static str` and `String`. | |
| pub enum PanicMessage { | |
| StaticStr(&'static str), | |
| String(String), | |
| Unknown, | |
| } | |
| impl From<Box<dyn Any + Send>> for PanicMessage { | |
| fn from(payload: Box<dyn Any + Send + 'static>) -> Self { | |
| if let Some(s) = payload.downcast_ref::<&'static str>() { | |
| return PanicMessage::StaticStr(s); | |
| } | |
| if let Ok(s) = payload.downcast::<String>() { | |
| return PanicMessage::String(*s); | |
| } | |
| PanicMessage::Unknown | |
| } | |
| } | |
| impl From<PanicMessage> for Box<dyn Any + Send> { | |
| fn from(val: PanicMessage) -> Self { | |
| match val { | |
| PanicMessage::StaticStr(s) => Box::new(s), | |
| PanicMessage::String(s) => Box::new(s), | |
| PanicMessage::Unknown => { | |
| struct UnknownPanicMessage; | |
| Box::new(UnknownPanicMessage) | |
| } | |
| } | |
| } | |
| } | |
| impl PanicMessage { | |
| pub fn as_str(&self) -> Option<&str> { | |
| match self { | |
| PanicMessage::StaticStr(s) => Some(s), | |
| PanicMessage::String(s) => Some(s), | |
| PanicMessage::Unknown => None, | |
| } | |
| } | |
| pub fn into_string(self) -> Option<String> { | |
| match self { | |
| PanicMessage::StaticStr(s) => Some(s.into()), | |
| PanicMessage::String(s) => Some(s), | |
| PanicMessage::Unknown => None, | |
| } | |
| } | |
| } | |
| impl<S> Encode<S> for PanicMessage { | |
| #[inline] | |
| fn encode(self, w: &mut Buffer, s: &mut S) { | |
| self.as_str().encode(w, s); | |
| } | |
| } | |
| impl<S> Decode<'_, '_, S> for PanicMessage { | |
| #[inline] | |
| fn decode(r: &mut &[u8], s: &mut S) -> Self { | |
| match Option::<String>::decode(r, s) { | |
| Some(s) => PanicMessage::String(s), | |
| None => PanicMessage::Unknown, | |
| } | |
| } | |
| } |