1 //! Zero-cost Futures in Rust
2 //!
3 //! This library is an implementation of futures in Rust which aims to provide
4 //! a robust implementation of handling asynchronous computations, ergonomic
5 //! composition and usage, and zero-cost abstractions over what would otherwise
6 //! be written by hand.
7 //!
8 //! Futures are a concept for an object which is a proxy for another value that
9 //! may not be ready yet. For example issuing an HTTP request may return a
10 //! future for the HTTP response, as it probably hasn't arrived yet. With an
11 //! object representing a value that will eventually be available, futures allow
12 //! for powerful composition of tasks through basic combinators that can perform
13 //! operations like chaining computations, changing the types of futures, or
14 //! waiting for two futures to complete at the same time.
15 //!
16 //! You can find extensive tutorials and documentations at [https://tokio.rs]
17 //! for both this crate (asynchronous programming in general) as well as the
18 //! Tokio stack to perform async I/O with.
19 //!
20 //! [https://tokio.rs]: https://tokio.rs
21 //!
22 //! ## Installation
23 //!
24 //! Add this to your `Cargo.toml`:
25 //!
26 //! ```toml
27 //! [dependencies]
28 //! futures = "0.1"
29 //! ```
30 //!
31 //! ## Examples
32 //!
33 //! Let's take a look at a few examples of how futures might be used:
34 //!
35 //! ```
36 //! extern crate futures;
37 //!
38 //! use std::io;
39 //! use std::time::Duration;
40 //! use futures::prelude::*;
41 //! use futures::future::Map;
42 //!
43 //! // A future is actually a trait implementation, so we can generically take a
44 //! // future of any integer and return back a future that will resolve to that
45 //! // value plus 10 more.
46 //! //
47 //! // Note here that like iterators, we're returning the `Map` combinator in
48 //! // the futures crate, not a boxed abstraction. This is a zero-cost
49 //! // construction of a future.
50 //! fn add_ten<F>(future: F) -> Map<F, fn(i32) -> i32>
51 //!     where F: Future<Item=i32>,
52 //! {
53 //!     fn add(a: i32) -> i32 { a + 10 }
54 //!     future.map(add)
55 //! }
56 //!
57 //! // Not only can we modify one future, but we can even compose them together!
58 //! // Here we have a function which takes two futures as input, and returns a
59 //! // future that will calculate the sum of their two values.
60 //! //
61 //! // Above we saw a direct return value of the `Map` combinator, but
62 //! // performance isn't always critical and sometimes it's more ergonomic to
63 //! // return a trait object like we do here. Note though that there's only one
64 //! // allocation here, not any for the intermediate futures.
65 //! fn add<'a, A, B>(a: A, b: B) -> Box<Future<Item=i32, Error=A::Error> + 'a>
66 //!     where A: Future<Item=i32> + 'a,
67 //!           B: Future<Item=i32, Error=A::Error> + 'a,
68 //! {
69 //!     Box::new(a.join(b).map(|(a, b)| a + b))
70 //! }
71 //!
72 //! // Futures also allow chaining computations together, starting another after
73 //! // the previous finishes. Here we wait for the first computation to finish,
74 //! // and then decide what to do depending on the result.
75 //! fn download_timeout(url: &str,
76 //!                     timeout_dur: Duration)
77 //!                     -> Box<Future<Item=Vec<u8>, Error=io::Error>> {
78 //!     use std::io;
79 //!     use std::net::{SocketAddr, TcpStream};
80 //!
81 //!     type IoFuture<T> = Box<Future<Item=T, Error=io::Error>>;
82 //!
83 //!     // First thing to do is we need to resolve our URL to an address. This
84 //!     // will likely perform a DNS lookup which may take some time.
85 //!     let addr = resolve(url);
86 //!
87 //!     // After we acquire the address, we next want to open up a TCP
88 //!     // connection.
89 //!     let tcp = addr.and_then(|addr| connect(&addr));
90 //!
91 //!     // After the TCP connection is established and ready to go, we're off to
92 //!     // the races!
93 //!     let data = tcp.and_then(|conn| download(conn));
94 //!
95 //!     // That all might take awhile, though, so let's not wait too long for it
96 //!     // to all come back. The `select` combinator here returns a future which
97 //!     // resolves to the first value that's ready plus the next future.
98 //!     //
99 //!     // Note we can also use the `then` combinator which is similar to
100 //!     // `and_then` above except that it receives the result of the
101 //!     // computation, not just the successful value.
102 //!     //
103 //!     // Again note that all the above calls to `and_then` and the below calls
104 //!     // to `map` and such require no allocations. We only ever allocate once
105 //!     // we hit the `Box::new()` call at the end here, which means we've built
106 //!     // up a relatively involved computation with only one box, and even that
107 //!     // was optional!
108 //!
109 //!     let data = data.map(Ok);
110 //!     let timeout = timeout(timeout_dur).map(Err);
111 //!
112 //!     let ret = data.select(timeout).then(|result| {
113 //!         match result {
114 //!             // One future succeeded, and it was the one which was
115 //!             // downloading data from the connection.
116 //!             Ok((Ok(data), _other_future)) => Ok(data),
117 //!
118 //!             // The timeout fired, and otherwise no error was found, so
119 //!             // we translate this to an error.
120 //!             Ok((Err(_timeout), _other_future)) => {
121 //!                 Err(io::Error::new(io::ErrorKind::Other, "timeout"))
122 //!             }
123 //!
124 //!             // A normal I/O error happened, so we pass that on through.
125 //!             Err((e, _other_future)) => Err(e),
126 //!         }
127 //!     });
128 //!     return Box::new(ret);
129 //!
130 //!     fn resolve(url: &str) -> IoFuture<SocketAddr> {
131 //!         // ...
132 //! #       panic!("unimplemented");
133 //!     }
134 //!
135 //!     fn connect(hostname: &SocketAddr) -> IoFuture<TcpStream> {
136 //!         // ...
137 //! #       panic!("unimplemented");
138 //!     }
139 //!
140 //!     fn download(stream: TcpStream) -> IoFuture<Vec<u8>> {
141 //!         // ...
142 //! #       panic!("unimplemented");
143 //!     }
144 //!
145 //!     fn timeout(stream: Duration) -> IoFuture<()> {
146 //!         // ...
147 //! #       panic!("unimplemented");
148 //!     }
149 //! }
150 //! # fn main() {}
151 //! ```
152 //!
153 //! Some more information can also be found in the [README] for now, but
154 //! otherwise feel free to jump in to the docs below!
155 //!
156 //! [README]: https://github.com/rust-lang-nursery/futures-rs#futures-rs
157 
158 #![no_std]
159 #![deny(missing_docs, missing_debug_implementations)]
160 #![doc(html_root_url = "https://docs.rs/futures/0.1")]
161 
162 #[macro_use]
163 #[cfg(feature = "use_std")]
164 extern crate std;
165 
166 macro_rules! if_std {
167     ($($i:item)*) => ($(
168         #[cfg(feature = "use_std")]
169         $i
170     )*)
171 }
172 
173 #[macro_use]
174 mod poll;
175 pub use poll::{Poll, Async, AsyncSink, StartSend};
176 
177 pub mod future;
178 pub use future::{Future, IntoFuture};
179 
180 pub mod stream;
181 pub use stream::Stream;
182 
183 pub mod sink;
184 pub use sink::Sink;
185 
186 #[deprecated(since = "0.1.4", note = "import through the future module instead")]
187 #[cfg(feature = "with-deprecated")]
188 #[doc(hidden)]
189 pub use future::{done, empty, failed, finished, lazy};
190 
191 #[doc(hidden)]
192 #[cfg(feature = "with-deprecated")]
193 #[deprecated(since = "0.1.4", note = "import through the future module instead")]
194 pub use future::{
195     Done, Empty, Failed, Finished, Lazy, AndThen, Flatten, FlattenStream, Fuse, IntoStream,
196     Join, Join3, Join4, Join5, Map, MapErr, OrElse, Select,
197     SelectNext, Then
198 };
199 
200 #[cfg(feature = "use_std")]
201 mod lock;
202 mod task_impl;
203 
204 mod resultstream;
205 
206 pub mod task;
207 pub mod executor;
208 #[cfg(feature = "use_std")]
209 pub mod sync;
210 #[cfg(feature = "use_std")]
211 pub mod unsync;
212 
213 
214 if_std! {
215     #[doc(hidden)]
216     #[deprecated(since = "0.1.4", note = "use sync::oneshot::channel instead")]
217     #[cfg(feature = "with-deprecated")]
218     pub use sync::oneshot::channel as oneshot;
219 
220     #[doc(hidden)]
221     #[deprecated(since = "0.1.4", note = "use sync::oneshot::Receiver instead")]
222     #[cfg(feature = "with-deprecated")]
223     pub use sync::oneshot::Receiver as Oneshot;
224 
225     #[doc(hidden)]
226     #[deprecated(since = "0.1.4", note = "use sync::oneshot::Sender instead")]
227     #[cfg(feature = "with-deprecated")]
228     pub use sync::oneshot::Sender as Complete;
229 
230     #[doc(hidden)]
231     #[deprecated(since = "0.1.4", note = "use sync::oneshot::Canceled instead")]
232     #[cfg(feature = "with-deprecated")]
233     pub use sync::oneshot::Canceled;
234 
235     #[doc(hidden)]
236     #[deprecated(since = "0.1.4", note = "import through the future module instead")]
237     #[cfg(feature = "with-deprecated")]
238     #[allow(deprecated)]
239     pub use future::{BoxFuture, collect, select_all, select_ok};
240 
241     #[doc(hidden)]
242     #[deprecated(since = "0.1.4", note = "import through the future module instead")]
243     #[cfg(feature = "with-deprecated")]
244     pub use future::{SelectAll, SelectAllNext, Collect, SelectOk};
245 }
246 
247 /// A "prelude" for crates using the `futures` crate.
248 ///
249 /// This prelude is similar to the standard library's prelude in that you'll
250 /// almost always want to import its entire contents, but unlike the standard
251 /// library's prelude you'll have to do so manually. An example of using this is:
252 ///
253 /// ```
254 /// use futures::prelude::*;
255 /// ```
256 ///
257 /// We may add items to this over time as they become ubiquitous as well, but
258 /// otherwise this should help cut down on futures-related imports when you're
259 /// working with the `futures` crate!
260 pub mod prelude {
261     #[doc(no_inline)]
262     pub use {Future, Stream, Sink, Async, AsyncSink, Poll, StartSend};
263     #[doc(no_inline)]
264     pub use IntoFuture;
265 }
266