trpl/lib.rs
1//! A support crate for [_The Rust Programming Language_][trpl].
2//!
3//! [trpl]: https://doc.rust-lang.org/book
4//!
5//! This crate mostly just re-exports items from *other* crates. It exists for
6//! two main reasons:
7//!
8//! 1. So that as you read along in _The Rust Programming Language_, you can
9//! add just one dependency, rather than however many we end up with, and
10//! likewise use only one set of imports.
11//!
12//! 2. So that we can more easily guarantee it keeps building and working. Since
13//! we control the contents of this crate and when it changes, readers will
14//! never be broken by upstream changes, e.g. if Tokio does a breaking 2.0
15//! release at some point.
16
17// For direct use within the `trpl` crate, *not* re-exported.
18use std::{future::Future, pin::pin};
19
20use futures::future;
21
22// Re-exports, to be used like `trpl::join`.
23pub use futures::{
24 future::{Either, join, join_all, join3},
25 join,
26};
27pub use tokio::{
28 fs::read_to_string,
29 runtime::Runtime,
30 // We use the `unbounded` variants because they most closely match the APIs
31 // from `std::sync::mpsc::channel`. Tokio's API choices are interesting:
32 //
33 // | `tokio::sync::mpsc` | `std::sync::mpsc` |
34 // | ------------------- | ----------------- |
35 // | `channel` | `sync_channel` |
36 // | `unbounded_channel` | `channel` |
37 //
38 // The book collapses these differences for pedagogical simplicity, so that
39 // readers are not asking why `unbounded` is now important and can focus on
40 // the more important differences between sync and async APIs.
41 sync::mpsc::{
42 UnboundedReceiver as Receiver, UnboundedSender as Sender,
43 unbounded_channel as channel,
44 },
45 task::{JoinHandle, spawn as spawn_task, yield_now},
46 time::{interval, sleep},
47};
48
49pub use tokio_stream::{
50 Stream, StreamExt, iter as stream_from_iter,
51 wrappers::{IntervalStream, UnboundedReceiverStream as ReceiverStream},
52};
53
54/// Run a single future to completion on a bespoke Tokio `Runtime`.
55///
56/// Every time you call this, a new instance of `tokio::runtime::Runtime` will
57/// be created (see the implementation for details: it is trivial). This is:
58///
59/// - Reasonable for teaching purposes, in that you do not generally need to set
60/// up more than one runtime anyway, and especially do not in basic code like
61/// we are showing!
62///
63/// - Not *that* far off from what Tokio itself does under the hood in its own
64/// `tokio::main` macro for supporting `async fn main`.
65pub fn block_on<F: Future>(future: F) -> F::Output {
66 let rt = Runtime::new().unwrap();
67 rt.block_on(future)
68}
69
70/// This function has been renamed to `block_on`; please see its documentation.
71/// This function remains to maintain compatibility with the online versions
72/// of the book that use the name `run`.
73pub fn run<F: Future>(future: F) -> F::Output {
74 block_on(future)
75}
76
77/// Run two futures, taking whichever finishes first and canceling the other.
78///
79/// Notice that this is built on [`futures::future::select`], which has the
80/// same overall semantics but does *not* drop the slower future. The idea there
81/// is that you can work with the first result and then later *also* continue
82/// waiting for the second future.
83///
84/// We drop the slower future for the sake of simplicity in the examples: no
85/// need to deal with the tuple and intentionally ignore the second future this
86/// way!
87///
88/// Note that this only works as “simply” as it does because:
89///
90/// - It takes ownership of the futures.
91/// - It internally *pins* the futures.
92/// - It throws away (rather than returning) the unused future (which is why it
93/// can get away with pinning them).
94pub async fn select<A, B, F1, F2>(f1: F1, f2: F2) -> Either<A, B>
95where
96 F1: Future<Output = A>,
97 F2: Future<Output = B>,
98{
99 let f1 = pin!(f1);
100 let f2 = pin!(f2);
101 match future::select(f1, f2).await {
102 Either::Left((a, _f2)) => Either::Left(a),
103 Either::Right((b, _f1)) => Either::Right(b),
104 }
105}
106
107/// This function has been renamed to `select`; please see its documentation.
108/// This function remains to maintain compatibility with the online versions
109/// of the book that use the name `race`.
110pub async fn race<A, B, F1, F2>(f1: F1, f2: F2) -> Either<A, B>
111where
112 F1: Future<Output = A>,
113 F2: Future<Output = B>,
114{
115 select(f1, f2).await
116}
117
118/// Fetch data from a URL. For more convenient use in _The Rust Programming
119/// Language_, panics instead of returning a [`Result`] if the request fails.
120pub async fn get(url: &str) -> Response {
121 Response(reqwest::get(url).await.unwrap())
122}
123
124/// A thin wrapper around [`reqwest::Response`] to make the demos in _The Rust
125/// Programming Language_ substantially nicer to use.
126pub struct Response(reqwest::Response);
127
128impl Response {
129 /// Get the full response text.
130 ///
131 /// If the response cannot be deserialized, this panics instead of returning
132 /// a [`Result`] (for convenience in the demo).
133 pub async fn text(self) -> String {
134 self.0.text().await.unwrap()
135 }
136}
137
138/// A thin wrapper around [`scraper::Html`] to make the demos in _The Rust
139/// Programming Language_ substantially nicer to use.
140pub struct Html {
141 inner: scraper::Html,
142}
143
144impl Html {
145 /// Parse an HTML document from a string.
146 ///
147 /// This is just a thin wrapper around `scraper::Html::parse_document` to
148 /// keep the exported API surface simpler.
149 pub fn parse(source: &str) -> Html {
150 Html {
151 inner: scraper::Html::parse_document(source),
152 }
153 }
154
155 /// Get the first item in the document matching a string selector. Returns
156 /// Some()
157 ///
158 /// If the selector is not a valid CSS selector, panics rather than
159 /// returning a [`Result`] for convenience.
160 pub fn select_first<'a>(
161 &'a self,
162 selector: &'a str,
163 ) -> Option<scraper::ElementRef<'a>> {
164 let selector = scraper::Selector::parse(selector).unwrap();
165 self.inner.select(&selector).nth(0)
166 }
167}