feat: expand error boundary concept

This commit is contained in:
Jonathan Kelley committed 2022-12-23 23:59:10 -05:00
1 parent 6b41c9d193
commit 85f6ea0545
3 files changed
+92 -9

No files matched your search

+69 -8
View File
@@ -67,7 +67,7 @@ impl ErrorBoundary {
/// })
/// }
/// ```
pub trait Throw {
pub trait Throw<S = ()>: Sized {
/// The value that will be returned in if the given value is `Ok`.
type Out;
@@ -94,6 +94,34 @@ pub trait Throw {
/// }
/// ```
fn throw(self, cx: &ScopeState) -> Option<Self::Out>;
/// Returns an option that evalutes to None if there is an error, injecting the error to the nearest error boundary.
///
/// If the value is `Ok`, then throw returns the value, not aborting the rendering preocess.
///
/// The call stack is saved for this component and provided to the error boundary
///
///
/// Note that you can also manually throw errors using the throw method on `ScopeState` directly,
/// which is what this trait shells out to.
///
///
/// ```rust, ignore
///
/// #[inline_props]
/// fn app(cx: Scope, count: String) -> Element {
/// let id: i32 = count.parse().throw(cx)?;
///
/// cx.render(rsx! {
/// div { "Count {}" }
/// })
/// }
/// ```
fn throw_with<D: Debug + 'static>(
self,
cx: &ScopeState,
e: impl FnOnce() -> D,
) -> Option<Self::Out>;
}
/// We call clone on any errors that can be owned out of a reference
@@ -109,6 +137,20 @@ impl<'a, T, O: Debug + 'static, E: ToOwned<Owned = O>> Throw for &'a Result<T, E
}
}
}
fn throw_with<D: Debug + 'static>(
self,
cx: &ScopeState,
err: impl FnOnce() -> D,
) -> Option<Self::Out> {
match self {
Ok(t) => Some(t),
Err(_e) => {
cx.throw(err());
None
}
}
}
}
/// Or just throw errors we know about
@@ -124,6 +166,17 @@ impl<T, E: Debug + 'static> Throw for Result<T, E> {
}
}
}
fn throw_with<D: Debug + 'static>(
self,
cx: &ScopeState,
error: impl FnOnce() -> D,
) -> Option<Self::Out> {
self.ok().or_else(|| {
cx.throw(error());
None
})
}
}
/// Or just throw errors we know about
@@ -131,12 +184,20 @@ impl<T> Throw for Option<T> {
type Out = T;
fn throw(self, cx: &ScopeState) -> Option<T> {
match self {
Some(t) => Some(t),
None => {
cx.throw("None error.");
None
}
}
self.or_else(|| {
cx.throw("None error.");
None
})
}
fn throw_with<D: Debug + 'static>(
self,
cx: &ScopeState,
error: impl FnOnce() -> D,
) -> Option<Self::Out> {
self.or_else(|| {
cx.throw(error());
None
})
}
}