Skip to main content

ferroui_reactiveui/
unhandled_error_exception.rs

1//! `UnhandledErrorException` (`ReactiveUI.Core/UnhandledErrorException.cs`).
2
3use std::error::Error;
4use std::fmt;
5
6/// The error of a pipeline that broke because nothing handled its error
7/// (`UnhandledErrorException`): what [`RxState::default_exception_handler`](crate::RxState::default_exception_handler)
8/// panics with when an object implementing
9/// [`IHandleObservableErrors`](crate::IHandleObservableErrors) errors and nothing subscribes to
10/// its `thrown_exceptions`.
11///
12/// Deviation (DEVIATIONS.md, ReactiveUI): the inner exception is kept as its message. The error is
13/// the payload of a panic (`std::panic::panic_any`), which has to be `Send`, and the errors of the
14/// reactive libraries (`Rc<dyn Error>`) are not.
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct UnhandledErrorException {
17    message: String,
18    inner_exception: Option<String>,
19}
20
21impl Default for UnhandledErrorException {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl UnhandledErrorException {
28    /// The exception with the default message of .NET (`UnhandledErrorException()`).
29    pub fn new() -> Self {
30        Self { message: "Exception of type 'ReactiveUI.UnhandledErrorException' was thrown.".to_owned(), inner_exception: None }
31    }
32
33    /// The exception with `message` (`UnhandledErrorException(string)`).
34    pub fn with_message(message: impl Into<String>) -> Self {
35        Self { message: message.into(), inner_exception: None }
36    }
37
38    /// The exception with `message`, caused by `inner_exception`
39    /// (`UnhandledErrorException(string, Exception)`).
40    pub fn with_inner(message: impl Into<String>, inner_exception: &dyn Error) -> Self {
41        Self { message: message.into(), inner_exception: Some(inner_exception.to_string()) }
42    }
43
44    /// The message (`Message`).
45    pub fn message(&self) -> &str {
46        &self.message
47    }
48
49    /// The message of the error that caused this one (`InnerException.Message`).
50    pub fn inner_exception(&self) -> Option<&str> {
51        self.inner_exception.as_deref()
52    }
53}
54
55impl fmt::Display for UnhandledErrorException {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        match &self.inner_exception {
58            Some(inner) => write!(f, "{} ({inner})", self.message),
59            None => f.write_str(&self.message),
60        }
61    }
62}
63
64impl Error for UnhandledErrorException {}