[][src]Crate futures01

Zero-cost Futures in Rust

This library is an implementation of futures in Rust which aims to provide a robust implementation of handling asynchronous computations, ergonomic composition and usage, and zero-cost abstractions over what would otherwise be written by hand.

Futures are a concept for an object which is a proxy for another value that may not be ready yet. For example issuing an HTTP request may return a future for the HTTP response, as it probably hasn't arrived yet. With an object representing a value that will eventually be available, futures allow for powerful composition of tasks through basic combinators that can perform operations like chaining computations, changing the types of futures, or waiting for two futures to complete at the same time.

You can find extensive tutorials and documentations at https://tokio.rs for both this crate (asynchronous programming in general) as well as the Tokio stack to perform async I/O with.

Installation

Add this to your Cargo.toml:

[dependencies]
futures = "0.1"

Examples

Let's take a look at a few examples of how futures might be used:

extern crate futures;

use std::io;
use std::time::Duration;
use futures::prelude::*;
use futures::future::Map;

// A future is actually a trait implementation, so we can generically take a
// future of any integer and return back a future that will resolve to that
// value plus 10 more.
//
// Note here that like iterators, we're returning the `Map` combinator in
// the futures crate, not a boxed abstraction. This is a zero-cost
// construction of a future.
fn add_ten<F>(future: F) -> Map<F, fn(i32) -> i32>
    where F: Future<Item=i32>,
{
    fn add(a: i32) -> i32 { a + 10 }
    future.map(add)
}

// Not only can we modify one future, but we can even compose them together!
// Here we have a function which takes two futures as input, and returns a
// future that will calculate the sum of their two values.
//
// Above we saw a direct return value of the `Map` combinator, but
// performance isn't always critical and sometimes it's more ergonomic to
// return a trait object like we do here. Note though that there's only one
// allocation here, not any for the intermediate futures.
fn add<'a, A, B>(a: A, b: B) -> Box<Future<Item=i32, Error=A::Error> + 'a>
    where A: Future<Item=i32> + 'a,
          B: Future<Item=i32, Error=A::Error> + 'a,
{
    Box::new(a.join(b).map(|(a, b)| a + b))
}

// Futures also allow chaining computations together, starting another after
// the previous finishes. Here we wait for the first computation to finish,
// and then decide what to do depending on the result.
fn download_timeout(url: &str,
                    timeout_dur: Duration)
                    -> Box<Future<Item=Vec<u8>, Error=io::Error>> {
    use std::io;
    use std::net::{SocketAddr, TcpStream};

    type IoFuture<T> = Box<Future<Item=T, Error=io::Error>>;

    // First thing to do is we need to resolve our URL to an address. This
    // will likely perform a DNS lookup which may take some time.
    let addr = resolve(url);

    // After we acquire the address, we next want to open up a TCP
    // connection.
    let tcp = addr.and_then(|addr| connect(&addr));

    // After the TCP connection is established and ready to go, we're off to
    // the races!
    let data = tcp.and_then(|conn| download(conn));

    // That all might take awhile, though, so let's not wait too long for it
    // to all come back. The `select` combinator here returns a future which
    // resolves to the first value that's ready plus the next future.
    //
    // Note we can also use the `then` combinator which is similar to
    // `and_then` above except that it receives the result of the
    // computation, not just the successful value.
    //
    // Again note that all the above calls to `and_then` and the below calls
    // to `map` and such require no allocations. We only ever allocate once
    // we hit the `Box::new()` call at the end here, which means we've built
    // up a relatively involved computation with only one box, and even that
    // was optional!

    let data = data.map(Ok);
    let timeout = timeout(timeout_dur).map(Err);

    let ret = data.select(timeout).then(|result| {
        match result {
            // One future succeeded, and it was the one which was
            // downloading data from the connection.
            Ok((Ok(data), _other_future)) => Ok(data),

            // The timeout fired, and otherwise no error was found, so
            // we translate this to an error.
            Ok((Err(_timeout), _other_future)) => {
                Err(io::Error::new(io::ErrorKind::Other, "timeout"))
            }

            // A normal I/O error happened, so we pass that on through.
            Err((e, _other_future)) => Err(e),
        }
    });
    return Box::new(ret);

    fn resolve(url: &str) -> IoFuture<SocketAddr> {
        // ...
    }

    fn connect(hostname: &SocketAddr) -> IoFuture<TcpStream> {
        // ...
    }

    fn download(stream: TcpStream) -> IoFuture<Vec<u8>> {
        // ...
    }

    fn timeout(stream: Duration) -> IoFuture<()> {
        // ...
    }
}

Some more information can also be found in the README for now, but otherwise feel free to jump in to the docs below!

Modules

executor

Executors

future

Futures

prelude

A "prelude" for crates using the futures crate.

sink

Asynchronous sinks

stream

Asynchronous streams

sync

Future-aware synchronization

task

Tasks used to drive a future computation

unsync

Future-aware single-threaded synchronization

Macros

task_local

A macro to create a static of type LocalKey

try_ready

A macro for extracting the successful type of a Poll<T, E>.

Structs

AndThen

Future for the and_then combinator, chaining a computation onto the end of another future which completes successfully.

Canceled

Error returned from a Receiver<T> whenever the corresponding Sender<T> is dropped.

Collect

A future which takes a list of futures and resolves with a vector of the completed values.

Complete

Represents the completion half of a oneshot through which the result of a computation is signaled.

Done

A future representing a value that is immediately ready.

Empty

A future which is never resolved.

Failed

A future representing a value that is immediately ready.

Finished

A future representing a value that is immediately ready.

Flatten

Future for the flatten combinator, flattening a future-of-a-future to get just the result of the final future.

FlattenStream

Future for the flatten_stream combinator, flattening a future-of-a-stream to get just the result of the final stream as a stream.

Fuse

A future which "fuses" a future once it's been resolved.

IntoStream

Future that forwards one element from the underlying future (whether it is success of error) and emits EOF after that.

Join

Future for the join combinator, waiting for two futures to complete.

Join3

Future for the join3 combinator, waiting for three futures to complete.

Join4

Future for the join4 combinator, waiting for four futures to complete.

Join5

Future for the join5 combinator, waiting for five futures to complete.

Lazy

A future which defers creation of the actual future until a callback is scheduled.

Map

Future for the map combinator, changing the type of a future.

MapErr

Future for the map_err combinator, changing the error type of a future.

Oneshot

A future representing the completion of a computation happening elsewhere in memory.

OrElse

Future for the or_else combinator, chaining a computation onto the end of a future which fails with an error.

Select

Future for the select combinator, waiting for one of two futures to complete.

SelectAll

Future for the select_all combinator, waiting for one of any of a list of futures to complete.

SelectNext

Future yielded as the second result in a Select future.

SelectOk

Future for the select_ok combinator, waiting for one of any of a list of futures to successfully complete. Unlike select_all, this future ignores all but the last error, if there are any.

Then

Future for the then combinator, chaining computations on the end of another future regardless of its outcome.

Enums

Async

Return type of future, indicating whether a value is ready or not.

AsyncSink

The result of an asynchronous attempt to send a value to a sink.

Traits

Future

Trait for types which are a placeholder of a value that may become available at some later point in time.

IntoFuture

Class of types which can be converted into a future.

Sink

A Sink is a value into which other values can be sent, asynchronously.

Stream

A stream of values, not all of which may have been produced yet.

Functions

collect

Creates a future which represents a collection of the results of the futures given.

done

Creates a new "leaf future" which will resolve with the given result.

empty

Creates a future which never resolves, representing a computation that never finishes.

failed

Creates a "leaf future" from an immediate value of a failed computation.

finished

Creates a "leaf future" from an immediate value of a finished and successful computation.

lazy

Creates a new future which will eventually be the same as the one created by the closure provided.

oneshot

Creates a new futures-aware, one-shot channel.

select_all

Creates a new future which will select over a list of futures.

select_ok

Creates a new future which will select the first successful future over a list of futures.

Type Definitions

Poll

Return type of the Future::poll method, indicates whether a future's value is ready or not.

StartSend

Return type of the Sink::start_send method, indicating the outcome of a send attempt. See AsyncSink for more details.