euv_ui/hook/error_boundary/impl.rs
1use super::*;
2
3/// Inherent implementation of [`ErrorBoundary`].
4impl ErrorBoundary {
5 /// Creates a new `ErrorBoundary` in the `Healthy`
6 /// phase.
7 pub fn new() -> Self {
8 Self {
9 phase: Signal::create(ErrorBoundaryPhase::Healthy),
10 }
11 }
12
13 /// Runs a closure and, if it panics, transitions
14 /// the boundary to `Caught` and returns `Err`.
15 ///
16 /// On success, the closure's return value is
17 /// returned wrapped in `Ok`. The closure is
18 /// wrapped in `AssertUnwindSafe` so it does not
19 /// have to satisfy `UnwindSafe`.
20 ///
21 /// # Arguments
22 ///
23 /// - `F: FnOnce() -> R + UnwindSafe` - A generic type parameter.
24 ///
25 /// # Returns
26 ///
27 /// - `Result<R, String>` - Result of the operation; an `Err` variant on failure.
28 pub fn try_with<F, R>(&self, closure: F) -> Result<R, String>
29 where
30 F: FnOnce() -> R + UnwindSafe,
31 {
32 match catch_unwind(closure) {
33 Ok(value) => Ok(value),
34 Err(payload) => {
35 let message: String = extract_message(&payload);
36 let _ = catch_unwind(AssertUnwindSafe(|| {
37 self.get_phase()
38 .set(ErrorBoundaryPhase::Caught(message.clone()));
39 }));
40 Err(message)
41 }
42 }
43 }
44
45 /// Transitions the boundary back to `Healthy`.
46 /// Useful when invalidating the cache (e.g.,
47 /// after a retry).
48 pub fn reset(&self) {
49 let _ = catch_unwind(AssertUnwindSafe(|| {
50 self.get_phase().set(ErrorBoundaryPhase::Healthy);
51 }));
52 }
53}
54
55/// Default-construction for [`ErrorBoundary`].
56impl Default for ErrorBoundary {
57 /// Constructs a default [`ErrorBoundary`] value.
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63/// Formatting / debug-printing for [`ErrorBoundary`].
64impl Display for ErrorBoundary {
65 /// Formats the [`ErrorBoundary`] via the supplied formatter.
66 ///
67 /// # Arguments
68 ///
69 /// - `&mut Formatter<'_>` - The formatter receiving the formatted output.
70 ///
71 /// # Returns
72 ///
73 /// - `FmtResult` - Result of the formatting operation.
74 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
75 write!(formatter, "ErrorBoundary({:?})", self.get_phase().get())
76 }
77}
78
79/// Equality comparison for [`ErrorBoundaryPhase`].
80impl PartialEq for ErrorBoundaryPhase {
81 /// Returns `true` when `self` and `other` are equivalent by the [`PartialEq`] contract.
82 ///
83 /// # Arguments
84 ///
85 /// - `&Self` - The other value to compare against `self`.
86 ///
87 /// # Returns
88 ///
89 /// - `bool` - `true` when `self` and `other` are equivalent by the trait contract.
90 fn eq(&self, other: &Self) -> bool {
91 match (self, other) {
92 (ErrorBoundaryPhase::Healthy, ErrorBoundaryPhase::Healthy) => true,
93 (ErrorBoundaryPhase::Caught(a), ErrorBoundaryPhase::Caught(b)) => a == b,
94 _ => false,
95 }
96 }
97}