use std::future::Future;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
use std::task::Waker;
use inplace_box::InplaceBox;
#[allow(clippy::incompatible_msrv)]
fn block_on<F: Future>(mut fut: F) -> F::Output {
let mut cx = Context::from_waker(Waker::noop());
let mut pinned = unsafe { Pin::new_unchecked(&mut fut) };
loop {
match pinned.as_mut().poll(&mut cx) {
Poll::Ready(v) => return v,
Poll::Pending => {}
}
}
}
struct YieldOnce(bool);
impl Future for YieldOnce {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
if self.0 {
Poll::Ready(())
} else {
self.0 = true;
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
#[test]
fn future_mut_ref_across_await() {
let result = block_on(async {
let mut value = 1_u32;
let r: &mut u32 = &mut value;
YieldOnce(false).await;
*r += 1;
*r
});
assert_eq!(result, 2);
}
#[test]
fn inplace_box_future_mut_ref_across_await() {
let fut = InplaceBox::<dyn Future<Output = u32>, 128>::new(async {
let mut value = 1_u32;
let r: &mut u32 = &mut value;
YieldOnce(false).await;
*r += 1;
*r
});
let result = block_on(fut);
assert_eq!(result, 2);
}