extern crate std;
use std::thread::LocalKey;
pub struct ExceptionContext<E: 'static> {
inner: &'static LocalKey<crate::unsync::ExceptionContext<E>>,
}
impl<E: 'static> ExceptionContext<E> {
pub const fn new(
local: &'static LocalKey<crate::unsync::ExceptionContext<E>>,
) -> ExceptionContext<E> {
Self { inner: local }
}
pub async fn throw(&self, e: E) -> ! {
self.inner.with(|ctx| {
crate::unsync::set_exception(ctx, e);
});
core::future::pending().await
}
pub fn catch<Fu: core::future::Future>(&self, f: Fu) -> Catching<E, Fu> {
Catching {
ctx: self.inner,
future: f,
}
}
}
pin_project_lite::pin_project! {
pub struct Catching<E: 'static, F> {
ctx: &'static LocalKey<crate::unsync::ExceptionContext<E>>,
#[pin]
future: F,
}
}
impl<E: 'static, F: core::future::Future> core::future::Future for Catching<E, F> {
type Output = Result<F::Output, E>;
fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
let this = self.project();
this.ctx
.with(|ctx| crate::unsync::poll_catching(ctx, this.future, cx))
}
}