dioxus_core/
render_error.rs1use std::{
2 fmt::{Debug, Display},
3 sync::Arc,
4};
5
6use crate::innerlude::*;
7
8#[derive(Debug, Clone, PartialEq)]
10pub enum RenderError {
11 Error(CapturedError),
16
17 Suspended(SuspendedFuture),
19}
20
21impl Default for RenderError {
22 fn default() -> Self {
23 struct RenderAbortedEarly;
24 impl Debug for RenderAbortedEarly {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 f.write_str("Render aborted early")
27 }
28 }
29 impl Display for RenderAbortedEarly {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 f.write_str("Render aborted early")
32 }
33 }
34 impl std::error::Error for RenderAbortedEarly {}
35 Self::Error(CapturedError(Arc::new(RenderAbortedEarly.into())))
36 }
37}
38
39impl Display for RenderError {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 match self {
42 Self::Error(e) => write!(f, "Render aborted: {e}"),
43 Self::Suspended(e) => write!(f, "Component suspended: {e:?}"),
44 }
45 }
46}
47
48impl From<CapturedError> for RenderError {
49 fn from(e: CapturedError) -> Self {
50 Self::Error(e)
51 }
52}
53
54impl<E: Into<anyhow::Error>> From<E> for RenderError {
55 fn from(e: E) -> Self {
56 let anyhow_err = e.into();
57
58 if let Some(suspended) = anyhow_err.downcast_ref::<SuspendedFuture>() {
59 return Self::Suspended(suspended.clone());
60 }
61
62 if let Some(render_error) = anyhow_err.downcast_ref::<RenderError>() {
63 return render_error.clone();
64 }
65
66 Self::Error(CapturedError(Arc::new(anyhow_err)))
67 }
68}
69
70#[derive(Debug, Clone)]
72pub struct CapturedError(pub Arc<anyhow::Error>);
73
74impl CapturedError {
75 pub fn from_display(t: impl Display) -> Self {
77 Self(Arc::new(anyhow::anyhow!(t.to_string())))
78 }
79
80 pub fn new<E>(error: E) -> Self
82 where
83 E: std::error::Error + Send + Sync + 'static,
84 {
85 anyhow::Error::new(error).into()
86 }
87
88 pub fn msg<M>(t: M) -> Self
90 where
91 M: Display + Debug + Send + Sync + 'static,
92 {
93 anyhow::Error::msg(t).into()
94 }
95
96 pub fn from_boxed(boxed_error: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
98 anyhow::Error::from_boxed(boxed_error).into()
99 }
100
101 pub fn _strong_count(&self) -> usize {
103 std::sync::Arc::strong_count(&self.0)
104 }
105
106 pub fn into_inner(self) -> Option<anyhow::Error> {
108 Arc::try_unwrap(self.0).ok()
109 }
110}
111
112#[cfg(feature = "serialize")]
113impl serde::Serialize for CapturedError {
114 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
115 where
116 S: serde::Serializer,
117 {
118 serializer.serialize_str(&self.0.to_string())
119 }
120}
121
122#[cfg(feature = "serialize")]
123impl<'de> serde::Deserialize<'de> for CapturedError {
124 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
125 where
126 D: serde::Deserializer<'de>,
127 {
128 let s = String::deserialize(deserializer)?;
129 Ok(Self::from_display(s))
130 }
131}
132
133impl std::ops::Deref for CapturedError {
134 type Target = anyhow::Error;
135
136 fn deref(&self) -> &Self::Target {
137 &self.0
138 }
139}
140
141impl<E: Into<anyhow::Error>> From<E> for CapturedError {
142 fn from(e: E) -> Self {
143 Self(Arc::new(e.into()))
144 }
145}
146
147impl std::fmt::Display for CapturedError {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 std::fmt::Display::fmt(&*self.0, f)
150 }
151}
152
153impl PartialEq for CapturedError {
154 fn eq(&self, other: &Self) -> bool {
155 Arc::ptr_eq(&self.0, &other.0)
156 }
157}
158
159#[test]
160fn assert_errs_can_downcast() {
161 fn assert_is_stderr_like<T: Send + Sync + Display + Debug>() {}
162
163 assert_is_stderr_like::<RenderError>();
164 assert_is_stderr_like::<CapturedError>();
165}