Skip to content

Instantly share code, notes, and snippets.

@cchudant
Last active May 9, 2020 15:55
Show Gist options
  • Save cchudant/c5ce721966d2bc1847a0df466d2e4391 to your computer and use it in GitHub Desktop.
Save cchudant/c5ce721966d2bc1847a0df466d2e4391 to your computer and use it in GitHub Desktop.
Async await desugar (kind of)
async fn unicorn(arg: i32) {
println!("Hi!");
do_things().await;
println!("Hi x2!");
for i in arg..5 {
let num = do_other_things().await;
println!("Future {} returned {}!", i, num);
}
}
use std::task::{Poll, Context};
use std::pin::Pin;
use std::future::Future;
use std::ops::Range;
enum UnicornFuture {
Begin { arg: i32 },
YieldPoint1 { arg: i32, doThingFuture: DoThingFuture },
YieldPoint2 { i: i32, range: Range<i32>, doOtherFuture: DoOtherFuture },
Completed
}
impl Future for UnicornFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let unpinned = Pin::into_inner(self);
loop {
return match unpinned {
UnicornFuture::Begin { arg } => {
println!("Hi!");
*unpinned = UnicornFuture::YieldPoint1 {
arg: *arg,
doThingFuture: do_things(),
};
Poll::Pending
},
UnicornFuture::YieldPoint1 { arg, doThingFuture } => {
match Pin::new(doThingFuture).poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(_) => {
println!("Hi x2!");
let range = (*arg)..5;
match range.next() {
Some(n) => {
*unpinned = UnicornFuture::YieldPoint2 {
i: n,
range,
doOtherFuture: do_other_things(),
};
continue;
},
None => {
*unpinned = UnicornFuture::Completed;
Poll::Ready(())
},
}
},
}
},
UnicornFuture::YieldPoint2 { i, range, doOtherFuture } => {
match Pin::new(doOtherFuture).poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(num) => {
println!("Future {} returned {}!", i, num);
match range.next() {
Some(n) => {
*unpinned = UnicornFuture::YieldPoint2 {
i: n,
range: *range,
doOtherFuture: do_other_things(),
};
continue;
},
None => {
*unpinned = UnicornFuture::Completed;
Poll::Ready(());
},
}
}
}
},
UnicornFuture::Completed => panic!("Poll after ready!")
}
}
}
}
fn unicorn(arg: i32) -> impl Future<Output=()> {
UnicornFuture::Begin { arg }
}
fn unicorn(arg: i32) -> impl Generator<&mut Context, Yield=(), Return=()> {
|mut cx: &mut Context| {
println!("Hi!");
let doThingsFuture = do_things();
loop {
match Pin::new(doThingsFuture).poll(cx) {
// or `match Pin::new(doThingsFuture).resume(cx)`
Poll::Pending => cx = yield,
Poll::Ready(_) => break,
}
}
println!("Hi x2!");
for i in arg..5 {
let doOtherFuture = do_other_things();
let num = loop {
match Pin::new(doOtherFuture).poll(cx) {
// or `match Pin::new(doOtherFuture).resume(cx)`
Poll::Pending => cx = yield,
Poll::Ready(num) => break num,
}
};
println!("Future {} returned {}!", i, num);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment