Skip to content

Instantly share code, notes, and snippets.

@lewsmith
Last active July 5, 2024 16:51
Show Gist options
  • Select an option

  • Save lewsmith/e08e5266d816d6bdc4fa70638c918953 to your computer and use it in GitHub Desktop.

Select an option

Save lewsmith/e08e5266d816d6bdc4fa70638c918953 to your computer and use it in GitHub Desktop.
Rust `await` coverage temporary fix
/// This is a temporary fix for a bug in coverage reports where awaits show as not covered.
///
/// The idea is that once the bug is fixed, you can easily remove all `.fix_cov()` calls and imports,
/// delete the `fix_coverage.rs` and eveything works as it previouslt did.
///
/// To use it just simply import the `FixCov` trait and add `.fix_cov` to any future, before the `.await`.
///
/// # Example
/// ```
/// use FixCov;
///
/// let users = repo.get_users().await; // <-- Not covered 😭
/// let users = repo.get_users().fix_cov().await; // <-- Covered 🎉
/// ```
///
use std::pin::Pin;
use std::task::{Context, Poll};
use futures_util::Future;
pin_project_lite::pin_project! {
pub struct AlwaysYeild<F> {
yeilded: bool,
#[pin]
inner: F,
}
}
pub trait FixCov {
fn fix_cov(self) -> AlwaysYeild<Self>
where
Self: Sized,
Self: Future,
{
AlwaysYeild::new(self)
}
}
impl<F, T> FixCov for F where F: Future<Output = T> {}
impl<F> AlwaysYeild<F> {
pub fn new(f: F) -> Self {
Self {
yeilded: false,
inner: f,
}
}
}
impl<F> Future for AlwaysYeild<F>
where
F: Future,
{
type Output = F::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let zelf = self.project();
if *zelf.yeilded {
zelf.inner.poll(cx)
} else {
*zelf.yeilded = true;
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment