Writing Rust Futures in 2019
Some examples of Futures I wish I'd found before (or wasn't able to find). These examples are almost just copy and paste from various places, so the resources are there, I just needed to figure out the bigger picture.
All examples use the Tokio runtime.
All examples use the futures crate v0.1.2x.
Code is available on Github.
Update: the part about Hyper has been moved to its own article.
§ Brief prologue: what is a Future
A Future is simply a plain Rust function which return type is a Future. I won't go in detail of what a Future is, others can explain that better than me. The standard return type is as follows:
fn something() -> impl Future<Item = (), Error = ()>
    // do something...
}
That reads as: return a Future which contains an Item or an Error.
Item can also be an integer:
fn something() -> impl Future<Item = i32, Error = ()>
    // do something...
}
Or the Error can be something more useful:
fn something() -> impl Future<Item = i32, Error = String>
    // do something...
}
or a custom type:
struct MyStruct {
    name: String,
    age: i32
}
fn something() -> impl Future<Item = MyStruct, Error = ()> {
    // do something...
}
Now let's see some basic examples. We'll be just scratching the surface of what can be accomplished with Futures.
§ Your first Future
fn my_fut() -> impl Future<Item = (), Error = ()> {
    println!("running my_fut");
    future::ok(())
}
fn main() {
    // the Future returns a unit
    tokio::run(my_fut());
}
Console output is:
$ cargo run
running my_fut
§ A Future that returns an integer
fn my_fut() -> impl Future<Item = i32, Error = ()> {
    println!("running my_fut");
    future::ok(42)
}
fn main() {
    // run the Future, forget about it
    tokio::run(my_fut());
    // run the future, inspect the return value
    let f = my_fut().map(|x| {
        println!("future resolved: {}", x);
        ()
    });
    tokio::run(f);
}
Console output is:
$ cargo run
running my_fut
future resolved: 42
§ A Future that sleeps for 1 second
fn svc_wait(t: u64) -> impl Future<Item = (), Error = ()> {
    println!("[start] waiting...");
    let when = Instant::now() + Duration::from_millis(t);
    Delay::new(when)
        .map_err(|e| panic!("timer failed; err={:?}", e))
        .and_then(|_| {
            println!("[end] waiting");
            Ok(())
        })
}
fn main() {
    // Future returns a ()
    let f = svc_wait(1000).map(|_| {
        println!("future finished");
        ()
    });
    tokio::run(f);
}
The console output will be:
[start] waiting...
... 1 sec ...
[end] waiting
future finished
It's important to note that if you want to simulate a long-lasting async task you should not use std::thread::sleep, you'll end up blocking the whole Tokio runtime thread!
§ (TODO) Manually implementing a Future
Futures are cool because you "fire&forget" them. But what if we want to track their progress?
We need to manually implement the .poll() to be able to observe the various stages.
I still have to figure out how this stuff work.
Here's some code pasted from elsewhere.
impl Future for Magazine {
    // here we return a single byte
    type Item = u8;
    type Error = io::Error;
    // this method is getting called from the runtime. Everytime we can read
    // a byte into the buffer, we return `Async::Ready`
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut buffer = [0;1];
        match self.0.poll_read(&mut buf) {
            Ok(Async::Ready(_num_bytes_read)) => Ok(Async::Ready(buffer[0])),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e)
        }
    }
}
struct AwakeFuture {
    name: String,
    count: i32,
}
impl AwakeFuture {
    fn new(name: String) -> AwakeFuture {
        AwakeFuture { name, count: 0 }
    }
}
impl Future for AwakeFuture {
    type Item = i32;
    type Error = ();
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.count {
            3 => {
                eprintln!(
                    "[{}] Future {} has finished counting",
                    self.count, self.name
                );
                Ok(Async::Ready(self.count))
            }
            _ => {
                eprintln!("[{}] Future {} is not yet ready ...", self.count, self.name);
                // FIXME: I'm afraid this won't ever work
                self.count += 1;
                Ok(Async::NotReady)
            }
        }
    }
}
fn main() {
    let awake_future = AwakeFuture::new(String::from("awake-future"));
    tokio::run(awake_future.map(|x| {
        eprint!("x={:?}", x);
        ()
    }));
}
§ One more thing: running more Futures together
§ Credits
Thanks to my friends of Rust Rome for the incredbile support and for answering all my questions.
Thanks to Bastian Gruber for his wonderful tutorials: namely this and this.
And don't forget the Hyper examples.
 
     
     
    