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