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 #![allow(bare_trait_objects, unknown_lints)] 161 #![doc(html_root_url = "https://docs.rs/futures/0.1")] 162 163 #[macro_use] 164 #[cfg(feature = "use_std")] 165 extern crate std; 166 167 macro_rules! if_std { 168 ($($i:item)*) => ($( 169 #[cfg(feature = "use_std")] 170 $i 171 )*) 172 } 173 174 #[macro_use] 175 mod poll; 176 pub use poll::{Poll, Async, AsyncSink, StartSend}; 177 178 pub mod future; 179 pub use future::{Future, IntoFuture}; 180 181 pub mod stream; 182 pub use stream::Stream; 183 184 pub mod sink; 185 pub use sink::Sink; 186 187 #[deprecated(since = "0.1.4", note = "import through the future module instead")] 188 #[cfg(feature = "with-deprecated")] 189 #[doc(hidden)] 190 pub use future::{done, empty, failed, finished, lazy}; 191 192 #[doc(hidden)] 193 #[cfg(feature = "with-deprecated")] 194 #[deprecated(since = "0.1.4", note = "import through the future module instead")] 195 pub use future::{ 196 Done, Empty, Failed, Finished, Lazy, AndThen, Flatten, FlattenStream, Fuse, IntoStream, 197 Join, Join3, Join4, Join5, Map, MapErr, OrElse, Select, 198 SelectNext, Then 199 }; 200 201 #[cfg(feature = "use_std")] 202 mod lock; 203 mod task_impl; 204 205 mod resultstream; 206 207 pub mod task; 208 pub mod executor; 209 #[cfg(feature = "use_std")] 210 pub mod sync; 211 #[cfg(feature = "use_std")] 212 pub mod unsync; 213 214 215 if_std! { 216 #[doc(hidden)] 217 #[deprecated(since = "0.1.4", note = "use sync::oneshot::channel instead")] 218 #[cfg(feature = "with-deprecated")] 219 pub use sync::oneshot::channel as oneshot; 220 221 #[doc(hidden)] 222 #[deprecated(since = "0.1.4", note = "use sync::oneshot::Receiver instead")] 223 #[cfg(feature = "with-deprecated")] 224 pub use sync::oneshot::Receiver as Oneshot; 225 226 #[doc(hidden)] 227 #[deprecated(since = "0.1.4", note = "use sync::oneshot::Sender instead")] 228 #[cfg(feature = "with-deprecated")] 229 pub use sync::oneshot::Sender as Complete; 230 231 #[doc(hidden)] 232 #[deprecated(since = "0.1.4", note = "use sync::oneshot::Canceled instead")] 233 #[cfg(feature = "with-deprecated")] 234 pub use sync::oneshot::Canceled; 235 236 #[doc(hidden)] 237 #[deprecated(since = "0.1.4", note = "import through the future module instead")] 238 #[cfg(feature = "with-deprecated")] 239 #[allow(deprecated)] 240 pub use future::{BoxFuture, collect, select_all, select_ok}; 241 242 #[doc(hidden)] 243 #[deprecated(since = "0.1.4", note = "import through the future module instead")] 244 #[cfg(feature = "with-deprecated")] 245 pub use future::{SelectAll, SelectAllNext, Collect, SelectOk}; 246 } 247 248 /// A "prelude" for crates using the `futures` crate. 249 /// 250 /// This prelude is similar to the standard library's prelude in that you'll 251 /// almost always want to import its entire contents, but unlike the standard 252 /// library's prelude you'll have to do so manually. An example of using this is: 253 /// 254 /// ``` 255 /// use futures::prelude::*; 256 /// ``` 257 /// 258 /// We may add items to this over time as they become ubiquitous as well, but 259 /// otherwise this should help cut down on futures-related imports when you're 260 /// working with the `futures` crate! 261 pub mod prelude { 262 #[doc(no_inline)] 263 pub use {Future, Stream, Sink, Async, AsyncSink, Poll, StartSend}; 264 #[doc(no_inline)] 265 pub use IntoFuture; 266 } 267