idb 0.6.5

A futures based crate for interacting with IndexedDB on browsers using webassembly
Documentation
macro_rules! impl_database_request_future {
    ($type: ident, $base_request: ty, $return_type: ty, $doc: expr) => {
        #[cfg_attr(any(docsrs, feature = "doc"), doc(cfg(feature = "futures")))]
        #[doc = $doc]
        pub struct $type {
            inner: $base_request,
            success_receiver: tokio::sync::oneshot::Receiver<Result<$return_type, crate::Error>>,
            error_receiver: tokio::sync::oneshot::Receiver<crate::Error>,
        }

        impl std::future::Future for $type {
            type Output = Result<$return_type, crate::Error>;

            fn poll(
                self: std::pin::Pin<&mut Self>,
                cx: &mut std::task::Context<'_>,
            ) -> std::task::Poll<Self::Output> {
                let this = self.get_mut();

                if let std::task::Poll::Ready(err) =
                    std::pin::Pin::new(&mut this.error_receiver).poll(cx)
                {
                    return match err {
                        Ok(err) => std::task::Poll::Ready(Err(err)),
                        Err(_) => {
                            std::task::Poll::Ready(Err(crate::Error::OneshotChannelReceiveError))
                        }
                    };
                }

                if let std::task::Poll::Ready(result) =
                    std::pin::Pin::new(&mut this.success_receiver).poll(cx)
                {
                    return match result {
                        Ok(result) => std::task::Poll::Ready(result),
                        Err(_) => {
                            std::task::Poll::Ready(Err(crate::Error::OneshotChannelReceiveError))
                        }
                    };
                }

                std::task::Poll::Pending
            }
        }

        impl Drop for $type {
            fn drop(&mut self) {
                self.inner.forget_callbacks();
            }
        }

        #[cfg_attr(any(docsrs, feature = "doc"), doc(cfg(feature = "futures")))]
        impl std::future::IntoFuture for $base_request {
            type Output = <Self::IntoFuture as std::future::Future>::Output;

            type IntoFuture = $type;

            fn into_future(mut self) -> Self::IntoFuture {
                let (error_sender, error_receiver) = tokio::sync::oneshot::channel();
                let (success_sender, success_receiver) = tokio::sync::oneshot::channel();

                crate::Request::on_error(&mut self, move |event| {
                    let result = error_callback(event.into());
                    let _ = error_sender.send(result);
                });

                crate::Request::on_success(&mut self, move |event| {
                    let result = success_callback(event.into());
                    let _ = success_sender.send(result);
                });

                $type {
                    inner: self,
                    success_receiver,
                    error_receiver,
                }
            }
        }

        fn error_callback(event: web_sys::Event) -> crate::Error {
            error_callback_inner(event).unwrap_err()
        }

        fn error_callback_inner(event: web_sys::Event) -> Result<(), crate::Error> {
            let target = event
                .target()
                .ok_or_else(|| crate::Error::EventTargetNotFound)?;
            let request = <$base_request>::try_from(target)?;

            let error = crate::Request::error(&request)?;

            match error {
                None => Err(crate::Error::DomExceptionNotFound),
                Some(error) => Err(crate::Error::DomException(error)),
            }
        }
    };
}