From a42f27bd552126bb15a6f7ed7bcf5163ba010aee Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Sat, 24 Aug 2024 07:42:06 -0600 Subject: [PATCH 01/25] Ch. 17: Fix up diagrams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Set their view boxes to the original height and width, so they are guaranteed to present correctly. - For Figure 17-02, use the trick of adding a hidden node and hidden arrow to it in “Task 2” to align the two boxes. --- dot/trpl17-02.dot | 23 ++++---- src/img/trp17-02.svg | 1 - src/img/trpl17-01.svg | 6 +-- src/img/trpl17-02.svg | 122 +++++++++++++++++++++--------------------- 4 files changed, 79 insertions(+), 73 deletions(-) delete mode 100644 src/img/trp17-02.svg diff --git a/dot/trpl17-02.dot b/dot/trpl17-02.dot index 512f33cb9b..07d66a3e4b 100644 --- a/dot/trpl17-02.dot +++ b/dot/trpl17-02.dot @@ -1,20 +1,25 @@ digraph { dpi = 300.0; - + rankdir = "LR"; splines = false; cluster = true; - + node [shape = diamond;]; - + + // The graphs end up with the correct order, i.e. Task 1 *above* Task 2, when + // this is first. + subgraph cluster_ColleagueB { + label = "Task 2"; + B1 -> B2 -> B3; + + B0 [style = invis;]; + B3 -> B0 [style = invis;] + } + subgraph cluster_ColleagueA { newrank = true; label = "Task 1"; A1 -> A2 -> A3 -> A4; } - - subgraph cluster_ColleagueB { - label = "Task 2"; - B1 -> B2 -> B3; - } -} \ No newline at end of file +} diff --git a/src/img/trp17-02.svg b/src/img/trp17-02.svg deleted file mode 100644 index 1ad970d72c..0000000000 --- a/src/img/trp17-02.svg +++ /dev/null @@ -1 +0,0 @@ -Task 1Task 2ParallelA1A2A3A4B1B2B3 \ No newline at end of file diff --git a/src/img/trpl17-01.svg b/src/img/trpl17-01.svg index c99989ec31..483bf7216d 100644 --- a/src/img/trpl17-01.svg +++ b/src/img/trpl17-01.svg @@ -1,11 +1,11 @@ - - + diff --git a/src/img/trpl17-02.svg b/src/img/trpl17-02.svg index 1ddb5d4cad..b2df090c23 100644 --- a/src/img/trpl17-02.svg +++ b/src/img/trpl17-02.svg @@ -1,94 +1,96 @@ - - + -cluster_ColleagueA - -Task 1 +cluster_ColleagueB + +Task 2 -cluster_ColleagueB - -Task 2 +cluster_ColleagueA + +Task 1 - + +B1 + +B1 + + + +B2 + +B2 + + + +B1->B2 + + + + + +B3 + +B3 + + + +B2->B3 + + + + + + + A1 - -A1 + +A1 - + A2 - -A2 + +A2 - + A1->A2 - - + + - + A3 - -A3 + +A3 - + A2->A3 - - + + - + A4 - -A4 + +A4 - + A3->A4 - - - - - -B1 - -B1 - - - -B2 - -B2 - - - -B1->B2 - - - - - -B3 - -B3 - - - -B2->B3 - - + + From f812ed07c6a6add5bdae3e2d9d2c059692753e8a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Sat, 24 Aug 2024 07:42:06 -0600 Subject: [PATCH 02/25] =?UTF-8?q?Ch.=2017=C2=A700:=20second=20round=20of?= =?UTF-8?q?=20edits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-00-async-await.md | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index e68c7420fc..bb289fdbf7 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -10,19 +10,19 @@ processes to complete. The video export will use as much CPU and GPU power as it can. If you only had one CPU core, and your operating system never paused that export until it completed, you could not do anything else on your computer while it was running. -That would be a pretty frustrating experience, though. Instead, your computer -can (and does!) invisibly interrupt the export often enough to let you get other -work done along the way. - -The file download is different. It does not take up very much CPU time. The CPU -needs to wait on data to arrive from the network. While you can start reading -the data once some of it arrives, it might take a while for the rest to arrive. -Even once the data has all arrived, videos can be quite large, so it might take -some time to load all the data from the network. Maybe it only takes a second or -two—but that is a very long time for a modern processor, which can do billions -of operations every second. It would be nice to be able to put the CPU to use -for other work while waiting for the network call to finish—so, again, your -computer will once again invisibly interrupt your program so other things can +That would be a pretty frustrating experience, though. Instead, your computer’s +operating sysem can (and does!) invisibly interrupt the export often enough to +let you get other work done along the way. + +The file download is different. It does not take up very much CPU time. Instead, +the CPU needs to wait on data to arrive from the network. While you can start +reading the data once some of it arrives, it might take a while for the rest to +arrive. Even once the data has all arrived, a video can be quite large, so it +might take some time to load it all. Maybe it only takes a second or two—but +that is a very long time for a modern processor, which can do billions of +operations every second. It would be nice to be able to put the CPU to use for +other work while waiting for the network call to finish—so, again, your +operating system will invisibly interrupt your program so other things can happen while the network operation is still ongoing. > Note: The video export is the kind of operation which is often described as @@ -33,8 +33,9 @@ happen while the network operation is still ongoing. > *input and output*. It can only go as fast as the data can be sent across the > network. -In both of these examples, the concurrency only happens at the level of a whole -program. The operating system interrupts one program to let other +In both of these examples, the operating system’s invisible interrupts provide a +form of concurrency. That concurrency only happens at the level of a whole +program, though: the operating system interrupts one program to let other programs get work done. In many cases, since we understand our programs at a much more granular level than the operating system does, we can spot lots of opportunities for concurrency that the operating system cannot see. @@ -72,12 +73,14 @@ In the previous chapter we treated parallelism and concurrency as mostly interchangeable. Now we need to distinguish between them more precisely, because the differences will show up as we start working. -Think about working on a software project as a team. +Consider the different ways a team could split up work on a software project. We +could assign a single individual multiple tasks, or we could assign one task per +team member, or we could do a mix of both approaches. When an individual works on several different tasks before any of them is complete, this is *concurrency*. Maybe you have two different projects checked out on your computer, and when you get bored or stuck on one project, you switch -to the other. You are just one person, and you cannot make progress on both +to the other. You are just one person, so you cannot make progress on both tasks tasks at the exact same time—but you can multi-task, making progress on multiple tasks by switching between them. @@ -106,15 +109,14 @@ tasks. Maybe you *thought* the task that one person was working on was totally independent from everyone else’s work, but it actually needs something finished by another person on the team. Some of the work could be done in parallel, but some of it was actually *serial*: it could only happen in a series, one thing -after the other. Likewise, you might realize that one of the tasks you were -working on needs the result from another of your tasks. Now your concurrent work -has also become serial. +after the other. Likewise, you might realize that one of your own tasks depends +on another of your tasks. Now your concurrent work has also become serial. -Parallelism and concurrency can intersect with each other, too. For example, if -it turns out your coworker is waiting on one of your projects to finish, you -might need to focus on that project and not give any time to your other task -until it is done. In that case, you and your coworker are no longer able to work -in parallel *and* you are no longer able to work concurrently. +Parallelism and concurrency can intersect with each other, too. If you learn +that a colleague is stuck until you finish one of your tasks, you will probably +focus all your efforts on that task to “unblock” your colleague. You and your +coworker are no longer able to work in parallel, and you are also no longer able +to work concurrently on your own tasks. The same basic dynamics come into play with software and hardware. On a machine with a single CPU core, the CPU can only do one operation at a time, but it can @@ -127,8 +129,8 @@ time. When working with async in Rust, we are always dealing with concurrency. Depending on the hardware, the operating system, and the async runtime we are -using—more on async runtimes shortly!—that concurrency may or may not also use -parallelism under the hood. +using—more on async runtimes shortly!—that concurrency may also use parallelism +under the hood. Now, let’s dive into how async programming in Rust actually works! In the rest of this chapter, we will: From c648c0e8daa4256d937e5eb12b7f2823f3d19031 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 30 Aug 2024 13:41:54 -0400 Subject: [PATCH 03/25] Use immutable borrow of `TcpStream` when creating `BufReader` --- listings/ch20-web-server/listing-20-02/src/main.rs | 2 +- listings/ch20-web-server/listing-20-03/src/main.rs | 2 +- listings/ch20-web-server/listing-20-05/src/main.rs | 2 +- listings/ch20-web-server/listing-20-06/src/main.rs | 2 +- listings/ch20-web-server/listing-20-07/src/main.rs | 2 +- listings/ch20-web-server/listing-20-09/src/main.rs | 2 +- listings/ch20-web-server/listing-20-10/src/main.rs | 2 +- listings/ch20-web-server/listing-20-11/src/main.rs | 2 +- listings/ch20-web-server/listing-20-12/src/main.rs | 2 +- listings/ch20-web-server/listing-20-13/src/main.rs | 2 +- listings/ch20-web-server/listing-20-14/src/main.rs | 2 +- listings/ch20-web-server/listing-20-15/src/main.rs | 2 +- listings/ch20-web-server/listing-20-16/src/main.rs | 2 +- listings/ch20-web-server/listing-20-17/src/main.rs | 2 +- listings/ch20-web-server/listing-20-18/src/main.rs | 2 +- listings/ch20-web-server/listing-20-19/src/main.rs | 2 +- listings/ch20-web-server/listing-20-20/src/main.rs | 2 +- listings/ch20-web-server/listing-20-21/src/main.rs | 2 +- listings/ch20-web-server/listing-20-22/src/main.rs | 2 +- listings/ch20-web-server/listing-20-23/src/main.rs | 2 +- listings/ch20-web-server/listing-20-24/src/main.rs | 2 +- listings/ch20-web-server/listing-20-25/src/main.rs | 2 +- .../no-listing-01-define-threadpool-struct/src/main.rs | 2 +- .../no-listing-02-impl-threadpool-new/src/main.rs | 2 +- .../ch20-web-server/no-listing-03-define-execute/src/main.rs | 2 +- .../no-listing-04-update-worker-definition/src/main.rs | 2 +- .../ch20-web-server/no-listing-05-fix-worker-new/src/main.rs | 2 +- .../no-listing-06-fix-threadpool-drop/src/main.rs | 2 +- listings/ch20-web-server/no-listing-07-final-code/src/main.rs | 2 +- src/ch20-01-single-threaded.md | 4 ++-- 30 files changed, 31 insertions(+), 31 deletions(-) diff --git a/listings/ch20-web-server/listing-20-02/src/main.rs b/listings/ch20-web-server/listing-20-02/src/main.rs index f139846c6d..1eff2eef3a 100644 --- a/listings/ch20-web-server/listing-20-02/src/main.rs +++ b/listings/ch20-web-server/listing-20-02/src/main.rs @@ -14,7 +14,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let http_request: Vec<_> = buf_reader .lines() .map(|result| result.unwrap()) diff --git a/listings/ch20-web-server/listing-20-03/src/main.rs b/listings/ch20-web-server/listing-20-03/src/main.rs index c72d4a9c67..17c8401d4d 100644 --- a/listings/ch20-web-server/listing-20-03/src/main.rs +++ b/listings/ch20-web-server/listing-20-03/src/main.rs @@ -15,7 +15,7 @@ fn main() { // ANCHOR: here fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let http_request: Vec<_> = buf_reader .lines() .map(|result| result.unwrap()) diff --git a/listings/ch20-web-server/listing-20-05/src/main.rs b/listings/ch20-web-server/listing-20-05/src/main.rs index d4b78b640e..437d9b626e 100644 --- a/listings/ch20-web-server/listing-20-05/src/main.rs +++ b/listings/ch20-web-server/listing-20-05/src/main.rs @@ -19,7 +19,7 @@ fn main() { // ANCHOR: here fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let http_request: Vec<_> = buf_reader .lines() .map(|result| result.unwrap()) diff --git a/listings/ch20-web-server/listing-20-06/src/main.rs b/listings/ch20-web-server/listing-20-06/src/main.rs index 5523a42d7c..843d846766 100644 --- a/listings/ch20-web-server/listing-20-06/src/main.rs +++ b/listings/ch20-web-server/listing-20-06/src/main.rs @@ -17,7 +17,7 @@ fn main() { // --snip-- fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); if request_line == "GET / HTTP/1.1" { diff --git a/listings/ch20-web-server/listing-20-07/src/main.rs b/listings/ch20-web-server/listing-20-07/src/main.rs index a14b7d538c..e19467b83b 100644 --- a/listings/ch20-web-server/listing-20-07/src/main.rs +++ b/listings/ch20-web-server/listing-20-07/src/main.rs @@ -15,7 +15,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); if request_line == "GET / HTTP/1.1" { diff --git a/listings/ch20-web-server/listing-20-09/src/main.rs b/listings/ch20-web-server/listing-20-09/src/main.rs index ffc51e803e..0f9356ab02 100644 --- a/listings/ch20-web-server/listing-20-09/src/main.rs +++ b/listings/ch20-web-server/listing-20-09/src/main.rs @@ -19,7 +19,7 @@ fn main() { fn handle_connection(mut stream: TcpStream) { // --snip-- // ANCHOR_END: here - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); // ANCHOR: here diff --git a/listings/ch20-web-server/listing-20-10/src/main.rs b/listings/ch20-web-server/listing-20-10/src/main.rs index 5a18b45c02..0679ec6002 100644 --- a/listings/ch20-web-server/listing-20-10/src/main.rs +++ b/listings/ch20-web-server/listing-20-10/src/main.rs @@ -24,7 +24,7 @@ fn handle_connection(mut stream: TcpStream) { // --snip-- // ANCHOR_END: here - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); // ANCHOR: here diff --git a/listings/ch20-web-server/listing-20-11/src/main.rs b/listings/ch20-web-server/listing-20-11/src/main.rs index 1181357b0e..075a0d9de6 100644 --- a/listings/ch20-web-server/listing-20-11/src/main.rs +++ b/listings/ch20-web-server/listing-20-11/src/main.rs @@ -21,7 +21,7 @@ fn main() { // ANCHOR_END: here fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-12/src/main.rs b/listings/ch20-web-server/listing-20-12/src/main.rs index 21b9a80f10..bde3e29d10 100644 --- a/listings/ch20-web-server/listing-20-12/src/main.rs +++ b/listings/ch20-web-server/listing-20-12/src/main.rs @@ -22,7 +22,7 @@ fn main() { // ANCHOR_END: here fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-13/src/main.rs b/listings/ch20-web-server/listing-20-13/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-13/src/main.rs +++ b/listings/ch20-web-server/listing-20-13/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-14/src/main.rs b/listings/ch20-web-server/listing-20-14/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-14/src/main.rs +++ b/listings/ch20-web-server/listing-20-14/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-15/src/main.rs b/listings/ch20-web-server/listing-20-15/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-15/src/main.rs +++ b/listings/ch20-web-server/listing-20-15/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-16/src/main.rs b/listings/ch20-web-server/listing-20-16/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-16/src/main.rs +++ b/listings/ch20-web-server/listing-20-16/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-17/src/main.rs b/listings/ch20-web-server/listing-20-17/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-17/src/main.rs +++ b/listings/ch20-web-server/listing-20-17/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-18/src/main.rs b/listings/ch20-web-server/listing-20-18/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-18/src/main.rs +++ b/listings/ch20-web-server/listing-20-18/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-19/src/main.rs b/listings/ch20-web-server/listing-20-19/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-19/src/main.rs +++ b/listings/ch20-web-server/listing-20-19/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-20/src/main.rs b/listings/ch20-web-server/listing-20-20/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-20/src/main.rs +++ b/listings/ch20-web-server/listing-20-20/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-21/src/main.rs b/listings/ch20-web-server/listing-20-21/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-21/src/main.rs +++ b/listings/ch20-web-server/listing-20-21/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-22/src/main.rs b/listings/ch20-web-server/listing-20-22/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/listing-20-22/src/main.rs +++ b/listings/ch20-web-server/listing-20-22/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-23/src/main.rs b/listings/ch20-web-server/listing-20-23/src/main.rs index b6aa046d1b..acd703f274 100644 --- a/listings/ch20-web-server/listing-20-23/src/main.rs +++ b/listings/ch20-web-server/listing-20-23/src/main.rs @@ -23,7 +23,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-24/src/main.rs b/listings/ch20-web-server/listing-20-24/src/main.rs index b6aa046d1b..acd703f274 100644 --- a/listings/ch20-web-server/listing-20-24/src/main.rs +++ b/listings/ch20-web-server/listing-20-24/src/main.rs @@ -23,7 +23,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/listing-20-25/src/main.rs b/listings/ch20-web-server/listing-20-25/src/main.rs index 86e8d9e78c..ee0f1efe74 100644 --- a/listings/ch20-web-server/listing-20-25/src/main.rs +++ b/listings/ch20-web-server/listing-20-25/src/main.rs @@ -25,7 +25,7 @@ fn main() { // ANCHOR_END: here fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs b/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs index f7b42167f9..e68f72c700 100644 --- a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs +++ b/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs @@ -23,7 +23,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs b/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs +++ b/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs b/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs +++ b/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs b/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs +++ b/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs b/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs index 79efb28a2a..1f075fde59 100644 --- a/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs +++ b/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs @@ -21,7 +21,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs b/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs index b6aa046d1b..acd703f274 100644 --- a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs +++ b/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs @@ -23,7 +23,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/listings/ch20-web-server/no-listing-07-final-code/src/main.rs b/listings/ch20-web-server/no-listing-07-final-code/src/main.rs index b6aa046d1b..acd703f274 100644 --- a/listings/ch20-web-server/no-listing-07-final-code/src/main.rs +++ b/listings/ch20-web-server/no-listing-07-final-code/src/main.rs @@ -23,7 +23,7 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); + let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = match &request_line[..] { diff --git a/src/ch20-01-single-threaded.md b/src/ch20-01-single-threaded.md index 9e7fe865b1..b474d926fe 100644 --- a/src/ch20-01-single-threaded.md +++ b/src/ch20-01-single-threaded.md @@ -143,8 +143,8 @@ connection, we now call the new `handle_connection` function and pass the `stream` to it. In the `handle_connection` function, we create a new `BufReader` instance that -wraps a mutable reference to the `stream`. `BufReader` adds buffering by -managing calls to the `std::io::Read` trait methods for us. +wraps a reference to the `stream`. `BufReader` adds buffering by managing calls +to the `std::io::Read` trait methods for us. We create a variable named `http_request` to collect the lines of the request the browser sends to our server. We indicate that we want to collect these From ef4a51843eea837c7982af42e0309d48f68d70ab Mon Sep 17 00:00:00 2001 From: faint <46868845+ficcialfaint@users.noreply.github.com> Date: Sat, 31 Aug 2024 20:38:53 +0300 Subject: [PATCH 04/25] cargo init usage suggestion --- src/ch01-03-hello-cargo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch01-03-hello-cargo.md b/src/ch01-03-hello-cargo.md index 5750e4f015..288ed4d3da 100644 --- a/src/ch01-03-hello-cargo.md +++ b/src/ch01-03-hello-cargo.md @@ -113,7 +113,7 @@ everything is in its place. If you started a project that doesn’t use Cargo, as we did with the “Hello, world!” project, you can convert it to a project that does use Cargo. Move the project code into the *src* directory and create an appropriate *Cargo.toml* -file. +file, or run `cargo init`. ### Building and Running a Cargo Project From 1de14c81c6c14204216ef28dddeca2579165e106 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Sat, 24 Aug 2024 08:26:56 -0600 Subject: [PATCH 05/25] Ch. 17: start restructuring chapter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create a section (which will be deleted or at least reintegrated once all is said and done) to hold content pulled out of other sections for the sake of clearer flow and understanding. - Pull “advanced” material from 17.00, 17.01, and 17.02 into the holding section and start reorganizing their content to account for shifting around materials. --- src/SUMMARY.md | 1 + src/ch17-01-futures-and-syntax.md | 128 +++++++------------------- src/ch17-02-concurrency-with-async.md | 12 +-- src/ch17-07-wip.md | 102 ++++++++++++++++++++ 4 files changed, 140 insertions(+), 103 deletions(-) create mode 100644 src/ch17-07-wip.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 2645cfcedf..33af2af759 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -108,6 +108,7 @@ - [More Ways of Combining Futures](ch17-04-more-ways-of-combining-futures.md) - [Streams](ch17-05-streams.md) - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.md) + - [Restructuring](ch17-07-wip.md) - [Object Oriented Programming Features of Rust](ch18-00-oop.md) - [Characteristics of Object-Oriented Languages](ch18-01-what-is-oo.md) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 272471247a..014a6dd33b 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -141,6 +141,10 @@ high-throughput web server with many CPU cores and a large amount of RAM has very different different needs than a microcontroller with a single core, a small amount of RAM, and no ability to do heap allocations. +Every async program in Rust has at least one place where it sets up a runtime +and executes the futures. Those runtimes also often supply async versions of +common functionality like file or network I/O. + > ### The `trpl` Crate > > To keep this chapter focused on learning async, rather than juggling parts of @@ -190,101 +194,32 @@ When we run this, we get the behavior we might have expected initially: {{#include ../listings/ch17-async-await/listing-17-04/output.txt}} ``` -Phew: we finally have some working async code! Now we can turn our attention to -how the `Future` trait works. - -### What Are Futures? +Phew: we finally have some working async code! Let’s briefly turn our attention +to how the `Future` trait works. A *future* is a data structure which manages the state of some async operation. -Rust provides the `Future` trait as a building block so different async -operations can be implemented with different data, but with a common interface. -Here is the definition of the trait: - -```rust -use std::pin::Pin; -use std::task::{Context, Poll}; - -pub trait Future { - type Output; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; -} -``` - -While we often interact with the futures created via async blocks, you can also -implement `Future` on your own data types. Indeed, many of the functions we will -see throughout this chapter return types with their own implementations of -`Future`. - -As we learned earlier, `Future`’s associated type `Output` says what the future -will resolves to. (This is analogous to the `Item` associated type for the -`Iterator` trait.) Beyond that, `Future` also has the `poll` method, which takes -a special `Pin` reference for its `self` parameter and a mutable reference to a -`Context` type, and returns a `Poll`. We will talk a little more -about `Pin` and `Context` later in the chapter. For now, let’s focus on what the -method returns, the `Poll` type: - -```rust -enum Poll { - Ready(T), - Pending -} -``` - -This `Poll` type is a lot like an `Option`: it has one variant which has a value -(`Ready(T)`), and one which does not (`Pending`). It means something quite -different, though! The `Pending` variant indicates that the future still has -work to do, so the caller will need to check again later. The `Ready` variant -indicates that the `Future` has finished its work and the `T` value is -available. - -> Note: With most futures, the caller should not call `poll()` again after the -> future has returned `Ready`. Many futures will panic if polled again after -> becoming ready! Futures which are safe to poll again will say so explicitly in -> their documentation. - -Under the hood, when you call `.await`, Rust compiles that to code which calls -`poll`, kind of (although not exactly ) -like this: - -```rust,ignore -match hello("async").poll() { - Ready(_) => { - // We’re done! - } - Pending => { - // But what goes here? - } -} -``` - -What should we do when the `Future` is still `Pending`? We need some way to try -again… and again, and again, until the future is finally ready. In other words, -a loop: - -```rust,ignore -let hello_fut = hello("async"); -loop { - match hello_fut.poll() { - Ready(_) => { - break; - } - Pending => { - // continue - } - } -} -``` - -If Rust compiled it to exactly that code, though, every `.await` would be -blocking—exactly the opposite of what we were going for! Instead, Rust needs -makes sure that the loop can hand off control to something which can pause work -on this future and work on other futures and check this one again later. That -“something” is an async runtime, and this scheduling and coordination work is -one of the main jobs for a runtime. +It is called a “future” because it represents work which may not be ready now, +but will become ready at some point in the future. (This same concept shows up +in many languages, sometimes under other names like “task” or “promise”.) Rust +provides a `Future` trait as a building block so different async operations can +be implemented with different data structures, but with a common interface. + +Most of the time when writing async Rust, we don’t work directly with the +`Future` trait. Instead, we use the `async` and `await` keywords we saw above. +Rust does the work of compiling them into the appropriate calls to the `Future` +trait, much like it does with `for` loops and the `Iterator` trait. + +We most often interact with the futures created via async blocks, but you can +also implement `Future` on your own data types. Indeed, many of the functions we +will see throughout this chapter return types with their own implementations of +`Future`. We will return to the definition of the trait at the end of the +chapter and dig into more of how it works, but this is enough detail to keep us +moving forward. + + Every *await point*—that is, every place where the code explicitly applies the -`.await` keyword—represents a place where control gets handed back to the +`await` keyword—represents a place where control gets handed back to the runtime. To make that work, Rust needs to keep track of the state involved in the async block, so that the runtime can kick off some other work and then come back when it is ready to try advancing this one again. This is an invisible @@ -311,6 +246,11 @@ structures all apply. Happily, the compiler also handles checking those for us, and has good error messages. We will work through a few of those later in the chapter! + + Now we can understand why the compiler stopped us from making `main` itself an async function in Listing 17-3. If `main` were an async function, something else would need to call `poll()` on whatever `main` returned, but main is the @@ -318,10 +258,6 @@ starting point for the program! Instead, we use the `trpl::block_on` function, which sets up a runtime and polls the `Future` returned by `hello` until it returns `Ready`. -Every async program in Rust has at least one place where it sets up a runtime and -executes the futures. Those runtimes also often supply async versions of common -functionality like file or network I/O. - > Note: We have skipped over some interesting implementation details in this > discussion, because you should not have to think about them when writing Rust. > @@ -343,5 +279,3 @@ of the things we can *do* with async. [crate-source]: https://github.com/rust-lang/book/tree/main/packages/trpl [futures-crate]: https://crates.io/crates/futures [tokio]: https://tokio.rs - - diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index a57d056814..4ac808a86d 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -228,12 +228,12 @@ long as the condition it relies on is true. -The `rx.recv()` call produces a `Future`, which we await. While waiting on -messages to arrive, the future will produce `Poll::Pending`, so the runtime will -pause it until it is time to check it again. Once a message arrives, `rx.recv()` -will respond with `Poll::Ready(Some(message))`. When the channel closes, -`rx.recv()` will respond with `Poll::Ready(None)` to indicate that there are no -more values, and we should stop polling—that is, stop awaiting. +The `rx.recv()` call produces a `Future`, which we await. The runtime will pause +the `Future` until it is ready. Once a message arrives, the future will resolve +to `Some(message)`, as many times as a message arrives. When the channel closes, +regardless of whether *any* messages have arrived, the future will instead +resolve to `None` to indicate that there are no more values, and we should stop +polling—that is, stop awaiting. The `while let` loop pulls all of this together. If the result of calling `rx.recv().await` is `Some(message)`, we get access to the message and we can diff --git a/src/ch17-07-wip.md b/src/ch17-07-wip.md new file mode 100644 index 0000000000..8f3f569203 --- /dev/null +++ b/src/ch17-07-wip.md @@ -0,0 +1,102 @@ +> ## Restructuring +> +> This is just a placeholder for material that needs to be restructured so that +> the earlier sections of the book can avoid getting sidetracked into details of +> things like `Pin` or even just the full gnarliness of the `Future` trait at +> points where it would be better for the text to keep moving. + +--- + +Here is the definition of the trait: + +```rust +use std::pin::Pin; +use std::task::{Context, Poll}; + +pub trait Future { + type Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} +``` + +As we learned earlier, `Future`’s associated type `Output` says what the future +will resolves to. (This is analogous to the `Item` associated type for the +`Iterator` trait.) Beyond that, `Future` also has the `poll` method, which takes +a special `Pin` reference for its `self` parameter and a mutable reference to a +`Context` type, and returns a `Poll`. We will talk a little more +about `Pin` and `Context` later in the chapter. For now, let’s focus on what the +method returns, the `Poll` type: + +```rust +enum Poll { + Ready(T), + Pending +} +``` + +This `Poll` type is a lot like an `Option`: it has one variant which has a value +(`Ready(T)`), and one which does not (`Pending`). It means something quite +different, though! The `Pending` variant indicates that the future still has +work to do, so the caller will need to check again later. The `Ready` variant +indicates that the `Future` has finished its work and the `T` value is +available. + +> Note: With most futures, the caller should not call `poll()` again after the +> future has returned `Ready`. Many futures will panic if polled again after +> becoming ready! Futures which are safe to poll again will say so explicitly in +> their documentation. + +Under the hood, when you call `.await`, Rust compiles that to code which calls +`poll`, kind of (although not exactly ) +like this: + +```rust,ignore +match hello("async").poll() { + Ready(_) => { + // We’re done! + } + Pending => { + // But what goes here? + } +} +``` + +What should we do when the `Future` is still `Pending`? We need some way to try +again… and again, and again, until the future is finally ready. In other words, +a loop: + +```rust,ignore +let hello_fut = hello("async"); +loop { + match hello_fut.poll() { + Ready(_) => { + break; + } + Pending => { + // continue + } + } +} +``` + +If Rust compiled it to exactly that code, though, every `.await` would be +blocking—exactly the opposite of what we were going for! Instead, Rust needs +makes sure that the loop can hand off control to something which can pause work +on this future and work on other futures and check this one again later. That +“something” is an async runtime, and this scheduling and coordination work is +one of the main jobs for a runtime. + +--- + +Recall our description of how `rx.recv()` waits in the [Counting][counting] +section. The `recv()` call returns a `Future`, and awaiting it polls it. In our +initial discussion, we noted that a runtime will pause the future until it is +ready with either `Some(message)` or `None` when the channel closes. With a +deeper understanding of `Future` in place, and specifically its `poll` method, +we can see how that works. The runtime knows the future is not ready when it +returns `Poll::Pending`. Conversely, the runtime knows the future is ready and +advances it when `poll` returns `Poll::Ready(Some(message))` or +`Poll::Ready(None)`. + +[counting]: /ch17-02-concurrency-with-async.md From 6b6b4501f11382d30144c9f9ca0f32328b8f5f3e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 10 Sep 2024 16:03:08 -0600 Subject: [PATCH 06/25] Upgrade to Rust 1.81 In addition to the baseline changes, skip over non-directory code where directories are needed to deal with things like `.DS_Store` files. Also add a bunch of context on error causes from `std::io::Error` because it was *impossible* to figure out exactly what the source of those were. --- .github/workflows/main.yml | 8 +-- .../listing-02-04/output.txt | 8 ++- .../output.txt | 10 +-- .../output.txt | 8 +-- .../output.txt | 4 +- .../listing-09-10/output.txt | 8 +++ .../listing-13-04/output.txt | 2 +- .../listing-13-05/output.txt | 2 +- .../listing-15-21/output.txt | 2 +- .../listing-16-14/output.txt | 2 +- .../no-listing-18-returns-closure/output.txt | 4 +- .../ch20-web-server/listing-20-22/output.txt | 2 +- .../output.txt | 2 +- packages/tools/src/bin/release_listings.rs | 64 ++++++++++++++++--- rust-toolchain | 2 +- src/title-page.md | 2 +- 16 files changed, 97 insertions(+), 33 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1737bce009..2b3ae3d5c3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,8 +12,8 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install 1.79 -c rust-docs - rustup default 1.79 + rustup toolchain install 1.81 -c rust-docs + rustup default 1.81 - name: Install mdbook run: | mkdir bin @@ -36,8 +36,8 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install 1.79 -c rust-docs - rustup default 1.79 + rustup toolchain install 1.81 -c rust-docs + rustup default 1.81 - name: Run `tools` package tests run: | cargo test diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt index bb997866a2..0f0bc21025 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt @@ -1,4 +1,10 @@ $ cargo build + Downloading crates ... + Downloaded rand_core v0.6.2 + Downloaded getrandom v0.2.2 + Downloaded rand_chacha v0.3.0 + Downloaded ppv-lite86 v0.2.10 + Downloaded libc v0.2.86 Compiling libc v0.2.86 Compiling getrandom v0.2.2 Compiling cfg-if v1.0.0 @@ -18,7 +24,7 @@ error[E0308]: mismatched types = note: expected reference `&String` found reference `&{integer}` note: method defined here - --> /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/cmp.rs:840:8 + --> /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/cmp.rs:839:8 For more information about this error, try `rustc --explain E0308`. error: could not compile `guessing_game` (bin "guessing_game") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt index 73ca9d62fb..85efb431ea 100644 --- a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt @@ -4,13 +4,15 @@ error[E0384]: cannot assign twice to immutable variable `x` --> src/main.rs:4:5 | 2 | let x = 5; - | - - | | - | first assignment to `x` - | help: consider making this binding mutable: `mut x` + | - first assignment to `x` 3 | println!("The value of x is: {x}"); 4 | x = 6; | ^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +2 | let mut x = 5; + | +++ For more information about this error, try `rustc --explain E0384`. error: could not compile `variables` (bin "variables") due to 1 previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt index dde05f4b3b..1eb76de43f 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt @@ -8,10 +8,10 @@ error[E0277]: cannot add `Option` to `i8` | = help: the trait `Add>` is not implemented for `i8` = help: the following other types implement trait `Add`: - <&'a i8 as Add> - <&i8 as Add<&i8>> - > - + `&'a i8` implements `Add` + `&i8` implements `Add<&i8>` + `i8` implements `Add<&i8>` + `i8` implements `Add` For more information about this error, try `rustc --explain E0277`. error: could not compile `enums` (bin "enums") due to 1 previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt index 5232f90378..43acd14d63 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt @@ -7,8 +7,8 @@ error[E0004]: non-exhaustive patterns: `None` not covered | ^ pattern `None` not covered | note: `Option` defined here - --> /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/option.rs:571:1 - ::: /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/option.rs:575:5 + --> /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/option.rs:574:1 + ::: /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/option.rs:578:5 | = note: not covered = note: the matched value is of type `Option` diff --git a/listings/ch09-error-handling/listing-09-10/output.txt b/listings/ch09-error-handling/listing-09-10/output.txt index dbc9bb13dc..f3c1641b24 100644 --- a/listings/ch09-error-handling/listing-09-10/output.txt +++ b/listings/ch09-error-handling/listing-09-10/output.txt @@ -9,6 +9,14 @@ error[E0277]: the `?` operator can only be used in a function that returns `Resu | ^ cannot use the `?` operator in a function that returns `()` | = help: the trait `FromResidual>` is not implemented for `()` +help: consider adding return type + | +3 ~ fn main() -> Result<(), Box> { +4 | let greeting_file = File::open("hello.txt")?; +5 + +6 + Ok(()) +7 + } + | For more information about this error, try `rustc --explain E0277`. error: could not compile `error-handling` (bin "error-handling") due to 1 previous error diff --git a/listings/ch13-functional-features/listing-13-04/output.txt b/listings/ch13-functional-features/listing-13-04/output.txt index b04a1a36c2..fbc00b5dfc 100644 --- a/listings/ch13-functional-features/listing-13-04/output.txt +++ b/listings/ch13-functional-features/listing-13-04/output.txt @@ -1,6 +1,6 @@ $ cargo run Locking 1 package to latest compatible version - Adding closure-example v0.1.0 (/Users/carolnichols/rust/book/tmp/listings/ch13-functional-features/listing-13-04) + Adding closure-example v0.1.0 (/Users/chris/dev/rust-lang/book/tmp/listings/ch13-functional-features/listing-13-04) Compiling closure-example v0.1.0 (file:///projects/closure-example) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s Running `target/debug/closure-example` diff --git a/listings/ch13-functional-features/listing-13-05/output.txt b/listings/ch13-functional-features/listing-13-05/output.txt index 1fddf5a982..695ee4bee3 100644 --- a/listings/ch13-functional-features/listing-13-05/output.txt +++ b/listings/ch13-functional-features/listing-13-05/output.txt @@ -1,6 +1,6 @@ $ cargo run Locking 1 package to latest compatible version - Adding closure-example v0.1.0 (/Users/carolnichols/rust/book/tmp/listings/ch13-functional-features/listing-13-05) + Adding closure-example v0.1.0 (/Users/chris/dev/rust-lang/book/tmp/listings/ch13-functional-features/listing-13-05) Compiling closure-example v0.1.0 (file:///projects/closure-example) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s Running `target/debug/closure-example` diff --git a/listings/ch15-smart-pointers/listing-15-21/output.txt b/listings/ch15-smart-pointers/listing-15-21/output.txt index 3509e8ec62..8501007f05 100644 --- a/listings/ch15-smart-pointers/listing-15-21/output.txt +++ b/listings/ch15-smart-pointers/listing-15-21/output.txt @@ -10,7 +10,7 @@ help: consider changing this to be a mutable reference in the `impl` method and | 2 ~ fn send(&mut self, msg: &str); 3 | } - ... +... 56 | impl Messenger for MockMessenger { 57 ~ fn send(&mut self, message: &str) { | diff --git a/listings/ch16-fearless-concurrency/listing-16-14/output.txt b/listings/ch16-fearless-concurrency/listing-16-14/output.txt index cb4167a5b8..cc96baed1d 100644 --- a/listings/ch16-fearless-concurrency/listing-16-14/output.txt +++ b/listings/ch16-fearless-concurrency/listing-16-14/output.txt @@ -22,7 +22,7 @@ note: required because it's used within this closure 11 | let handle = thread::spawn(move || { | ^^^^^^^ note: required by a bound in `spawn` - --> /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/thread/mod.rs:691:1 + --> /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/thread/mod.rs:688:1 For more information about this error, try `rustc --explain E0277`. error: could not compile `shared-state` (bin "shared-state") due to 1 previous error diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt b/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt index bc736bd689..3a23426392 100644 --- a/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt +++ b/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt @@ -6,11 +6,11 @@ error[E0746]: return type cannot have an unboxed trait object 1 | fn returns_closure() -> dyn Fn(i32) -> i32 { | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | -help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type +help: consider returning an `impl Trait` instead of a `dyn Trait` | 1 | fn returns_closure() -> impl Fn(i32) -> i32 { | ~~~~ -help: box the return type, and wrap all of the returned values in `Box::new` +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` | 1 ~ fn returns_closure() -> Box i32> { 2 ~ Box::new(|x| x + 1) diff --git a/listings/ch20-web-server/listing-20-22/output.txt b/listings/ch20-web-server/listing-20-22/output.txt index 84ebe928b0..554bfd8591 100644 --- a/listings/ch20-web-server/listing-20-22/output.txt +++ b/listings/ch20-web-server/listing-20-22/output.txt @@ -9,7 +9,7 @@ error[E0507]: cannot move out of `worker.thread` which is behind a mutable refer | move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait | note: `JoinHandle::::join` takes ownership of the receiver `self`, which moves `worker.thread` - --> /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/thread/mod.rs:1718:17 + --> /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/thread/mod.rs:1778:17 For more information about this error, try `rustc --explain E0507`. error: could not compile `hello` (lib) due to 1 previous error diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt b/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt index 1ffe5206b1..6867dcbcaf 100644 --- a/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt +++ b/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt @@ -7,7 +7,7 @@ error[E0599]: no method named `join` found for enum `Option` in the current scop | ^^^^ method not found in `Option>` | note: the method `join` exists on the type `JoinHandle<()>` - --> /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/thread/mod.rs:1718:5 + --> /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/thread/mod.rs:1778:5 help: consider using `Option::expect` to unwrap the `JoinHandle<()>` value, panicking if the value is an `Option::None` | 52 | worker.thread.expect("REASON").join().unwrap(); diff --git a/packages/tools/src/bin/release_listings.rs b/packages/tools/src/bin/release_listings.rs index c9a2f45974..09fb209761 100644 --- a/packages/tools/src/bin/release_listings.rs +++ b/packages/tools/src/bin/release_listings.rs @@ -28,26 +28,59 @@ fn main() -> Result<(), Box> { let chapter = chapter?; let chapter_path = chapter.path(); + if !chapter_path.is_dir() { + eprintln!( + "'{}' is not a directory, skipping", + chapter_path.display() + ); + continue; + } + let chapter_name = chapter_path .file_name() .expect("Chapter should've had a name"); // Create a corresponding chapter dir in `tmp/listings` let output_chapter_path = out_dir.join(chapter_name); - fs::create_dir(&output_chapter_path)?; + fs::create_dir(&output_chapter_path).map_err(|e| { + format!( + "could not create dir at '{}': {e}", + output_chapter_path.display() + ) + })?; // For each listing in the chapter directory, - for listing in fs::read_dir(chapter_path)? { - let listing = listing?; + for listing in fs::read_dir(&chapter_path).map_err(|e| { + format!("Could not read '{}': {e}", chapter_path.display()) + })? { + let listing = listing.map_err(|e| { + format!( + "bad dir entry listing in {}: {e}", + chapter_path.display() + ) + })?; let listing_path = listing.path(); + if !listing_path.is_dir() { + eprintln!( + "'{}' is not a directory, skipping", + chapter_path.display() + ); + continue; + } + let listing_name = listing_path .file_name() .expect("Listing should've had a name"); // Create a corresponding listing dir in the tmp chapter dir let output_listing_dir = output_chapter_path.join(listing_name); - fs::create_dir(&output_listing_dir)?; + fs::create_dir(&output_listing_dir).map_err(|e| { + format!( + "could not create dir '{}': {e}", + output_listing_dir.display() + ) + })?; // Copy all the cleaned files in the listing to the tmp directory copy_cleaned_listing_files(listing_path, output_listing_dir)?; @@ -79,8 +112,12 @@ fn copy_cleaned_listing_files( from: PathBuf, to: PathBuf, ) -> Result<(), Box> { - for item in fs::read_dir(from)? { - let item = item?; + for item in fs::read_dir(&from).map_err(|e| { + format!("Could not read_dir on '{}': {e}", from.display()) + })? { + let item = item.map_err(|e| { + format!("invalid dir entry in {}: {e}", from.display()) + })?; let item_path = item.path(); let item_name = @@ -90,7 +127,12 @@ fn copy_cleaned_listing_files( if item_path.is_dir() { // Don't copy `target` directories if item_name != "target" { - fs::create_dir(&output_item)?; + fs::create_dir(&output_item).map_err(|e| { + format!( + "Could not create output directory '{}': {e}", + output_item.display() + ) + })?; copy_cleaned_listing_files(item_path, output_item)?; } } else { @@ -105,7 +147,13 @@ fn copy_cleaned_listing_files( )?; } else { // Copy any non-Rust files without modification - fs::copy(item_path, output_item)?; + fs::copy(&item_path, &output_item).map_err(|e| { + format!( + "Could not copy from '{}' to '{}': {e}", + item_path.display(), + output_item.display() + ) + })?; } } } diff --git a/rust-toolchain b/rust-toolchain index 17420a571f..ea3769f296 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.79 +1.81 diff --git a/src/title-page.md b/src/title-page.md index dee3c84cb8..613de0ddd7 100644 --- a/src/title-page.md +++ b/src/title-page.md @@ -2,7 +2,7 @@ *by Steve Klabnik and Carol Nichols, with contributions from the Rust Community* -This version of the text assumes you’re using Rust 1.79.0 (released 2024-06-13) +This version of the text assumes you’re using Rust 1.81.0 (released 2024-09-04) or later. See the [“Installation” section of Chapter 1][install] to install or update Rust. From 299fd1f3e11dd61ca136fb51d713f6b0ba7515ff Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 11 Sep 2024 16:53:38 -0600 Subject: [PATCH 07/25] Clarify Cargo.toml generation with `cargo init`. --- src/ch01-03-hello-cargo.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ch01-03-hello-cargo.md b/src/ch01-03-hello-cargo.md index 288ed4d3da..dea721d38c 100644 --- a/src/ch01-03-hello-cargo.md +++ b/src/ch01-03-hello-cargo.md @@ -113,7 +113,8 @@ everything is in its place. If you started a project that doesn’t use Cargo, as we did with the “Hello, world!” project, you can convert it to a project that does use Cargo. Move the project code into the *src* directory and create an appropriate *Cargo.toml* -file, or run `cargo init`. +file. One easy way to get that *Cargo.toml* file is to run `cargo init`, which +will create it for you automatically. ### Building and Running a Cargo Project From d5932d2f98d62c5612dbeb71ba630b4f92c5347d Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 11 Sep 2024 17:22:59 -0600 Subject: [PATCH 08/25] Update build instructions: include mdbook plugins Fixes #4018 --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 8befc1b31e..9648db0ae0 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,16 @@ rust-lang/rust uses in [this file][rust-mdbook]. To get it: $ cargo install mdbook --locked --version ``` +The book also uses two mdbook plugins which are part of this repository. If you +do not install them, you will see warnings when building and the output will not +look right, but you *will* still be able to build the book. To use the plugins, +you should run: + +```bash +$ cargo install --locked --path packages/mdbook-trpl-listing +$ cargo install --locked --path packages/mdbook-trpl-note +``` + ## Building To build the book, type: From c552952e9fd1300b05080d1a761ceb8face681d7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Sat, 24 Aug 2024 08:26:56 -0600 Subject: [PATCH 09/25] Ch. 17: rename `trpl::block_on` to `trpl::run` The `block_on` name is what both Tokio and smol use, but it is a bit obscure from the point of view of introducing this material. `run` says much more clearly what it does *for the level we care about here*, I think. --- .../listing-17-04/src/main.rs | 2 +- .../listing-17-05/src/main.rs | 2 +- .../listing-17-06/src/main.rs | 2 +- .../listing-17-07/src/main.rs | 2 +- .../listing-17-08/src/main.rs | 2 +- .../listing-17-09/src/main.rs | 2 +- .../listing-17-10/src/main.rs | 2 +- .../listing-17-11/src/main.rs | 2 +- .../listing-17-12/src/main.rs | 2 +- .../listing-17-13/src/main.rs | 2 +- .../listing-17-14/src/main.rs | 2 +- .../listing-17-15/src/main.rs | 2 +- .../listing-17-16/src/main.rs | 2 +- .../listing-17-17/src/main.rs | 2 +- .../listing-17-18/src/main.rs | 2 +- .../listing-17-19/src/main.rs | 2 +- .../listing-17-20/src/main.rs | 2 +- .../listing-17-21/src/main.rs | 2 +- .../listing-17-22/src/main.rs | 2 +- .../listing-17-23/src/main.rs | 2 +- .../listing-17-24/src/main.rs | 2 +- .../listing-17-25/src/main.rs | 2 +- .../listing-17-26/src/main.rs | 2 +- .../listing-17-27/src/main.rs | 2 +- .../listing-17-28/src/main.rs | 2 +- .../listing-17-29/src/main.rs | 2 +- .../listing-17-30/src/main.rs | 2 +- .../listing-17-31/src/main.rs | 2 +- .../listing-17-32/src/main.rs | 2 +- .../listing-17-33/src/main.rs | 2 +- .../listing-17-34/src/main.rs | 2 +- .../listing-17-35/src/main.rs | 2 +- .../listing-17-36/src/main.rs | 2 +- .../listing-17-37/src/main.rs | 2 +- .../listing-17-38/src/main.rs | 2 +- .../listing-17-39/src/main.rs | 2 +- .../listing-17-40/src/main.rs | 2 +- packages/trpl/src/lib.rs | 2 +- packages/trpl/tests/integration/main.rs | 32 +++++++++---------- src/ch17-01-futures-and-syntax.md | 14 ++++---- src/ch17-02-concurrency-with-async.md | 13 ++++---- 41 files changed, 67 insertions(+), 68 deletions(-) diff --git a/listings/ch17-async-await/listing-17-04/src/main.rs b/listings/ch17-async-await/listing-17-04/src/main.rs index 563aee05b7..f3e685ac67 100644 --- a/listings/ch17-async-await/listing-17-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -2,7 +2,7 @@ extern crate trpl; // required for mdbook test // ANCHOR: main fn main() { - trpl::block_on(async { + trpl::run(async { hello("async").await; }); } diff --git a/listings/ch17-async-await/listing-17-05/src/main.rs b/listings/ch17-async-await/listing-17-05/src/main.rs index 2fe6a5f29d..8eb415ee73 100644 --- a/listings/ch17-async-await/listing-17-05/src/main.rs +++ b/listings/ch17-async-await/listing-17-05/src/main.rs @@ -4,7 +4,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); diff --git a/listings/ch17-async-await/listing-17-06/src/main.rs b/listings/ch17-async-await/listing-17-06/src/main.rs index 67c735fd39..5415e1fcee 100644 --- a/listings/ch17-async-await/listing-17-06/src/main.rs +++ b/listings/ch17-async-await/listing-17-06/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: handle let handle = trpl::spawn_task(async { for i in 1..10 { diff --git a/listings/ch17-async-await/listing-17-07/src/main.rs b/listings/ch17-async-await/listing-17-07/src/main.rs index ef52e32840..2cd5de9bae 100644 --- a/listings/ch17-async-await/listing-17-07/src/main.rs +++ b/listings/ch17-async-await/listing-17-07/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: join let fut1 = async { for i in 1..10 { diff --git a/listings/ch17-async-await/listing-17-08/src/main.rs b/listings/ch17-async-await/listing-17-08/src/main.rs index 743a22e239..56daddc10f 100644 --- a/listings/ch17-async-await/listing-17-08/src/main.rs +++ b/listings/ch17-async-await/listing-17-08/src/main.rs @@ -1,7 +1,7 @@ extern crate trpl; // required for mdbook test fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: channel let (tx, mut rx) = trpl::channel(); diff --git a/listings/ch17-async-await/listing-17-09/src/main.rs b/listings/ch17-async-await/listing-17-09/src/main.rs index 2a98d028bb..e11ae51787 100644 --- a/listings/ch17-async-await/listing-17-09/src/main.rs +++ b/listings/ch17-async-await/listing-17-09/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: many-messages let (tx, mut rx) = trpl::channel(); diff --git a/listings/ch17-async-await/listing-17-10/src/main.rs b/listings/ch17-async-await/listing-17-10/src/main.rs index 1eb0a163ef..5ada1d2f6d 100644 --- a/listings/ch17-async-await/listing-17-10/src/main.rs +++ b/listings/ch17-async-await/listing-17-10/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { let (tx, mut rx) = trpl::channel(); // ANCHOR: futures diff --git a/listings/ch17-async-await/listing-17-11/src/main.rs b/listings/ch17-async-await/listing-17-11/src/main.rs index 025ed3a1ab..95e6480677 100644 --- a/listings/ch17-async-await/listing-17-11/src/main.rs +++ b/listings/ch17-async-await/listing-17-11/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: with-move let (tx, mut rx) = trpl::channel(); diff --git a/listings/ch17-async-await/listing-17-12/src/main.rs b/listings/ch17-async-await/listing-17-12/src/main.rs index 03fa6a61b5..d5a2e56e34 100644 --- a/listings/ch17-async-await/listing-17-12/src/main.rs +++ b/listings/ch17-async-await/listing-17-12/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: here let (tx, mut rx) = trpl::channel(); diff --git a/listings/ch17-async-await/listing-17-13/src/main.rs b/listings/ch17-async-await/listing-17-13/src/main.rs index 87b244daa8..0bb425d366 100644 --- a/listings/ch17-async-await/listing-17-13/src/main.rs +++ b/listings/ch17-async-await/listing-17-13/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); diff --git a/listings/ch17-async-await/listing-17-14/src/main.rs b/listings/ch17-async-await/listing-17-14/src/main.rs index 684b174bdc..249ffd0f68 100644 --- a/listings/ch17-async-await/listing-17-14/src/main.rs +++ b/listings/ch17-async-await/listing-17-14/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); diff --git a/listings/ch17-async-await/listing-17-15/src/main.rs b/listings/ch17-async-await/listing-17-15/src/main.rs index 5bc9c2c3bd..9fefdcf463 100644 --- a/listings/ch17-async-await/listing-17-15/src/main.rs +++ b/listings/ch17-async-await/listing-17-15/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); diff --git a/listings/ch17-async-await/listing-17-16/src/main.rs b/listings/ch17-async-await/listing-17-16/src/main.rs index 020a4d37f3..1888a53568 100644 --- a/listings/ch17-async-await/listing-17-16/src/main.rs +++ b/listings/ch17-async-await/listing-17-16/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::{future::Future, time::Duration}; fn main() { - trpl::block_on(async { + trpl::run(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); diff --git a/listings/ch17-async-await/listing-17-17/src/main.rs b/listings/ch17-async-await/listing-17-17/src/main.rs index b7fed9b427..7773660519 100644 --- a/listings/ch17-async-await/listing-17-17/src/main.rs +++ b/listings/ch17-async-await/listing-17-17/src/main.rs @@ -7,7 +7,7 @@ use std::{ }; fn main() { - trpl::block_on(async { + trpl::run(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); diff --git a/listings/ch17-async-await/listing-17-18/src/main.rs b/listings/ch17-async-await/listing-17-18/src/main.rs index 2c5748960d..80f546b30d 100644 --- a/listings/ch17-async-await/listing-17-18/src/main.rs +++ b/listings/ch17-async-await/listing-17-18/src/main.rs @@ -7,7 +7,7 @@ use std::{ }; fn main() { - trpl::block_on(async { + trpl::run(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); diff --git a/listings/ch17-async-await/listing-17-19/src/main.rs b/listings/ch17-async-await/listing-17-19/src/main.rs index 2088dbe21a..12ab2704b2 100644 --- a/listings/ch17-async-await/listing-17-19/src/main.rs +++ b/listings/ch17-async-await/listing-17-19/src/main.rs @@ -1,7 +1,7 @@ extern crate trpl; // required for mdbook test fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: here let a = async { 1u32 }; let b = async { "Hello!" }; diff --git a/listings/ch17-async-await/listing-17-20/src/main.rs b/listings/ch17-async-await/listing-17-20/src/main.rs index 0ac89fe6c1..308c14a4ac 100644 --- a/listings/ch17-async-await/listing-17-20/src/main.rs +++ b/listings/ch17-async-await/listing-17-20/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: here let slow = async { println!("'slow' started."); diff --git a/listings/ch17-async-await/listing-17-21/src/main.rs b/listings/ch17-async-await/listing-17-21/src/main.rs index fa5cfe3c80..2dfb52b7d4 100644 --- a/listings/ch17-async-await/listing-17-21/src/main.rs +++ b/listings/ch17-async-await/listing-17-21/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::{thread, time::Duration}; fn main() { - trpl::block_on(async { + trpl::run(async { // We will call `slow` here later }); } diff --git a/listings/ch17-async-await/listing-17-22/src/main.rs b/listings/ch17-async-await/listing-17-22/src/main.rs index 55975462fa..391cf39e19 100644 --- a/listings/ch17-async-await/listing-17-22/src/main.rs +++ b/listings/ch17-async-await/listing-17-22/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::{thread, time::Duration}; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: slow-futures let a = async { println!("'a' started."); diff --git a/listings/ch17-async-await/listing-17-23/src/main.rs b/listings/ch17-async-await/listing-17-23/src/main.rs index f9c795fc0c..961431d396 100644 --- a/listings/ch17-async-await/listing-17-23/src/main.rs +++ b/listings/ch17-async-await/listing-17-23/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::{thread, time::Duration}; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: here let one_ms = Duration::from_millis(1); diff --git a/listings/ch17-async-await/listing-17-24/src/main.rs b/listings/ch17-async-await/listing-17-24/src/main.rs index e95e286a39..165022108b 100644 --- a/listings/ch17-async-await/listing-17-24/src/main.rs +++ b/listings/ch17-async-await/listing-17-24/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::{thread, time::Duration}; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: yields let a = async { println!("'a' started."); diff --git a/listings/ch17-async-await/listing-17-25/src/main.rs b/listings/ch17-async-await/listing-17-25/src/main.rs index eaea8509c3..31ce58d9e9 100644 --- a/listings/ch17-async-await/listing-17-25/src/main.rs +++ b/listings/ch17-async-await/listing-17-25/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::{Duration, Instant}; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: here let one_ns = Duration::from_nanos(1); let start = Instant::now(); diff --git a/listings/ch17-async-await/listing-17-26/src/main.rs b/listings/ch17-async-await/listing-17-26/src/main.rs index 58c83229d4..cdab724687 100644 --- a/listings/ch17-async-await/listing-17-26/src/main.rs +++ b/listings/ch17-async-await/listing-17-26/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::time::Duration; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: here let slow = async { trpl::sleep(Duration::from_millis(100)).await; diff --git a/listings/ch17-async-await/listing-17-27/src/main.rs b/listings/ch17-async-await/listing-17-27/src/main.rs index d30da0d226..6c2ae688e4 100644 --- a/listings/ch17-async-await/listing-17-27/src/main.rs +++ b/listings/ch17-async-await/listing-17-27/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use std::{future::Future, time::Duration}; fn main() { - trpl::block_on(async { + trpl::run(async { let slow = async { trpl::sleep(Duration::from_secs(5)).await; "Finally finished" diff --git a/listings/ch17-async-await/listing-17-28/src/main.rs b/listings/ch17-async-await/listing-17-28/src/main.rs index 20e81e77c4..d34a2a8f0e 100644 --- a/listings/ch17-async-await/listing-17-28/src/main.rs +++ b/listings/ch17-async-await/listing-17-28/src/main.rs @@ -5,7 +5,7 @@ use std::{future::Future, time::Duration}; use trpl::Either; fn main() { - trpl::block_on(async { + trpl::run(async { let slow = async { trpl::sleep(Duration::from_secs(5)).await; "Finally finished" diff --git a/listings/ch17-async-await/listing-17-29/src/main.rs b/listings/ch17-async-await/listing-17-29/src/main.rs index 7900b39ce4..faa6b6a1ca 100644 --- a/listings/ch17-async-await/listing-17-29/src/main.rs +++ b/listings/ch17-async-await/listing-17-29/src/main.rs @@ -1,7 +1,7 @@ extern crate trpl; // required for mdbook test fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: stream let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let iter = values.iter().map(|n| n * 2); diff --git a/listings/ch17-async-await/listing-17-30/src/main.rs b/listings/ch17-async-await/listing-17-30/src/main.rs index 8f8dd7d93f..0a7fc87c21 100644 --- a/listings/ch17-async-await/listing-17-30/src/main.rs +++ b/listings/ch17-async-await/listing-17-30/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use trpl::StreamExt; fn main() { - trpl::block_on(async { + trpl::run(async { let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let iter = values.iter().map(|n| n * 2); let mut stream = trpl::stream_from_iter(iter); diff --git a/listings/ch17-async-await/listing-17-31/src/main.rs b/listings/ch17-async-await/listing-17-31/src/main.rs index d312640b7f..017185bed5 100644 --- a/listings/ch17-async-await/listing-17-31/src/main.rs +++ b/listings/ch17-async-await/listing-17-31/src/main.rs @@ -3,7 +3,7 @@ extern crate trpl; // required for mdbook test use trpl::StreamExt; fn main() { - trpl::block_on(async { + trpl::run(async { let values = 1..101; let iter = values.map(|n| n * 2); let stream = trpl::stream_from_iter(iter); diff --git a/listings/ch17-async-await/listing-17-32/src/main.rs b/listings/ch17-async-await/listing-17-32/src/main.rs index dd1693790d..d9a7733d43 100644 --- a/listings/ch17-async-await/listing-17-32/src/main.rs +++ b/listings/ch17-async-await/listing-17-32/src/main.rs @@ -4,7 +4,7 @@ extern crate trpl; // required for mdbook test use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { let mut messages = get_messages(); while let Some(message) = messages.next().await { diff --git a/listings/ch17-async-await/listing-17-33/src/main.rs b/listings/ch17-async-await/listing-17-33/src/main.rs index 6ad2bc72f9..de919073f8 100644 --- a/listings/ch17-async-await/listing-17-33/src/main.rs +++ b/listings/ch17-async-await/listing-17-33/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { let mut messages = pin!(get_messages().timeout(Duration::from_millis(200))); diff --git a/listings/ch17-async-await/listing-17-34/src/main.rs b/listings/ch17-async-await/listing-17-34/src/main.rs index 7446a2e795..b4dda21d52 100644 --- a/listings/ch17-async-await/listing-17-34/src/main.rs +++ b/listings/ch17-async-await/listing-17-34/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { let mut messages = pin!(get_messages().timeout(Duration::from_millis(200))); diff --git a/listings/ch17-async-await/listing-17-35/src/main.rs b/listings/ch17-async-await/listing-17-35/src/main.rs index a2b36ca487..13bd0b1121 100644 --- a/listings/ch17-async-await/listing-17-35/src/main.rs +++ b/listings/ch17-async-await/listing-17-35/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { let mut messages = pin!(get_messages().timeout(Duration::from_millis(200))); diff --git a/listings/ch17-async-await/listing-17-36/src/main.rs b/listings/ch17-async-await/listing-17-36/src/main.rs index b4cb9c094c..bc10dd48c9 100644 --- a/listings/ch17-async-await/listing-17-36/src/main.rs +++ b/listings/ch17-async-await/listing-17-36/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: main let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals(); diff --git a/listings/ch17-async-await/listing-17-37/src/main.rs b/listings/ch17-async-await/listing-17-37/src/main.rs index 4e28174860..72da09d75f 100644 --- a/listings/ch17-async-await/listing-17-37/src/main.rs +++ b/listings/ch17-async-await/listing-17-37/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: main let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() diff --git a/listings/ch17-async-await/listing-17-38/src/main.rs b/listings/ch17-async-await/listing-17-38/src/main.rs index 899d14fc23..a5f51618f5 100644 --- a/listings/ch17-async-await/listing-17-38/src/main.rs +++ b/listings/ch17-async-await/listing-17-38/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { // ANCHOR: throttle let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() diff --git a/listings/ch17-async-await/listing-17-39/src/main.rs b/listings/ch17-async-await/listing-17-39/src/main.rs index 1b4e686ea2..ecf406e93d 100644 --- a/listings/ch17-async-await/listing-17-39/src/main.rs +++ b/listings/ch17-async-await/listing-17-39/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() .map(|count| format!("Interval #{count}")) diff --git a/listings/ch17-async-await/listing-17-40/src/main.rs b/listings/ch17-async-await/listing-17-40/src/main.rs index 7bd605d528..f1f3d4b0c0 100644 --- a/listings/ch17-async-await/listing-17-40/src/main.rs +++ b/listings/ch17-async-await/listing-17-40/src/main.rs @@ -5,7 +5,7 @@ use std::{pin::pin, thread, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { - trpl::block_on(async { + trpl::run(async { let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() .map(|count| format!("Interval #{count}")) diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index e096d9d2cd..6d3a4bdaab 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -63,7 +63,7 @@ pub use tokio_stream::{ /// /// - Not *that* far off from what Tokio itself does under the hood in its own /// `tokio::main` macro for supporting `async fn main`. -pub fn block_on(future: F) -> F::Output { +pub fn run(future: F) -> F::Output { let rt = Runtime::new().unwrap(); rt.block_on(future) } diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index 639c460eb6..b67d8680a7 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -14,20 +14,20 @@ use std::{pin::Pin, time::Duration}; use futures::Future; use trpl::{Either, Receiver, Sender}; -/// This test is foundational for all the others, as they depend on `block_on`. +/// This test is foundational for all the others, as they depend on `run`. /// /// If we mess this up, *all* the tests below will fail -- so by the same token, /// if all the tests below are failing, this one probably is too; fix it and the /// others will likely start working again. #[test] -fn re_exported_block_on_works() { - let val = trpl::block_on(async { "Hello" }); +fn re_exported_run_works() { + let val = trpl::run(async { "Hello" }); assert_eq!(val, "Hello"); } #[test] fn re_exported_spawn_works() { - let result = trpl::block_on(async { + let result = trpl::run(async { let handle_a = trpl::spawn_task(async { "Hello" }); let handle_b = trpl::spawn_task(async { "Goodbye" }); vec![handle_a.await.unwrap(), handle_b.await.unwrap()] @@ -38,7 +38,7 @@ fn re_exported_spawn_works() { #[test] fn re_exported_sleep_works() { - let val = trpl::block_on(async { + let val = trpl::run(async { trpl::sleep(Duration::from_micros(1)).await; "Done!" }); @@ -47,7 +47,7 @@ fn re_exported_sleep_works() { #[test] fn re_exported_channel_apis_work() { - trpl::block_on(async { + trpl::run(async { // Explicitly naming the type to confirm the re-exports are aligned. let (tx, mut rx): (Sender<&str>, Receiver<&str>) = trpl::channel(); @@ -67,7 +67,7 @@ mod re_exported_join_apis_work { #[test] fn join_fn() { - let result = trpl::block_on(async { + let result = trpl::run(async { let a = async { 1 }; let b = async { 2 }; trpl::join(a, b).await @@ -78,7 +78,7 @@ mod re_exported_join_apis_work { #[test] fn join3_fn() { - let result = trpl::block_on(async { + let result = trpl::run(async { let a = async { 1 }; let b = async { 2 }; let c = async { 3 }; @@ -91,7 +91,7 @@ mod re_exported_join_apis_work { #[test] fn join_all_fn() { - let result = trpl::block_on(async { + let result = trpl::run(async { let a = async { format!("{}", 1) }; let b = async { "Hello".to_string() }; @@ -117,7 +117,7 @@ mod re_exported_join_apis_work { #[test] fn join_macro() { - let result = trpl::block_on(async { + let result = trpl::run(async { let a = async { 1 }; let b = async { "Hello" }; @@ -139,7 +139,7 @@ fn race() { #[derive(Debug, PartialEq)] struct Fast; - let val = trpl::block_on(async { + let val = trpl::run(async { let slow = async { trpl::sleep(Duration::from_millis(1_000)).await; Slow @@ -158,7 +158,7 @@ fn race() { #[test] fn yield_now() { - let result = trpl::block_on(async { + let result = trpl::run(async { trpl::yield_now().await; "done" }); @@ -168,7 +168,7 @@ fn yield_now() { #[test] fn read_to_string() { - let result = trpl::block_on(async { + let result = trpl::run(async { trpl::read_to_string("tests/integration/to-read.txt") .await .unwrap() @@ -181,7 +181,7 @@ fn read_to_string() { fn stream_iter() { use trpl::StreamExt; - let result = trpl::block_on(async { + let result = trpl::run(async { let ns = vec![1, 2, 3]; let mut stream = trpl::stream_from_iter(ns); let mut result = vec![]; @@ -202,7 +202,7 @@ fn receiver_stream() { use trpl::ReceiverStream; use trpl::StreamExt; - let result: Vec = trpl::block_on(async { + let result: Vec = trpl::run(async { println!("startup"); let (tx, rx) = trpl::channel(); let rx_stream = ReceiverStream::new(rx); @@ -220,7 +220,7 @@ fn receiver_stream() { fn re_exported_interval_stream_works() { use trpl::{IntervalStream, StreamExt}; - trpl::block_on(async { + trpl::run(async { let mut interval_stream = IntervalStream::new(trpl::interval(Duration::from_millis(1))) .take(1); diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 014a6dd33b..3ee9c3ebca 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -174,13 +174,13 @@ $ cargo add trpl ``` Then, in our `main` function, let’s wrap the call to `hello` with the -`trpl::block_on` function, which takes in a `Future` and runs it until it -completes. Since `hello` returns a `Future`, we could simply wrap it directly in -`trpl::block_on`. However, for most of the examples in the chapter, we will be +`trpl::run` function, which takes in a `Future` and runs it until it completes. +Since `hello` returns a `Future`, we could simply wrap it directly in +`trpl::run`. However, for most of the examples in the chapter, we will be doing more than just one async function call, so instead we will pass an `async` block and explicitly await the result of calling `hello`. -+ ```rust {{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:main}} @@ -254,9 +254,9 @@ chapter! Now we can understand why the compiler stopped us from making `main` itself an async function in Listing 17-3. If `main` were an async function, something else would need to call `poll()` on whatever `main` returned, but main is the -starting point for the program! Instead, we use the `trpl::block_on` function, -which sets up a runtime and polls the `Future` returned by `hello` until it -returns `Ready`. +starting point for the program! Instead, we use the `trpl::run` function, which +sets up a runtime and polls the `Future` returned by `hello` until it returns +`Ready`. > Note: We have skipped over some interesting implementation details in this > discussion, because you should not have to think about them when writing Rust. diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 4ac808a86d..5bebbc20dc 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -26,13 +26,12 @@ to implement the same counting example as with threads, in Listing 17-5. -As our starting point, we set up our `main` function with `trpl::block_on`, so +As our starting point, we set up our `main` function with `trpl::run`, so that our top-level function can be async. > Note: From this point forward in the chapter, every example will include this -> exact same wrapping code with `trpl::block_on` in `main`, so we will often -> skip it just like we do with `main`. Don’t forget to include it in your -> code! +> exact same wrapping code with `trpl::run` in `main`, so we will often skip it +> just like we do with `main`. Don’t forget to include it in your code! Then we write two loops within that block, each with a `trpl::sleep` call in it, which waits for half a second (500 milliseconds) before sending the next @@ -192,9 +191,9 @@ received or the send side of the channel closes. By contrast, we do not await the `send` call, because it does not block. It does not need to, because the channel we are sending it into is unbounded. -> Note: Since this is all wrapped in a `trpl::block_on`, this would effectively -> block anything happening outside that. That is the whole point of `block_on`, -> in fact: to allow you to *choose* where to block on some set of async code to +> Note: Since this is all wrapped in a `trpl::run`, this would effectively block +> anything happening outside that. That is the whole point of `block_on`, in +> fact: to allow you to *choose* where to block on some set of async code to > transition between sync and async code. However, *within* this block, the > `.await` does not block further operations—as we will see! From cd12a1e853b9e0edfc1ad72845ee0c4bc4209454 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 10 Sep 2024 07:22:20 -0600 Subject: [PATCH 10/25] Ch. 17: more edits for first three sections These make up *most* of the rest of the edits I caught while rereading which are not *major structural revisions*, along with some of the bits required for those major structural revisions. --- src/ch17-00-async-await.md | 11 +++-- src/ch17-01-futures-and-syntax.md | 28 ++++------- src/ch17-02-concurrency-with-async.md | 70 ++++++++++++++------------- src/ch17-07-wip.md | 8 +++ 4 files changed, 61 insertions(+), 56 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index bb289fdbf7..5540f0b795 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -16,8 +16,8 @@ let you get other work done along the way. The file download is different. It does not take up very much CPU time. Instead, the CPU needs to wait on data to arrive from the network. While you can start -reading the data once some of it arrives, it might take a while for the rest to -arrive. Even once the data has all arrived, a video can be quite large, so it +reading the data once some of it is present, it might take a while for the rest +to show up. Even once the data is all present, a video can be quite large, so it might take some time to load it all. Maybe it only takes a second or two—but that is a very long time for a modern processor, which can do billions of operations every second. It would be nice to be able to put the CPU to use for @@ -54,9 +54,10 @@ data that they are processing is completely ready. > *non*-blocking. We could avoid blocking our main thread by spawning a dedicated thread to -download each file. But it would be nicer if the call were not blocking in the -first place. It would also be nice if we could write in the same direct style -we use in blocking code. Something like this: +download each file. However, we would eventually find that the overhead of those +threads was a problem. It would also be nicer if the call were not blocking in +the first place. Last but not least, it would be better if we could write in the +same direct style we use in blocking code. Something like this: ```rust,ignore,does_not_compile let data = fetch_data_from(url).await; diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 3ee9c3ebca..dc53ac9eda 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -195,7 +195,7 @@ When we run this, we get the behavior we might have expected initially: ``` Phew: we finally have some working async code! Let’s briefly turn our attention -to how the `Future` trait works. +to how futures actually work. A *future* is a data structure which manages the state of some async operation. It is called a “future” because it represents work which may not be ready now, @@ -204,13 +204,11 @@ in many languages, sometimes under other names like “task” or “promise”. provides a `Future` trait as a building block so different async operations can be implemented with different data structures, but with a common interface. -Most of the time when writing async Rust, we don’t work directly with the -`Future` trait. Instead, we use the `async` and `await` keywords we saw above. -Rust does the work of compiling them into the appropriate calls to the `Future` -trait, much like it does with `for` loops and the `Iterator` trait. - -We most often interact with the futures created via async blocks, but you can -also implement `Future` on your own data types. Indeed, many of the functions we +Most of the time when writing async Rust, we use the `async` and `await` +keywords we saw above. Rust compiles them into equivalent code using the +`Future` trait, much like it compiles `for` loops into equivalent code using the +`Iterator` trait. Because Rust provides the `Future` trait, though, you can also +implement it for your own data types when you need to. Many of the functions we will see throughout this chapter return types with their own implementations of `Future`. We will return to the definition of the trait at the end of the chapter and dig into more of how it works, but this is enough detail to keep us @@ -258,17 +256,11 @@ starting point for the program! Instead, we use the `trpl::run` function, which sets up a runtime and polls the `Future` returned by `hello` until it returns `Ready`. -> Note: We have skipped over some interesting implementation details in this -> discussion, because you should not have to think about them when writing Rust. -> -> If you want to understand how things work “under the hood,” though, the -> official [_Asynchronous Programming in Rust_][async-book] book covers them: -> -> - [Chapter 2: Under the Hood: Executing Futures and Tasks][under-the-hood] -> - [Chapter 4: Pinning][pinning]. +> Note: We skipped over most of the details of how the `Future` trait works so +> far. We will come back to some of those later in the chapter! -Now that you know the basics of how futures and runtimes work, we can see some -of the things we can *do* with async. +Now that you know the basics of working with futures, we can dig into more of +the things we can *do* with async. [impl-trait]: ch10-02-traits.html#traits-as-parameters [iterators-lazy]: ch13-02-iterators.html diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 5bebbc20dc..b785e7dc76 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -7,8 +7,9 @@ threads and futures. In many cases, the APIs for working with concurrency using async are very similar to those for using threads. In other cases, they end up being shaped -fairly differently. Even when the APIs look similar, they often have different -behavior and they nearly always have different performance characteristics. +quite differently. Even when the APIs *look* similar between threads and async, +they often have different behavior—and they nearly always have different +performance characteristics. ### Counting @@ -61,7 +62,11 @@ hi number 5 from the first task! This version stops as soon as the for loop in the body of the main async block finishes, because the task spawned by `spawn_task` is shut down when the main function ends. If you want to run all the way to the completion of the task, you -will need to use a join handle to wait for the first task to complete. +will need to use a join handle to wait for the first task to complete. With +threads, we used the `join` method to “block” until the thread was done running. +In Listing 17-6, we can use `await` to do the same thing, because the task +handle itself is a future. Its `Output` type is a `Result`, so we also unwrap it +after awaiting it. @@ -71,11 +76,7 @@ will need to use a join handle to wait for the first task to complete. -With threads, we used the `join` method to “block” until the thread was done -running. In Listing 17-6, we can use `await` to do the same thing, because the -task handle itself is a future. Its `Output` type is a `Result`, so we also -unwrap it after awaiting it. This updated version runs till *both* loops -finish. +This updated version runs till *both* loops finish. @@ -304,9 +308,9 @@ in Chapter 16, we saw that we often need to use move data into closures when working with threads. The same basic dynamics apply to async blocks, so the `move` keyword works with async blocks just like it does with closures. -In Listing 17-11, we change the async block for sending messages an `async move` -block. When we run *this* version of the code, it shuts down gracefully after -the last message is sent. +In Listing 17-11, we change the async block for sending messages from a plain +`async` block to an `async move` block. When we run *this* version of the code, +it shuts down gracefully after the last message is sent and received. diff --git a/src/ch17-07-wip.md b/src/ch17-07-wip.md index 8f3f569203..a29543b628 100644 --- a/src/ch17-07-wip.md +++ b/src/ch17-07-wip.md @@ -89,6 +89,14 @@ one of the main jobs for a runtime. --- +> Note: If you want to understand how things work “under the hood,” the official +> [_Asynchronous Programming in Rust_][async-book] book covers them: +> +> - [Chapter 2: Under the Hood: Executing Futures and Tasks][under-the-hood] +> - [Chapter 4: Pinning][pinning]. + +--- + Recall our description of how `rx.recv()` waits in the [Counting][counting] section. The `recv()` call returns a `Future`, and awaiting it polls it. In our initial discussion, we noted that a runtime will pause the future until it is From 9b13b95ca11c6c272d8f8b081209488a310991fa Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 10 Sep 2024 16:03:08 -0600 Subject: [PATCH 11/25] Upgrade Ch. 17 listings for Rust 1.81 --- .../ch17-async-await/listing-17-01/output.txt | 6 +- .../ch17-async-await/listing-17-02/output.txt | 10 +-- .../ch17-async-await/listing-17-03/output.txt | 6 +- .../ch17-async-await/listing-17-04/output.txt | 28 +------ .../ch17-async-await/listing-17-16/output.txt | 83 +------------------ .../ch17-async-await/listing-17-18/output.txt | 66 +++------------ .../no-listing-stream-ext/output.txt | 14 +--- src/ch17-03-more-futures.md | 13 +-- 8 files changed, 28 insertions(+), 198 deletions(-) diff --git a/listings/ch17-async-await/listing-17-01/output.txt b/listings/ch17-async-await/listing-17-01/output.txt index 46e6cd3111..92b5d5e4d5 100644 --- a/listings/ch17-async-await/listing-17-01/output.txt +++ b/listings/ch17-async-await/listing-17-01/output.txt @@ -1,9 +1,9 @@ $ cargo run - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-01) + Compiling async_await v0.1.0 (file:///projects/async_await) warning: unused implementer of `Future` that must be used - --> src/main.rs:3:5 + --> src/main.rs:2:5 | -3 | hello("async"); +2 | hello("async"); | ^^^^^^^^^^^^^^ | = note: futures do nothing unless you `.await` or poll them diff --git a/listings/ch17-async-await/listing-17-02/output.txt b/listings/ch17-async-await/listing-17-02/output.txt index 5400d6f5e1..d2809af719 100644 --- a/listings/ch17-async-await/listing-17-02/output.txt +++ b/listings/ch17-async-await/listing-17-02/output.txt @@ -1,11 +1,11 @@ $ cargo run - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-02) + Compiling async_await v0.1.0 (file:///projects/async_await) error[E0728]: `await` is only allowed inside `async` functions and blocks - --> src/main.rs:3:20 + --> src/main.rs:2:20 | -2 | fn main() { - | ---- this is not `async` -3 | hello("async").await; +1 | fn main() { + | --------- this is not `async` +2 | hello("async").await; | ^^^^^ only allowed inside `async` functions and blocks For more information about this error, try `rustc --explain E0728`. diff --git a/listings/ch17-async-await/listing-17-03/output.txt b/listings/ch17-async-await/listing-17-03/output.txt index 17922a261c..e61d87f805 100644 --- a/listings/ch17-async-await/listing-17-03/output.txt +++ b/listings/ch17-async-await/listing-17-03/output.txt @@ -1,9 +1,9 @@ $ cargo run - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-03-fix) + Compiling async_await v0.1.0 (file:///projects/async_await) error[E0752]: `main` function is not allowed to be `async` - --> src/main.rs:2:1 + --> src/main.rs:1:1 | -2 | async fn main() { +1 | async fn main() { | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` For more information about this error, try `rustc --explain E0752`. diff --git a/listings/ch17-async-await/listing-17-04/output.txt b/listings/ch17-async-await/listing-17-04/output.txt index d0d2eb5d91..b928fb6020 100644 --- a/listings/ch17-async-await/listing-17-04/output.txt +++ b/listings/ch17-async-await/listing-17-04/output.txt @@ -1,27 +1 @@ -cargo run - Compiling proc-macro2 v1.0.85 - Compiling unicode-ident v1.0.12 - Compiling autocfg v1.3.0 - Compiling futures-sink v0.3.30 - Compiling pin-project-lite v0.2.14 - Compiling libc v0.2.155 - Compiling futures-core v0.3.30 - Compiling memchr v2.7.2 - Compiling pin-utils v0.1.0 - Compiling futures-io v0.3.30 - Compiling futures-task v0.3.30 - Compiling futures-channel v0.3.30 - Compiling slab v0.4.9 - Compiling num_cpus v1.16.0 - Compiling tokio v1.38.0 - Compiling quote v1.0.36 - Compiling syn v2.0.66 - Compiling futures-macro v0.3.30 - Compiling futures-util v0.3.30 - Compiling futures-executor v0.3.30 - Compiling futures v0.3.30 - Compiling trpl v0.1.0 (/Users/chris/dev/rust-lang/book/packages/trpl) - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-03) - Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.91s - Running `target/debug/async_await` -Hello, async! \ No newline at end of file +$ diff --git a/listings/ch17-async-await/listing-17-16/output.txt b/listings/ch17-async-await/listing-17-16/output.txt index 1fcc787041..b928fb6020 100644 --- a/listings/ch17-async-await/listing-17-16/output.txt +++ b/listings/ch17-async-await/listing-17-16/output.txt @@ -1,82 +1 @@ -cargo run - Compiling proc-macro2 v1.0.82 - Compiling unicode-ident v1.0.12 - Compiling autocfg v1.3.0 - Compiling futures-core v0.3.30 - Compiling pin-project-lite v0.2.14 - Compiling libc v0.2.154 - Compiling futures-sink v0.3.30 - Compiling memchr v2.7.2 - Compiling futures-task v0.3.30 - Compiling futures-io v0.3.30 - Compiling futures-channel v0.3.30 - Compiling pin-utils v0.1.0 - Compiling slab v0.4.9 - Compiling num_cpus v1.16.0 - Compiling tokio v1.37.0 - Compiling quote v1.0.36 - Compiling syn v2.0.63 - Compiling futures-macro v0.3.30 - Compiling futures-util v0.3.30 - Compiling futures-executor v0.3.30 - Compiling futures v0.3.30 - Compiling trpl v0.1.0 (/Users/chris/dev/rust-lang/book/packages/trpl) - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-20) -error[E0277]: `dyn std::future::Future` cannot be unpinned - --> src/main.rs:47:24 - | -47 | trpl::join_all(futures).await; - | -------------- ^^^^^^^ the trait `Unpin` is not implemented for `dyn std::future::Future`, which is required by `Box>: std::future::Future` - | | - | required by a bound introduced by this call - | - = note: consider using the `pin!` macro - consider using `Box::pin` if you need to access the pinned value outside of the current scope - = note: required for `Box>` to implement `std::future::Future` -note: required by a bound in `join_all` - --> /Users/chris/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:105:14 - | -102 | pub fn join_all(iter: I) -> JoinAll - | -------- required by a bound in this function -... -105 | I::Item: Future, - | ^^^^^^ required by this bound in `join_all` - -error[E0277]: `dyn std::future::Future` cannot be unpinned - --> src/main.rs:47:9 - | -47 | trpl::join_all(futures).await; - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `dyn std::future::Future`, which is required by `Box>: std::future::Future` - | - = note: consider using the `pin!` macro - consider using `Box::pin` if you need to access the pinned value outside of the current scope - = note: required for `Box>` to implement `std::future::Future` -note: required by a bound in `JoinAll` - --> /Users/chris/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:29:8 - | -27 | pub struct JoinAll - | ------- required by a bound in this struct -28 | where -29 | F: Future, - | ^^^^^^ required by this bound in `JoinAll` - -error[E0277]: `dyn std::future::Future` cannot be unpinned - --> src/main.rs:47:33 - | -47 | trpl::join_all(futures).await; - | ^^^^^ the trait `Unpin` is not implemented for `dyn std::future::Future`, which is required by `Box>: std::future::Future` - | - = note: consider using the `pin!` macro - consider using `Box::pin` if you need to access the pinned value outside of the current scope - = note: required for `Box>` to implement `std::future::Future` -note: required by a bound in `JoinAll` - --> /Users/chris/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:29:8 - | -27 | pub struct JoinAll - | ------- required by a bound in this struct -28 | where -29 | F: Future, - | ^^^^^^ required by this bound in `JoinAll` - -For more information about this error, try `rustc --explain E0277`. -error: could not compile `async_await` (bin "async_await") due to 3 previous errors +$ diff --git a/listings/ch17-async-await/listing-17-18/output.txt b/listings/ch17-async-await/listing-17-18/output.txt index 365d1f0145..f6a657d5ae 100644 --- a/listings/ch17-async-await/listing-17-18/output.txt +++ b/listings/ch17-async-await/listing-17-18/output.txt @@ -1,54 +1,14 @@ $ cargo run - Updating crates.io index - Compiling proc-macro2 v1.0.82 - Compiling unicode-ident v1.0.12 - Compiling autocfg v1.3.0 - Compiling pin-project-lite v0.2.14 - Compiling libc v0.2.154 - Compiling futures-core v0.3.30 - Compiling futures-sink v0.3.30 - Compiling futures-task v0.3.30 - Compiling futures-io v0.3.30 - Compiling pin-utils v0.1.0 - Compiling memchr v2.7.2 - Compiling futures-channel v0.3.30 - Compiling slab v0.4.9 - Compiling num_cpus v1.16.0 - Compiling quote v1.0.36 - Compiling tokio v1.37.0 - Compiling syn v2.0.63 - Compiling tokio-stream v0.1.15 - Compiling futures-macro v0.3.30 - Compiling futures-util v0.3.30 - Compiling futures-executor v0.3.30 - Compiling futures v0.3.30 - Compiling trpl v0.1.0 (/Users/chris/dev/rust-lang/book/packages/trpl) - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-14) -error[E0308]: mismatched types - --> src/main.rs:43:37 - | -8 | let tx1_fut = async move { - | _______________________- -9 | | let vals = vec![ -10 | | String::from("hi"), -11 | | String::from("from"), -... | -19 | | } -20 | | }; - | |_________- the expected `async` block -21 | -22 | let rx_fut = async { - | ______________________- -23 | | while let Some(value) = rx.recv().await { -24 | | println!("received '{value}'"); -25 | | } -26 | | }; - | |_________- the found `async` block -... -43 | let futures = vec![tx1_fut, rx_fut, tx_fut]; - | ^^^^^^ expected `async` block, found a different `async` block - | - = note: expected `async` block `{async block@src/main.rs:8:23: 20:10}` - found `async` block `{async block@src/main.rs:22:22: 26:10}` - = note: no two async blocks, even if identical, have the same type - = help: consider pinning your async block and and casting it to a trait object +error: failed to get `trpl` as a dependency of package `async_await v0.1.0 (/Users/chris/dev/rust-lang/book/tmp/listings/ch17-async-await/listing-17-18)` + +Caused by: + failed to load source for dependency `trpl` + +Caused by: + Unable to update /Users/chris/dev/rust-lang/book/tmp/packages/trpl + +Caused by: + failed to read `/Users/chris/dev/rust-lang/book/tmp/packages/trpl/Cargo.toml` + +Caused by: + No such file or directory (os error 2) diff --git a/listings/ch17-async-await/no-listing-stream-ext/output.txt b/listings/ch17-async-await/no-listing-stream-ext/output.txt index 46e6cd3111..10a18bc488 100644 --- a/listings/ch17-async-await/no-listing-stream-ext/output.txt +++ b/listings/ch17-async-await/no-listing-stream-ext/output.txt @@ -1,14 +1,2 @@ $ cargo run - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-01) -warning: unused implementer of `Future` that must be used - --> src/main.rs:3:5 - | -3 | hello("async"); - | ^^^^^^^^^^^^^^ - | - = note: futures do nothing unless you `.await` or poll them - = note: `#[warn(unused_must_use)]` on by default - -warning: `async_await` (bin "async_await") generated 1 warning - Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.21s - Running `target/debug/async_await` +error: a bin target must be available for `cargo run` diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index b27e68ad73..461f9e4c9e 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -40,18 +40,7 @@ Unfortunately, this does not compile. Instead, we get this error: From 3cfdf2d66a40ca2739df1e39a8595ad1a1fa649e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 10 Sep 2024 15:59:07 -0600 Subject: [PATCH 12/25] Ch. 17: rework 17.03 (and overall structure) from my own analysis --- .../listing-17-18/src/main.rs | 13 +- src/ch17-03-more-futures.md | 160 ++---------------- src/ch17-07-wip.md | 139 +++++++++++++++ 3 files changed, 162 insertions(+), 150 deletions(-) diff --git a/listings/ch17-async-await/listing-17-18/src/main.rs b/listings/ch17-async-await/listing-17-18/src/main.rs index 80f546b30d..c5ccc0b5bd 100644 --- a/listings/ch17-async-await/listing-17-18/src/main.rs +++ b/listings/ch17-async-await/listing-17-18/src/main.rs @@ -11,7 +11,10 @@ fn main() { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); + // ANCHOR: here let tx1_fut = pin!(async move { + // snip... + // ANCHOR_END: here let vals = vec![ String::from("hi"), String::from("from"), @@ -23,15 +26,23 @@ fn main() { tx1.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } + // ANCHOR: here }); + // ANCHOR_END: here + // ANCHOR: here let rx_fut = pin!(async { + // snip... + // ANCHOR_END: here while let Some(value) = rx.recv().await { println!("received '{value}'"); } + // ANCHOR: here }); let tx_fut = pin!(async move { + // snip... + // ANCHOR_END: here let vals = vec![ String::from("more"), String::from("messages"), @@ -43,9 +54,9 @@ fn main() { tx.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } + // ANCHOR: here }); - // ANCHOR: here let futures: Vec>> = vec![tx1_fut, rx_fut, tx_fut]; // ANCHOR_END: here diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 461f9e4c9e..b48247e512 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -19,7 +19,7 @@ This is definitely a nice improvement over needing to swap between `join` and `join3` and `join4` and so on! However, even this macro form only works when we know the number of futures ahead of time. In real-world Rust, though, pushing futures into a collection and then waiting on some or all the futures in that -collection to complete is a very common pattern. +collection to complete is a common pattern. To check all the futures in some collection, we will need to iterate over and join on *all* of them. The `trpl::join_all` function accepts any type which @@ -44,15 +44,6 @@ copy just the compiler error --> - - -> Note: Beta readers, the error version shown here is landing in Rust 1.81.0! -> If you are using an earlier version, you will see a *much* less helpful error -> message here. We fixed it as part of writing this chapter! - ```text error[E0308]: mismatched types --> src/main.rs:43:37 @@ -213,140 +204,11 @@ For more information about an error, try `rustc --explain E0277`. That is a *lot* to digest, so let’s pull it apart. The first part of the message tell us that the first async block (`src/main.rs:8:23: 20:10`) does not implement the `Unpin` trait, and suggests using `pin!` or `Box::pin` to resolve -it. The rest of the message tells us *why* that is required: the `JoinAll` -struct returned by `trpl::join_all` is generic over a type `F` which must -implement the `Future` trait, directly awaiting a Future requires that the -future implement the `Unpin` trait. Understanding this error means we need to -dive into a little more of how the `Future` type actually works, in particular -the idea of *pinning*. - -### Pinning and the Pin and Unpin Traits - - - -Let’s look again at the definition of `Future`, focusing now on its `poll` -method’s `self` type: - -```rust -use std::pin::Pin; -use std::task::{Context, Poll}; - -pub trait Future { - type Output; - - // Required method - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; -} -``` - -This is the first time we have seen a method where `self` has a type annotation -like this. When we specify the type of `self` like this, we are telling Rust -what type `self` must be to call this method. These kinds of type annotations -for `self` are similar to those for other function parameters, but with the -restriction that the type annotation has to be the type on which the method is -implemented, or a reference or smart pointer to that type. We will see more on -this syntax in Chapter 18. For now, it is enough to know that if we want to poll -a future (to check whether it is `Pending` or `Ready(Output)`), we need a -mutable reference to the type, which is wrapped in a `Pin`. - -`Pin` is a smart pointer, much like `Box`, `Rc`, and the others we saw in -Chapter 15. Unlike those, however, `Pin` only works with *other pointer types* -like reference (`&` and `&mut`) and smart pointers (`Box`, `Rc`, and so on). To -be precise, `Pin` works with types which implement the `Deref` or `DerefMut` -traits, which we covered in Chapter 15. You can think of this restriction as -equivalent to only working with pointers, though, since implementing `Deref` or -`DerefMut` means your type behaves like a pointer type. - -Recalling that `.await` is implemented in terms of calls to `poll()`, this -starts to explain the error message we saw above—but that was in terms of -`Unpin`, not `Pin`. So what exactly are `Pin` and `Unpin`, how do they relate, -and why does `Future` need `self` to be in a `Pin` type to call `poll`? - -In [“What Are Futures”][what-are-futures], we described how a series of await -points in a future get compiled into a state machine—and noted how the compiler -helps make sure that state machine follows all of Rust’s normal rules around -safety, including borrowing and ownership. To make that work, Rust looks at what -data is needed between each await point and the next await point or the end of -the async block. It then creates a corresponding variant in the state machine it -creates. Each variant gets the access it needs to the data that will be used in -that section of the source code, whether by taking ownership of that data or by -getting a mutable or immutable reference to it. - -So far so good: if we get anything wrong about the ownership or references in a -given async block, the borrow checker will tell us. When we want to move around -the future that corresponds to that block—like moving it into a `Vec` to pass to -`join_all`—things get trickier. - -When we move a future—whether by pushing into a data structure to use as an -iterator with `join_all`, or returning them from a function—that actually means -moving the state machine Rust creates for us. And unlike most other types in -Rust, the futures Rust creates for async blocks can end up with references to -themselves in the fields of any given variant. Any object which has a reference -to itself is unsafe to move, though, because references always point to the -actual memory address of the thing they refer to. If you move the data structure -itself, you *have* to update any references to it, or they will be left pointing -to the old location. - -In principle, you could make the Rust compiler try to update every reference to -an object every time it gets moved. That would potentially be a lot of -performance overhead, especially given there can be a whole web of references -that need updating. On the other hand, if we could make sure the data structure -in question *does not move in memory*, we do not have to update any references. -And this is exactly what Rust’s borrow checker already guarantees: you cannot -move an item which has any active references to it using safe code. - -`Pin` builds on that to give us the exact guarantee we need. When we *pin* a -value by wrapping a pointer to it in `Pin`, it can no longer move. Thus, if you -have `Pin>`, you actually pin the `SomeType` value, *not* the -`Box` pointer. In fact, the pinned box pointer can move around freely. Remember: -we care about making sure the data ultimately being referenced stays in its -place. If a pointer moves around, but the data it points to is in the same -place, there is no problem. - -However, most types are perfectly safe to move around, even if they happen to be -behind a `Pin` pointer. We only need to think about pinning when items have -internal references. Primitive values like numbers and booleans do not have any -internal structure like that, so they are obviously safe. Neither do most types -you normally work with in Rust. A `Vec`, for example, does not have any internal -references it needs to keep up to date this way, so you can move it around -without worrying. If you have a `Pin>`, you would have to do -everything via Pin’s safe but restrictive APIs, even though a `Vec` is -always safe to move if there are no other references to it. We need a way to -tell the compiler that it is actually just fine to move items around in cases -like these. For that, we have `Unpin`. - -`Unpin` is a marker trait, like `Send` and `Sync`, which we saw in Chapter 16. -Recall that marker traits have no functionality of their own. They exist only to -tell the compiler that it is safe to use the type which implements a given trait -in a particular context. `Unpin` informs the compiler that a given type does -*not* need to uphold any particular guarantees about whether the value in -question can be moved. - -Just like `Send` and `Sync`, the compiler implements `Unpin` automatically for -all types where it can prove it is safe. Implementing `Unpin` manually is unsafe -because it requires *you* to uphold all the guarantees which make `Pin` and -`Unpin` safe yourself for a type with internal references. In practice, this is -a very rare thing to implement yourself! - -> Note: This combination of `Pin` and `Unpin` allows a whole class of complex -> types to be safe in Rust which are otherwise difficult to implement because -> they are self-referential. Types which require `Pin` show up *most* commonly -> in async Rust today, but you might—very rarely!—see it in other contexts, too. -> -> The specific mechanics for how `Pin` and `Unpin` work under the hood are -> covered extensively in the API documentation for `std::pin`, so if you would -> like to understand them more deeply, that is a great place to start. - -Now we know enough to fix the last errors with `join_all`. We tried to move the -futures produced by an async blocks into a `Vec>>`, -but as we have seen, those futures may have internal references, so they do not -implement `Unpin`. They need to be pinned, and then we can pass the `Pin` type -into the `Vec`, confident that the underlying data in the futures will *not* be -moved. - -Listing 17-17 shows how we put this all into practice. First, we update the type -annotation for `futures`, with a `Pin` wrapping each `Box`. Second, we use -`Box::pin` to pin the futures themselves. +it. Later in the chapter, we will dig into a few more details about `Pin` and +`Unpin`. For the moment, though, we can just follow the compiler’s advice to get +unstuck! In Listing 17-17, we start by updating the type annotation for +`futures`, with a `Pin` wrapping each `Box`. Second, we use `Box::pin` to pin +the futures themselves. @@ -398,11 +260,11 @@ references to the dynamic `Future` type, as in Listing 17-18. -There is another, more serious, issue as well. We got this far by ignoring the -fact that we might have different `Output` types. For example, in Listing 17-19, -the anonymous future for `a` implements `Future`, the anonymous -future for `b` implements `Future`, and the anonymous future for -`c` implements `Future`. +There is one last issue to fix. We got this far by ignoring the fact that we +might have different `Output` types. For example, in Listing 17-19, the +anonymous future for `a` implements `Future`, the anonymous future +for `b` implements `Future`, and the anonymous future for `c` +implements `Future`. diff --git a/src/ch17-07-wip.md b/src/ch17-07-wip.md index a29543b628..8c3f644428 100644 --- a/src/ch17-07-wip.md +++ b/src/ch17-07-wip.md @@ -108,3 +108,142 @@ advances it when `poll` returns `Poll::Ready(Some(message))` or `Poll::Ready(None)`. [counting]: /ch17-02-concurrency-with-async.md + +--- + + + +The rest of the message tells us *why* that is required: the `JoinAll` +struct returned by `trpl::join_all` is generic over a type `F` which must +implement the `Future` trait, directly awaiting a Future requires that the +future implement the `Unpin` trait. Understanding this error means we need to +dive into a little more of how the `Future` type actually works, in particular +the idea of *pinning*. + +### Pinning and the Pin and Unpin Traits + + + +Let’s look again at the definition of `Future`, focusing now on its `poll` +method’s `self` type: + +```rust +use std::pin::Pin; +use std::task::{Context, Poll}; + +pub trait Future { + type Output; + + // Required method + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} +``` + +This is the first time we have seen a method where `self` has a type annotation +like this. When we specify the type of `self` like this, we are telling Rust +what type `self` must be to call this method. These kinds of type annotations +for `self` are similar to those for other function parameters, but with the +restriction that the type annotation has to be the type on which the method is +implemented, or a reference or smart pointer to that type. We will see more on +this syntax in Chapter 18. For now, it is enough to know that if we want to poll +a future (to check whether it is `Pending` or `Ready(Output)`), we need a +mutable reference to the type, which is wrapped in a `Pin`. + +`Pin` is a smart pointer, much like `Box`, `Rc`, and the others we saw in +Chapter 15. Unlike those, however, `Pin` only works with *other pointer types* +like reference (`&` and `&mut`) and smart pointers (`Box`, `Rc`, and so on). To +be precise, `Pin` works with types which implement the `Deref` or `DerefMut` +traits, which we covered in Chapter 15. You can think of this restriction as +equivalent to only working with pointers, though, since implementing `Deref` or +`DerefMut` means your type behaves like a pointer type. + +Recalling that `.await` is implemented in terms of calls to `poll()`, this +starts to explain the error message we saw above—but that was in terms of +`Unpin`, not `Pin`. So what exactly are `Pin` and `Unpin`, how do they relate, +and why does `Future` need `self` to be in a `Pin` type to call `poll`? + +In [“What Are Futures”][what-are-futures], we described how a series of await +points in a future get compiled into a state machine—and noted how the compiler +helps make sure that state machine follows all of Rust’s normal rules around +safety, including borrowing and ownership. To make that work, Rust looks at what +data is needed between each await point and the next await point or the end of +the async block. It then creates a corresponding variant in the state machine it +creates. Each variant gets the access it needs to the data that will be used in +that section of the source code, whether by taking ownership of that data or by +getting a mutable or immutable reference to it. + +So far so good: if we get anything wrong about the ownership or references in a +given async block, the borrow checker will tell us. When we want to move around +the future that corresponds to that block—like moving it into a `Vec` to pass to +`join_all`—things get trickier. + +When we move a future—whether by pushing into a data structure to use as an +iterator with `join_all`, or returning them from a function—that actually means +moving the state machine Rust creates for us. And unlike most other types in +Rust, the futures Rust creates for async blocks can end up with references to +themselves in the fields of any given variant. Any object which has a reference +to itself is unsafe to move, though, because references always point to the +actual memory address of the thing they refer to. If you move the data structure +itself, you *have* to update any references to it, or they will be left pointing +to the old location. + +In principle, you could make the Rust compiler try to update every reference to +an object every time it gets moved. That would potentially be a lot of +performance overhead, especially given there can be a whole web of references +that need updating. On the other hand, if we could make sure the data structure +in question *does not move in memory*, we do not have to update any references. +And this is exactly what Rust’s borrow checker already guarantees: you cannot +move an item which has any active references to it using safe code. + +`Pin` builds on that to give us the exact guarantee we need. When we *pin* a +value by wrapping a pointer to it in `Pin`, it can no longer move. Thus, if you +have `Pin>`, you actually pin the `SomeType` value, *not* the +`Box` pointer. In fact, the pinned box pointer can move around freely. Remember: +we care about making sure the data ultimately being referenced stays in its +place. If a pointer moves around, but the data it points to is in the same +place, there is no problem. + +However, most types are perfectly safe to move around, even if they happen to be +behind a `Pin` pointer. We only need to think about pinning when items have +internal references. Primitive values like numbers and booleans do not have any +internal structure like that, so they are obviously safe. Neither do most types +you normally work with in Rust. A `Vec`, for example, does not have any internal +references it needs to keep up to date this way, so you can move it around +without worrying. If you have a `Pin>`, you would have to do +everything via Pin’s safe but restrictive APIs, even though a `Vec` is +always safe to move if there are no other references to it. We need a way to +tell the compiler that it is actually just fine to move items around in cases +like these. For that, we have `Unpin`. + +`Unpin` is a marker trait, like `Send` and `Sync`, which we saw in Chapter 16. +Recall that marker traits have no functionality of their own. They exist only to +tell the compiler that it is safe to use the type which implements a given trait +in a particular context. `Unpin` informs the compiler that a given type does +*not* need to uphold any particular guarantees about whether the value in +question can be moved. + +Just like `Send` and `Sync`, the compiler implements `Unpin` automatically for +all types where it can prove it is safe. Implementing `Unpin` manually is unsafe +because it requires *you* to uphold all the guarantees which make `Pin` and +`Unpin` safe yourself for a type with internal references. In practice, this is +a very rare thing to implement yourself! + +> Note: This combination of `Pin` and `Unpin` allows a whole class of complex +> types to be safe in Rust which are otherwise difficult to implement because +> they are self-referential. Types which require `Pin` show up *most* commonly +> in async Rust today, but you might—very rarely!—see it in other contexts, too. +> +> The specific mechanics for how `Pin` and `Unpin` work under the hood are +> covered extensively in the API documentation for `std::pin`, so if you would +> like to understand them more deeply, that is a great place to start. + +Now we know enough to fix the last errors with `join_all`. We tried to move the +futures produced by an async blocks into a `Vec>>`, +but as we have seen, those futures may have internal references, so they do not +implement `Unpin`. They need to be pinned, and then we can pass the `Pin` type +into the `Vec`, confident that the underlying data in the futures will *not* be +moved. From 97902d50a7db50d3f4782f91b64377c34acabf30 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 11 Sep 2024 08:29:03 -0600 Subject: [PATCH 13/25] Ch. 17: rework 17.04 with my own edits and analysis This does *not* yet incorporate any of the relevant feedback from Carol on this, so a couple spots are still pretty messy. --- src/ch17-04-more-ways-of-combining-futures.md | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index b7f50315cd..b221585b67 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -47,9 +47,10 @@ But *how* would you hand control back to the runtime in those cases? ### Yielding Let’s simulate a long-running operation. Listing 17-21 introduces a `slow` -function which uses `std::thread::sleep` to block the current thread for some -number of milliseconds. We can use `slow` to stand in for real-world operations -which are both long-running and blocking. +function. It uses `std::thread::sleep` instead of `trpl::sleep` so that calling +`slow` will block the current thread for some number of milliseconds. We can use +`slow` to stand in for real-world operations which are both long-running and +blocking. @@ -163,11 +164,10 @@ lot in one millisecond! You can see this for yourself by setting up a little benchmark, like the one in Listing 17-25. (This is not an especially rigorous way to do performance testing, but it suffices to show the difference here.) Here, we skip all the -status printing, pass a one-nanosecond `Duration` to `sleep`, let each future -run by itself so that they do not interfere with each other, and get rid of all -the status printing that we did to see the back-and-forth between tasks in -Listings 17-23 and 17-24. Then we run for 1,000 iterations and see how long -`sleep` takes vs. `yield_now`. +status printing, pass a one-nanosecond `Duration` to `trple::sleep`, and let +each future run by itself, with no switching between the futures. Then we run +for 1,000 iterations and see how long the future using `trpl::sleep` takes +compared to the future using `trpl::yield_now`. @@ -233,19 +233,21 @@ Listing 17-27 shows this declaration. -The types line up now, so let’s think about the *behavior* we need. We want to -race the future passed in against the duration. We can use `trpl::sleep` to make -a timer future from the duration, and use `trpl::race` to run the future and the -timer against each other. - -When we saw `race` earlier in Listing 17-20, we ignored its return type, because -we were just interested in seeing the behavior of `fast` and `slow` when we ran -the program. Here, though, its return value tells us whether the future or the -sleep finished first. With `race`, both futures passed as arguments can -legitimately “win,” so it does not make sense to use a `Result` to represent the -return type. Instead, it returns a similar type called `Either`. Unlike -`Result`, there is no notion of success or failure baked into `Either`. Instead, -it uses `Left` and `Right` to indicate “one or the other”: +That satisfies our goals for the types. Now let’s think about the *behavior* we +need: we want to race the future passed in against the duration. We can use +`trpl::sleep` to make a timer future from the duration, and use `trpl::race` to +run that timer with the future the caller passes in. + +The `trpl::race` function returns a value to indicate which of the futures +passed to it finishes first. (When we saw `race` earlier in Listing 17-20, we +ignored its return value, because we were only interested in seeing the behavior +of `fast` and `slow` when we ran the program.) Because either future passed as +an argument to `race` can legitimately “win,” it does not make sense to use a +`Result` to represent the return type. Instead, `race` returns a type we have +not seen before, `Either`. The `Either` type is somewhat like a `Result`, in +that it has two cases. Unlike `Result`, though, there is no notion of success or +failure baked into `Either`. Instead, it uses `Left` and `Right` to indicate +“one or the other”. ```rust enum Either { @@ -256,17 +258,19 @@ enum Either { The `race` function returns `Left` if the first argument finishes first, with that future’s output, and `Right` with the second future argument’s output if -*that* one finishes first. We also know that `race` is not fair, and polls -arguments in the order they are passed. For `timeout`, we pass the future to -`race` first so it gets a chance to complete even if `max_time` is a very short -duration. If `future` finishes first, `race` will return `Left` with the output -from `future`. If `timer` finishes first, `race` will return `Right` with the -timer’s output of `()`. +*that* one finishes first. + +We also know that `race` is not fair, and polls arguments in the order they are +passed. Thus, we pass the caller-supplied future to `race` first so it gets a +chance to complete even if `max_time` is a very short duration. If `future` +finishes first, `race` will return `Left` with the output from `future`. If +`timer` finishes first, `race` will return `Right` with the timer’s output of +`()`. In Listing 17-28, we match on the result of awaiting `trpl::race`. If the future succeeded and we get a `Left(output)`, we return `Ok(output)`. If the sleep timer elapsed instead and we get a `Right(())`, we ignore the `()` with -`_` and return `Err(duration)` instead. +`_` and return `Err(max_time)` instead. From 68049c6e152cd71e53b7795ec8149301ba15822b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 11 Sep 2024 11:11:02 -0600 Subject: [PATCH 14/25] Ch. 17: rework 17.05 with my own edits and analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Along with the wording and phrasing-level edits, pull out a fair bit of material for the “advanced” section at the end, specifically the details of what `Stream` and `StreamExt` actually do. --- src/ch17-05-streams.md | 215 ++++++++++++++--------------------------- src/ch17-07-wip.md | 78 +++++++++++++++ 2 files changed, 153 insertions(+), 140 deletions(-) diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index 8a44d37059..9fd9049430 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -1,22 +1,25 @@ ## Streams -So far in this chapter, we have mostly stuck with individual futures. The one -big exception was the async channel we used. Recall how we used the receiver for -our async channel in the [“Message Passing”][17-02-messages] earlier in the -chapter, which waits on a sequence of items produced over time—a *stream*. +So far in this chapter, we have mostly stuck to individual futures. The one big +exception was the async channel we used. Recall how we used the receiver for our +async channel in the [“Message Passing”][17-02-messages] earlier in the chapter. +The async `recv` method produces a sequence of items over time. This is an +instance of a much more general pattern, often called a *stream*. A sequence of items is something we have seen before, when we looked at the `Iterator` trait in Chapter 13, but there are two differences between iterators and the async channel receiver. The first difference is the element of time: iterators are synchronous, while the channel receiver is asynchronous. The -second difference is the API. With iterators, if we worked with them directly -rather than using `iter` or `.into_iter` (including implicitly with a `for` -loop), we called `next`, whereas with the channel we call `recv`. Otherwise, -these APIs feel very similar. - -That is not a coincidence. A stream—of messages or of anything else—is like an -an asynchronous form of iteration. In fact, we can create a stream from any -iterator. Like an iterator, we can work with a stream by calling its `next` +second difference is the API. When working directly with an `Iterator`, we call +its synchronous `next` method. With a `trpl::Receiver`, we call an asynchronous +`recv` method instead, but these APIs otherwise feel very similar. + +That similarity is not a coincidence. A stream is like an asynchronous form of +iteration. Whereas the `trpl::Receiver` specifically waits to receive messages, +though, a general-purpose stream API needs to be much more general: it will just +provide the next item like `Iterator` does, but asynchronously. In fact, this is +roughly how it works in Rust, so we can actually create a stream from any +iterator. As with an iterator, we can work with a stream by calling its `next` method, and then awaiting the output, as in Listing 17-29. @@ -32,9 +35,8 @@ We start with an array of numbers, which we convert to an iterator and then call using the `trpl::stream_from_iter` function. Then we loop over the items in the stream as they arrive with the `while let` loop -Unfortunately, this does not yet work. When we try to run the code, it does not -compile. Instead, as we can see in the output, it reports that there is no -`next` method available. +Unfortunately, when we try to run the code, it does not compile. Instead, as we +can see in the output, it reports that there is no `next` method available. but there *is* a very common definition used throughout the -ecosystem. Let’s review the definitions of the `Iterator` and `Future` traits, -so we can build up to how a `Stream` trait that merges them together might look. - -From `Iterator`, we have the idea of a sequence: its `next` method provides an -`Option`. From `Future`, we have the idea of readiness over time: -its `poll` method provides a `Poll`. To represent a sequence of -items which become ready over time, we define a `Stream` trait which has all of -those features put together: - -```rust -use std::pin::Pin; -use std::task::{Context, Poll}; - -trait Stream { - type Item; - - fn poll_next( - self: Pin<&mut Self>, - cx: &mut Context<'_> - ) -> Poll>; -} -``` - -The `Stream` trait defines an associated type `Item` for the type of the items -produced by the stream. This is like `Iterator`: there may be zero to many of -these, and unlike `Future`, where there was a single `Output`. - -`Stream` also defines a method to get those items. We call it `poll_next`, to -make it clear that it polls like `Future::poll` and produces a sequence of items -like `Iterator::next`. Its return type uses both `Poll` and `Option`. The outer -type is `Poll`, since it has to be checked for readiness, just like a future. -The inner type is `Option`, since it needs to signal whether there are more -messages, just like an iterator. - -Something very similar to this will likely end up standardized as part of Rust’s -standard library. In the meantime, it is part of the toolkit of most runtimes, -so you can rely on it, and everything we cover below should generally apply! - -In the example we saw above, though, we did not use `poll_next` *or* `Stream`, -but instead `next` and `StreamExt`. We *could* work directly in terms of the -`poll_next` API by hand-writing our own `Stream` state machines, of course, just -as we *could* work with futures directly via their `poll` method. Using `await` -is much nicer, though, so the `StreamExt` trait supplies the `next` method so -we can do just that. - -```rust -{{#rustdoc_include ../listings/ch17-async-await/no-listing-stream-ext/src/lib.rs:here}} -``` - - - -> Note: The actual definition we will use looks slightly different than this, -> because it supports versions of Rust which did not yet support using async -> functions in traits. As a result, it looks like this: -> -> ```rust,ignore -> fn next(&mut self) -> Next<'_, Self> where Self: Unpin; -> ``` -> -> That `Next` type is just a simple `struct` which implements `Future` and gives -> a way to name the lifetime of the reference to `self` with `Next<'_, Self>`, -> so that `.await` can work with this! - -The `StreamExt` trait is also the home of all the interesting methods available -to use with streams. `StreamExt` is automatically implemented for every type -which implements `Stream`, but they are separated out so that the community can -iterate on the foundational trait distinctly from the convenience APIs. - -Now that we have a handle on the core traits that make streams work, let’s see -how we can use some of those interesting `StreamExt` methods to combine -streams in interesting ways. +Of course, this is not very interesting. We could do that with normal iterators +and without any async at all. So let’s look at some of the other things we can +do which are unique to streams. ### Composing Streams Lots of things are naturally represented as streams: items becoming available in -a queue over time, or working with more data than can fit in a computer’s memory -by only pulling chunks of it from the file system at a time, or data arriving -over the network over time. And because streams are futures, we can use them -with any other kind of future, and we can combine them in interesting ways. For -example, we can debounce events to avoid triggering too many network calls, set -timeouts on sequences of long-running operations, or throttle user interface -events to avoid doing needless work. +a queue, or working with more data than can fit in a computer’s memory by only +pulling chunks of it from the file system at a time, or data arriving over the +network over time. Because streams are futures, we can use them with any other +kind of future, too, and we can combine them in interesting ways. For example, +we can debounce events to avoid triggering too many network calls, set timeouts +on sequences of long-running operations, or throttle user interface events to +avoid doing needless work. Let’s start by building a little stream of messages, similar to what we might see from a WebSocket or other real-time communication protocols. In Listing @@ -201,9 +133,9 @@ see from a WebSocket or other real-time communication protocols. In Listing String>`. For its implementation, we create an async channel, loop over the first ten letters of the English alphabet, and send them across the channel. -We also use a new type: `ReceiverStream`. This converts the `rx` receiver from -the `trpl::channel` into a stream. Back in `main`, we use a `while let` loop to -print all the messages from the stream. +We also use a new type: `ReceiverStream`, which converts the `rx` receiver from +the `trpl::channel` into a `Stream` with a `next` method. Back in `main`, we use +a `while let` loop to print all the messages from the stream. @@ -236,6 +168,16 @@ We could do this with the regular `Receiver` API, or even the regular `Iterator` API, though. Let’s add something that requires streams, like adding a timeout which applies to every item in the stream, and a delay on the items we emit. +In Listing 17-33, we start by adding a timeout to the stream with the `timeout` +method, which comes from the `StreamExt` trait. Then we update the body of the +`while let` loop, because the stream now returns a `Result`. The `Ok` variant +indicates a message arrived in time; the `Err` variant indicates that the +timeout elapsed before any message arrived. We `match` on that result and either +print the message when we receive it successfully, or print a notice about the +timeout. Finally, notice that we pin the messages after applying the timeout to +them, because the timeout helper produces a future which needs to be pinned to +be polled. + ```rust @@ -244,16 +186,6 @@ which applies to every item in the stream, and a delay on the items we emit. -The first thing we do in Listing 17-33 is add a timeout to the stream with the -`timeout` method, which comes from the `StreamExt` trait. Then we update the -body of the `while let` loop, because the stream now returns a `Result`. The -`Ok` variant indicates a message arrived in time; the `Err` variant indicates -that the timeout elapsed before any message arrived. We `match` on that result -and either print the message when we receive it successfully, or print a notice -about the timeout. Finally, notice that we pinned the messages after applying -the timeout to them, because the timeout helper produces a future which needs -to be pinned to be polled. - However, since there are no delays between messages, this timeout does not change the behavior of the program. Let’s add a variable delay to the messages we send. In `get_messages`, we use the `enumerate` iterator method with the @@ -277,10 +209,11 @@ function, because then we would return a `Future>` instead of just a `Stream>`. The caller would have to await `get_messages` itself to get access to the stream. But remember: everything in a given future happens linearly; concurrency happens *between* -futures. Awaiting `get_messages` would require it to send all the messages, and -sleeping between sending them, before returning the receiver stream. As a -result, The timeout would end up useless, because there would be no delays in -the stream itself: the delays all happen before the stream is even available. +futures. Awaiting `get_messages` would require it to send all the messages, +including sleeping between sending each message, before returning the receiver +stream. As a result, the timeout would end up useless. There would be no delays +in the stream itself: the delays would all happen before the stream was even +available. Instead, we leave `get_messages` as a regular function which returns a stream, and spawn a task to handle the async `sleep` calls. @@ -333,12 +266,13 @@ this stream of messages. ### Merging Streams -First, let’s create another stream, called `get_intervals`, which will emit an -item every millisecond if we let it run directly. For simplicity, we can use the -`sleep` function to send a message on a delay, and combine it with the same -approach of creating a stream from a channel we used in `get_messages`. The -difference is that this time, we are going to send back the count of intervals -which has elapsed, so the return type will be `impl Stream`. +First, let’s create another stream, which will emit an item every millisecond if +we let it run directly. For simplicity, we can use the `sleep` function to send +a message on a delay, and combine it with the same approach of creating a stream +from a channel we used in `get_messages`. The difference is that this time, we +are going to send back the count of intervals which has elapsed, so the return +type will be `impl Stream`, and we can call the function +`get_intervals`. In Listing 17-35, we start by defining a `count` in the task. (We could define it outside the task, too, but it is clearer to limit the scope of any given @@ -358,7 +292,8 @@ the infinite loop. This kind of infinite loop, which only ends when the whole runtime gets torn down, is fairly common in async Rust: many programs need to keep running -indefinitely. With async, this does not block anything else! +indefinitely. With async, this does not block anything else, as long as there is +at least one await point in each iteration through the loop. Back in our main function’s async block, we start by calling `get_intervals`. Then we merge the `messages` and `intervals` streams with the `merge` method. @@ -388,10 +323,10 @@ already in the basic format we want and has to handle timeout errors. First, we can use the `map` helper method to transform the `intervals` into a string. Second, we need to match the `Timeout` from `messages`. Since we do not actually *want* a timeout for `intervals`, though, we can just create a timeout which is -longer than the other durations we are using. Here, we create a 10-second time -out with `Duration::from_secs(10)`. Finally, we need to make `merged` both +longer than the other durations we are using. Here, we create a 10-second +timeout with `Duration::from_secs(10)`. Finally, we need to make `stream` mutable, so that the `while let` loop’s `next` calls can iterate through the -stream, and pinned, so that it is safe to do so. +stream, and pin it so that it is safe to do so. diff --git a/src/ch17-07-wip.md b/src/ch17-07-wip.md index 8c3f644428..7e0fef4bfe 100644 --- a/src/ch17-07-wip.md +++ b/src/ch17-07-wip.md @@ -247,3 +247,81 @@ but as we have seen, those futures may have internal references, so they do not implement `Unpin`. They need to be pinned, and then we can pass the `Pin` type into the `Vec`, confident that the underlying data in the futures will *not* be moved. + +--- + +### The Stream API + +Unlike `Iterator` and `Future`, there is no definition of a `Stream` trait in +the standard library yet as of the time of writing, but there *is* a very common definition used throughout the +ecosystem. Let’s review the definitions of the `Iterator` and `Future` traits, +so we can build up to how a `Stream` trait that merges them together might look. + +From `Iterator`, we have the idea of a sequence: its `next` method provides an +`Option`. From `Future`, we have the idea of readiness over time: +its `poll` method provides a `Poll`. To represent a sequence of +items which become ready over time, we define a `Stream` trait which has all of +those features put together: + +```rust +use std::pin::Pin; +use std::task::{Context, Poll}; + +trait Stream { + type Item; + + fn poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_> + ) -> Poll>; +} +``` + +The `Stream` trait defines an associated type `Item` for the type of the items +produced by the stream. This is like `Iterator`: there may be zero to many of +these, and unlike `Future`, where there was a single `Output`. + +`Stream` also defines a method to get those items. We call it `poll_next`, to +make it clear that it polls like `Future::poll` and produces a sequence of items +like `Iterator::next`. Its return type uses both `Poll` and `Option`. The outer +type is `Poll`, since it has to be checked for readiness, just like a future. +The inner type is `Option`, since it needs to signal whether there are more +messages, just like an iterator. + +Something very similar to this will likely end up standardized as part of Rust’s +standard library. In the meantime, it is part of the toolkit of most runtimes, +so you can rely on it, and everything we cover below should generally apply! + +In the example we saw above, though, we did not use `poll_next` *or* `Stream`, +but instead `next` and `StreamExt`. We *could* work directly in terms of the +`poll_next` API by hand-writing our own `Stream` state machines, of course, just +as we *could* work with futures directly via their `poll` method. Using `await` +is much nicer, though, so the `StreamExt` trait supplies the `next` method so +we can do just that. + +```rust +{{#rustdoc_include ../listings/ch17-async-await/no-listing-stream-ext/src/lib.rs:here}} +``` + + + +> Note: The actual definition we will use looks slightly different than this, +> because it supports versions of Rust which did not yet support using async +> functions in traits. As a result, it looks like this: +> +> ```rust,ignore +> fn next(&mut self) -> Next<'_, Self> where Self: Unpin; +> ``` +> +> That `Next` type is just a simple `struct` which implements `Future` and gives +> a way to name the lifetime of the reference to `self` with `Next<'_, Self>`, +> so that `.await` can work with this! + +The `StreamExt` trait is also the home of all the interesting methods available +to use with streams. `StreamExt` is automatically implemented for every type +which implements `Stream`, but they are separated out so that the community can +iterate on the foundational trait distinctly from the convenience APIs. From 0d8da8bae22843edc88ea25463e198d9af27c934 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 11 Sep 2024 12:28:01 -0600 Subject: [PATCH 15/25] Ch. 17: fold together 17.03 and 17.04 --- src/SUMMARY.md | 5 +- src/ch17-03-more-futures.md | 300 +++++++++++++++++- src/ch17-04-more-ways-of-combining-futures.md | 299 ----------------- ...{ch17-05-streams.md => ch17-04-streams.md} | 0 ...-07-wip.md => ch17-05-traits-for-async.md} | 2 + 5 files changed, 303 insertions(+), 303 deletions(-) delete mode 100644 src/ch17-04-more-ways-of-combining-futures.md rename src/{ch17-05-streams.md => ch17-04-streams.md} (100%) rename src/{ch17-07-wip.md => ch17-05-traits-for-async.md} (99%) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 33af2af759..b2af389757 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -105,10 +105,9 @@ - [Futures and the Async Syntax](ch17-01-futures-and-syntax.md) - [Concurrency With Async](ch17-02-concurrency-with-async.md) - [Working With More Than Two Futures](ch17-03-more-futures.md) - - [More Ways of Combining Futures](ch17-04-more-ways-of-combining-futures.md) - - [Streams](ch17-05-streams.md) + - [Streams](ch17-04-streams.md) + - [Digging Into the Traits for Async](ch17-05-traits-for-async.md) - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.md) - - [Restructuring](ch17-07-wip.md) - [Object Oriented Programming Features of Rust](ch18-00-oop.md) - [Characteristics of Object-Oriented Languages](ch18-01-what-is-oo.md) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index b48247e512..1affdf7def 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -294,6 +294,304 @@ need to reach for `pin` now and again to use them with those APIs. `Pin` and building a runtime itself, rather than for day to day Rust code. When you see them, though, now you will know what to do! +### Racing futures + +When we “join” futures with the `join` family of functions and macros, we +require *all* of them to finish before we move on. Sometimes, though, we only +need *some* future from a set to finish before we move on—kind of like racing +one future against another. This operation is often named `race` for exactly +that reason. + +In Listing 17-20, we use `race` to run two futures, `slow` and `fast`, against +each other. Each one prints a message when it starts running, pauses for some +amount of time by calling and awaiting `sleep`, and then prints another message +when it finishes. Then we pass both to `trpl::race` and wait for one of them to +finish. (The outcome here won’t be too surprising: `fast` wins!) + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} +``` + + + +Notice that if you flip the order of the arguments to `race`, the order of the +“started” messages changes, even though the `fast` future always completes +first. That is because the implementation of this particular `race` function is +not fair. It always runs the futures passed as arguments in the order they are +passed. Other implementations *are* fair, and will randomly choose which future +to poll first. Regardless of whether the implementation of race we are using is +fair, though, *one* of the futures will run up to the first `.await` in its body +before another task can start. + +Recall from [“What Are Futures?”][futures] that at each await point, Rust pauses +the async block and hands control back to a runtime. The inverse is also true: +Rust *only* pauses async blocks and hands control back to a runtime at an await +point. Everything between await points is synchronous. + +That means if you do a bunch of work in an async block without an await point, +that future will block any other futures from making progress. (You may +sometimes hear this referred to as one future *starving* other futures. And this +applies to threads, too!) In many cases, that may not be a big deal. However, if +you are doing some kind of expensive setup or long-running work, or if you have +a future which will keep doing some particular task indefinitely, you will need +to think about when and where to hand control back to the runtime. + +But *how* would you hand control back to the runtime in those cases? + +### Yielding + +Let’s simulate a long-running operation. Listing 17-21 introduces a `slow` +function. It uses `std::thread::sleep` instead of `trpl::sleep` so that calling +`slow` will block the current thread for some number of milliseconds. We can use +`slow` to stand in for real-world operations which are both long-running and +blocking. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:slow}} +``` + + + +In Listing 17-22, we use `slow` to emulate doing this kind of CPU-bound work in +a pair of futures. To begin, each future only hands control back to the runtime +*after* carrying out a bunch of slow operations. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:slow-futures}} +``` + + + +If you run this, you will see this output: + + + +```text +'a' started. +'a' ran for 30ms +'a' ran for 10ms +'a' ran for 20ms +'b' started. +'b' ran for 75ms +'b' ran for 10ms +'b' ran for 15ms +'b' ran for 350ms +'a' finished. +``` + +As with our earlier example, `race` still finishes as soon as `a` is done. There +is no interleaving between the two futures, though. The `a` future does all of +its work until the `trpl::sleep` call is awaited, then the `b` future does all +of its work until its own `trpl::sleep` call is awaited, and then the `a` future +completes. To allow both futures to make progress between their slow tasks, we +need await points so we can hand control back to the runtime. That means we need +something we can await! + +We can already see this kind of handoff happening in Listing 17-22: if we +removed the `trpl::sleep` at the end of the `a` future, it would complete +without the `b` future running *at all*. Maybe we could use the `sleep` function +as a starting point? + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:here}} +``` + + + +In Listing 17-23, we add `trpl::sleep` calls with await points between each call +to `slow`. Now the two futures’ work is interleaved: + + + +```text +'a' started. +'a' ran for 30ms +'b' started. +'b' ran for 75ms +'a' ran for 10ms +'b' ran for 10ms +'a' ran for 20ms +'b' ran for 15ms +'a' finished. +``` + +The `a` future still runs for a bit before handing off control to `b`, because +it calls `slow` before ever calling `trpl::sleep`, but after that the futures +swap back and forth each time one of them hits an await point. In this case, we +have done that after every call to `slow`, but we could break up the work +however makes the most sense to us. + +We do not really want to *sleep* here, though: we want to make progress as fast +as we can. We just need to hand back control to the runtime. We can do that +directly, using the `yield_now` function. In Listing 17-24, we replace all those +`sleep` calls with `yield_now`. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:yields}} +``` + + + +This is both clearer about the actual intent and can be significantly faster +than using `sleep`, because timers like the one used by `sleep` often have +limits to how granular they can be. The version of `sleep` we are using, for +example, will always sleep for at least a millisecond, even if we pass it a +`Duration` of one nanosecond. Again, modern computers are *fast*: they can do a +lot in one millisecond! + +You can see this for yourself by setting up a little benchmark, like the one in +Listing 17-25. (This is not an especially rigorous way to do performance +testing, but it suffices to show the difference here.) Here, we skip all the +status printing, pass a one-nanosecond `Duration` to `trple::sleep`, and let +each future run by itself, with no switching between the futures. Then we run +for 1,000 iterations and see how long the future using `trpl::sleep` takes +compared to the future using `trpl::yield_now`. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:here}} +``` + + + +The version with `yield_now` is *way* faster! + +This means that async can be useful even for CPU-bound tasks, depending on what +else your program is doing, because it provides a useful tool for structuring +the relationships between different parts of the program. This is a form of +*cooperative multitasking*, where each future has both the power to determine +when it hands over control via await points. Each future therefore also has the +*responsibility* to avoid blocking for too long. In some Rust-based embedded +operating systems, this is the *only* kind of multitasking! + +In real-world code, you will not usually be alternating function calls with +await points on every single line, of course. The underlying dynamic is an +important one to keep in mind, though! + +### Building Our Own Async Abstractions + +We can also compose futures together to create new patterns. For example, we can +build a `timeout` function with async building blocks we already have. When we +are done, the result will be another building block we could use to build up yet +further async abstractions. + +Listing 17-26 shows how we would expect this `timeout` to work with a slow +future. + ++ +```rust,ignore +{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:here}} +``` + + + +Let’s implement this! To begin, let’s think about the API for `timeout`: + +- It needs to be an async function itself so we can await it. +- Its first parameter should be a future to run. We can make it generic to allow + it to work with any future. +- Its second parameter will be the maximum time to wait. If we use a `Duration`, + that will make it easy to pass along to `trpl::sleep`. +- It should return a `Result`. If the future completes successfully, the + `Result` will be `Ok` with the value produced by the future. If the timeout + elapses first, the `Result` will be `Err` with the duration that the timeout + waited for. + +Listing 17-27 shows this declaration. + + + ++ +```rust,ignore +{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:declaration}} +``` + + + +That satisfies our goals for the types. Now let’s think about the *behavior* we +need: we want to race the future passed in against the duration. We can use +`trpl::sleep` to make a timer future from the duration, and use `trpl::race` to +run that timer with the future the caller passes in. + +The `trpl::race` function returns a value to indicate which of the futures +passed to it finishes first. (When we saw `race` earlier in Listing 17-20, we +ignored its return value, because we were only interested in seeing the behavior +of `fast` and `slow` when we ran the program.) Because either future passed as +an argument to `race` can legitimately “win,” it does not make sense to use a +`Result` to represent the return type. Instead, `race` returns a type we have +not seen before, `Either`. The `Either` type is somewhat like a `Result`, in +that it has two cases. Unlike `Result`, though, there is no notion of success or +failure baked into `Either`. Instead, it uses `Left` and `Right` to indicate +“one or the other”. + +```rust +enum Either { + Left(A), + Right(B) +} +``` + +The `race` function returns `Left` if the first argument finishes first, with +that future’s output, and `Right` with the second future argument’s output if +*that* one finishes first. + +We also know that `race` is not fair, and polls arguments in the order they are +passed. Thus, we pass the caller-supplied future to `race` first so it gets a +chance to complete even if `max_time` is a very short duration. If `future` +finishes first, `race` will return `Left` with the output from `future`. If +`timer` finishes first, `race` will return `Right` with the timer’s output of +`()`. + +In Listing 17-28, we match on the result of awaiting `trpl::race`. If the +future succeeded and we get a `Left(output)`, we return `Ok(output)`. If the +sleep timer elapsed instead and we get a `Right(())`, we ignore the `()` with +`_` and return `Err(max_time)` instead. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:implementation}} +``` + + + +With that, we have a working `timeout`, built out of two other async helpers. If +we run our code, it will print the failure mode after the timeout: + +```text +Failed after 2 seconds +``` + +Because futures compose with other futures, you can build really powerful tools +using smaller async building blocks. For example, you can use this same approach +to combine timeouts with retries, and in turn use those with things like network +calls—one of the examples from the beginning of the chapter! + +Over the last two sections, we have seen how to work with multiple futures at +the same time. Up next, let’s look at how we can work with multiple futures in a +sequence over time, with *streams*. + [collections]: ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: ch12-03-improving-error-handling-and-modularity.html -[what-are-futures]: ch17-01-futures-and-syntax.html#what-are-futures +[futures]: ch17-01-futures-and-syntax.html#what-are-futures diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md deleted file mode 100644 index b221585b67..0000000000 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ /dev/null @@ -1,299 +0,0 @@ -## More Ways of Combining Futures - -When we “join” futures with the `join` family of functions and macros, we -require *all* of them to finish before we move on. Sometimes, though, we only -need *some* future from a set to finish before we move on—kind of like racing -one future against another. This operation is often named `race` for exactly -that reason. - -In Listing 17-20, we use `race` to run two futures, `slow` and `fast`, against -each other. Each one prints a message when it starts running, pauses for some -amount of time by calling and awaiting `sleep`, and then prints another message -when it finishes. Then we pass both to `trpl::race` and wait for one of them to -finish. (The outcome here won’t be too surprising: `fast` wins!) - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} -``` - - - -Notice that if you flip the order of the arguments to `race`, the order of the -“started” messages changes, even though the `fast` future always completes -first. That is because the implementation of this particular `race` function is -not fair. It always runs the futures passed as arguments in the order they are -passed. Other implementations *are* fair, and will randomly choose which future -to poll first. Regardless of whether the implementation of race we are using is -fair, though, *one* of the futures will run up to the first `.await` in its body -before another task can start. - -Recall from [“What Are Futures?”][futures] that at each await point, Rust pauses -the async block and hands control back to a runtime. The inverse is also true: -Rust *only* pauses async blocks and hands control back to a runtime at an await -point. Everything between await points is synchronous. - -That means if you do a bunch of work in an async block without an await point, -that future will block any other futures from making progress. (You may -sometimes hear this referred to as one future *starving* other futures. And this -applies to threads, too!) In many cases, that may not be a big deal. However, if -you are doing some kind of expensive setup or long-running work, or if you have -a future which will keep doing some particular task indefinitely, you will need -to think about when and where to hand control back to the runtime. - -But *how* would you hand control back to the runtime in those cases? - -### Yielding - -Let’s simulate a long-running operation. Listing 17-21 introduces a `slow` -function. It uses `std::thread::sleep` instead of `trpl::sleep` so that calling -`slow` will block the current thread for some number of milliseconds. We can use -`slow` to stand in for real-world operations which are both long-running and -blocking. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:slow}} -``` - - - -In Listing 17-22, we use `slow` to emulate doing this kind of CPU-bound work in -a pair of futures. To begin, each future only hands control back to the runtime -*after* carrying out a bunch of slow operations. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:slow-futures}} -``` - - - -If you run this, you will see this output: - - - -```text -'a' started. -'a' ran for 30ms -'a' ran for 10ms -'a' ran for 20ms -'b' started. -'b' ran for 75ms -'b' ran for 10ms -'b' ran for 15ms -'b' ran for 350ms -'a' finished. -``` - -As with our earlier example, `race` still finishes as soon as `a` is done. There -is no interleaving between the two futures, though. The `a` future does all of -its work until the `trpl::sleep` call is awaited, then the `b` future does all -of its work until its own `trpl::sleep` call is awaited, and then the `a` future -completes. To allow both futures to make progress between their slow tasks, we -need await points so we can hand control back to the runtime. That means we need -something we can await! - -We can already see this kind of handoff happening in Listing 17-22: if we -removed the `trpl::sleep` at the end of the `a` future, it would complete -without the `b` future running *at all*. Maybe we could use the `sleep` function -as a starting point? - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:here}} -``` - - - -In Listing 17-23, we add `trpl::sleep` calls with await points between each call -to `slow`. Now the two futures’ work is interleaved: - - - -```text -'a' started. -'a' ran for 30ms -'b' started. -'b' ran for 75ms -'a' ran for 10ms -'b' ran for 10ms -'a' ran for 20ms -'b' ran for 15ms -'a' finished. -``` - -The `a` future still runs for a bit before handing off control to `b`, because -it calls `slow` before ever calling `trpl::sleep`, but after that the futures -swap back and forth each time one of them hits an await point. In this case, we -have done that after every call to `slow`, but we could break up the work -however makes the most sense to us. - -We do not really want to *sleep* here, though: we want to make progress as fast -as we can. We just need to hand back control to the runtime. We can do that -directly, using the `yield_now` function. In Listing 17-24, we replace all those -`sleep` calls with `yield_now`. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:yields}} -``` - - - -This is both clearer about the actual intent and can be significantly faster -than using `sleep`, because timers like the one used by `sleep` often have -limits to how granular they can be. The version of `sleep` we are using, for -example, will always sleep for at least a millisecond, even if we pass it a -`Duration` of one nanosecond. Again, modern computers are *fast*: they can do a -lot in one millisecond! - -You can see this for yourself by setting up a little benchmark, like the one in -Listing 17-25. (This is not an especially rigorous way to do performance -testing, but it suffices to show the difference here.) Here, we skip all the -status printing, pass a one-nanosecond `Duration` to `trple::sleep`, and let -each future run by itself, with no switching between the futures. Then we run -for 1,000 iterations and see how long the future using `trpl::sleep` takes -compared to the future using `trpl::yield_now`. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:here}} -``` - - - -The version with `yield_now` is *way* faster! - -This means that async can be useful even for CPU-bound tasks, depending on what -else your program is doing, because it provides a useful tool for structuring -the relationships between different parts of the program. This is a form of -*cooperative multitasking*, where each future has both the power to determine -when it hands over control via await points. Each future therefore also has the -*responsibility* to avoid blocking for too long. In some Rust-based embedded -operating systems, this is the *only* kind of multitasking! - -In real-world code, you will not usually be alternating function calls with -await points on every single line, of course. The underlying dynamic is an -important one to keep in mind, though! - -### Building Our Own Async Abstractions - -We can also compose futures together to create new patterns. For example, we can -build a `timeout` function with async building blocks we already have. When we -are done, the result will be another building block we could use to build up yet -further async abstractions. - -Listing 17-26 shows how we would expect this `timeout` to work with a slow -future. - -- -```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:here}} -``` - - - -Let’s implement this! To begin, let’s think about the API for `timeout`: - -- It needs to be an async function itself so we can await it. -- Its first parameter should be a future to run. We can make it generic to allow - it to work with any future. -- Its second parameter will be the maximum time to wait. If we use a `Duration`, - that will make it easy to pass along to `trpl::sleep`. -- It should return a `Result`. If the future completes successfully, the - `Result` will be `Ok` with the value produced by the future. If the timeout - elapses first, the `Result` will be `Err` with the duration that the timeout - waited for. - -Listing 17-27 shows this declaration. - - - -- -```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:declaration}} -``` - - - -That satisfies our goals for the types. Now let’s think about the *behavior* we -need: we want to race the future passed in against the duration. We can use -`trpl::sleep` to make a timer future from the duration, and use `trpl::race` to -run that timer with the future the caller passes in. - -The `trpl::race` function returns a value to indicate which of the futures -passed to it finishes first. (When we saw `race` earlier in Listing 17-20, we -ignored its return value, because we were only interested in seeing the behavior -of `fast` and `slow` when we ran the program.) Because either future passed as -an argument to `race` can legitimately “win,” it does not make sense to use a -`Result` to represent the return type. Instead, `race` returns a type we have -not seen before, `Either`. The `Either` type is somewhat like a `Result`, in -that it has two cases. Unlike `Result`, though, there is no notion of success or -failure baked into `Either`. Instead, it uses `Left` and `Right` to indicate -“one or the other”. - -```rust -enum Either { - Left(A), - Right(B) -} -``` - -The `race` function returns `Left` if the first argument finishes first, with -that future’s output, and `Right` with the second future argument’s output if -*that* one finishes first. - -We also know that `race` is not fair, and polls arguments in the order they are -passed. Thus, we pass the caller-supplied future to `race` first so it gets a -chance to complete even if `max_time` is a very short duration. If `future` -finishes first, `race` will return `Left` with the output from `future`. If -`timer` finishes first, `race` will return `Right` with the timer’s output of -`()`. - -In Listing 17-28, we match on the result of awaiting `trpl::race`. If the -future succeeded and we get a `Left(output)`, we return `Ok(output)`. If the -sleep timer elapsed instead and we get a `Right(())`, we ignore the `()` with -`_` and return `Err(max_time)` instead. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:implementation}} -``` - - - -With that, we have a working `timeout`, built out of two other async helpers. If -we run our code, it will print the failure mode after the timeout: - -```text -Failed after 2 seconds -``` - -Because futures compose with other futures, you can build really powerful tools -using smaller async building blocks. For example, you can use this same approach -to combine timeouts with retries, and in turn use those with things like network -calls—one of the examples from the beginning of the chapter! - -Over the last two sections, we have seen how to work with multiple futures at -the same time. Up next, let’s look at how we can work with multiple futures in a -sequence over time, with *streams*. - -[futures]: ch17-01-futures-and-syntax.html#what-are-futures diff --git a/src/ch17-05-streams.md b/src/ch17-04-streams.md similarity index 100% rename from src/ch17-05-streams.md rename to src/ch17-04-streams.md diff --git a/src/ch17-07-wip.md b/src/ch17-05-traits-for-async.md similarity index 99% rename from src/ch17-07-wip.md rename to src/ch17-05-traits-for-async.md index 7e0fef4bfe..cc5dc6939e 100644 --- a/src/ch17-07-wip.md +++ b/src/ch17-05-traits-for-async.md @@ -1,3 +1,5 @@ +## Digging Into the Traits for Async + > ## Restructuring > > This is just a placeholder for material that needs to be restructured so that From 7da825f835b30a7d1535567f35355a05b5a9c47f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 11 Sep 2024 12:37:41 -0600 Subject: [PATCH 16/25] Ch. 17: Make the new 17.05 actually work as a deep dive! --- .../no-listing-stream-ext/src/lib.rs | 2 + src/ch17-01-futures-and-syntax.md | 5 +- src/ch17-05-traits-for-async.md | 209 +++++++++++------- 3 files changed, 134 insertions(+), 82 deletions(-) diff --git a/listings/ch17-async-await/no-listing-stream-ext/src/lib.rs b/listings/ch17-async-await/no-listing-stream-ext/src/lib.rs index e236c99260..09a980c04d 100644 --- a/listings/ch17-async-await/no-listing-stream-ext/src/lib.rs +++ b/listings/ch17-async-await/no-listing-stream-ext/src/lib.rs @@ -14,5 +14,7 @@ trait StreamExt: Stream { async fn next(&mut self) -> Option where Self: Unpin; + + // other methods... } // ANCHOR_END: here diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index dc53ac9eda..9dc8d1eff0 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -33,7 +33,7 @@ The warning tells us that just calling `hello` was not enough: we also need to We will work through each of these in turn. We can answer the first question by learning what the syntax means, so let’s start there. -### Async functions +### Async Functions In Rust, writing `async fn` is equivalent to writing a function which returns a *future* of the return type. That is, when the compiler sees a function like @@ -264,9 +264,6 @@ the things we can *do* with async. [impl-trait]: ch10-02-traits.html#traits-as-parameters [iterators-lazy]: ch13-02-iterators.html -[under-the-hood]: https://rust-lang.github.io/async-book/02_execution/01_chapter.html -[pinning]: https://rust-lang.github.io/async-book/04_pinning/01_chapter.html -[async-book]: https://rust-lang.github.io/async-book/ [crate-source]: https://github.com/rust-lang/book/tree/main/packages/trpl [futures-crate]: https://crates.io/crates/futures diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index cc5dc6939e..827e625e23 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -1,15 +1,19 @@ ## Digging Into the Traits for Async -> ## Restructuring -> -> This is just a placeholder for material that needs to be restructured so that -> the earlier sections of the book can avoid getting sidetracked into details of -> things like `Pin` or even just the full gnarliness of the `Future` trait at -> points where it would be better for the text to keep moving. +Throughout the chapter, we have used the `Future`, `Pin`, `Unpin`, `Stream`, and +`StreamExt` traits in various ways. So far, though, we have avoided digging too +far into the details of how they work or how they fit together. Much of the time +when writing Rust day to day, this is fine. Sometimes, though, you will hit +situations where understanding a few more of these details matters. In this +section, we will dig down *enough* further to help with those situations—while +still leaving the *really* deep dive for other documentation! + ---- +### Future -Here is the definition of the trait: +Back in [Async Functions][async-functions], we noted that `Future` is a trait. +Let’s start by taking a closer look at how it works. Here is how Rust defines +a `Future`: ```rust use std::pin::Pin; @@ -22,13 +26,16 @@ pub trait Future { } ``` -As we learned earlier, `Future`’s associated type `Output` says what the future -will resolves to. (This is analogous to the `Item` associated type for the -`Iterator` trait.) Beyond that, `Future` also has the `poll` method, which takes -a special `Pin` reference for its `self` parameter and a mutable reference to a -`Context` type, and returns a `Poll`. We will talk a little more -about `Pin` and `Context` later in the chapter. For now, let’s focus on what the -method returns, the `Poll` type: +That trait definition includes a bunch of new types and also some syntax we have +not seen before, so let’s walk through the definition piece by piece. + +First, `Future`’s associated type `Output` says what the future resolves to. +This is analogous to the `Item` associated type for the `Iterator` trait. +Second, `Future` also has the `poll` method, which takes a special `Pin` +reference for its `self` parameter and a mutable reference to a `Context` type, +and returns a `Poll`. We will talk a little more about `Pin` and +`Context` later in the section. For now, let’s focus on what the method returns, +the `Poll` type: ```rust enum Poll { @@ -89,49 +96,68 @@ on this future and work on other futures and check this one again later. That “something” is an async runtime, and this scheduling and coordination work is one of the main jobs for a runtime. ---- - -> Note: If you want to understand how things work “under the hood,” the official -> [_Asynchronous Programming in Rust_][async-book] book covers them: -> -> - [Chapter 2: Under the Hood: Executing Futures and Tasks][under-the-hood] -> - [Chapter 4: Pinning][pinning]. - ---- - -Recall our description of how `rx.recv()` waits in the [Counting][counting] -section. The `recv()` call returns a `Future`, and awaiting it polls it. In our -initial discussion, we noted that a runtime will pause the future until it is -ready with either `Some(message)` or `None` when the channel closes. With a -deeper understanding of `Future` in place, and specifically its `poll` method, -we can see how that works. The runtime knows the future is not ready when it +Recall our description (in the [Counting][counting] section) of waiting on +`rx.recv()` . The `recv()` call returns a `Future`, and awaiting it polls it. In +our initial discussion, we noted that a runtime will pause the future until it +is ready with either `Some(message)` or `None` when the channel closes. With our +deeper understanding of `Future` in place, and specifically `Future::poll`, we +can see how that works. The runtime knows the future is not ready when it returns `Poll::Pending`. Conversely, the runtime knows the future is ready and advances it when `poll` returns `Poll::Ready(Some(message))` or `Poll::Ready(None)`. -[counting]: /ch17-02-concurrency-with-async.md +The exact details of how a runtime does that are more than we will cover in even +this deep dive section. The key here is to see the basic mechanic of futures: a +runtime *polls* each future it is responsible for, putting it back to sleep when +it is not yet ready. ---- +### Pinning and the Pin and Unpin Traits - - > Incoherent sentence and a *lot* of material in it which we do not unpack in this paragraph. - --> +When we introduced the idea of pinning, while working on Listing 17-16, we ran +into a very gnarly error message. Here is the relevant part of it again: -The rest of the message tells us *why* that is required: the `JoinAll` -struct returned by `trpl::join_all` is generic over a type `F` which must -implement the `Future` trait, directly awaiting a Future requires that the -future implement the `Unpin` trait. Understanding this error means we need to -dive into a little more of how the `Future` type actually works, in particular -the idea of *pinning*. + -### Pinning and the Pin and Unpin Traits +```text +error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned + --> src/main.rs:46:33 + | +46 | trpl::join_all(futures).await; + | ^^^^^ the trait `Unpin` is not implemented for `{async block@src/main.rs:8:23: 20:10}`, which is required by `Box<{async block@src/main.rs:8:23: 20:10}>: std::future::Future` + | + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope + = note: required for `Box<{async block@src/main.rs:8:23: 20:10}>` to implement `std::future::Future` +note: required by a bound in `JoinAll` + --> /Users/chris/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:29:8 + | +27 | pub struct JoinAll + | ------- required by a bound in this struct +28 | where +29 | F: Future, + | ^^^^^^ required by this bound in `JoinAll` + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. +``` - +When we read this error message carefully, it not only tells us that we need to +pin the values but also us why pinning is required. The `trpl::join_all` +function returns a struct called `JoinAll`. That struct in turn is generic over +a type `F`, which is constrained to implement the `Future` trait. Finally, +directly awaiting a Future requires that the future in question implement the +`Unpin` trait. That’s a lot! But we can understand it, if we dive a little +further into how the `Future` type actually works, in particular around +*pinning*. -Let’s look again at the definition of `Future`, focusing now on its `poll` -method’s `self` type: +Let’s look again at the definition of `Future`, focusing specifically on the +`poll` method’s `self` type: ```rust use std::pin::Pin; @@ -155,13 +181,13 @@ this syntax in Chapter 18. For now, it is enough to know that if we want to poll a future (to check whether it is `Pending` or `Ready(Output)`), we need a mutable reference to the type, which is wrapped in a `Pin`. -`Pin` is a smart pointer, much like `Box`, `Rc`, and the others we saw in -Chapter 15. Unlike those, however, `Pin` only works with *other pointer types* -like reference (`&` and `&mut`) and smart pointers (`Box`, `Rc`, and so on). To -be precise, `Pin` works with types which implement the `Deref` or `DerefMut` -traits, which we covered in Chapter 15. You can think of this restriction as -equivalent to only working with pointers, though, since implementing `Deref` or -`DerefMut` means your type behaves like a pointer type. +`Pin` is a wrapper type, much like the `Box`, `Rc`, and other smart pointer +types we saw in Chapter 15. Unlike those, however, `Pin` only works with *other +pointer types* like reference (`&` and `&mut`) and smart pointers (`Box`, `Rc`, +and so on). To be precise, `Pin` works with types which implement the `Deref` or +`DerefMut` traits, which we covered in Chapter 15. You can think of this +restriction as equivalent to only working with pointers, though, since +implementing `Deref` or `DerefMut` means your type behaves like a pointer type. Recalling that `.await` is implemented in terms of calls to `poll()`, this starts to explain the error message we saw above—but that was in terms of @@ -234,6 +260,13 @@ because it requires *you* to uphold all the guarantees which make `Pin` and `Unpin` safe yourself for a type with internal references. In practice, this is a very rare thing to implement yourself! +Now we know enough to understand the errors reported for that `join_all` call. +We originally tried to move the futures produced by an async blocks into a +`Vec>>`, but as we have seen, those futures may have +internal references, so they do not implement `Unpin`. They need to be pinned, +and then we can pass the `Pin` type into the `Vec`, confident that the +underlying data in the futures will *not* be moved. + > Note: This combination of `Pin` and `Unpin` allows a whole class of complex > types to be safe in Rust which are otherwise difficult to implement because > they are self-referential. Types which require `Pin` show up *most* commonly @@ -242,29 +275,32 @@ a very rare thing to implement yourself! > The specific mechanics for how `Pin` and `Unpin` work under the hood are > covered extensively in the API documentation for `std::pin`, so if you would > like to understand them more deeply, that is a great place to start. +> +> If you want to understand how things work “under the hood” in even more +> detail, the official [_Asynchronous Programming in Rust_][async-book] book has +> you covered: +> +> - [Chapter 2: Under the Hood: Executing Futures and Tasks][under-the-hood] +> - [Chapter 4: Pinning][pinning]. -Now we know enough to fix the last errors with `join_all`. We tried to move the -futures produced by an async blocks into a `Vec>>`, -but as we have seen, those futures may have internal references, so they do not -implement `Unpin`. They need to be pinned, and then we can pass the `Pin` type -into the `Vec`, confident that the underlying data in the futures will *not* be -moved. - ---- +Now that we have a deeper grasp on the `Future`, `Pin`, and `Unpin` traits, we +can turn our attention to the `Stream` trait. -### The Stream API +### The Stream Trait -Unlike `Iterator` and `Future`, there is no definition of a `Stream` trait in -the standard library yet as of the time of writing, but there *is* a very common definition used throughout the -ecosystem. Let’s review the definitions of the `Iterator` and `Future` traits, -so we can build up to how a `Stream` trait that merges them together might look. +ecosystem. -From `Iterator`, we have the idea of a sequence: its `next` method provides an +Let’s review the definitions of the `Iterator` and `Future` traits, so we can +build up to how a `Stream` trait that merges them together might look. From +`Iterator`, we have the idea of a sequence: its `next` method provides an `Option`. From `Future`, we have the idea of readiness over time: its `poll` method provides a `Poll`. To represent a sequence of -items which become ready over time, we define a `Stream` trait which has all of -those features put together: +items which become ready over time, we define a `Stream` trait which puts those +features together: ```rust use std::pin::Pin; @@ -282,11 +318,12 @@ trait Stream { The `Stream` trait defines an associated type `Item` for the type of the items produced by the stream. This is like `Iterator`: there may be zero to many of -these, and unlike `Future`, where there was a single `Output`. +these, and unlike `Future`, where there is always a single `Output` (even if it +the unit type `()`). `Stream` also defines a method to get those items. We call it `poll_next`, to make it clear that it polls like `Future::poll` and produces a sequence of items -like `Iterator::next`. Its return type uses both `Poll` and `Option`. The outer +like `Iterator::next`. Its return type combines `Poll`with `Option`. The outer type is `Poll`, since it has to be checked for readiness, just like a future. The inner type is `Option`, since it needs to signal whether there are more messages, just like an iterator. @@ -295,12 +332,12 @@ Something very similar to this will likely end up standardized as part of Rust standard library. In the meantime, it is part of the toolkit of most runtimes, so you can rely on it, and everything we cover below should generally apply! -In the example we saw above, though, we did not use `poll_next` *or* `Stream`, -but instead `next` and `StreamExt`. We *could* work directly in terms of the -`poll_next` API by hand-writing our own `Stream` state machines, of course, just -as we *could* work with futures directly via their `poll` method. Using `await` -is much nicer, though, so the `StreamExt` trait supplies the `next` method so -we can do just that. +In the example we saw in the section on streaming, though, we did not use +`poll_next` *or* `Stream`, but instead used `next` and `StreamExt`. We *could* +work directly in terms of the `poll_next` API by hand-writing our own `Stream` +state machines, of course, just as we *could* work with futures directly via +their `poll` method. Using `await` is much nicer, though, so the `StreamExt` +trait supplies the `next` method so we can do just that. ```rust {{#rustdoc_include ../listings/ch17-async-await/no-listing-stream-ext/src/lib.rs:here}} @@ -327,3 +364,19 @@ The `StreamExt` trait is also the home of all the interesting methods available to use with streams. `StreamExt` is automatically implemented for every type which implements `Stream`, but they are separated out so that the community can iterate on the foundational trait distinctly from the convenience APIs. + +In the version of `StreamExt` used in the `trpl` crate, the trait not only +defines the `next` method, it also supplies an implementation of `next`, which +correctly handles the details of calling `Stream::poll_next`. This means that +even when you need to write your own streaming data type, you *only* have to +implement `Stream`, and then anyone who uses your data type can use `StreamExt` +and its methods with it automatically. + +[counting]: /ch17-02-concurrency-with-async.md +[async-book]: https://rust-lang.github.io/async-book/ +[under-the-hood]: https://rust-lang.github.io/async-book/02_execution/01_chapter.html +[pinning]: https://rust-lang.github.io/async-book/04_pinning/01_chapter.html + +That’s all we’re going to cover for the lower-level details on these traits. To +wrap up, let’s consider how futures (including streams), tasks, and threads all +fit together! From 1d3517ce9993cfb5e6dfdf6d508f250a7afb235b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 11 Sep 2024 16:40:41 -0600 Subject: [PATCH 17/25] Ch. 17: integrate a number of the outstanding review comments Bonus: fix some style guide issues, too! Co-authored-by: Carol (Nichols || Goulding) Co-authored-by: James Munns Co-authored-by: Tim McNamara --- src/SUMMARY.md | 2 +- src/ch17-01-futures-and-syntax.md | 40 ++++++------ src/ch17-02-concurrency-with-async.md | 92 +++++++++++++++------------ src/ch17-03-more-futures.md | 81 +++++++++++++---------- src/ch17-04-streams.md | 4 +- src/ch17-05-traits-for-async.md | 61 ++++++++++-------- 6 files changed, 155 insertions(+), 125 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index b2af389757..40f5c22424 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -104,7 +104,7 @@ - [Async and Await](ch17-00-async-await.md) - [Futures and the Async Syntax](ch17-01-futures-and-syntax.md) - [Concurrency With Async](ch17-02-concurrency-with-async.md) - - [Working With More Than Two Futures](ch17-03-more-futures.md) + - [Working With Any Number of Futures](ch17-03-more-futures.md) - [Streams](ch17-04-streams.md) - [Digging Into the Traits for Async](ch17-05-traits-for-async.md) - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.md) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 9dc8d1eff0..5ce095f31b 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -78,9 +78,9 @@ returned a `Future`. Then Rust warned us that we did not do anything with the future. This is because futures are *lazy*: they don’t do anything until you ask them to with `await`. This should remind you of our discussion of iterators [back in Chapter -13][iterators-lazy]. Iterators do nothing unless you call their `.next()` -method—whether directly, or using `for` loops or methods like `.map()` which use -`.next()` under the hood. +13][iterators-lazy]. Iterators do nothing unless you call their `next` +method—whether directly, or using `for` loops or methods like `map` which use +`next` under the hood. With futures, the same basic idea applies: they do nothing unless you explicitly ask them to. This laziness allows Rust to avoid running async code until it is @@ -237,27 +237,27 @@ enum MyAsyncStateMachine { Writing that out by hand would be tedious and error-prone, especially when making changes to code later. Instead, the Rust compiler creates and manages the -state machine data structures for async code automatically. +state machine data structures for async code automatically. If you’re wondering: +yep, the normal borrowing and ownership rules around data structures all apply. +Happily, the compiler also handles checking those for us, and has good error +messages. We will work through a few of those later in the chapter! -If you’re wondering: yep, the normal borrowing and ownership rules around data -structures all apply. Happily, the compiler also handles checking those for us, -and has good error messages. We will work through a few of those later in the -chapter! - - +Ultimately, something has to execute that state machine. That something is a +runtime. This is why you may sometimes come across references to *executors* +when looking into runtimes: an executor is the part of a runtime responsible for +executing the async code. Now we can understand why the compiler stopped us from making `main` itself an async function in Listing 17-3. If `main` were an async function, something else -would need to call `poll()` on whatever `main` returned, but main is the -starting point for the program! Instead, we use the `trpl::run` function, which -sets up a runtime and polls the `Future` returned by `hello` until it returns -`Ready`. - -> Note: We skipped over most of the details of how the `Future` trait works so -> far. We will come back to some of those later in the chapter! +would need to manage the state machine for whatever future `main` returned, but +main is the starting point for the program! Instead, we use the `trpl::run` +function, which sets up a runtime and polls the `Future` returned by `hello` +until it returns `Ready`. + +> Note: some runtimes provide macros to make it so you *can* write an async main +> function. Those macros rewrite `async fn main() { ... }` to be a normal `fn +> main` which does the same thing we did by hand in Listing 17-TODO: call a +> function which runs a future to completion the way `trpl::run` does. Now that you know the basics of working with futures, we can dig into more of the things we can *do* with async. diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index b785e7dc76..369cb63b1c 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -103,14 +103,19 @@ with different syntax: using `.await` instead of calling `join` on the join handle, and awaiting the `sleep` calls. The bigger difference is that we did not need to spawn another operating system -thread to do this. In fact, we do not even a task here. Given that async blocks -compile to anonymous futures, we can put each loop in an async block and have -the runtime run them both to completion using `trpl::join`. - - +thread to do this. In fact, we do not even need to spawn a task here. Because +async blocks compile to anonymous futures, we can put each loop in an async +block and have the runtime run them both to completion using the `trpl::join` +function. + +In Chapter 16, we showed how to use the `join` method on the `JoinHandle` type +returned when you call `std::thread::spawn`. The `trpl::join` function is +similar, but for futures. When you give it two futures, it produces a single new +future whose output is a tuple with the output of each of the futures you passed +in once *both* complete. Thus, in Listing 17-7, we use `trpl::join` to wait for +both `fut1` and `fut2` to finish. We do *not* await `fut1` and `fut2`, but +instead the new future produced by `trpl::join`. We ignore the output, because +it is just a tuple with two unit values in it. @@ -147,7 +152,7 @@ what we saw with threads. That is because the `trpl::join` function is *fair*, meaning it checks each future equally often, alternating between them, and never lets one race ahead if the other is ready. With threads, the operating system decides which thread to check and how long to let it run. With async Rust, the -runtime decides which future to check. (In practice, the details get complicated +runtime decides which taks to check. (In practice, the details get complicated because an async runtime might use operating system threads under the hood as part of how it manages concurrency, so guaranteeing fairness can be more work for a runtime—but it is still possible!) Runtimes do not have to guarantee @@ -184,11 +189,11 @@ version of the API is only a little different from the thread-based version: it uses a mutable rather than an immutable receiver `rx`, and its `recv` method produces a future we need to await rather than producing the value directly. Now we can send messages from the sender to the receiver. Notice that we do not have -to spawn a separate thread or even a task; we merely need to await the -`rx.recv()` call. +to spawn a separate thread or even a task; we merely need to await the `rx.recv` +call. -The synchronous `Receiver::recv()` method in `std::mpsc::channel` blocks until -it receives a message. The `trpl::Receiver::recv()` method does not, because it +The synchronous `Receiver::recv` method in `std::mpsc::channel` blocks until +it receives a message. The `trpl::Receiver::recv` method does not, because it is async. Instead of blocking, it hands control back to the runtime until either a message is received or the send side of the channel closes. By contrast, we do not await the `send` call, because it does not block. It does not need to, @@ -221,17 +226,17 @@ know how many messages are coming in. In the real world, though, we will generally be waiting on some *unknown* number of messages. In that case, we need to keep waiting until we determine that there are no more messages. -In synchronous code, we might use a `for` loop to process a sequence of items -like this, regardless of how many items are in the loop. However, Rust does not -yet have a way to write a `for` loop over an *asynchronous* series of items. -Instead, we need to use a new kind of loop we haven’t seen before, the `while -let` conditional loop. A `while let` loop is the loop version of the `if let` -construct we saw back in Chapter 6. The loop while continue executing as long as -the pattern matches. +In Listing 16-10, we used a `for` loop to process all the items received from a +synchronous channel. However, Rust does not yet have a way to write a `for` loop +over an *asynchronous* series of items. Instead, we need to use a new kind of +loop we haven’t seen before, the `while let` conditional loop. A `while let` +loop is the loop version of the `if let` construct we saw back in Chapter 6. The +loop will continue executing as long as the pattern it specifies continues to +match the value. -The `rx.recv()` call produces a `Future`, which we await. The runtime will pause +The `rx.recv` call produces a `Future`, which we await. The runtime will pause the `Future` until it is ready. Once a message arrives, the future will resolve to `Some(message)`, as many times as a message arrives. When the channel closes, regardless of whether *any* messages have arrived, the future will instead @@ -247,8 +252,9 @@ again, so the runtime pauses it again until another message arrives. The code now successfully sends and receives all of the messages. Unfortunately, there are still a couple problems. For one thing, the messages do not arrive at half-second intervals. They arrive all at once, two seconds (2,000 milliseconds) -after we start the program. For another, this program also never stops! You will -need to shut it down using ctrl-c. +after we start the program. For another, this program also never exits! Instead, +it waits forever for new messages. You will need to shut it down using ctrl-c. Let’s start by understanding why the messages all come in at once after the full delay, rather than coming in with delays in between each one. Within a given @@ -263,7 +269,10 @@ let` loop get to go through any of the `.await` points on the `recv` calls. To get the behavior we want, where the sleep delay happens between receiving each message, we need to put the `tx` and `rx` operations in their own async blocks. Then the runtime can execute each of them separately using `trpl::join`, -just like in the counting example. +just like in the counting example. Once again, we await the result of calling +`trpl::join`, not the individual futures. If we awaited the individual futures +in sequence, we would just end up back in a sequential flow—exactly what we are +trying *not* to do. @@ -278,28 +287,28 @@ just like in the counting example. With the updated code in Listing 17-10, the messages get printed at 500-millisecond intervals, rather than all in a rush after two seconds. -The program still never stops, because of the way `while let` loop interacts -with `trpl::join`: +The program still never exits, though, because of the way `while let` loop +interacts with `trpl::join`: * The future returned from `trpl::join` only completes once *both* futures passed to it have completed. * The `tx` future completes once it finishes sleeping after sending the last message in `vals`. * The `rx` future will not complete until the `while let` loop ends. -* The `while let` loop will not end until `rx.recv().await` produces `None`. -* The `rx.recv().await` will only return `None` once the other end of the - channel is closed. -* The channel will only close if we call `rx.close()` or when the sender side, +* The `while let` loop will not end until awaiting `rx.recv` produces `None`. +* Awaiting `rx.recv` will only return `None` once the other end of the channel + is closed. +* The channel will only close if we call `rx.close` or when the sender side, `tx`, is dropped. -* We do not call `rx.close()` anywhere, and `tx` will not be dropped until the - async block ends. -* The block cannot end because it is blocked on `trpl::join` completing, - which takes us back to the top of this list! +* We do not call `rx.close` anywhere, and `tx` will not be dropped until the + outermost async block passed to `trpl::run` ends. +* The block cannot end because it is blocked on `trpl::join` completing, which + takes us back to the top of this list! -We could manually close `rx` by calling `rx.close()` somewhere, but that does -not make much sense. Stopping after handling some arbitrary number of messages -would make the program shut down, but we could miss messages. We need some other -way to make sure that `tx` gets dropped *before* the end of the function. +We could manually close `rx` by calling `rx.close` somewhere, but that does not +make much sense. Stopping after handling some arbitrary number of messages would +make the program shut down, but we could miss messages. We need some other way +to make sure that `tx` gets dropped *before* the end of the function. Right now, the async block where we send the messages only borrows `tx`, but if we could move `tx` into that async block, it would be dropped once that block @@ -324,9 +333,10 @@ This async channel is also a multiple-producer channel, so we can call `clone` on `tx` if we want to send messages from multiple futures. In Listing 17-12, we clone `tx`, creating `tx1` outside the first async block. We move `tx1` into that block just as we did before with `tx`. Then, later, we move the original -`tx` into a *new* async block, where we send more messages on a slightly -slower delay. (We happen to put this new async block after the async block -for receiving messages, but it could go before it just as well.) +`tx` into a *new* async block, where we send more messages on a slightly slower +delay. We happen to put this new async block after the async block for receiving +messages, but it could go before it just as well. They key is the order of the +futures are awaited in, not the order they are created in. Both of the async blocks for sending messages need to be `async move` blocks, so that both `tx` and `tx1` get dropped when those blocks finish. Otherwise we will diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 1affdf7def..9643836686 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -1,11 +1,12 @@ -## Working With More Than Two Futures +## Working With Any Number of Futures When we switched from using two futures to three in the previous section, we also had to switch from using `join` to using `join3`. It would be annoying to -do this every time we changed our code. Happily, we have a macro form of `join` -to which we can pass an arbitrary number of arguments. It also handles awaiting -the futures itself. Thus, we could rewrite the code from Listing 17-12 to use -`join!` instead of `join3`, as in Listing 17-13: +have to call a different function every time we changed the number of futures we +wanted to join. Happily, we have a macro form of `join` to which we can pass an +arbitrary number of arguments. It also handles awaiting the futures itself. +Thus, we could rewrite the code from Listing 17-12 to use `join!` instead of +`join3`, as in Listing 17-13: @@ -96,8 +97,8 @@ implement the `Future` trait. > able to work with a dynamic collection of futures where we do not know what > they will all be until runtime. -We start by wrapping each of the futures in the `vec!` in a `Box::new()`, as -shown in Listing 17-15. +We start by wrapping each of the futures in the `vec!` in a `Box::new`, as shown +in Listing 17-15. @@ -241,7 +242,7 @@ There is a bit more we can explore here. For one thing, using `Pin>` comes with a small amount of extra overhead from putting these futures on the heap with `Box`—and we are only doing that to get the types to line up. We don’t actually *need* the heap allocation, after all: these futures are local to this -particular function. As noted above, `Pin` is itself a smart pointer, so we can +particular function. As noted above, `Pin` is itself a wrapper type, so we can get the benefit of having a single type in the `Vec`—the original reason we reached for `Box`—without doing a heap allocation. We can use `Pin` directly with each future, using the `std::pin::pin` macro. @@ -260,11 +261,10 @@ references to the dynamic `Future` type, as in Listing 17-18. -There is one last issue to fix. We got this far by ignoring the fact that we -might have different `Output` types. For example, in Listing 17-19, the -anonymous future for `a` implements `Future`, the anonymous future -for `b` implements `Future`, and the anonymous future for `c` -implements `Future`. +We got this far by ignoring the fact that we might have different `Output` +types. For example, in Listing 17-19, the anonymous future for `a` implements +`Future`, the anonymous future for `b` implements `Future`, and the anonymous future for `c` implements `Future`. @@ -277,8 +277,7 @@ implements `Future`. We can use `trpl::join!` to await them, because it allows you to pass in multiple future types and produces a tuple of those types. We *cannot* use `trpl::join_all`, because it requires the futures passed in all to have the same -type. (Remember, that error is what got us started on this adventure with -`Pin`!) +type. Remember, that error is what got us started on this adventure with `Pin`! This is a fundamental tradeoff: we can either deal with a dynamic number of futures with `join_all`, as long as they all have the same type, or we can deal @@ -287,13 +286,6 @@ even if they have different types. This is the same as working with any other types in Rust, though. Futures are not special, even though we have some nice syntax for working with them, and that is a good thing. -In practice, you will usually work directly with `async` and `.await`, and -secondarily with functions and macros like `join` or `join_all`. You will only -need to reach for `pin` now and again to use them with those APIs. `Pin` and -`Unpin` are mostly important for building lower-level libraries, or when you are -building a runtime itself, rather than for day to day Rust code. When you see -them, though, now you will know what to do! - ### Racing futures When we “join” futures with the `join` family of functions and macros, we @@ -302,11 +294,16 @@ need *some* future from a set to finish before we move on—kind of like racing one future against another. This operation is often named `race` for exactly that reason. -In Listing 17-20, we use `race` to run two futures, `slow` and `fast`, against -each other. Each one prints a message when it starts running, pauses for some -amount of time by calling and awaiting `sleep`, and then prints another message -when it finishes. Then we pass both to `trpl::race` and wait for one of them to -finish. (The outcome here won’t be too surprising: `fast` wins!) +> Note: Under the hood, `race` is built on a more general function, `select`, +> which you will encounter more often in real-world Rust code. A `select` +> function can do a lot of things that `trpl::race` function cannot, but it also +> has some additional complexity that we can skip over for now. + +In Listing 17-20, we use `trpl::race` to run two futures, `slow` and `fast`, +against each other. Each one prints a message when it starts running, pauses for +some amount of time by calling and awaiting `sleep`, and then prints another +message when it finishes. Then we pass both to `trpl::race` and wait for one of +them to finish. (The outcome here won’t be too surprising: `fast` wins!) @@ -507,12 +504,12 @@ future. Let’s implement this! To begin, let’s think about the API for `timeout`: -- It needs to be an async function itself so we can await it. -- Its first parameter should be a future to run. We can make it generic to allow +* It needs to be an async function itself so we can await it. +* Its first parameter should be a future to run. We can make it generic to allow it to work with any future. -- Its second parameter will be the maximum time to wait. If we use a `Duration`, +* Its second parameter will be the maximum time to wait. If we use a `Duration`, that will make it easy to pass along to `trpl::sleep`. -- It should return a `Result`. If the future completes successfully, the +* It should return a `Result`. If the future completes successfully, the `Result` will be `Ok` with the value produced by the future. If the timeout elapses first, the `Result` will be `Err` with the duration that the timeout waited for. @@ -588,9 +585,25 @@ using smaller async building blocks. For example, you can use this same approach to combine timeouts with retries, and in turn use those with things like network calls—one of the examples from the beginning of the chapter! -Over the last two sections, we have seen how to work with multiple futures at -the same time. Up next, let’s look at how we can work with multiple futures in a -sequence over time, with *streams*. +In practice, you will usually work directly with `async` and `.await`, and +secondarily with functions and macros like `join`, `join_all`, `race`, and so +on. You will only need to reach for `pin` now and again to use them with those +APIs. + +We have now seen a number of ways to work with multiple futures at the same +time. Up next, we will look at how we can work with multiple futures in a +sequence over time, with *streams*. Here are a couple more things you might want +to consider first, though: + +* We used a `Vec` with `join_all` to wait for all of the futures in some group + to finish. How could you use a `Vec` to process a group of futures in + sequence, instead? What are the tradeoffs of doing that? + +* Take a look at the `futures::stream::FuturesUnordered` type from the `futures` + crate. How would using it be different from using a `Vec`? (Don’t worry about + the fact that it is from the `stream` part of the crate; it works just fine + with any collection of futures.) + [collections]: ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: ch12-03-improving-error-handling-and-modularity.html diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 9fd9049430..e4ae1ed7e1 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -129,7 +129,7 @@ avoid doing needless work. Let’s start by building a little stream of messages, similar to what we might see from a WebSocket or other real-time communication protocols. In Listing -17-32, we create a function `get_messages()` which returns `impl Stream`. For its implementation, we create an async channel, loop over the first ten letters of the English alphabet, and send them across the channel. @@ -310,7 +310,7 @@ Finally, we loop over that combined stream instead of over `messages` (Listing At this point, neither `messages` nor `intervals` needs to be pinned or mutable, because both will be combined into the single `merged` stream. However, this -call to `merge` does not type check! (Neither does the `next` call in the `while +call to `merge` does not compile! (Neither does the `next` call in the `while let` loop, but we will come back to that after fixing this.) The two streams have different types. The `messages` stream has the type `Timeout>`, where `Timeout` is the type which implements `Stream` diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 827e625e23..9eb31d2fa4 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -51,10 +51,10 @@ work to do, so the caller will need to check again later. The `Ready` variant indicates that the `Future` has finished its work and the `T` value is available. -> Note: With most futures, the caller should not call `poll()` again after the +> Note: With most futures, the caller should not call `poll` again after the > future has returned `Ready`. Many futures will panic if polled again after > becoming ready! Futures which are safe to poll again will say so explicitly in -> their documentation. +> their documentation. This is similar to how `Iterator::next` behaves! Under the hood, when you call `.await`, Rust compiles that to code which calls `poll`, kind of (although not exactly ) @@ -97,9 +97,9 @@ on this future and work on other futures and check this one again later. That one of the main jobs for a runtime. Recall our description (in the [Counting][counting] section) of waiting on -`rx.recv()` . The `recv()` call returns a `Future`, and awaiting it polls it. In -our initial discussion, we noted that a runtime will pause the future until it -is ready with either `Some(message)` or `None` when the channel closes. With our +`rx.recv`. The `recv` call returns a `Future`, and awaiting it polls it. In our +initial discussion, we noted that a runtime will pause the future until it is +ready with either `Some(message)` or `None` when the channel closes. With our deeper understanding of `Future` in place, and specifically `Future::poll`, we can see how that works. The runtime knows the future is not ready when it returns `Poll::Pending`. Conversely, the runtime knows the future is ready and @@ -176,20 +176,25 @@ like this. When we specify the type of `self` like this, we are telling Rust what type `self` must be to call this method. These kinds of type annotations for `self` are similar to those for other function parameters, but with the restriction that the type annotation has to be the type on which the method is -implemented, or a reference or smart pointer to that type. We will see more on -this syntax in Chapter 18. For now, it is enough to know that if we want to poll -a future (to check whether it is `Pending` or `Ready(Output)`), we need a -mutable reference to the type, which is wrapped in a `Pin`. - -`Pin` is a wrapper type, much like the `Box`, `Rc`, and other smart pointer -types we saw in Chapter 15. Unlike those, however, `Pin` only works with *other -pointer types* like reference (`&` and `&mut`) and smart pointers (`Box`, `Rc`, -and so on). To be precise, `Pin` works with types which implement the `Deref` or -`DerefMut` traits, which we covered in Chapter 15. You can think of this -restriction as equivalent to only working with pointers, though, since -implementing `Deref` or `DerefMut` means your type behaves like a pointer type. - -Recalling that `.await` is implemented in terms of calls to `poll()`, this +implemented, or a reference or smart pointer to that type, or a `Pin` wrapping a +reference to that type. We will see more on this syntax in Chapter 18. For now, +it is enough to know that if we want to poll a future (to check whether it is +`Pending` or `Ready(Output)`), we need a mutable reference to the type, which is +wrapped in a `Pin`. + +`Pin` is a wrapper type. In some ways, it is like the `Box`, `Rc`, and other +smart pointer types we saw in Chapter 15, which also wrap other types. Unlike +those, however, `Pin` only works with *other pointer types* like reference (`&` +and `&mut`) and smart pointers (`Box`, `Rc`, and so on). To be precise, `Pin` +works with types which implement the `Deref` or `DerefMut` traits, which we +covered in Chapter 15. You can think of this restriction as equivalent to only +working with pointers, though, since implementing `Deref` or `DerefMut` means +your type behaves like a pointer type. `Pin` is also not a pointer itself, and +it does not have any behavior of its own like the ref counting of `Rc` or `Arc`. +It is purely a tool the compiler can use to uphold the relevant guarantees, by +wrapping pointers in the type. + +Recalling that `.await` is implemented in terms of calls to `poll`, this starts to explain the error message we saw above—but that was in terms of `Unpin`, not `Pin`. So what exactly are `Pin` and `Unpin`, how do they relate, and why does `Future` need `self` to be in a `Pin` type to call `poll`? @@ -267,6 +272,10 @@ internal references, so they do not implement `Unpin`. They need to be pinned, and then we can pass the `Pin` type into the `Vec`, confident that the underlying data in the futures will *not* be moved. +`Pin` and `Unpin` are mostly important for building lower-level libraries, or +when you are building a runtime itself, rather than for day to day Rust code. +When you see them, though, now you will know what to do! + > Note: This combination of `Pin` and `Unpin` allows a whole class of complex > types to be safe in Rust which are otherwise difficult to implement because > they are self-referential. Types which require `Pin` show up *most* commonly @@ -283,16 +292,14 @@ underlying data in the futures will *not* be moved. > - [Chapter 2: Under the Hood: Executing Futures and Tasks][under-the-hood] > - [Chapter 4: Pinning][pinning]. -Now that we have a deeper grasp on the `Future`, `Pin`, and `Unpin` traits, we -can turn our attention to the `Stream` trait. - ### The Stream Trait -As described in the section introducing streams, streams are like asynchronous -iterators. Unlike `Iterator` and `Future`, there is no definition of a `Stream` -trait in the standard library as of the time of writing, but there *is* a very common definition used throughout the -ecosystem. +Now that we have a deeper grasp on the `Future`, `Pin`, and `Unpin` traits, we +can turn our attention to the `Stream` trait. As described in the section +introducing streams, streams are like asynchronous iterators. Unlike `Iterator` +and `Future`, there is no definition of a `Stream` trait in the standard library +as of the time of writing, but there +*is* a very common definition used throughout the ecosystem. Let’s review the definitions of the `Iterator` and `Future` traits, so we can build up to how a `Stream` trait that merges them together might look. From From c4d02bf83bbef781f0541dffaa9dd1414852e410 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 12 Sep 2024 15:28:10 -0600 Subject: [PATCH 18/25] =?UTF-8?q?Ch.=2017:=20address=20the=20rest=20of=20J?= =?UTF-8?q?ames=E2=80=99=20review=20comments=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: James Munns --- src/ch17-03-more-futures.md | 21 ++++---- src/ch17-06-futures-tasks-threads.md | 74 +++++++++++++++++++++------- 2 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 9643836686..b9f1fccc65 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -322,18 +322,19 @@ to poll first. Regardless of whether the implementation of race we are using is fair, though, *one* of the futures will run up to the first `.await` in its body before another task can start. -Recall from [“What Are Futures?”][futures] that at each await point, Rust pauses -the async block and hands control back to a runtime. The inverse is also true: -Rust *only* pauses async blocks and hands control back to a runtime at an await -point. Everything between await points is synchronous. +Recall from [“What Are Futures?”][futures] that at each await point, Rust gives +a runtime a chance to pause the task and switch to another one if the future +being awaited is not ready. The inverse is also true: Rust *only* pauses async +blocks and hands control back to a runtime at an await point. Everything between +await points is synchronous. That means if you do a bunch of work in an async block without an await point, -that future will block any other futures from making progress. (You may -sometimes hear this referred to as one future *starving* other futures. And this -applies to threads, too!) In many cases, that may not be a big deal. However, if -you are doing some kind of expensive setup or long-running work, or if you have -a future which will keep doing some particular task indefinitely, you will need -to think about when and where to hand control back to the runtime. +that future will block any other futures from making progress. You may sometimes +hear this referred to as one future *starving* other futures. In many cases, +that may not be a big deal. However, if you are doing some kind of expensive +setup or long-running work, or if you have a future which will keep doing some +particular task indefinitely, you will need to think about when and where to +hand control back to the runtime. But *how* would you hand control back to the runtime in those cases? diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 7ee933c4f7..ad3a4d24da 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -12,8 +12,8 @@ However, they are not without their tradeoffs. On many operating systems, they use a fair bit of memory for each thread, and they come with some overhead for starting up and shutting down. Threads are also only an option when your operating system and hardware support them! Unlike mainstream desktop and mobile -operating systems, many embedded operating systems, like those used on some -microcontrollers, do not have OS-level threads at all. +computers, some embedded systems do not have an OS at all, so they also do not +have threads! The async model provides a different—and ultimately complementary—set of tradeoffs. In the async model, concurrent operations do not require their own @@ -55,21 +55,20 @@ possible both *between* and *within* tasks. In that regard, tasks are kind of like lightweight, runtime-managed threads with added capabilities that come from being managed by a runtime instead of by the operating system. Futures are an even more granular unit of concurrency, where each future may represent a tree -of other futures. +of other futures. That is, the runtime—specifically, its executor—manages tasks, +and tasks manage futures. However, this does not mean that async tasks are always better than threads, any more than that threads are always better than tasks. On the one hand, concurrency with threads is in some ways a simpler programming -model than concurrency with `async`. Threads are somewhat “fire and forget”, and -they only allow interaction with the rest of the program via tools like channels -or their final result via `join`. On the other hand, they have no native -equivalent to a future, so they simply run to completion, without interruption -except by the operating system itself. Threads also have no mechanisms for -cancellation—a subject we have not covered in depth in this chapter, but which -is implicit in the fact that whenever we ended a future, its state got cleaned -up correctly. +model than concurrency with `async`. Threads are somewhat “fire and forget,” +they have no native equivalent to a future, so they simply run to completion, +without interruption except by the operating system itself. That is, they have +no *intra-task concurrency* like futures can. Threads in Rust also have no +mechanisms for cancellation—a subject we have not covered in depth in this +chapter, but which is implicit in the fact that whenever we ended a future, its +state got cleaned up correctly. These limitations make threads harder to compose than futures. It is much more difficult, for example, to build something like the `timeout` we built in @@ -83,10 +82,11 @@ and how to group them. And it turns out that threads and tasks often work very well together, because tasks can (at least in some runtimes) be moved around between threads. We have not mentioned it up until now, but under the hood the `Runtime` we have been using, including the `spawn_blocking` and `spawn_task` -functions, are multithreaded by default! Many runtimes can transparently move -tasks around between threads based on the current utilization of the threads, to -hopefully improve the overall performance of the system. To build that actually -requires threads *and* tasks, and therefore futures. +functions, is multithreaded by default! Many runtimes use an approach called +*work stealing* to transparently move tasks around between threads based on the +current utilization of the threads, with the aim of improving the overall +performance of the system. To build that actually requires threads *and* tasks, +and therefore futures. As a default way of thinking about which to use when: @@ -98,7 +98,47 @@ As a default way of thinking about which to use when: And if you need some mix of parallelism and concurrency, you do not have to choose between threads and async. You can use them together freely, letting each -one serve the part it is best at. +one serve the part it is best at. For example, Listing 17-TODO shows a fairly +common example of this kind of mix in real-world Rust code. + + + ++ +```rust +use std::thread; + +fn main() { + let (tx, mut rx) = trpl::channel(); + + thread::spawn(move || { + for i in 1..11 { + tx.send(i).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + trpl::run(async { + while let Some(message) = rx.recv().await { + println!("{message}"); + } + }); +} +``` + + + +We begin by creating an async channel. Then we spawn a thread which takes +ownership of the sender side of the channel. Within the thread, we send the +numbers 1 through 10, and sleep for a second in between each. Finally, we run a +future created with an async block passed to `trpl::run` just like we have +throughout the chapter. In that future, we await those messages, just like in +the other message-passing examples we have seen. + +To return to the examples we opened the chapter with: you could imagine running +a set of video encoding tasks using a dedicated thread, since video encoding is +compute bound, but notifying the UI that those operations are done with an async +channel. Examples of this kind of mix abound! ## Summary From c35b7d9453b9ed86b0ace0f46f824f0f36f189ba Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 12 Sep 2024 17:30:24 -0600 Subject: [PATCH 19/25] Ch. 17: address most of the rest of Carol's outstanding comments --- .../listing-17-18/src/main.rs | 6 +- .../listing-17-27/src/main.rs | 2 +- .../listing-17-28/src/main.rs | 10 +++- src/ch17-00-async-await.md | 4 +- src/ch17-02-concurrency-with-async.md | 25 +++++--- src/ch17-03-more-futures.md | 60 +++++++++++-------- src/ch17-04-streams.md | 2 +- 7 files changed, 65 insertions(+), 44 deletions(-) diff --git a/listings/ch17-async-await/listing-17-18/src/main.rs b/listings/ch17-async-await/listing-17-18/src/main.rs index c5ccc0b5bd..41820fc8a5 100644 --- a/listings/ch17-async-await/listing-17-18/src/main.rs +++ b/listings/ch17-async-await/listing-17-18/src/main.rs @@ -13,7 +13,7 @@ fn main() { let tx1 = tx.clone(); // ANCHOR: here let tx1_fut = pin!(async move { - // snip... + // --snip-- // ANCHOR_END: here let vals = vec![ String::from("hi"), @@ -32,7 +32,7 @@ fn main() { // ANCHOR_END: here // ANCHOR: here let rx_fut = pin!(async { - // snip... + // --snip-- // ANCHOR_END: here while let Some(value) = rx.recv().await { println!("received '{value}'"); @@ -41,7 +41,7 @@ fn main() { }); let tx_fut = pin!(async move { - // snip... + // --snip-- // ANCHOR_END: here let vals = vec![ String::from("more"), diff --git a/listings/ch17-async-await/listing-17-27/src/main.rs b/listings/ch17-async-await/listing-17-27/src/main.rs index 6c2ae688e4..d2edded63d 100644 --- a/listings/ch17-async-await/listing-17-27/src/main.rs +++ b/listings/ch17-async-await/listing-17-27/src/main.rs @@ -20,7 +20,7 @@ fn main() { // ANCHOR: declaration async fn timeout( - future: F, + future_to_try: F, max_time: Duration, ) -> Result { // Here is where our implementation will go! diff --git a/listings/ch17-async-await/listing-17-28/src/main.rs b/listings/ch17-async-await/listing-17-28/src/main.rs index d34a2a8f0e..9efb5e7921 100644 --- a/listings/ch17-async-await/listing-17-28/src/main.rs +++ b/listings/ch17-async-await/listing-17-28/src/main.rs @@ -2,8 +2,12 @@ extern crate trpl; // required for mdbook test use std::{future::Future, time::Duration}; +// ANCHOR: implementation use trpl::Either; +// --snip-- +// ANCHOR: implementation + fn main() { trpl::run(async { let slow = async { @@ -11,7 +15,7 @@ fn main() { "Finally finished" }; - match timeout(Duration::from_secs(2), slow).await { + match timeout(slow, Duration::from_secs(2)).await { Ok(message) => println!("Succeeded with '{message}'"), Err(duration) => { println!("Failed after {} seconds", duration.as_secs()) @@ -21,11 +25,11 @@ fn main() { } async fn timeout( + future_to_try: F, max_time: Duration, - future: F, ) -> Result { // ANCHOR: implementation - match trpl::race(future, trpl::sleep(max_time)).await { + match trpl::race(future_to_try, trpl::sleep(max_time)).await { Either::Left(output) => Ok(output), Either::Right(_) => Err(max_time), } diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 5540f0b795..2e20b366cd 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -11,8 +11,8 @@ The video export will use as much CPU and GPU power as it can. If you only had one CPU core, and your operating system never paused that export until it completed, you could not do anything else on your computer while it was running. That would be a pretty frustrating experience, though. Instead, your computer’s -operating sysem can (and does!) invisibly interrupt the export often enough to -let you get other work done along the way. +operating sysem can—and does!—invisibly interrupt the export often enough to let +you get other work done along the way. The file download is different. It does not take up very much CPU time. Instead, the CPU needs to wait on data to arrive from the network. While you can start diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 369cb63b1c..98a4e393d9 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -173,7 +173,11 @@ each case *before* running the code! ### Message Passing Sharing data between futures will also be familiar: we will use message passing -again, but this with async versions of the types and functions. +again, but this with async versions of the types and functions. We will take a +slightly different path than we did in Chapter 16, to illustrate some of the key +differences between thread-based and futures-based concurrency. In Listing 17-8, +we will begin with just a single async block—*not* spawning a separate task like +we spawned a separate thread. @@ -183,7 +187,7 @@ again, but this with async versions of the types and functions. -We start by using `trpl::channel`, an async version of the multiple-producer, +Here, we use `trpl::channel`, an async version of the multiple-producer, single-consumer channel API we used with threads back in Chapter 16. The async version of the API is only a little different from the thread-based version: it uses a mutable rather than an immutable receiver `rx`, and its `recv` method @@ -206,9 +210,13 @@ because the channel we are sending it into is unbounded. > code, and thus where to transition between sync and async code. In most async > runtimes, `run` is actually named `block_on` for exactly this reason. -It is hard to see the effect of async in Listing 17-8, though, since the message -will arrive right away! Let’s go ahead and send a whole series of messages, and -sleep in between them, as shown in Listing 17-9: +Notice two things about this example: First, the message will arrive right away! +Second, although we use a future here, there is no concurrency yet. Everything +in the listing happens in sequence, just as it would if there were no futures +involved. + +Let’s address the first part by sending a series of messages, and sleep in +between them, as shown in Listing 17-9: @@ -262,9 +270,10 @@ async block, the order that `.await` keywords appear in the code is also the order they happen when running the program. There is only one async block in Listing 17-9, so everything in it runs -linearly. All the `tx.send` calls happen, interspersed with all of the -`trpl::sleep` calls and their associated await points. Only then does the `while -let` loop get to go through any of the `.await` points on the `recv` calls. +linearly. There is still no concurrency. All the `tx.send` calls happen, +interspersed with all of the `trpl::sleep` calls and their associated await +points. Only then does the `while let` loop get to go through any of the +`.await` points on the `recv` calls. To get the behavior we want, where the sleep delay happens between receiving each message, we need to put the `tx` and `rx` operations in their own async diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index b9f1fccc65..7a57548d63 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -125,10 +125,10 @@ object (Listing 17-16). The type we had to write here is a little involved, so let’s walk through it: -* The innermost type is the future itself. We note explicitly that it the output - of the future is the unit type `()` by writing `Future`. +* The innermost type is the future itself. We note explicitly that the output of + the future is the unit type `()` by writing `Future`. * Then we annotate the trait with `dyn` to mark it as dynamic. -* The entire trait is wrapped in a `Box`. +* The entire trait reference is wrapped in a `Box`. * Finally, we state explicitly that `futures` is a `Vec` containing these items. That already made a big difference. Now when we run the compiler, we only have @@ -330,12 +330,16 @@ await points is synchronous. That means if you do a bunch of work in an async block without an await point, that future will block any other futures from making progress. You may sometimes -hear this referred to as one future *starving* other futures. In many cases, +hear this referred to as one future *starving* other futures. In some cases, that may not be a big deal. However, if you are doing some kind of expensive setup or long-running work, or if you have a future which will keep doing some particular task indefinitely, you will need to think about when and where to hand control back to the runtime. +By the same token, if you have long-running blocking operations, async can be a +useful tool for providing ways for different parts of the program to relate to +each other. + But *how* would you hand control back to the runtime in those cases? ### Yielding @@ -473,17 +477,21 @@ compared to the future using `trpl::yield_now`. The version with `yield_now` is *way* faster! -This means that async can be useful even for CPU-bound tasks, depending on what -else your program is doing, because it provides a useful tool for structuring -the relationships between different parts of the program. This is a form of -*cooperative multitasking*, where each future has both the power to determine -when it hands over control via await points. Each future therefore also has the -*responsibility* to avoid blocking for too long. In some Rust-based embedded -operating systems, this is the *only* kind of multitasking! +This means that async can be useful even for compute-bound tasks, depending on +what else your program is doing, because it provides a useful tool for +structuring the relationships between different parts of the program. This is a +form of *cooperative multitasking*, where each future has both the power to +determine when it hands over control via await points. Each future therefore +also has the responsibility to avoid blocking for too long. In some Rust-based +embedded operating systems, this is the *only* kind of multitasking! In real-world code, you will not usually be alternating function calls with -await points on every single line, of course. The underlying dynamic is an -important one to keep in mind, though! +await points on every single line, of course. While yielding control like this +is relatively inexpensive, it is not free! In many cases, trying to break up a +compute-bound task might make it significantly slower, so sometimes it is better +for *overall* performance to let an operation block briefly. You should always +measure to see what your code’s actual performance bottlenecks are. The +underlying dynamic is an important one to keep in mind if you *are* seeing a lot of work happening in serial that you expected to happen concurrently, though! ### Building Our Own Async Abstractions @@ -535,13 +543,12 @@ run that timer with the future the caller passes in. The `trpl::race` function returns a value to indicate which of the futures passed to it finishes first. (When we saw `race` earlier in Listing 17-20, we ignored its return value, because we were only interested in seeing the behavior -of `fast` and `slow` when we ran the program.) Because either future passed as -an argument to `race` can legitimately “win,” it does not make sense to use a -`Result` to represent the return type. Instead, `race` returns a type we have -not seen before, `Either`. The `Either` type is somewhat like a `Result`, in -that it has two cases. Unlike `Result`, though, there is no notion of success or -failure baked into `Either`. Instead, it uses `Left` and `Right` to indicate -“one or the other”. +of `fast` and `slow` when we ran the program.) Either future can legitimately +“win,” so it does not make sense to return a `Result`. Instead, `race` returns a +type we have not seen before, `trpl::Either`. The `Either` type is somewhat like +a `Result`, in that it has two cases. Unlike `Result`, though, there is no +notion of success or failure baked into `Either`. Instead, it uses `Left` and +`Right` to indicate “one or the other”. ```rust enum Either { @@ -552,19 +559,20 @@ enum Either { The `race` function returns `Left` if the first argument finishes first, with that future’s output, and `Right` with the second future argument’s output if -*that* one finishes first. +*that* one finishes first. This matches the order the arguments appear when +calling the function: the first argument is to the left of the second argument. We also know that `race` is not fair, and polls arguments in the order they are -passed. Thus, we pass the caller-supplied future to `race` first so it gets a -chance to complete even if `max_time` is a very short duration. If `future` +passed. Thus, we pass `future_to_try` to `race` first so it gets a chance to +complete even if `max_time` is a very short duration. If `future_to_try` finishes first, `race` will return `Left` with the output from `future`. If `timer` finishes first, `race` will return `Right` with the timer’s output of `()`. In Listing 17-28, we match on the result of awaiting `trpl::race`. If the -future succeeded and we get a `Left(output)`, we return `Ok(output)`. If the -sleep timer elapsed instead and we get a `Right(())`, we ignore the `()` with -`_` and return `Err(max_time)` instead. +`future_to_try` succeeded and we get a `Left(output)`, we return `Ok(output)`. +If the sleep timer elapsed instead and we get a `Right(())`, we ignore the `()` +with `_` and return `Err(max_time)` instead. diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index e4ae1ed7e1..3510aa4164 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -123,7 +123,7 @@ a queue, or working with more data than can fit in a computer’s memory by only pulling chunks of it from the file system at a time, or data arriving over the network over time. Because streams are futures, we can use them with any other kind of future, too, and we can combine them in interesting ways. For example, -we can debounce events to avoid triggering too many network calls, set timeouts +we can batch up events to avoid triggering too many network calls, set timeouts on sequences of long-running operations, or throttle user interface events to avoid doing needless work. From 453247c7904db6d6661dd80dbaa80717773b2ffd Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 13 Sep 2024 14:15:44 -0600 Subject: [PATCH 20/25] Ch. 17: address Tim and Carol's outstanding comments Co-authored-by: Tim McNamara Co-authored-by: Carol (Nichols || Goulding) --- src/ch17-01-futures-and-syntax.md | 41 ++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 5ce095f31b..687ce8870b 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -1,10 +1,30 @@ ## Futures and the Async Syntax -Like other languages with async, Rust uses the `async` and `await` keywords for -async programming. (If you are familiar with other languages’ approach to async, -you may notice some significant differences, though.) In Rust, blocks and -functions can be marked `async`, and you can wait on the result of an `async` -function or block to resolve using the `await` keyword. +They key elements of asynchronous programming in Rust are *futures* and Rust’s +`async` and `await` keywords. + +A future is a value that may not ready yet. Every future holds its own +information about the progress that has been made and what "ready" means. In +Rust, we say that types which implement the `Future` trait are futures. The +`async` keyword can be applied to blocks and functions to specify that they can +be interrupted and resumed. Within an async block or async function, you can use +the `await` keyword to wait for a future to become ready, called *awaiting a +future*. Each place you await a future within an async block or function is a +place that async block or function may get paused and resumed. + +> Note: Many other languages use the `async` and `await` keywords for async +> programming. If you are familiar with other languages’ approach to async, you +> may notice some significant differences in how Rust does things, including how +> it handles the syntax. That is for good reason, as we will see! + +That may all feel a bit abstract. Let’s write our first async program: a little +web scraper. This will have a fair bit of new syntax, but don’t worry. We will +explain it all as we go. + + Let’s write our first async function, and call it: @@ -37,8 +57,8 @@ learning what the syntax means, so let’s start there. In Rust, writing `async fn` is equivalent to writing a function which returns a *future* of the return type. That is, when the compiler sees a function like -`async fn hello` in Listing 17-1, it is basically equivalent to a function -defined like this instead: +`async fn hello` in Listing 17-1, it is equivalent to a function defined like +this instead: ```rust use std::future::Future; @@ -131,8 +151,11 @@ However, we get another compiler error here: {{#include ../listings/ch17-async-await/listing-17-03/output.txt}} ``` -The problem is that async code needs a *runtime*: a Rust crate which manages the -details of executing asynchronous code. +Rust won't allow us too mark `main` as `async`. The underlying problem is that +async code needs a *runtime*: a Rust crate which manages the details of +executing asynchronous code. A program's `main` function can initialize a +runtime, but it is not a runtime itself. (We will see more about why this is a +bit later.) Most languages which support async bundle a runtime with the language. Rust does not. Instead, there are many different async runtimes available, each of which From ccafd066cb6ccb1a99b4409f0dd35f744ff8694a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 13 Sep 2024 17:02:11 -0600 Subject: [PATCH 21/25] Ch. 17: Fix some typos! --- src/ch17-00-async-await.md | 4 ++-- src/ch17-03-more-futures.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 2e20b366cd..1749cc17a7 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -11,8 +11,8 @@ The video export will use as much CPU and GPU power as it can. If you only had one CPU core, and your operating system never paused that export until it completed, you could not do anything else on your computer while it was running. That would be a pretty frustrating experience, though. Instead, your computer’s -operating sysem can—and does!—invisibly interrupt the export often enough to let -you get other work done along the way. +operating system can—and does!—invisibly interrupt the export often enough to +let you get other work done along the way. The file download is different. It does not take up very much CPU time. Instead, the CPU needs to wait on data to arrive from the network. While you can start diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 7a57548d63..1ed95f14cc 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -462,7 +462,7 @@ lot in one millisecond! You can see this for yourself by setting up a little benchmark, like the one in Listing 17-25. (This is not an especially rigorous way to do performance testing, but it suffices to show the difference here.) Here, we skip all the -status printing, pass a one-nanosecond `Duration` to `trple::sleep`, and let +status printing, pass a one-nanosecond `Duration` to `trpl::sleep`, and let each future run by itself, with no switching between the futures. Then we run for 1,000 iterations and see how long the future using `trpl::sleep` takes compared to the future using `trpl::yield_now`. From 6f5773e64dc469b2794a121b70d4be971ac1d2d4 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 16 Sep 2024 15:57:18 -0600 Subject: [PATCH 22/25] Remove duplicate integration test from root I accidentally copied these in when pulling in the `trpl-note` mdbook preprocessor many months ago, and we did not notice amidst the many other changes in that PR! --- tests/integration/main.rs | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 tests/integration/main.rs diff --git a/tests/integration/main.rs b/tests/integration/main.rs deleted file mode 100644 index 6944fae693..0000000000 --- a/tests/integration/main.rs +++ /dev/null @@ -1,22 +0,0 @@ -use assert_cmd::Command; - -#[test] -fn supports_html_renderer() { - let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) - .unwrap() - .args(["supports", "html"]) - .ok(); - assert!(cmd.is_ok()); -} - -#[test] -fn errors_for_other_renderers() { - let cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")) - .unwrap() - .args(["supports", "total-nonsense"]) - .ok(); - assert!(cmd.is_err()); -} - -// It would be nice to add an actual fixture for an mdbook, but doing *that* is -// going to be a bit of a pain, and what I have should cover it for now. From cc5db976931262d046bbba8cc25fc80e477f8c1b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 13 Sep 2024 16:21:10 -0600 Subject: [PATCH 23/25] Ch. 17: rewrite 17.01 with a better example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `reqwest` and `scraper` dependencies to the `trpl` crate. Wrap them in `trpl` re-exports which keep the API surface low. Rewrite the whole first section to use `race` along with those `trpl` re-exports to show a more “real” example of async code right form the start, including actual concurrency, unlike the previous introduction. Update 17.03 to account for having introduced `race` already, and update listing numbers for rewritten 17.01. The *inclues* for them were fixed already, but not these! --- Cargo.lock | 1890 +++++++++++++++-- Cargo.toml | 2 +- .../ch17-async-await/listing-17-01/Cargo.lock | 1788 +++++++++++++++- .../ch17-async-await/listing-17-01/Cargo.toml | 5 +- .../ch17-async-await/listing-17-01/output.txt | 14 - .../listing-17-01/src/main.rs | 17 +- .../ch17-async-await/listing-17-02/Cargo.lock | 1788 +++++++++++++++- .../ch17-async-await/listing-17-02/Cargo.toml | 5 +- .../ch17-async-await/listing-17-02/output.txt | 12 - .../listing-17-02/src/main.rs | 18 +- .../ch17-async-await/listing-17-03/Cargo.lock | 1788 +++++++++++++++- .../ch17-async-await/listing-17-03/Cargo.toml | 5 +- .../ch17-async-await/listing-17-03/output.txt | 10 - .../listing-17-03/src/main.rs | 19 +- .../ch17-async-await/listing-17-04/Cargo.lock | 1661 ++++++++++++++- .../ch17-async-await/listing-17-04/Cargo.toml | 6 +- .../ch17-async-await/listing-17-04/output.txt | 4 +- .../listing-17-04/src/main.rs | 24 +- .../ch17-async-await/listing-17-05/Cargo.lock | 1661 ++++++++++++++- .../ch17-async-await/listing-17-05/Cargo.toml | 4 +- .../listing-17-05/src/main.rs | 35 +- .../ch17-async-await/listing-17-06/Cargo.lock | 1706 ++++++++++++++- .../listing-17-06/src/main.rs | 8 +- .../listing-17-07/src/main.rs | 20 +- .../listing-17-08/src/main.rs | 24 +- .../listing-17-09/src/main.rs | 24 +- .../listing-17-10/src/main.rs | 38 +- .../listing-17-11/src/main.rs | 9 +- .../listing-17-12/src/main.rs | 27 +- .../listing-17-13/src/main.rs | 8 +- .../listing-17-14/src/main.rs | 4 +- .../listing-17-15/src/main.rs | 3 +- .../ch17-async-await/listing-17-16/Cargo.lock | 12 + .../listing-17-16/src/main.rs | 6 +- .../ch17-async-await/listing-17-17/Cargo.lock | 12 - .../output.txt | 0 .../listing-17-17/src/main.rs | 22 +- .../listing-17-18/src/main.rs | 17 +- .../output.txt | 0 .../listing-17-19/src/main.rs | 62 +- .../ch17-async-await/listing-17-20/Cargo.lock | 262 +-- .../listing-17-20/src/main.rs | 19 +- .../ch17-async-await/listing-17-21/Cargo.lock | 262 ++- .../listing-17-21/src/main.rs | 25 +- .../listing-17-22/src/main.rs | 25 +- .../listing-17-23/src/main.rs | 17 +- .../listing-17-24/src/main.rs | 20 +- .../ch17-async-await/listing-17-25/Cargo.lock | 262 +-- .../listing-17-25/src/main.rs | 60 +- .../ch17-async-await/listing-17-26/Cargo.lock | 262 ++- .../listing-17-26/src/main.rs | 33 +- .../listing-17-27/src/main.rs | 17 +- .../listing-17-28/src/main.rs | 17 +- .../ch17-async-await/listing-17-29/Cargo.lock | 1714 ++++++++++++++- .../ch17-async-await/listing-17-29/Cargo.toml | 1 + .../listing-17-29/src/main.rs | 36 +- .../listing-17-30/src/main.rs | 4 +- .../listing-17-31/src/main.rs | 11 +- .../listing-17-32/src/main.rs | 26 +- .../listing-17-33/src/main.rs | 17 +- .../listing-17-34/src/main.rs | 18 +- .../listing-17-35/src/main.rs | 19 +- .../listing-17-36/src/main.rs | 11 +- .../listing-17-37/src/main.rs | 7 +- .../listing-17-38/src/main.rs | 9 +- .../listing-17-39/src/main.rs | 22 +- .../listing-17-40/src/main.rs | 12 +- .../ch17-async-await/listing-17-41/Cargo.lock | 292 +++ .../ch17-async-await/listing-17-41/Cargo.toml | 8 + .../listing-17-41/src/main.rs | 67 + packages/trpl/Cargo.lock | 1706 ++++++++++++++- packages/trpl/Cargo.toml | 2 + packages/trpl/src/lib.rs | 51 + packages/trpl/tests/integration/main.rs | 11 + src/ch17-01-futures-and-syntax.md | 450 ++-- src/ch17-02-concurrency-with-async.md | 50 +- src/ch17-03-more-futures.md | 134 +- src/ch17-04-streams.md | 72 +- src/ch17-05-traits-for-async.md | 4 +- src/ch17-06-futures-tasks-threads.md | 8 +- 80 files changed, 16954 insertions(+), 1847 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-01/output.txt delete mode 100644 listings/ch17-async-await/listing-17-02/output.txt delete mode 100644 listings/ch17-async-await/listing-17-03/output.txt rename listings/ch17-async-await/{listing-17-16 => listing-17-17}/output.txt (100%) rename listings/ch17-async-await/{listing-17-18 => listing-17-19}/output.txt (100%) create mode 100644 listings/ch17-async-await/listing-17-41/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-41/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-41/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index d54e8284e1..21c0d5e8a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,278 +2,1806 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cc" +version = "1.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "docopt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" +dependencies = [ + "lazy_static", + "regex", + "serde", + "strsim", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "listing-scraper-01" +version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.4", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rust-book-tools" +version = "0.0.1" +dependencies = [ + "docopt", + "flate2", + "lazy_static", + "regex", + "serde", + "tar", + "walkdir", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags 2.5.0", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "memchr", + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", ] [[package]] -name = "bitflags" -version = "1.3.2" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "bitflags" -version = "2.5.0" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "syn" +version = "2.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] -name = "crc32fast" -version = "1.4.0" +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" dependencies = [ - "cfg-if", + "futures-core", ] [[package]] -name = "docopt" -version = "1.1.1" +name = "system-configuration" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "lazy_static", - "regex", - "serde", - "strsim", + "bitflags 2.5.0", + "core-foundation", + "system-configuration-sys", ] [[package]] -name = "errno" -version = "0.3.8" +name = "system-configuration-sys" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ + "core-foundation-sys", "libc", - "windows-sys", ] [[package]] -name = "filetime" -version = "0.2.23" +name = "tar" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ - "cfg-if", + "filetime", "libc", - "redox_syscall", - "windows-sys", + "xattr", ] [[package]] -name = "flate2" -version = "1.0.30" +name = "tempfile" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ - "crc32fast", - "miniz_oxide", + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "tendril" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] [[package]] -name = "libc" -version = "0.2.153" +name = "tinyvec" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] [[package]] -name = "linux-raw-sys" -version = "0.4.13" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "memchr" -version = "2.7.2" +name = "tokio" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] [[package]] -name = "miniz_oxide" -version = "0.7.2" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "adler", + "native-tls", + "tokio", ] [[package]] -name = "proc-macro2" -version = "1.0.80" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "unicode-ident", + "rustls", + "rustls-pki-types", + "tokio", ] [[package]] -name = "quote" -version = "1.0.36" +name = "tokio-stream" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ - "proc-macro2", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] -name = "redox_syscall" -version = "0.4.1" +name = "tokio-util" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ - "bitflags 1.3.2", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] -name = "regex" -version = "1.10.4" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", ] [[package]] -name = "regex-automata" -version = "0.4.6" +name = "tower-layer" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "pin-project-lite", + "tracing-core", ] [[package]] -name = "regex-syntax" -version = "0.8.3" +name = "tracing-core" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] [[package]] -name = "rust-book-tools" -version = "0.0.1" +name = "trpl" +version = "0.1.0" dependencies = [ - "docopt", - "flate2", - "lazy_static", - "regex", - "serde", - "tar", - "walkdir", + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", ] [[package]] -name = "rustix" -version = "0.38.34" +name = "try-lock" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", + "tinyvec", ] [[package]] -name = "same-file" -version = "1.0.6" +name = "unicode-width" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ + "same-file", "winapi-util", ] [[package]] -name = "serde" -version = "1.0.197" +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "serde_derive", + "try-lock", ] [[package]] -name = "serde_derive" -version = "1.0.197" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ + "bumpalo", + "log", + "once_cell", "proc-macro2", "quote", "syn", + "wasm-bindgen-shared", ] [[package]] -name = "strsim" -version = "0.10.0" +name = "wasm-bindgen-futures" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] [[package]] -name = "syn" -version = "2.0.59" +name = "wasm-bindgen-macro" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ - "proc-macro2", "quote", - "unicode-ident", + "wasm-bindgen-macro-support", ] [[package]] -name = "tar" -version = "0.4.40" +name = "wasm-bindgen-macro-support" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ - "filetime", - "libc", - "xattr", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] -name = "unicode-ident" -version = "1.0.0" +name = "wasm-bindgen-shared" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] -name = "walkdir" -version = "2.5.0" +name = "web-sys" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ - "same-file", - "winapi-util", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -307,6 +1835,36 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -316,11 +1874,20 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -334,51 +1901,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xattr" @@ -390,3 +1957,30 @@ dependencies = [ "linux-raw-sys", "rustix", ] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 20fc14643d..5b7ef40548 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["packages/tools"] +members = [ "listings/ch17-async-await/listing-scraper-01","packages/tools"] default-members = ["packages/tools"] resolver = "2" exclude = [ diff --git a/listings/ch17-async-await/listing-17-01/Cargo.lock b/listings/ch17-async-await/listing-17-01/Cargo.lock index d30b928a6c..207879da8f 100644 --- a/listings/ch17-async-await/listing-17-01/Cargo.lock +++ b/listings/ch17-async-await/listing-17-01/Cargo.lock @@ -3,5 +3,1791 @@ version = 3 [[package]] -name = "async_await" +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cc" +version = "1.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "listing-scraper-01" version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-01/Cargo.toml b/listings/ch17-async-await/listing-17-01/Cargo.toml index 67729afc80..9fad6d6a96 100644 --- a/listings/ch17-async-await/listing-17-01/Cargo.toml +++ b/listings/ch17-async-await/listing-17-01/Cargo.toml @@ -1,6 +1,7 @@ [package] -name = "async_await" +name = "listing-scraper-01" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-01/output.txt b/listings/ch17-async-await/listing-17-01/output.txt deleted file mode 100644 index 92b5d5e4d5..0000000000 --- a/listings/ch17-async-await/listing-17-01/output.txt +++ /dev/null @@ -1,14 +0,0 @@ -$ cargo run - Compiling async_await v0.1.0 (file:///projects/async_await) -warning: unused implementer of `Future` that must be used - --> src/main.rs:2:5 - | -2 | hello("async"); - | ^^^^^^^^^^^^^^ - | - = note: futures do nothing unless you `.await` or poll them - = note: `#[warn(unused_must_use)]` on by default - -warning: `async_await` (bin "async_await") generated 1 warning - Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.21s - Running `target/debug/async_await` diff --git a/listings/ch17-async-await/listing-17-01/src/main.rs b/listings/ch17-async-await/listing-17-01/src/main.rs index 68c82536aa..b4d9323f5f 100644 --- a/listings/ch17-async-await/listing-17-01/src/main.rs +++ b/listings/ch17-async-await/listing-17-01/src/main.rs @@ -1,10 +1,17 @@ -// ANCHOR: all +extern crate trpl; // required for mdbook test + fn main() { - hello("async"); + // TODO: we'll add this next! } -async fn hello(name: &str) { - let greeting = format!("Hello, {name}!"); - println!("{greeting}"); +// ANCHOR: all +use trpl::Html; + +async fn page_title(url: &str) -> Option { + let response = trpl::get(url).await; + let response_text = response.text().await; + Html::parse(&response_text) + .select_first("title") + .map(|title_element| title_element.inner_html()) } // ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-02/Cargo.lock b/listings/ch17-async-await/listing-17-02/Cargo.lock index d30b928a6c..cb7d407618 100644 --- a/listings/ch17-async-await/listing-17-02/Cargo.lock +++ b/listings/ch17-async-await/listing-17-02/Cargo.lock @@ -3,5 +3,1791 @@ version = 3 [[package]] -name = "async_await" +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cc" +version = "1.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "listing-scraper-01" version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-02/Cargo.toml b/listings/ch17-async-await/listing-17-02/Cargo.toml index 67729afc80..9fad6d6a96 100644 --- a/listings/ch17-async-await/listing-17-02/Cargo.toml +++ b/listings/ch17-async-await/listing-17-02/Cargo.toml @@ -1,6 +1,7 @@ [package] -name = "async_await" +name = "listing-scraper-01" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-02/output.txt b/listings/ch17-async-await/listing-17-02/output.txt deleted file mode 100644 index d2809af719..0000000000 --- a/listings/ch17-async-await/listing-17-02/output.txt +++ /dev/null @@ -1,12 +0,0 @@ -$ cargo run - Compiling async_await v0.1.0 (file:///projects/async_await) -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> src/main.rs:2:20 - | -1 | fn main() { - | --------- this is not `async` -2 | hello("async").await; - | ^^^^^ only allowed inside `async` functions and blocks - -For more information about this error, try `rustc --explain E0728`. -error: could not compile `async_await` (bin "async_await") due to 1 previous error diff --git a/listings/ch17-async-await/listing-17-02/src/main.rs b/listings/ch17-async-await/listing-17-02/src/main.rs index 153458bc0a..e9c43b34d7 100644 --- a/listings/ch17-async-await/listing-17-02/src/main.rs +++ b/listings/ch17-async-await/listing-17-02/src/main.rs @@ -1,10 +1,16 @@ -// ANCHOR: main +extern crate trpl; // required for mdbook test + +use trpl::Html; + fn main() { - hello("async").await; + // TODO: we'll add this next! } -// ANCHOR_END: main -async fn hello(name: &str) { - let greeting = format!("Hello, {name}!"); - println!("{greeting}"); +async fn page_title(url: &str) -> Option { + // ANCHOR: chaining + let response_text = trpl::get(url).await.text().await; + // ANCHOR_END: chaining + Html::parse(&response_text) + .select_first("title") + .map(|title_element| title_element.inner_html()) } diff --git a/listings/ch17-async-await/listing-17-03/Cargo.lock b/listings/ch17-async-await/listing-17-03/Cargo.lock index d30b928a6c..cb7d407618 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.lock +++ b/listings/ch17-async-await/listing-17-03/Cargo.lock @@ -3,5 +3,1791 @@ version = 3 [[package]] -name = "async_await" +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cc" +version = "1.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "listing-scraper-01" version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-03/Cargo.toml b/listings/ch17-async-await/listing-17-03/Cargo.toml index 67729afc80..9fad6d6a96 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.toml +++ b/listings/ch17-async-await/listing-17-03/Cargo.toml @@ -1,6 +1,7 @@ [package] -name = "async_await" +name = "listing-scraper-01" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-03/output.txt b/listings/ch17-async-await/listing-17-03/output.txt deleted file mode 100644 index e61d87f805..0000000000 --- a/listings/ch17-async-await/listing-17-03/output.txt +++ /dev/null @@ -1,10 +0,0 @@ -$ cargo run - Compiling async_await v0.1.0 (file:///projects/async_await) -error[E0752]: `main` function is not allowed to be `async` - --> src/main.rs:1:1 - | -1 | async fn main() { - | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` - -For more information about this error, try `rustc --explain E0752`. -error: could not compile `async_await` (bin "async_await") due to 1 previous error diff --git a/listings/ch17-async-await/listing-17-03/src/main.rs b/listings/ch17-async-await/listing-17-03/src/main.rs index 443cadcc0e..23290fff4a 100644 --- a/listings/ch17-async-await/listing-17-03/src/main.rs +++ b/listings/ch17-async-await/listing-17-03/src/main.rs @@ -1,10 +1,21 @@ +extern crate trpl; // required for mdbook test + +use trpl::Html; + // ANCHOR: main async fn main() { - hello("async").await; + let args: Vec = std::env::args().collect(); + let url = &args[1]; + match page_title(url).await { + Some(title) => println!("The title for {url} was {title}"), + None => println!("{url} had no title"), + } } // ANCHOR_END: main -async fn hello(name: &str) { - let greeting = format!("Hello, {name}!"); - println!("{greeting}"); +async fn page_title(url: &str) -> Option { + let response_text = trpl::get(url).await.text().await; + Html::parse(&response_text) + .select_first("title") + .map(|title_element| title_element.inner_html()) } diff --git a/listings/ch17-async-await/listing-17-04/Cargo.lock b/listings/ch17-async-await/listing-17-04/Cargo.lock index b6971aa2e9..cb7d407618 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.lock +++ b/listings/ch17-async-await/listing-17-04/Cargo.lock @@ -4,26 +4,38 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] -name = "async_await" -version = "0.1.0" +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "trpl", + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -32,24 +44,57 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + [[package]] name = "cc" -version = "1.0.99" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -57,6 +102,148 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -146,11 +333,65 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -159,134 +400,1394 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "libc" -version = "0.2.155" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "memchr" -version = "2.7.2" +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] [[package]] -name = "miniz_oxide" -version = "0.7.3" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "adler", + "bytes", + "http", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ - "hermit-abi", - "libc", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", ] [[package]] -name = "object" -version = "0.36.0" +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ - "memchr", + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "hyper-rustls" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "hyper-tls" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper-util" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ - "unicode-ident", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] -name = "quote" -version = "1.0.36" +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "proc-macro2", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "indexmap" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] [[package]] -name = "slab" -version = "0.4.9" +name = "ipnet" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "listing-scraper-01" +version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", + "scopeguard", ] [[package]] -name = "syn" -version = "2.0.66" +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", ] [[package]] -name = "tokio" -version = "1.38.0" +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "adler2", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "mio" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", ] [[package]] -name = "trpl" -version = "0.1.0" +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "futures", - "tokio", - "tokio-stream", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-04/Cargo.toml b/listings/ch17-async-await/listing-17-04/Cargo.toml index 5f2e9ac2d0..9fad6d6a96 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.toml +++ b/listings/ch17-async-await/listing-17-04/Cargo.toml @@ -1,9 +1,7 @@ [package] -name = "async_await" +name = "listing-scraper-01" version = "0.1.0" edition = "2021" [dependencies] -trpl = { version = "0.1.0", path = "../../../packages/trpl" } - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-04/output.txt b/listings/ch17-async-await/listing-17-04/output.txt index b928fb6020..a9b7a86ff3 100644 --- a/listings/ch17-async-await/listing-17-04/output.txt +++ b/listings/ch17-async-await/listing-17-04/output.txt @@ -1 +1,3 @@ -$ +$ cargo run "http://www.rust-lang.org" +The title for http://www.rust-lang.org was + Rust Programming Language diff --git a/listings/ch17-async-await/listing-17-04/src/main.rs b/listings/ch17-async-await/listing-17-04/src/main.rs index f3e685ac67..dbc0d4c6e1 100644 --- a/listings/ch17-async-await/listing-17-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -1,14 +1,24 @@ extern crate trpl; // required for mdbook test -// ANCHOR: main +use trpl::Html; + fn main() { + let args: Vec = std::env::args().collect(); + + // ANCHOR: run trpl::run(async { - hello("async").await; - }); + let url = &args[1]; + match page_title(url).await { + Some(title) => println!("The title for {url} was {title}"), + None => println!("{url} had no title"), + } + }) + // ANCHOR_END: run } -// ANCHOR_END: main -async fn hello(name: &str) { - let greeting = format!("Hello, {name}!"); - println!("{greeting}"); +async fn page_title(url: &str) -> Option { + let response_text = trpl::get(url).await.text().await; + Html::parse(&response_text) + .select_first("title") + .map(|title_element| title_element.inner_html()) } diff --git a/listings/ch17-async-await/listing-17-05/Cargo.lock b/listings/ch17-async-await/listing-17-05/Cargo.lock index 2e0f3ebedb..cb7d407618 100644 --- a/listings/ch17-async-await/listing-17-05/Cargo.lock +++ b/listings/ch17-async-await/listing-17-05/Cargo.lock @@ -4,26 +4,38 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] -name = "async_await" -version = "0.1.0" +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "trpl", + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -32,24 +44,57 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + [[package]] name = "cc" -version = "1.0.97" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -57,6 +102,148 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -146,11 +333,65 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -159,134 +400,1394 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "libc" -version = "0.2.154" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "memchr" -version = "2.7.2" +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] [[package]] -name = "miniz_oxide" -version = "0.7.2" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "adler", + "bytes", + "http", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ - "hermit-abi", - "libc", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", ] [[package]] -name = "object" -version = "0.32.2" +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ - "memchr", + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "hyper-rustls" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "hyper-tls" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] [[package]] -name = "proc-macro2" -version = "1.0.82" +name = "hyper-util" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ - "unicode-ident", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] -name = "quote" -version = "1.0.36" +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "proc-macro2", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "indexmap" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] [[package]] -name = "slab" -version = "0.4.9" +name = "ipnet" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "listing-scraper-01" +version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", + "scopeguard", ] [[package]] -name = "syn" -version = "2.0.63" +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", ] [[package]] -name = "tokio" -version = "1.37.0" +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "adler2", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "mio" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", ] [[package]] -name = "trpl" -version = "0.1.0" +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "futures", - "tokio", - "tokio-stream", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-05/Cargo.toml b/listings/ch17-async-await/listing-17-05/Cargo.toml index 349041d3eb..9fad6d6a96 100644 --- a/listings/ch17-async-await/listing-17-05/Cargo.toml +++ b/listings/ch17-async-await/listing-17-05/Cargo.toml @@ -1,9 +1,7 @@ [package] -name = "async_await" +name = "listing-scraper-01" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-05/src/main.rs b/listings/ch17-async-await/listing-17-05/src/main.rs index 8eb415ee73..8a5546afd5 100644 --- a/listings/ch17-async-await/listing-17-05/src/main.rs +++ b/listings/ch17-async-await/listing-17-05/src/main.rs @@ -1,21 +1,34 @@ extern crate trpl; // required for mdbook test // ANCHOR: all -use std::time::Duration; +use trpl::{Either, Html}; fn main() { + let args: Vec = std::env::args().collect(); + trpl::run(async { - trpl::spawn_task(async { - for i in 1..10 { - println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(500)).await; - } - }); + let title_fut_1 = page_title(&args[1]); + let title_fut_2 = page_title(&args[2]); + + let (url, maybe_title) = + match trpl::race(title_fut_1, title_fut_2).await { + Either::Left(left) => left, + Either::Right(right) => right, + }; - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(500)).await; + println!("{url} returned first"); + match maybe_title { + Some(title) => println!("Its page title is: '{title}'"), + None => println!("Its title could not be parsed."), } - }); + }) +} + +async fn page_title(url: &str) -> (&str, Option) { + let text = trpl::get(url).await.text().await; + let title = Html::parse(&text) + .select_first("title") + .map(|title| title.inner_html()); + (url, title) } // ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-06/Cargo.lock b/listings/ch17-async-await/listing-17-06/Cargo.lock index 2e0f3ebedb..a55aeb1e1c 100644 --- a/listings/ch17-async-await/listing-17-06/Cargo.lock +++ b/listings/ch17-async-await/listing-17-06/Cargo.lock @@ -17,6 +17,19 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "async_await" version = "0.1.0" @@ -24,6 +37,12 @@ dependencies = [ "trpl", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -45,6 +64,36 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + [[package]] name = "cc" version = "1.0.97" @@ -57,6 +106,148 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -146,6 +337,35 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.28.1" @@ -153,140 +373,1488 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "h2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] [[package]] -name = "libc" -version = "0.2.154" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] -name = "memchr" -version = "2.7.2" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.2" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" dependencies = [ - "adler", + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "hermit-abi", - "libc", + "bytes", + "fnv", + "itoa", ] [[package]] -name = "object" -version = "0.32.2" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "memchr", + "bytes", + "http", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "httparse" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] -name = "proc-macro2" -version = "1.0.82" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ - "unicode-ident", + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", ] [[package]] -name = "quote" -version = "1.0.36" +name = "hyper-rustls" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ - "proc-macro2", + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "hyper-tls" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] [[package]] -name = "slab" -version = "0.4.9" +name = "hyper-util" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] -name = "syn" -version = "2.0.63" +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "tokio" -version = "1.37.0" +name = "indexmap" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "wasm-bindgen", ] [[package]] -name = "trpl" -version = "0.1.0" +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "futures", - "tokio", - "tokio-stream", + "autocfg", + "scopeguard", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "log" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-06/src/main.rs b/listings/ch17-async-await/listing-17-06/src/main.rs index 5415e1fcee..8eb415ee73 100644 --- a/listings/ch17-async-await/listing-17-06/src/main.rs +++ b/listings/ch17-async-await/listing-17-06/src/main.rs @@ -1,11 +1,11 @@ extern crate trpl; // required for mdbook test +// ANCHOR: all use std::time::Duration; fn main() { trpl::run(async { - // ANCHOR: handle - let handle = trpl::spawn_task(async { + trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); trpl::sleep(Duration::from_millis(500)).await; @@ -16,8 +16,6 @@ fn main() { println!("hi number {i} from the second task!"); trpl::sleep(Duration::from_millis(500)).await; } - - handle.await.unwrap(); - // ANCHOR_END: handle }); } +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-07/src/main.rs b/listings/ch17-async-await/listing-17-07/src/main.rs index 2cd5de9bae..5415e1fcee 100644 --- a/listings/ch17-async-await/listing-17-07/src/main.rs +++ b/listings/ch17-async-await/listing-17-07/src/main.rs @@ -4,22 +4,20 @@ use std::time::Duration; fn main() { trpl::run(async { - // ANCHOR: join - let fut1 = async { + // ANCHOR: handle + let handle = trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); trpl::sleep(Duration::from_millis(500)).await; } - }; + }); - let fut2 = async { - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(500)).await; - } - }; + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(500)).await; + } - trpl::join(fut1, fut2).await; - // ANCHOR_END: join + handle.await.unwrap(); + // ANCHOR_END: handle }); } diff --git a/listings/ch17-async-await/listing-17-08/src/main.rs b/listings/ch17-async-await/listing-17-08/src/main.rs index 56daddc10f..2cd5de9bae 100644 --- a/listings/ch17-async-await/listing-17-08/src/main.rs +++ b/listings/ch17-async-await/listing-17-08/src/main.rs @@ -1,15 +1,25 @@ extern crate trpl; // required for mdbook test +use std::time::Duration; + fn main() { trpl::run(async { - // ANCHOR: channel - let (tx, mut rx) = trpl::channel(); + // ANCHOR: join + let fut1 = async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(500)).await; + } + }; - let val = String::from("hi"); - tx.send(val).unwrap(); + let fut2 = async { + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(500)).await; + } + }; - let received = rx.recv().await.unwrap(); - println!("Got: {received}"); - // ANCHOR_END: channel + trpl::join(fut1, fut2).await; + // ANCHOR_END: join }); } diff --git a/listings/ch17-async-await/listing-17-09/src/main.rs b/listings/ch17-async-await/listing-17-09/src/main.rs index e11ae51787..56daddc10f 100644 --- a/listings/ch17-async-await/listing-17-09/src/main.rs +++ b/listings/ch17-async-await/listing-17-09/src/main.rs @@ -1,27 +1,15 @@ extern crate trpl; // required for mdbook test -use std::time::Duration; - fn main() { trpl::run(async { - // ANCHOR: many-messages + // ANCHOR: channel let (tx, mut rx) = trpl::channel(); - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; - - for val in vals { - tx.send(val).unwrap(); - trpl::sleep(Duration::from_millis(500)).await; - } + let val = String::from("hi"); + tx.send(val).unwrap(); - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - // ANCHOR_END: many-messages + let received = rx.recv().await.unwrap(); + println!("Got: {received}"); + // ANCHOR_END: channel }); } diff --git a/listings/ch17-async-await/listing-17-10/src/main.rs b/listings/ch17-async-await/listing-17-10/src/main.rs index 5ada1d2f6d..e11ae51787 100644 --- a/listings/ch17-async-await/listing-17-10/src/main.rs +++ b/listings/ch17-async-await/listing-17-10/src/main.rs @@ -4,32 +4,24 @@ use std::time::Duration; fn main() { trpl::run(async { + // ANCHOR: many-messages let (tx, mut rx) = trpl::channel(); - // ANCHOR: futures - let tx_fut = async { - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("future"), + ]; - for val in vals { - tx.send(val).unwrap(); - trpl::sleep(Duration::from_millis(500)).await; - } - }; + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_millis(500)).await; + } - let rx_fut = async { - // ANCHOR: loop - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - // ANCHOR_END: loop - }; - - trpl::join(tx_fut, rx_fut).await; - // ANCHOR_END: futures + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + // ANCHOR_END: many-messages }); } diff --git a/listings/ch17-async-await/listing-17-11/src/main.rs b/listings/ch17-async-await/listing-17-11/src/main.rs index 95e6480677..f8e641d6d0 100644 --- a/listings/ch17-async-await/listing-17-11/src/main.rs +++ b/listings/ch17-async-await/listing-17-11/src/main.rs @@ -4,10 +4,10 @@ use std::time::Duration; fn main() { trpl::run(async { - // ANCHOR: with-move let (tx, mut rx) = trpl::channel(); - let tx_fut = async move { + // ANCHOR: futures + let tx_fut = async { let vals = vec![ String::from("hi"), String::from("from"), @@ -23,12 +23,11 @@ fn main() { let rx_fut = async { while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); + println!("received '{value}'"); } }; trpl::join(tx_fut, rx_fut).await; - // ANCHOR_END: with-move + // ANCHOR_END: futures }); } -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-12/src/main.rs b/listings/ch17-async-await/listing-17-12/src/main.rs index d5a2e56e34..c22b7d2d75 100644 --- a/listings/ch17-async-await/listing-17-12/src/main.rs +++ b/listings/ch17-async-await/listing-17-12/src/main.rs @@ -4,11 +4,10 @@ use std::time::Duration; fn main() { trpl::run(async { - // ANCHOR: here + // ANCHOR: with-move let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - let tx1_fut = async move { + let tx_fut = async move { let vals = vec![ String::from("hi"), String::from("from"), @@ -17,32 +16,18 @@ fn main() { ]; for val in vals { - tx1.send(val).unwrap(); + tx.send(val).unwrap(); trpl::sleep(Duration::from_millis(500)).await; } }; let rx_fut = async { while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - }; - - let tx_fut = async move { - let vals = vec![ - String::from("more"), - String::from("messages"), - String::from("for"), - String::from("you"), - ]; - - for val in vals { - tx.send(val).unwrap(); - trpl::sleep(Duration::from_millis(1500)).await; + eprintln!("received '{value}'"); } }; - trpl::join3(tx1_fut, tx_fut, rx_fut).await; - // ANCHOR_END: here + trpl::join(tx_fut, rx_fut).await; + // ANCHOR_END: with-move }); } diff --git a/listings/ch17-async-await/listing-17-13/src/main.rs b/listings/ch17-async-await/listing-17-13/src/main.rs index 0bb425d366..d5a2e56e34 100644 --- a/listings/ch17-async-await/listing-17-13/src/main.rs +++ b/listings/ch17-async-await/listing-17-13/src/main.rs @@ -4,6 +4,7 @@ use std::time::Duration; fn main() { trpl::run(async { + // ANCHOR: here let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); @@ -17,7 +18,7 @@ fn main() { for val in vals { tx1.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).await; + trpl::sleep(Duration::from_millis(500)).await; } }; @@ -37,12 +38,11 @@ fn main() { for val in vals { tx.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).await; + trpl::sleep(Duration::from_millis(1500)).await; } }; - // ANCHOR: here - trpl::join!(tx1_fut, tx_fut, rx_fut); + trpl::join3(tx1_fut, tx_fut, rx_fut).await; // ANCHOR_END: here }); } diff --git a/listings/ch17-async-await/listing-17-14/src/main.rs b/listings/ch17-async-await/listing-17-14/src/main.rs index 249ffd0f68..0bb425d366 100644 --- a/listings/ch17-async-await/listing-17-14/src/main.rs +++ b/listings/ch17-async-await/listing-17-14/src/main.rs @@ -42,9 +42,7 @@ fn main() { }; // ANCHOR: here - let futures = vec![tx1_fut, rx_fut, tx_fut]; - - trpl::join_all(futures).await; + trpl::join!(tx1_fut, tx_fut, rx_fut); // ANCHOR_END: here }); } diff --git a/listings/ch17-async-await/listing-17-15/src/main.rs b/listings/ch17-async-await/listing-17-15/src/main.rs index 9fefdcf463..249ffd0f68 100644 --- a/listings/ch17-async-await/listing-17-15/src/main.rs +++ b/listings/ch17-async-await/listing-17-15/src/main.rs @@ -42,8 +42,7 @@ fn main() { }; // ANCHOR: here - let futures = - vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; + let futures = vec![tx1_fut, rx_fut, tx_fut]; trpl::join_all(futures).await; // ANCHOR_END: here diff --git a/listings/ch17-async-await/listing-17-16/Cargo.lock b/listings/ch17-async-await/listing-17-16/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-16/Cargo.lock +++ b/listings/ch17-async-await/listing-17-16/Cargo.lock @@ -265,12 +265,24 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "trpl" version = "0.1.0" dependencies = [ "futures", "tokio", + "tokio-stream", ] [[package]] diff --git a/listings/ch17-async-await/listing-17-16/src/main.rs b/listings/ch17-async-await/listing-17-16/src/main.rs index 1888a53568..9fefdcf463 100644 --- a/listings/ch17-async-await/listing-17-16/src/main.rs +++ b/listings/ch17-async-await/listing-17-16/src/main.rs @@ -1,6 +1,6 @@ extern crate trpl; // required for mdbook test -use std::{future::Future, time::Duration}; +use std::time::Duration; fn main() { trpl::run(async { @@ -42,10 +42,10 @@ fn main() { }; // ANCHOR: here - let futures: Vec>> = + let futures = vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; - // ANCHOR_END: here trpl::join_all(futures).await; + // ANCHOR_END: here }); } diff --git a/listings/ch17-async-await/listing-17-17/Cargo.lock b/listings/ch17-async-await/listing-17-17/Cargo.lock index 2e0f3ebedb..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-17/Cargo.lock +++ b/listings/ch17-async-await/listing-17-17/Cargo.lock @@ -265,24 +265,12 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "tokio-stream" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - [[package]] name = "trpl" version = "0.1.0" dependencies = [ "futures", "tokio", - "tokio-stream", ] [[package]] diff --git a/listings/ch17-async-await/listing-17-16/output.txt b/listings/ch17-async-await/listing-17-17/output.txt similarity index 100% rename from listings/ch17-async-await/listing-17-16/output.txt rename to listings/ch17-async-await/listing-17-17/output.txt diff --git a/listings/ch17-async-await/listing-17-17/src/main.rs b/listings/ch17-async-await/listing-17-17/src/main.rs index 7773660519..1888a53568 100644 --- a/listings/ch17-async-await/listing-17-17/src/main.rs +++ b/listings/ch17-async-await/listing-17-17/src/main.rs @@ -1,17 +1,13 @@ extern crate trpl; // required for mdbook test -use std::{ - future::Future, - pin::{pin, Pin}, - time::Duration, -}; +use std::{future::Future, time::Duration}; fn main() { trpl::run(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); - let tx1_fut = pin!(async move { + let tx1_fut = async move { let vals = vec![ String::from("hi"), String::from("from"), @@ -23,15 +19,15 @@ fn main() { tx1.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - }); + }; - let rx_fut = pin!(async { + let rx_fut = async { while let Some(value) = rx.recv().await { println!("received '{value}'"); } - }); + }; - let tx_fut = pin!(async move { + let tx_fut = async move { let vals = vec![ String::from("more"), String::from("messages"), @@ -43,11 +39,11 @@ fn main() { tx.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - }); + }; // ANCHOR: here - let futures: Vec>>> = - vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; + let futures: Vec>> = + vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; // ANCHOR_END: here trpl::join_all(futures).await; diff --git a/listings/ch17-async-await/listing-17-18/src/main.rs b/listings/ch17-async-await/listing-17-18/src/main.rs index 41820fc8a5..7773660519 100644 --- a/listings/ch17-async-await/listing-17-18/src/main.rs +++ b/listings/ch17-async-await/listing-17-18/src/main.rs @@ -11,10 +11,7 @@ fn main() { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); - // ANCHOR: here let tx1_fut = pin!(async move { - // --snip-- - // ANCHOR_END: here let vals = vec![ String::from("hi"), String::from("from"), @@ -26,23 +23,15 @@ fn main() { tx1.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - // ANCHOR: here }); - // ANCHOR_END: here - // ANCHOR: here let rx_fut = pin!(async { - // --snip-- - // ANCHOR_END: here while let Some(value) = rx.recv().await { println!("received '{value}'"); } - // ANCHOR: here }); let tx_fut = pin!(async move { - // --snip-- - // ANCHOR_END: here let vals = vec![ String::from("more"), String::from("messages"), @@ -54,11 +43,11 @@ fn main() { tx.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - // ANCHOR: here }); - let futures: Vec>> = - vec![tx1_fut, rx_fut, tx_fut]; + // ANCHOR: here + let futures: Vec>>> = + vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; // ANCHOR_END: here trpl::join_all(futures).await; diff --git a/listings/ch17-async-await/listing-17-18/output.txt b/listings/ch17-async-await/listing-17-19/output.txt similarity index 100% rename from listings/ch17-async-await/listing-17-18/output.txt rename to listings/ch17-async-await/listing-17-19/output.txt diff --git a/listings/ch17-async-await/listing-17-19/src/main.rs b/listings/ch17-async-await/listing-17-19/src/main.rs index 12ab2704b2..41820fc8a5 100644 --- a/listings/ch17-async-await/listing-17-19/src/main.rs +++ b/listings/ch17-async-await/listing-17-19/src/main.rs @@ -1,14 +1,66 @@ extern crate trpl; // required for mdbook test +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; + fn main() { trpl::run(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); // ANCHOR: here - let a = async { 1u32 }; - let b = async { "Hello!" }; - let c = async { true }; + let tx1_fut = pin!(async move { + // --snip-- + // ANCHOR_END: here + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("future"), + ]; + + for val in vals { + tx1.send(val).unwrap(); + trpl::sleep(Duration::from_secs(1)).await; + } + // ANCHOR: here + }); - let (a_result, b_result, c_result) = trpl::join!(a, b, c); - println!("{a_result}, {b_result}, {c_result}"); // ANCHOR_END: here + // ANCHOR: here + let rx_fut = pin!(async { + // --snip-- + // ANCHOR_END: here + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + // ANCHOR: here + }); + + let tx_fut = pin!(async move { + // --snip-- + // ANCHOR_END: here + let vals = vec![ + String::from("more"), + String::from("messages"), + String::from("for"), + String::from("you"), + ]; + + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_secs(1)).await; + } + // ANCHOR: here + }); + + let futures: Vec>> = + vec![tx1_fut, rx_fut, tx_fut]; + // ANCHOR_END: here + + trpl::join_all(futures).await; }); } diff --git a/listings/ch17-async-await/listing-17-20/Cargo.lock b/listings/ch17-async-await/listing-17-20/Cargo.lock index 3be4eaaa53..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-20/Cargo.lock +++ b/listings/ch17-async-await/listing-17-20/Cargo.lock @@ -45,18 +45,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - [[package]] name = "cc" version = "1.0.97" @@ -176,16 +164,6 @@ version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "memchr" version = "2.7.2" @@ -201,17 +179,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.48.0", -] - [[package]] name = "num_cpus" version = "1.16.0" @@ -231,29 +198,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "parking_lot" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.5", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -284,36 +228,12 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" -dependencies = [ - "bitflags", -] - [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - [[package]] name = "slab" version = "0.4.9" @@ -323,22 +243,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "syn" version = "2.0.63" @@ -357,27 +261,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", - "bytes", - "libc", - "mio", "num_cpus", - "parking_lot", "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", ] [[package]] -name = "tokio-macros" -version = "2.2.0" +name = "tokio-stream" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ - "proc-macro2", - "quote", - "syn", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -386,6 +282,7 @@ version = "0.1.0" dependencies = [ "futures", "tokio", + "tokio-stream", ] [[package]] @@ -393,148 +290,3 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/listings/ch17-async-await/listing-17-20/src/main.rs b/listings/ch17-async-await/listing-17-20/src/main.rs index 308c14a4ac..12ab2704b2 100644 --- a/listings/ch17-async-await/listing-17-20/src/main.rs +++ b/listings/ch17-async-await/listing-17-20/src/main.rs @@ -1,23 +1,14 @@ extern crate trpl; // required for mdbook test -use std::time::Duration; - fn main() { trpl::run(async { // ANCHOR: here - let slow = async { - println!("'slow' started."); - trpl::sleep(Duration::from_millis(100)).await; - println!("'slow' finished."); - }; - - let fast = async { - println!("'fast' started."); - trpl::sleep(Duration::from_millis(50)).await; - println!("'fast' finished."); - }; + let a = async { 1u32 }; + let b = async { "Hello!" }; + let c = async { true }; - trpl::race(slow, fast).await; + let (a_result, b_result, c_result) = trpl::join!(a, b, c); + println!("{a_result}, {b_result}, {c_result}"); // ANCHOR_END: here }); } diff --git a/listings/ch17-async-await/listing-17-21/Cargo.lock b/listings/ch17-async-await/listing-17-21/Cargo.lock index 2e0f3ebedb..3be4eaaa53 100644 --- a/listings/ch17-async-await/listing-17-21/Cargo.lock +++ b/listings/ch17-async-await/listing-17-21/Cargo.lock @@ -45,6 +45,18 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + [[package]] name = "cc" version = "1.0.97" @@ -164,6 +176,16 @@ version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "memchr" version = "2.7.2" @@ -179,6 +201,17 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -198,6 +231,29 @@ dependencies = [ "memchr", ] +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -228,12 +284,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags", +] + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -243,6 +323,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "syn" version = "2.0.63" @@ -261,19 +357,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", + "bytes", + "libc", + "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "tokio-macros" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -282,7 +386,6 @@ version = "0.1.0" dependencies = [ "futures", "tokio", - "tokio-stream", ] [[package]] @@ -290,3 +393,148 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/listings/ch17-async-await/listing-17-21/src/main.rs b/listings/ch17-async-await/listing-17-21/src/main.rs index 2dfb52b7d4..308c14a4ac 100644 --- a/listings/ch17-async-await/listing-17-21/src/main.rs +++ b/listings/ch17-async-await/listing-17-21/src/main.rs @@ -1,16 +1,23 @@ extern crate trpl; // required for mdbook test -use std::{thread, time::Duration}; +use std::time::Duration; fn main() { trpl::run(async { - // We will call `slow` here later - }); -} + // ANCHOR: here + let slow = async { + println!("'slow' started."); + trpl::sleep(Duration::from_millis(100)).await; + println!("'slow' finished."); + }; -// ANCHOR: slow -fn slow(name: &str, ms: u64) { - thread::sleep(Duration::from_millis(ms)); - println!("'{name}' ran for {ms}ms"); + let fast = async { + println!("'fast' started."); + trpl::sleep(Duration::from_millis(50)).await; + println!("'fast' finished."); + }; + + trpl::race(slow, fast).await; + // ANCHOR_END: here + }); } -// ANCHOR_END: slow diff --git a/listings/ch17-async-await/listing-17-22/src/main.rs b/listings/ch17-async-await/listing-17-22/src/main.rs index 391cf39e19..2dfb52b7d4 100644 --- a/listings/ch17-async-await/listing-17-22/src/main.rs +++ b/listings/ch17-async-await/listing-17-22/src/main.rs @@ -4,32 +4,13 @@ use std::{thread, time::Duration}; fn main() { trpl::run(async { - // ANCHOR: slow-futures - let a = async { - println!("'a' started."); - slow("a", 30); - slow("a", 10); - slow("a", 20); - trpl::sleep(Duration::from_millis(50)).await; - println!("'a' finished."); - }; - - let b = async { - println!("'b' started."); - slow("b", 75); - slow("b", 10); - slow("b", 15); - slow("b", 350); - trpl::sleep(Duration::from_millis(50)).await; - println!("'b' finished."); - }; - - trpl::race(a, b).await; - // ANCHOR_END: slow-futures + // We will call `slow` here later }); } +// ANCHOR: slow fn slow(name: &str, ms: u64) { thread::sleep(Duration::from_millis(ms)); println!("'{name}' ran for {ms}ms"); } +// ANCHOR_END: slow diff --git a/listings/ch17-async-await/listing-17-23/src/main.rs b/listings/ch17-async-await/listing-17-23/src/main.rs index 961431d396..391cf39e19 100644 --- a/listings/ch17-async-await/listing-17-23/src/main.rs +++ b/listings/ch17-async-await/listing-17-23/src/main.rs @@ -4,35 +4,28 @@ use std::{thread, time::Duration}; fn main() { trpl::run(async { - // ANCHOR: here - let one_ms = Duration::from_millis(1); - + // ANCHOR: slow-futures let a = async { println!("'a' started."); slow("a", 30); - trpl::sleep(one_ms).await; slow("a", 10); - trpl::sleep(one_ms).await; slow("a", 20); - trpl::sleep(one_ms).await; + trpl::sleep(Duration::from_millis(50)).await; println!("'a' finished."); }; let b = async { println!("'b' started."); slow("b", 75); - trpl::sleep(one_ms).await; slow("b", 10); - trpl::sleep(one_ms).await; slow("b", 15); - trpl::sleep(one_ms).await; - slow("b", 35); - trpl::sleep(one_ms).await; + slow("b", 350); + trpl::sleep(Duration::from_millis(50)).await; println!("'b' finished."); }; - // ANCHOR_END: here trpl::race(a, b).await; + // ANCHOR_END: slow-futures }); } diff --git a/listings/ch17-async-await/listing-17-24/src/main.rs b/listings/ch17-async-await/listing-17-24/src/main.rs index 165022108b..961431d396 100644 --- a/listings/ch17-async-await/listing-17-24/src/main.rs +++ b/listings/ch17-async-await/listing-17-24/src/main.rs @@ -4,31 +4,33 @@ use std::{thread, time::Duration}; fn main() { trpl::run(async { - // ANCHOR: yields + // ANCHOR: here + let one_ms = Duration::from_millis(1); + let a = async { println!("'a' started."); slow("a", 30); - trpl::yield_now().await; + trpl::sleep(one_ms).await; slow("a", 10); - trpl::yield_now().await; + trpl::sleep(one_ms).await; slow("a", 20); - trpl::yield_now().await; + trpl::sleep(one_ms).await; println!("'a' finished."); }; let b = async { println!("'b' started."); slow("b", 75); - trpl::yield_now().await; + trpl::sleep(one_ms).await; slow("b", 10); - trpl::yield_now().await; + trpl::sleep(one_ms).await; slow("b", 15); - trpl::yield_now().await; + trpl::sleep(one_ms).await; slow("b", 35); - trpl::yield_now().await; + trpl::sleep(one_ms).await; println!("'b' finished."); }; - // ANCHOR_END: yields + // ANCHOR_END: here trpl::race(a, b).await; }); diff --git a/listings/ch17-async-await/listing-17-25/Cargo.lock b/listings/ch17-async-await/listing-17-25/Cargo.lock index 3be4eaaa53..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-25/Cargo.lock +++ b/listings/ch17-async-await/listing-17-25/Cargo.lock @@ -45,18 +45,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - [[package]] name = "cc" version = "1.0.97" @@ -176,16 +164,6 @@ version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "memchr" version = "2.7.2" @@ -201,17 +179,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.48.0", -] - [[package]] name = "num_cpus" version = "1.16.0" @@ -231,29 +198,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "parking_lot" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.5", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -284,36 +228,12 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" -dependencies = [ - "bitflags", -] - [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - [[package]] name = "slab" version = "0.4.9" @@ -323,22 +243,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "syn" version = "2.0.63" @@ -357,27 +261,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", - "bytes", - "libc", - "mio", "num_cpus", - "parking_lot", "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", ] [[package]] -name = "tokio-macros" -version = "2.2.0" +name = "tokio-stream" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ - "proc-macro2", - "quote", - "syn", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -386,6 +282,7 @@ version = "0.1.0" dependencies = [ "futures", "tokio", + "tokio-stream", ] [[package]] @@ -393,148 +290,3 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/listings/ch17-async-await/listing-17-25/src/main.rs b/listings/ch17-async-await/listing-17-25/src/main.rs index 31ce58d9e9..165022108b 100644 --- a/listings/ch17-async-await/listing-17-25/src/main.rs +++ b/listings/ch17-async-await/listing-17-25/src/main.rs @@ -1,36 +1,40 @@ extern crate trpl; // required for mdbook test -use std::time::{Duration, Instant}; +use std::{thread, time::Duration}; fn main() { trpl::run(async { - // ANCHOR: here - let one_ns = Duration::from_nanos(1); - let start = Instant::now(); - async { - for _ in 1..1000 { - trpl::sleep(one_ns).await; - } - } - .await; - let time = Instant::now() - start; - println!( - "'sleep' version finished after {} seconds.", - time.as_secs_f32() - ); + // ANCHOR: yields + let a = async { + println!("'a' started."); + slow("a", 30); + trpl::yield_now().await; + slow("a", 10); + trpl::yield_now().await; + slow("a", 20); + trpl::yield_now().await; + println!("'a' finished."); + }; - let start = Instant::now(); - async { - for _ in 1..1000 { - trpl::yield_now().await; - } - } - .await; - let time = Instant::now() - start; - println!( - "'yield' version finished after {} seconds.", - time.as_secs_f32() - ); - // ANCHOR_END: here + let b = async { + println!("'b' started."); + slow("b", 75); + trpl::yield_now().await; + slow("b", 10); + trpl::yield_now().await; + slow("b", 15); + trpl::yield_now().await; + slow("b", 35); + trpl::yield_now().await; + println!("'b' finished."); + }; + // ANCHOR_END: yields + + trpl::race(a, b).await; }); } + +fn slow(name: &str, ms: u64) { + thread::sleep(Duration::from_millis(ms)); + println!("'{name}' ran for {ms}ms"); +} diff --git a/listings/ch17-async-await/listing-17-26/Cargo.lock b/listings/ch17-async-await/listing-17-26/Cargo.lock index 2e0f3ebedb..3be4eaaa53 100644 --- a/listings/ch17-async-await/listing-17-26/Cargo.lock +++ b/listings/ch17-async-await/listing-17-26/Cargo.lock @@ -45,6 +45,18 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + [[package]] name = "cc" version = "1.0.97" @@ -164,6 +176,16 @@ version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "memchr" version = "2.7.2" @@ -179,6 +201,17 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -198,6 +231,29 @@ dependencies = [ "memchr", ] +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -228,12 +284,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags", +] + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -243,6 +323,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "syn" version = "2.0.63" @@ -261,19 +357,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", + "bytes", + "libc", + "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "tokio-macros" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -282,7 +386,6 @@ version = "0.1.0" dependencies = [ "futures", "tokio", - "tokio-stream", ] [[package]] @@ -290,3 +393,148 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/listings/ch17-async-await/listing-17-26/src/main.rs b/listings/ch17-async-await/listing-17-26/src/main.rs index cdab724687..31ce58d9e9 100644 --- a/listings/ch17-async-await/listing-17-26/src/main.rs +++ b/listings/ch17-async-await/listing-17-26/src/main.rs @@ -1,21 +1,36 @@ extern crate trpl; // required for mdbook test -use std::time::Duration; +use std::time::{Duration, Instant}; fn main() { trpl::run(async { // ANCHOR: here - let slow = async { - trpl::sleep(Duration::from_millis(100)).await; - "I finished!" - }; + let one_ns = Duration::from_nanos(1); + let start = Instant::now(); + async { + for _ in 1..1000 { + trpl::sleep(one_ns).await; + } + } + .await; + let time = Instant::now() - start; + println!( + "'sleep' version finished after {} seconds.", + time.as_secs_f32() + ); - match timeout(slow, Duration::from_millis(10)).await { - Ok(message) => println!("Succeeded with '{message}'"), - Err(duration) => { - println!("Failed after {} seconds", duration.as_secs()) + let start = Instant::now(); + async { + for _ in 1..1000 { + trpl::yield_now().await; } } + .await; + let time = Instant::now() - start; + println!( + "'yield' version finished after {} seconds.", + time.as_secs_f32() + ); // ANCHOR_END: here }); } diff --git a/listings/ch17-async-await/listing-17-27/src/main.rs b/listings/ch17-async-await/listing-17-27/src/main.rs index d2edded63d..cdab724687 100644 --- a/listings/ch17-async-await/listing-17-27/src/main.rs +++ b/listings/ch17-async-await/listing-17-27/src/main.rs @@ -1,12 +1,13 @@ extern crate trpl; // required for mdbook test -use std::{future::Future, time::Duration}; +use std::time::Duration; fn main() { trpl::run(async { + // ANCHOR: here let slow = async { - trpl::sleep(Duration::from_secs(5)).await; - "Finally finished" + trpl::sleep(Duration::from_millis(100)).await; + "I finished!" }; match timeout(slow, Duration::from_millis(10)).await { @@ -15,14 +16,6 @@ fn main() { println!("Failed after {} seconds", duration.as_secs()) } } + // ANCHOR_END: here }); } - -// ANCHOR: declaration -async fn timeout( - future_to_try: F, - max_time: Duration, -) -> Result { - // Here is where our implementation will go! -} -// ANCHOR_END: declaration diff --git a/listings/ch17-async-await/listing-17-28/src/main.rs b/listings/ch17-async-await/listing-17-28/src/main.rs index 9efb5e7921..d2edded63d 100644 --- a/listings/ch17-async-await/listing-17-28/src/main.rs +++ b/listings/ch17-async-await/listing-17-28/src/main.rs @@ -2,12 +2,6 @@ extern crate trpl; // required for mdbook test use std::{future::Future, time::Duration}; -// ANCHOR: implementation -use trpl::Either; - -// --snip-- -// ANCHOR: implementation - fn main() { trpl::run(async { let slow = async { @@ -15,7 +9,7 @@ fn main() { "Finally finished" }; - match timeout(slow, Duration::from_secs(2)).await { + match timeout(slow, Duration::from_millis(10)).await { Ok(message) => println!("Succeeded with '{message}'"), Err(duration) => { println!("Failed after {} seconds", duration.as_secs()) @@ -24,14 +18,11 @@ fn main() { }); } +// ANCHOR: declaration async fn timeout( future_to_try: F, max_time: Duration, ) -> Result { - // ANCHOR: implementation - match trpl::race(future_to_try, trpl::sleep(max_time)).await { - Either::Left(output) => Ok(output), - Either::Right(_) => Err(max_time), - } - // ANCHOR_END: implementation + // Here is where our implementation will go! } +// ANCHOR_END: declaration diff --git a/listings/ch17-async-await/listing-17-29/Cargo.lock b/listings/ch17-async-await/listing-17-29/Cargo.lock index 36905af42a..a55aeb1e1c 100644 --- a/listings/ch17-async-await/listing-17-29/Cargo.lock +++ b/listings/ch17-async-await/listing-17-29/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -17,6 +17,19 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "async_await" version = "0.1.0" @@ -24,6 +37,12 @@ dependencies = [ "trpl", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -32,9 +51,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -45,11 +64,41 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + [[package]] name = "cc" -version = "1.0.99" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cfg-if" @@ -57,6 +106,148 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -146,11 +337,65 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" -version = "0.29.0" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -159,134 +404,1457 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "libc" -version = "0.2.155" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "memchr" -version = "2.7.4" +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "adler", + "bytes", + "http", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ - "hermit-abi", - "libc", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", ] [[package]] -name = "object" -version = "0.36.0" +name = "httparse" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ - "memchr", + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "hyper-rustls" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "hyper-tls" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper-util" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ - "unicode-ident", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] -name = "quote" -version = "1.0.36" +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "proc-macro2", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "indexmap" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] [[package]] -name = "slab" -version = "0.4.9" +name = "ipnet" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", + "scopeguard", ] [[package]] -name = "syn" -version = "2.0.66" +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", ] [[package]] -name = "tokio" -version = "1.38.0" +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "adler", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "mio" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "libc", + "wasi", + "windows-sys 0.48.0", ] [[package]] -name = "trpl" -version = "0.1.0" +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "futures", - "tokio", - "tokio-stream", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-29/Cargo.toml b/listings/ch17-async-await/listing-17-29/Cargo.toml index e094f067f1..349041d3eb 100644 --- a/listings/ch17-async-await/listing-17-29/Cargo.toml +++ b/listings/ch17-async-await/listing-17-29/Cargo.toml @@ -4,5 +4,6 @@ version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [dependencies] trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-29/src/main.rs b/listings/ch17-async-await/listing-17-29/src/main.rs index faa6b6a1ca..9efb5e7921 100644 --- a/listings/ch17-async-await/listing-17-29/src/main.rs +++ b/listings/ch17-async-await/listing-17-29/src/main.rs @@ -1,15 +1,37 @@ extern crate trpl; // required for mdbook test +use std::{future::Future, time::Duration}; + +// ANCHOR: implementation +use trpl::Either; + +// --snip-- +// ANCHOR: implementation + fn main() { trpl::run(async { - // ANCHOR: stream - let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let iter = values.iter().map(|n| n * 2); - let mut stream = trpl::stream_from_iter(iter); + let slow = async { + trpl::sleep(Duration::from_secs(5)).await; + "Finally finished" + }; - while let Some(value) = stream.next().await { - println!("The value was: {value}"); + match timeout(slow, Duration::from_secs(2)).await { + Ok(message) => println!("Succeeded with '{message}'"), + Err(duration) => { + println!("Failed after {} seconds", duration.as_secs()) + } } - // ANCHOR_END: stream }); } + +async fn timeout( + future_to_try: F, + max_time: Duration, +) -> Result { + // ANCHOR: implementation + match trpl::race(future_to_try, trpl::sleep(max_time)).await { + Either::Left(output) => Ok(output), + Either::Right(_) => Err(max_time), + } + // ANCHOR_END: implementation +} diff --git a/listings/ch17-async-await/listing-17-30/src/main.rs b/listings/ch17-async-await/listing-17-30/src/main.rs index 0a7fc87c21..faa6b6a1ca 100644 --- a/listings/ch17-async-await/listing-17-30/src/main.rs +++ b/listings/ch17-async-await/listing-17-30/src/main.rs @@ -1,9 +1,8 @@ extern crate trpl; // required for mdbook test -use trpl::StreamExt; - fn main() { trpl::run(async { + // ANCHOR: stream let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let iter = values.iter().map(|n| n * 2); let mut stream = trpl::stream_from_iter(iter); @@ -11,5 +10,6 @@ fn main() { while let Some(value) = stream.next().await { println!("The value was: {value}"); } + // ANCHOR_END: stream }); } diff --git a/listings/ch17-async-await/listing-17-31/src/main.rs b/listings/ch17-async-await/listing-17-31/src/main.rs index 017185bed5..0a7fc87c21 100644 --- a/listings/ch17-async-await/listing-17-31/src/main.rs +++ b/listings/ch17-async-await/listing-17-31/src/main.rs @@ -4,14 +4,11 @@ use trpl::StreamExt; fn main() { trpl::run(async { - let values = 1..101; - let iter = values.map(|n| n * 2); - let stream = trpl::stream_from_iter(iter); + let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let iter = values.iter().map(|n| n * 2); + let mut stream = trpl::stream_from_iter(iter); - let mut filtered = - stream.filter(|value| value % 3 == 0 || value % 5 == 0); - - while let Some(value) = filtered.next().await { + while let Some(value) = stream.next().await { println!("The value was: {value}"); } }); diff --git a/listings/ch17-async-await/listing-17-32/src/main.rs b/listings/ch17-async-await/listing-17-32/src/main.rs index d9a7733d43..017185bed5 100644 --- a/listings/ch17-async-await/listing-17-32/src/main.rs +++ b/listings/ch17-async-await/listing-17-32/src/main.rs @@ -1,26 +1,18 @@ extern crate trpl; // required for mdbook test -// ANCHOR: all -use trpl::{ReceiverStream, Stream, StreamExt}; +use trpl::StreamExt; fn main() { trpl::run(async { - let mut messages = get_messages(); + let values = 1..101; + let iter = values.map(|n| n * 2); + let stream = trpl::stream_from_iter(iter); - while let Some(message) = messages.next().await { - println!("{message}"); + let mut filtered = + stream.filter(|value| value % 3 == 0 || value % 5 == 0); + + while let Some(value) = filtered.next().await { + println!("The value was: {value}"); } }); } - -fn get_messages() -> impl Stream { - let (tx, rx) = trpl::channel(); - - let messages = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; - for message in messages { - tx.send(format!("Message: '{message}'")).unwrap(); - } - - ReceiverStream::new(rx) -} -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-33/src/main.rs b/listings/ch17-async-await/listing-17-33/src/main.rs index de919073f8..d9a7733d43 100644 --- a/listings/ch17-async-await/listing-17-33/src/main.rs +++ b/listings/ch17-async-await/listing-17-33/src/main.rs @@ -1,23 +1,17 @@ extern crate trpl; // required for mdbook test -// ANCHOR: timeout -use std::{pin::pin, time::Duration}; +// ANCHOR: all use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { trpl::run(async { - let mut messages = - pin!(get_messages().timeout(Duration::from_millis(200))); + let mut messages = get_messages(); - while let Some(result) = messages.next().await { - match result { - Ok(message) => println!("{message}"), - Err(reason) => eprintln!("Problem: {reason:?}"), - } + while let Some(message) = messages.next().await { + println!("{message}"); } - }) + }); } -// ANCHOR_END: timeout fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); @@ -29,3 +23,4 @@ fn get_messages() -> impl Stream { ReceiverStream::new(rx) } +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-34/src/main.rs b/listings/ch17-async-await/listing-17-34/src/main.rs index b4dda21d52..de919073f8 100644 --- a/listings/ch17-async-await/listing-17-34/src/main.rs +++ b/listings/ch17-async-await/listing-17-34/src/main.rs @@ -1,7 +1,7 @@ extern crate trpl; // required for mdbook test +// ANCHOR: timeout use std::{pin::pin, time::Duration}; - use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { @@ -17,21 +17,15 @@ fn main() { } }) } +// ANCHOR_END: timeout -// ANCHOR: messages fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); - trpl::spawn_task(async move { - let messages = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; - for (index, message) in messages.into_iter().enumerate() { - let time_to_sleep = if index % 2 == 0 { 100 } else { 300 }; - trpl::sleep(Duration::from_millis(time_to_sleep)).await; - - tx.send(format!("Message: '{message}'")).unwrap(); - } - }); + let messages = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; + for message in messages { + tx.send(format!("Message: '{message}'")).unwrap(); + } ReceiverStream::new(rx) } -// ANCHOR_END: messages diff --git a/listings/ch17-async-await/listing-17-35/src/main.rs b/listings/ch17-async-await/listing-17-35/src/main.rs index 13bd0b1121..b4dda21d52 100644 --- a/listings/ch17-async-await/listing-17-35/src/main.rs +++ b/listings/ch17-async-await/listing-17-35/src/main.rs @@ -18,6 +18,7 @@ fn main() { }) } +// ANCHOR: messages fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); @@ -33,20 +34,4 @@ fn get_messages() -> impl Stream { ReceiverStream::new(rx) } - -// ANCHOR: intervals -fn get_intervals() -> impl Stream { - let (tx, rx) = trpl::channel(); - - trpl::spawn_task(async move { - let mut count = 0; - loop { - trpl::sleep(Duration::from_millis(1)).await; - count += 1; - tx.send(count).unwrap(); - } - }); - - ReceiverStream::new(rx) -} -// ANCHOR_END: intervals +// ANCHOR_END: messages diff --git a/listings/ch17-async-await/listing-17-36/src/main.rs b/listings/ch17-async-await/listing-17-36/src/main.rs index bc10dd48c9..13bd0b1121 100644 --- a/listings/ch17-async-await/listing-17-36/src/main.rs +++ b/listings/ch17-async-await/listing-17-36/src/main.rs @@ -6,13 +6,10 @@ use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { trpl::run(async { - // ANCHOR: main - let messages = get_messages().timeout(Duration::from_millis(200)); - let intervals = get_intervals(); - let merged = messages.merge(intervals); - // ANCHOR_END: main + let mut messages = + pin!(get_messages().timeout(Duration::from_millis(200))); - while let Some(result) = merged.next().await { + while let Some(result) = messages.next().await { match result { Ok(message) => println!("{message}"), Err(reason) => eprintln!("Problem: {reason:?}"), @@ -37,6 +34,7 @@ fn get_messages() -> impl Stream { ReceiverStream::new(rx) } +// ANCHOR: intervals fn get_intervals() -> impl Stream { let (tx, rx) = trpl::channel(); @@ -51,3 +49,4 @@ fn get_intervals() -> impl Stream { ReceiverStream::new(rx) } +// ANCHOR_END: intervals diff --git a/listings/ch17-async-await/listing-17-37/src/main.rs b/listings/ch17-async-await/listing-17-37/src/main.rs index 72da09d75f..bc10dd48c9 100644 --- a/listings/ch17-async-await/listing-17-37/src/main.rs +++ b/listings/ch17-async-await/listing-17-37/src/main.rs @@ -8,14 +8,11 @@ fn main() { trpl::run(async { // ANCHOR: main let messages = get_messages().timeout(Duration::from_millis(200)); - let intervals = get_intervals() - .map(|count| format!("Interval: {count}")) - .timeout(Duration::from_secs(10)); + let intervals = get_intervals(); let merged = messages.merge(intervals); - let mut stream = pin!(merged); // ANCHOR_END: main - while let Some(result) = stream.next().await { + while let Some(result) = merged.next().await { match result { Ok(message) => println!("{message}"), Err(reason) => eprintln!("Problem: {reason:?}"), diff --git a/listings/ch17-async-await/listing-17-38/src/main.rs b/listings/ch17-async-await/listing-17-38/src/main.rs index a5f51618f5..72da09d75f 100644 --- a/listings/ch17-async-await/listing-17-38/src/main.rs +++ b/listings/ch17-async-await/listing-17-38/src/main.rs @@ -6,15 +6,14 @@ use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { trpl::run(async { - // ANCHOR: throttle + // ANCHOR: main let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() - .map(|count| format!("Interval #{count}")) - .throttle(Duration::from_millis(100)) + .map(|count| format!("Interval: {count}")) .timeout(Duration::from_secs(10)); - let merged = messages.merge(intervals).take(20); + let merged = messages.merge(intervals); let mut stream = pin!(merged); - // ANCHOR_END: throttle + // ANCHOR_END: main while let Some(result) = stream.next().await { match result { diff --git a/listings/ch17-async-await/listing-17-39/src/main.rs b/listings/ch17-async-await/listing-17-39/src/main.rs index ecf406e93d..a5f51618f5 100644 --- a/listings/ch17-async-await/listing-17-39/src/main.rs +++ b/listings/ch17-async-await/listing-17-39/src/main.rs @@ -6,38 +6,35 @@ use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { trpl::run(async { + // ANCHOR: throttle let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() .map(|count| format!("Interval #{count}")) - .throttle(Duration::from_millis(500)) + .throttle(Duration::from_millis(100)) .timeout(Duration::from_secs(10)); let merged = messages.merge(intervals).take(20); let mut stream = pin!(merged); + // ANCHOR_END: throttle while let Some(result) = stream.next().await { match result { - Ok(item) => println!("{item}"), + Ok(message) => println!("{message}"), Err(reason) => eprintln!("Problem: {reason:?}"), } } - }); + }) } -// ANCHOR: errors fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); trpl::spawn_task(async move { let messages = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; - for (index, message) in messages.into_iter().enumerate() { let time_to_sleep = if index % 2 == 0 { 100 } else { 300 }; trpl::sleep(Duration::from_millis(time_to_sleep)).await; - if let Err(send_error) = tx.send(format!("Message: '{message}'")) { - eprintln!("Cannot send message '{message}': {send_error}"); - break; - } + tx.send(format!("Message: '{message}'")).unwrap(); } }); @@ -52,14 +49,9 @@ fn get_intervals() -> impl Stream { loop { trpl::sleep(Duration::from_millis(1)).await; count += 1; - - if let Err(send_error) = tx.send(count) { - eprintln!("Could not send interval {count}: {send_error}"); - break; - }; + tx.send(count).unwrap(); } }); ReceiverStream::new(rx) } -// ANCHOR_END: errors diff --git a/listings/ch17-async-await/listing-17-40/src/main.rs b/listings/ch17-async-await/listing-17-40/src/main.rs index f1f3d4b0c0..ecf406e93d 100644 --- a/listings/ch17-async-await/listing-17-40/src/main.rs +++ b/listings/ch17-async-await/listing-17-40/src/main.rs @@ -1,6 +1,6 @@ extern crate trpl; // required for mdbook test -use std::{pin::pin, thread, time::Duration}; +use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; @@ -23,6 +23,7 @@ fn main() { }); } +// ANCHOR: errors fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); @@ -43,16 +44,13 @@ fn get_messages() -> impl Stream { ReceiverStream::new(rx) } -// ANCHOR: threads fn get_intervals() -> impl Stream { let (tx, rx) = trpl::channel(); - // This is *not* `trpl::spawn` but `std::thread::spawn`! - thread::spawn(move || { + trpl::spawn_task(async move { let mut count = 0; loop { - // Likewise, this is *not* `trpl::sleep` but `std::thread::sleep`! - thread::sleep(Duration::from_millis(1)); + trpl::sleep(Duration::from_millis(1)).await; count += 1; if let Err(send_error) = tx.send(count) { @@ -64,4 +62,4 @@ fn get_intervals() -> impl Stream { ReceiverStream::new(rx) } -// ANCHOR_END: threads +// ANCHOR_END: errors diff --git a/listings/ch17-async-await/listing-17-41/Cargo.lock b/listings/ch17-async-await/listing-17-41/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-41/Cargo.lock @@ -0,0 +1,292 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "async_await" +version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +dependencies = [ + "memchr", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", + "tokio-stream", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/listings/ch17-async-await/listing-17-41/Cargo.toml b/listings/ch17-async-await/listing-17-41/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-41/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "async_await" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-41/src/main.rs b/listings/ch17-async-await/listing-17-41/src/main.rs new file mode 100644 index 0000000000..f1f3d4b0c0 --- /dev/null +++ b/listings/ch17-async-await/listing-17-41/src/main.rs @@ -0,0 +1,67 @@ +extern crate trpl; // required for mdbook test + +use std::{pin::pin, thread, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::run(async { + let messages = get_messages().timeout(Duration::from_millis(200)); + let intervals = get_intervals() + .map(|count| format!("Interval #{count}")) + .throttle(Duration::from_millis(500)) + .timeout(Duration::from_secs(10)); + let merged = messages.merge(intervals).take(20); + let mut stream = pin!(merged); + + while let Some(result) = stream.next().await { + match result { + Ok(item) => println!("{item}"), + Err(reason) => eprintln!("Problem: {reason:?}"), + } + } + }); +} + +fn get_messages() -> impl Stream { + let (tx, rx) = trpl::channel(); + + trpl::spawn_task(async move { + let messages = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; + + for (index, message) in messages.into_iter().enumerate() { + let time_to_sleep = if index % 2 == 0 { 100 } else { 300 }; + trpl::sleep(Duration::from_millis(time_to_sleep)).await; + + if let Err(send_error) = tx.send(format!("Message: '{message}'")) { + eprintln!("Cannot send message '{message}': {send_error}"); + break; + } + } + }); + + ReceiverStream::new(rx) +} + +// ANCHOR: threads +fn get_intervals() -> impl Stream { + let (tx, rx) = trpl::channel(); + + // This is *not* `trpl::spawn` but `std::thread::spawn`! + thread::spawn(move || { + let mut count = 0; + loop { + // Likewise, this is *not* `trpl::sleep` but `std::thread::sleep`! + thread::sleep(Duration::from_millis(1)); + count += 1; + + if let Err(send_error) = tx.send(count) { + eprintln!("Could not send interval {count}: {send_error}"); + break; + }; + } + }); + + ReceiverStream::new(rx) +} +// ANCHOR_END: threads diff --git a/packages/trpl/Cargo.lock b/packages/trpl/Cargo.lock index 03bebc8dd8..bc42cb8b60 100644 --- a/packages/trpl/Cargo.lock +++ b/packages/trpl/Cargo.lock @@ -17,6 +17,25 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -38,6 +57,36 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + [[package]] name = "cc" version = "1.0.98" @@ -50,6 +99,148 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -139,6 +330,35 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.28.1" @@ -146,140 +366,1488 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "h2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] [[package]] -name = "libc" -version = "0.2.155" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] -name = "memchr" -version = "2.7.2" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.3" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" dependencies = [ - "adler", + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "hermit-abi", - "libc", + "bytes", + "fnv", + "itoa", ] [[package]] -name = "object" -version = "0.32.2" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "memchr", + "bytes", + "http", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "httparse" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] -name = "proc-macro2" -version = "1.0.84" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ - "unicode-ident", + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", ] [[package]] -name = "quote" -version = "1.0.36" +name = "hyper-rustls" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ - "proc-macro2", + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "hyper-tls" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] [[package]] -name = "slab" -version = "0.4.9" +name = "hyper-util" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] -name = "syn" -version = "2.0.66" +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "tokio" -version = "1.37.0" +name = "indexmap" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "wasm-bindgen", ] [[package]] -name = "trpl" -version = "0.1.0" +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "futures", - "tokio", - "tokio-stream", + "autocfg", + "scopeguard", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "log" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/packages/trpl/Cargo.toml b/packages/trpl/Cargo.toml index 5fd0029ac7..62a602ea19 100644 --- a/packages/trpl/Cargo.toml +++ b/packages/trpl/Cargo.toml @@ -12,6 +12,8 @@ authors = ["Chris Krycho "] [dependencies] futures = "0.3" +reqwest = "0.12" +scraper = "0.20" tokio = { version = "1", default-features = false, features = [ "fs", "rt-multi-thread", diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 6d3a4bdaab..999cb6e273 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -97,3 +97,54 @@ where Either::Right((b, _f1)) => Either::Right(b), } } + +/// Fetch data from a URL. For more convenient use in _The Rust Programming +/// Language_, panics instead of returning a [`Result`] if the request fails. +pub async fn get(url: &str) -> Response { + Response(reqwest::get(url).await.unwrap()) +} + +/// A thin wrapper around [`reqwest::Response`] to make the demos in _The Rust +/// Programming Language_ substantially nicer to use. +pub struct Response(reqwest::Response); + +impl Response { + /// Get the full response text. + /// + /// If the response cannot be deserialized, this panics instead of returning + /// a [`Result`] (for convenience in the demo). + pub async fn text(self) -> String { + self.0.text().await.unwrap() + } +} + +/// A thin wrapper around [`scraper::Html`] to make the demos in _The Rust +/// Programming Language_ substantially nicer to use. +pub struct Html { + inner: scraper::Html, +} + +impl Html { + /// Parse an HTML document from a string. + /// + /// This is just a thin wrapper around `scraper::Html::parse_document` to + /// keep the exported API surface simpler. + pub fn parse(source: &str) -> Html { + Html { + inner: scraper::Html::parse_document(source), + } + } + + /// Get the first item in the document matching a string selector. Returns + /// Some() + /// + /// If the selector is not a valid CSS selector, panics rather than + /// returning a [`Result`] for convenience. + pub fn select_first<'a>( + &'a self, + selector: &'a str, + ) -> Option> { + let selector = scraper::Selector::parse(selector).unwrap(); + self.inner.select(&selector).nth(0) + } +} diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index b67d8680a7..afc5f81864 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -229,3 +229,14 @@ fn re_exported_interval_stream_works() { assert!(interval_stream.next().await.is_none()); }); } + +#[test] +fn re_exported_html() { + use trpl::Html; + + let doc = Html::parse( + "

Hello!

", + ); + let p = doc.select_first("p").map(|el| el.inner_html()); + assert_eq!(p, Some(String::from("Hello!"))); +} diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 687ce8870b..bf7e26bde0 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -1,72 +1,163 @@ ## Futures and the Async Syntax -They key elements of asynchronous programming in Rust are *futures* and Rust’s +The key elements of asynchronous programming in Rust are *futures* and Rust’s `async` and `await` keywords. -A future is a value that may not ready yet. Every future holds its own -information about the progress that has been made and what "ready" means. In -Rust, we say that types which implement the `Future` trait are futures. The -`async` keyword can be applied to blocks and functions to specify that they can -be interrupted and resumed. Within an async block or async function, you can use -the `await` keyword to wait for a future to become ready, called *awaiting a +A *future* is a value which may not be ready now, but will become ready at some +point in the future. (This same concept shows up in many languages, sometimes +under other names like “task” or “promise”.) Rust provides a `Future` trait as a +building block so different async operations can be implemented with different +data structures, but with a common interface. In Rust, we say that types which +implement the `Future` trait are futures. Each type which implements `Future` +holds its own information about the progress that has been made and what "ready" +means. + +The `async` keyword can be applied to blocks and functions to specify that they +can be interrupted and resumed. Within an async block or async function, you can +use the `await` keyword to wait for a future to become ready, called *awaiting a future*. Each place you await a future within an async block or function is a place that async block or function may get paused and resumed. -> Note: Many other languages use the `async` and `await` keywords for async -> programming. If you are familiar with other languages’ approach to async, you -> may notice some significant differences in how Rust does things, including how -> it handles the syntax. That is for good reason, as we will see! +Some other languages also use `async` and `await` keywords for async +programming. If you are familiar with those languages, you may notice some +significant differences in how Rust does things, including how it handles the +syntax. That is for good reason, as we will see! + +Most of the time when writing async Rust, we use the `async` and `await` +keywords. Rust compiles them into equivalent code using the `Future` trait, much +like it compiles `for` loops into equivalent code using the `Iterator` trait. +Because Rust provides the `Future` trait, though, you can also implement it for +your own data types when you need to. Many of the functions we will see +throughout this chapter return types with their own implementations of `Future`. +We will return to the definition of the trait at the end of the chapter and dig +into more of how it works, but this is enough detail to keep us moving forward. That may all feel a bit abstract. Let’s write our first async program: a little -web scraper. This will have a fair bit of new syntax, but don’t worry. We will -explain it all as we go. +web scraper. We will pass in two URLs from the command line, fetch both of them +concurrently, and return the result of whichever one finishes first. This +example will have a fair bit of new syntax, but don’t worry. We will explain +everything you need to know as we go. - +### Our First Async Program + +To keep this chapter focused on learning async, rather than juggling parts of +the ecosystem, we have created the `trpl` crate (`trpl` is short for “The Rust +Programming Language”). It re-exports all the types, traits, and functions you +will need, primarily from the [`futures`][futures-crate] and [`tokio`][tokio] +crates. + +- The `futures` crate is an official home for Rust experimentation for async + code, and is actually where the `Future` type was originally designed. + +- Tokio is the most widely used async runtime in Rust today, especially (but + not only!) for web applications. There are other great runtimes out there, + and they may be more suitable for your purposes. We use Tokio under the hood + for `trpl` because it is good and widely used. + +In some cases, `trpl` also renames or wraps the original APIs to let us stay +focused on the details relevant to chapter. If you want to understand what the +crate does, we encourage you to check out [its source code][crate-source]. You +will be able to see what crate each re-export comes from, and we have left +extensive comments explaining what the crate does. + +Go ahead and add the `trpl` crate to your `hello-async` project: + +```console +$ cargo add trpl +``` -Let’s write our first async function, and call it: +Now we can use the various pieces provided by `trpl` to write our first async +program. We will build a little command line tool which fetches two web pages, +pulls the `` element from each, and prints out the title of whichever +finishes that whole process first. -<Listing number="17-1" file-name="src/main.rs" caption="Defining a very simple async function"> +<Listing number="17-1" file-name="src/main.rs" caption="Defining an async function to get the title element from an HTML page"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:all}} +{{#include ../listings/ch17-async-await/listing-17-01/src/main.rs:all}} ``` </Listing> -If we compile and run this… nothing happens, and we get a compiler warning: +In Listing 17-1, we define a function named `page_title`, and we mark it with +the `async` keyword. Then we use the `trpl::get` function to fetch whatever URL +is passed in, and, and we await the response by using the `await` keyword. Then +we get the text of the response by calling its `text` method and once again +awaiting it with the `await` keyword. Both of these steps are asynchronous. For +`get`, we need to wait for the server to send back the first part of its +response, which will include HTTP headers, cookies, and so on. That part of the +response can be delivered separately from the body of the request. Especially if +the body is very large, it can take some time for it all to arrive. Thus, we +have to wait for the *entirety* of the response to arrive, so the `text` method +is also async. + +We have to explicitly await both of these futures, because futures in Rust are +*lazy*: they don’t do anything until you ask them to with `await`. (In fact, +Rust will show a compiler warning if you do not use a future.) This should +remind you of our discussion of iterators [back in Chapter 13][iterators-lazy]. +Iterators do nothing unless you call their `next` method—whether directly, or +using `for` loops or methods like `map` which use `next` under the hood. With +futures, the same basic idea applies: they do nothing unless you explicitly ask +them to. This laziness allows Rust to avoid running async code until it is +actually needed. -```console -{{#include ../listings/ch17-async-await/listing-17-01/output.txt}} -``` +> Note: This is different from the behavior we saw when using `thread::spawn` in +> the previous chapter, where the closure we passed to another thread started +> running immediately. It is also different from how many other languages +> approach async! But it is important for Rust. We will see why that is later. -The warning tells us that just calling `hello` was not enough: we also need to -`.await` or poll the future it returns. This raises some important questions: +Once we have `response_text`, we can then parse it into an instance of the +`Html` type using `Html::parse`. Instead of a raw string, we now have a data +type we can use to work with the HTML as a richer data structure. In particular, +we can use the `select_first` method to find the first instance of a given CSS +selector. By passing the string `"title"`, we will get the first `<title>` +element in the document, if there is one. Since there may not be any matching +element, `select_first` returns an `Option<ElementRef>`. Finally, we use the +`Option::map` method, which lets us work with the item in the `Option` if it is +present, and do nothing if it is not. (We could also use a `match` expression +here, but `map` is more idiomatic.) In the body of the function we supply to +`map`, we call `inner_html` on the `title_element` to get its content, which is +a `String`. When all is said and done, we have an `Option<String>`. + +Notice that Rust’s `await` keyword goes after the expression you are awaiting, +not before it. That is, it is a *postfix keyword*. This may be different from +what you might be used to if you have used async in other languages. Rust chose +this because it makes chains of methods much nicer to work with. As a result, we +can change the body of `page_url_for` to chain the `trpl::get` and `text` +function calls together with `await` between them, as shown in Listing 17-2: + +<Listing number="17-2" file-name="src/main.rs" caption="Chaining with the `await` keyword"> -- Given there is no return type on the function, how is it returning a future? -- What exactly is a future? -- Why do we need to `.await` or poll futures to make them do something? -- How do `.await` and polling relate to each other? +```rust +{{#include ../listings/ch17-async-await/listing-17-02/src/main.rs:chaining}} +``` + +</Listing> -We will work through each of these in turn. We can answer the first question by -learning what the syntax means, so let’s start there. +With that, we have successfully written our first async function! Before we add +some code in `main` to call it, let’s talk a little more about what we have +written and what it means. -### Async Functions +When Rust sees a block marked with the `async` keyword, it compiles it into a +unique, anonymous data type which implements the `Future` trait. When Rust +sees a function marked with `async`, it compiles it into a non-async function +whose body is an async block. Thus, an async function’s return type is the type +of the anonymous data type the compiler creates for that async block. -In Rust, writing `async fn` is equivalent to writing a function which returns a -*future* of the return type. That is, when the compiler sees a function like -`async fn hello` in Listing 17-1, it is equivalent to a function defined like -this instead: +Thus, writing `async fn` is equivalent to writing a function which returns a +*future* of the return type. When the compiler sees a function like `async fn +page_title` in Listing 17-1, it is equivalent to a non-async function defined +like this: ```rust use std::future::Future; -fn hello<'a>(name: &'a str) -> impl Future<Output = ()> + 'a { +fn page_title(url: &str) -> impl Future<Output = Option<String>> + '_ { async move { - let greeting = format!("Hello, {name}!"); - println!("{greeting}"); + let text = trpl::get(url).await.text().await; + Html::parse(&text) + .select_first("title") + .map(|title| title.inner_html()) } } ``` @@ -76,137 +167,90 @@ Let’s walk through each part of the transformed version: * It uses the `impl Trait` syntax we discussed back in the [“Traits as Parameters”][impl-trait] section in Chapter 10. * The returned trait is a `Future`, with an associated type of `Output`. Notice - that the `Output` type is `()`, which is the same as the the original return - type from the `async fn` version of `hello`. + that the `Output` type is `Option<String>`, which is the same as the the + original return type from the `async fn` version of `page_title`. * All of the code called in the body of the original function is wrapped in an `async move` block. Remember that blocks are expressions. This whole block is the expression returned from the function. +* This async block produces a value with the type `Option<String>`, as described + above. That value matches the `Output` type in the return type. This is just + like other blocks you have seen. * The new function body is an `async move` block because of how it uses the - `name` argument. -* The new version of the function makes the lifetime of the `name` parameter - explicit so that it can reference it in the output type. -* The async block itself has the “unit” value `()`, since it ends with a - `println!` statement. That value matches the `Output` type in the return type. - -An `async` block corresponds to a data type which implements the `Future` trait, -and the result of the async block will be the `Output` of the `Future`. Thus, an -`async fn`’s return type is an anonymous data type the compiler creates for us, -which implements `Future`. The associated `Output` type for the `Future` is the -return type of the original `async fn`. Thus, calling `hello` in Listing 17-1 -returned a `Future<Output = ()>`. - -Then Rust warned us that we did not do anything with the future. This is because -futures are *lazy*: they don’t do anything until you ask them to with `await`. -This should remind you of our discussion of iterators [back in Chapter -13][iterators-lazy]. Iterators do nothing unless you call their `next` -method—whether directly, or using `for` loops or methods like `map` which use -`next` under the hood. - -With futures, the same basic idea applies: they do nothing unless you explicitly -ask them to. This laziness allows Rust to avoid running async code until it is -actually needed. - -> Note: This is different from the behavior we saw when using `thread::spawn` in -> the previous chapter, where the closure we passed to another thread started -> running immediately. It is also different from how many other languages -> approach async! But it is important for Rust. We will see why that is later. -<!-- TODO: we need to pay off that promise later in the chapter! --> - -For now, let’s start by awaiting the future returned by `hello` to actually have -it run. Rust’s `await` keyword goes after the expression you are awaiting, not -before it. That is, it is a *postfix keyword*. (This is different from what you -might be used to if you have used async in languages like JavaScript or C#. Rust -chose this because it makes chains of methods much nicer to work with.) In -Listing 17-2, we add `.await` to the `hello` call in `main`. - -<Listing number="17-2" caption="Attempting to fix a compiler warning by awaiting a future" file-name="src/main.rs"> + `name` argument. (We will talk about `async` vs. `async move` much more later + in the chapter.) +* The new version of the function has a kind of lifetime we have not seen before + in the output type: `'_`. Because the function returns a `Future` which refers + to a reference—in this case, the reference from the `url` parameter—we need to + tell Rust that we mean for that reference to be included. We do not have to + name the lifetime here, because Rust is smart enough to know there is only one + reference which could be involved, but we *do* have to be explicit that the + resulting `Future` is bound by that lifetime. + +Now we can call `page_title` in `main`. To start, we will just get the title for +a single page. In Listing 17-3, we follow the same pattern we used for getting +command line arguments back in Chapter 12. Then we pass the first URL +`page_title`, and await the result. Since the value produced by the future is an +`Option<String>`, we use a `match` expression to print different messages to +account for whether the page had a `<title>`. + +<Listing number="17-3" file-name="src/main.rs" caption="Calling the `page_title` function from `main` with a user-supplied argument"> -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-02/src/main.rs:main}} +```rust +{{#include ../listings/ch17-async-await/listing-17-03/src/main.rs:main}} ``` </Listing> -Oh no! We have gone from a compiler warning to an actual error: - -```console -{{#include ../listings/ch17-async-await/listing-17-02/output.txt}} -``` - -This time, the compiler is informing us we cannot use `.await` in `main`, -because `main` is not an `async` function. Your first thought might be to make -`main` an async function then, as in Listing 17-3. - -<Listing number="17-3" caption="Attempting to make `main` an `async fn`" file-name="src/main.rs"> - -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-03/src/main.rs:main}} -``` - -</Listing> +Unfortunately, this does not compile. The only place we can use the `await` +keyword is in async functions or blocks, so Rust will not let us mark `main` as +`async`. -However, we get another compiler error here: +<!-- manual-regeneration +cd listings/ch17-async-await/listing-17-03 +cargo build +copy just the compiler error +--> -```console -{{#include ../listings/ch17-async-await/listing-17-03/output.txt}} +```text +error[E0752]: `main` function is not allowed to be `async` + --> src/main.rs:6:1 + | +6 | async fn main() { + | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` ``` -Rust won't allow us too mark `main` as `async`. The underlying problem is that -async code needs a *runtime*: a Rust crate which manages the details of -executing asynchronous code. A program's `main` function can initialize a -runtime, but it is not a runtime itself. (We will see more about why this is a -bit later.) +The reason is that async code needs a *runtime*: a Rust crate which manages the +details of executing asynchronous code. A program's `main` function can +initialize a runtime, but it is not a runtime itself. (We will see more about +why this is a bit later.) Every async program in Rust has at least one place +where it sets up a runtime and executes the futures. Most languages which support async bundle a runtime with the language. Rust does not. Instead, there are many different async runtimes available, each of which makes different tradeoffs suitable to the use case they target. For example, a high-throughput web server with many CPU cores and a large amount of RAM has very different different needs than a microcontroller with a single core, a -small amount of RAM, and no ability to do heap allocations. - -Every async program in Rust has at least one place where it sets up a runtime -and executes the futures. Those runtimes also often supply async versions of -common functionality like file or network I/O. - -> ### The `trpl` Crate -> -> To keep this chapter focused on learning async, rather than juggling parts of -> the ecosystem, we have created the `trpl` crate (`trpl` is short for “The Rust -> Programming Language”). It re-exports all the types, traits, and functions you -> will need, primarily from the [`futures`][futures-crate] and [`tokio`][tokio] -> crates. -> -> - The `futures` crate is an official home for Rust experimentation for async -> code, and is actually where the `Future` type was originally designed. -> -> - Tokio is the most widely used async runtime in Rust today, especially (but -> not only!) for web applications. There are other great runtimes out there, -> and they may be more suitable for your purposes. We use Tokio under the hood -> for `trpl` because it is good and widely used. -> -> In some cases, `trpl` also renames or wraps the original APIs to let us stay -> focused on the details relevant to chapter. If you want to understand what the -> crate does, we encourage you to check out [its source code][crate-source]. You -> will be able to see what crate each re-export comes from, and we have left -> extensive comments explaining what the crate does. +small amount of RAM, and no ability to do heap allocations. The crates which +provide those runtimes also often supply async versions of common functionality +like file or network I/O. -Go ahead and add the `trpl` crate to your `hello-async` project: - -```console -$ cargo add trpl -``` +Here, and throughout the rest of this chapter, we will use the `run` function +from the `trpl` crate, which takes a future as an argument and runs it to +completion. Behind the scenes, calling `run` sets up a runtime to use to run the +future passed in. Once the future completes, `run` returns whatever value the +future produced. -Then, in our `main` function, let’s wrap the call to `hello` with the -`trpl::run` function, which takes in a `Future` and runs it until it completes. -Since `hello` returns a `Future`, we could simply wrap it directly in -`trpl::run`. However, for most of the examples in the chapter, we will be -doing more than just one async function call, so instead we will pass an `async` -block and explicitly await the result of calling `hello`. +We could pass the future returned by `page_title` directly to `run`. Once it +completed, we would be able to match on the resulting `Option<String>`, the way +we tried to do in Listing 17-3. However, for most of the examples in the chapter +(and most async code in the real world!), we will be doing more than just one +async function call, so instead we will pass an `async` block and explicitly +await the result of calling `page_title`, as in Listing 17-4. -<Listing number="17-4" caption="Using the `run` helper function to wait on a future in non-async code" file-name="src/main.rs"> +<Listing number="17-4" caption="Awaiting an async block with `trpl::run`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:run}} ``` </Listing> @@ -217,44 +261,27 @@ When we run this, we get the behavior we might have expected initially: {{#include ../listings/ch17-async-await/listing-17-04/output.txt}} ``` -Phew: we finally have some working async code! Let’s briefly turn our attention -to how futures actually work. - -A *future* is a data structure which manages the state of some async operation. -It is called a “future” because it represents work which may not be ready now, -but will become ready at some point in the future. (This same concept shows up -in many languages, sometimes under other names like “task” or “promise”.) Rust -provides a `Future` trait as a building block so different async operations can -be implemented with different data structures, but with a common interface. +Phew: we finally have some working async code! This now compiles, and we can run +it. Pick a couple URLs and run the command line tool. You may discover that some +sites are reliably faster than others, while in other cases which site “wins” +varies from run to run. Let’s briefly turn our attention back to how futures +work. -Most of the time when writing async Rust, we use the `async` and `await` -keywords we saw above. Rust compiles them into equivalent code using the -`Future` trait, much like it compiles `for` loops into equivalent code using the -`Iterator` trait. Because Rust provides the `Future` trait, though, you can also -implement it for your own data types when you need to. Many of the functions we -will see throughout this chapter return types with their own implementations of -`Future`. We will return to the definition of the trait at the end of the -chapter and dig into more of how it works, but this is enough detail to keep us -moving forward. - -<!-- TODO: need to introduce/transition with this next paragraph. --> - -Every *await point*—that is, every place where the code explicitly applies the -`await` keyword—represents a place where control gets handed back to the -runtime. To make that work, Rust needs to keep track of the state involved in -the async block, so that the runtime can kick off some other work and then come -back when it is ready to try advancing this one again. This is an invisible -state machine, as if you wrote something like this: +Each *await point*—that is, every place where the code uses the `await` +keyword—represents a place where control gets handed back to the runtime. To +make that work, Rust needs to keep track of the state involved in the async +block, so that the runtime can kick off some other work and then come back when +it is ready to try advancing this one again. This is an invisible state machine, +as if you wrote something like this: ```rust -enum MyAsyncStateMachine { - FirstAwaitPoint { - // the state used up to the first await point... +enum PageTitleFuture<'a> { + GetAwaitPoint { + url: &'a str, }, - SecondAwaitPoint { - // the state used up to the second await point... + TextAwaitPoint { + response: trpl::Response, }, - // etc. for each `.await` point... } ``` @@ -266,24 +293,69 @@ Happily, the compiler also handles checking those for us, and has good error messages. We will work through a few of those later in the chapter! Ultimately, something has to execute that state machine. That something is a -runtime. This is why you may sometimes come across references to *executors* +runtime. (This is why you may sometimes come across references to *executors* when looking into runtimes: an executor is the part of a runtime responsible for -executing the async code. +executing the async code.) Now we can understand why the compiler stopped us from making `main` itself an -async function in Listing 17-3. If `main` were an async function, something else -would need to manage the state machine for whatever future `main` returned, but -main is the starting point for the program! Instead, we use the `trpl::run` -function, which sets up a runtime and polls the `Future` returned by `hello` +async function back in Listing 17-3. If `main` were an async function, something +else would need to manage the state machine for whatever future `main` returned, +but main is the starting point for the program! Instead, we use the `trpl::run` +function, which sets up a runtime and runs the future returned by `page_title` until it returns `Ready`. > Note: some runtimes provide macros to make it so you *can* write an async main > function. Those macros rewrite `async fn main() { ... }` to be a normal `fn -> main` which does the same thing we did by hand in Listing 17-TODO: call a +> main` which does the same thing we did by hand in Listing 17-5: call a > function which runs a future to completion the way `trpl::run` does. -Now that you know the basics of working with futures, we can dig into more of -the things we can *do* with async. +Let’s put these pieces together and see how we can write concurrent code, by +calling `page_title_for` with two different URLs passed in from the command line +and racing it. + +<Listing number="17-5" caption="" file-name="src/main.rs"> + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:all}} +``` + +</Listing> + +In Listing 17-5, we begin by calling `page_title` with both of the user-supplied +URLs. We save the futures produced by calling `page_title` as `title_fut_1` and +`title_fut_2`. Remember, these don’t do anything yet, because futures are lazy, +and we have not yet awaited them. Then we pass the futures `trpl::race`, which +returns a value to indicate which of the futures passed to it finishes first. + +Either future can legitimately “win,” so it does not make sense to return a +`Result`. Instead, `race` returns a type we have not seen before, +`trpl::Either`. The `Either` type is somewhat like a `Result`, in that it has +two cases. Unlike `Result`, though, there is no notion of success or failure +baked into `Either`. Instead, it uses `Left` and `Right` to indicate “one or the +other”. + +```rust +enum Either<A, B> { + Left(A), + Right(B) +} +``` + +The `race` function returns `Left` if the first argument finishes first, with +that future’s output, and `Right` with the second future argument’s output if +*that* one finishes first. This matches the order the arguments appear when +calling the function: the first argument is to the left of the second argument. + +We also update `page_title_for` to return the same URL passed in. That way, if +the page which returns first does not have a `<title>` we can resolve, we can +still print a meaningful message. With that information available, we wrap up by +updating our `println!` output to indicate both which URL finished first and +what the `<title>` was for the web page at that URL, if any. + +You have built a small working web scraper now, which we could extend in a bunch +of different directions. More importantly, you have learned the basics of +working with futures, so we can now dig into even more of the things we can *do* +with async. [impl-trait]: ch10-02-traits.html#traits-as-parameters [iterators-lazy]: ch13-02-iterators.html diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 98a4e393d9..9449910c3e 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -17,12 +17,12 @@ The first task we tackled in Chapter 16 was counting up on two separate threads. Let’s do the same using async. The `trpl` crate supplies a `spawn_task` function which looks very similar to the `thread::spawn` API, and a `sleep` function which is an async version of the `thread::sleep` API. We can use these together -to implement the same counting example as with threads, in Listing 17-5. +to implement the same counting example as with threads, in Listing 17-6. -<Listing number="17-5" caption="Using `spawn_task` to count with two" file-name="src/main.rs"> +<Listing number="17-6" caption="Using `spawn_task` to count with two" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-06/src/main.rs:all}} ``` </Listing> @@ -64,14 +64,14 @@ finishes, because the task spawned by `spawn_task` is shut down when the main function ends. If you want to run all the way to the completion of the task, you will need to use a join handle to wait for the first task to complete. With threads, we used the `join` method to “block” until the thread was done running. -In Listing 17-6, we can use `await` to do the same thing, because the task +In Listing 17-7, we can use `await` to do the same thing, because the task handle itself is a future. Its `Output` type is a `Result`, so we also unwrap it after awaiting it. -<Listing number="17-6" caption="Using `.await` with a join handle to run a task to completion" file-name="src/main.rs"> +<Listing number="17-7" caption="Using `.await` with a join handle to run a task to completion" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-06/src/main.rs:handle}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-07/src/main.rs:handle}} ``` </Listing> @@ -112,15 +112,15 @@ In Chapter 16, we showed how to use the `join` method on the `JoinHandle` type returned when you call `std::thread::spawn`. The `trpl::join` function is similar, but for futures. When you give it two futures, it produces a single new future whose output is a tuple with the output of each of the futures you passed -in once *both* complete. Thus, in Listing 17-7, we use `trpl::join` to wait for +in once *both* complete. Thus, in Listing 17-8, we use `trpl::join` to wait for both `fut1` and `fut2` to finish. We do *not* await `fut1` and `fut2`, but instead the new future produced by `trpl::join`. We ignore the output, because it is just a tuple with two unit values in it. -<Listing number="17-7" caption="Using `trpl::join` to await two anonymous futures" file-name="src/main.rs"> +<Listing number="17-8" caption="Using `trpl::join` to await two anonymous futures" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-07/src/main.rs:join}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:join}} ``` </Listing> @@ -175,14 +175,14 @@ each case *before* running the code! Sharing data between futures will also be familiar: we will use message passing again, but this with async versions of the types and functions. We will take a slightly different path than we did in Chapter 16, to illustrate some of the key -differences between thread-based and futures-based concurrency. In Listing 17-8, +differences between thread-based and futures-based concurrency. In Listing 17-9, we will begin with just a single async block—*not* spawning a separate task like we spawned a separate thread. -<Listing number="17-8" caption="Creating an async channel and assigning the two halves to `tx` and `rx`" file-name="src/main.rs"> +<Listing number="17-9" caption="Creating an async channel and assigning the two halves to `tx` and `rx`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:channel}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:channel}} ``` </Listing> @@ -216,14 +216,14 @@ in the listing happens in sequence, just as it would if there were no futures involved. Let’s address the first part by sending a series of messages, and sleep in -between them, as shown in Listing 17-9: +between them, as shown in Listing 17-10: <!-- We cannot test this one because it never stops! --> -<Listing number="17-9" caption="Sending and receiving multiple messages over the async channel and sleeping with an `.await` between each message" file-name="src/main.rs"> +<Listing number="17-10" caption="Sending and receiving multiple messages over the async channel and sleeping with an `.await` between each message" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:many-messages}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:many-messages}} ``` </Listing> @@ -269,7 +269,7 @@ delay, rather than coming in with delays in between each one. Within a given async block, the order that `.await` keywords appear in the code is also the order they happen when running the program. -There is only one async block in Listing 17-9, so everything in it runs +There is only one async block in Listing 17-10, so everything in it runs linearly. There is still no concurrency. All the `tx.send` calls happen, interspersed with all of the `trpl::sleep` calls and their associated await points. Only then does the `while let` loop get to go through any of the @@ -285,15 +285,15 @@ trying *not* to do. <!-- We cannot test this one because it never stops! --> -<Listing number="17-10" caption="Separating `send` and `recv` into their own `async` blocks and awaiting the futures for those blocks" file-name="src/main.rs"> +<Listing number="17-11" caption="Separating `send` and `recv` into their own `async` blocks and awaiting the futures for those blocks" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:futures}} ``` </Listing> -With the updated code in Listing 17-10, the messages get printed at +With the updated code in Listing 17-11, the messages get printed at 500-millisecond intervals, rather than all in a rush after two seconds. The program still never exits, though, because of the way `while let` loop @@ -326,20 +326,20 @@ in Chapter 16, we saw that we often need to use move data into closures when working with threads. The same basic dynamics apply to async blocks, so the `move` keyword works with async blocks just like it does with closures. -In Listing 17-11, we change the async block for sending messages from a plain +In Listing 17-12, we change the async block for sending messages from a plain `async` block to an `async move` block. When we run *this* version of the code, it shuts down gracefully after the last message is sent and received. -<Listing number="17-11" caption="A working example of sending and receiving messages between futures which correctly shuts down when complete" file-name="src/main.rs"> +<Listing number="17-12" caption="A working example of sending and receiving messages between futures which correctly shuts down when complete" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:with-move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:with-move}} ``` </Listing> This async channel is also a multiple-producer channel, so we can call `clone` -on `tx` if we want to send messages from multiple futures. In Listing 17-12, we +on `tx` if we want to send messages from multiple futures. In Listing 17-13, we clone `tx`, creating `tx1` outside the first async block. We move `tx1` into that block just as we did before with `tx`. Then, later, we move the original `tx` into a *new* async block, where we send more messages on a slightly slower @@ -352,10 +352,10 @@ that both `tx` and `tx1` get dropped when those blocks finish. Otherwise we will end up back in the same infinite loop we started out in. Finally, we switch from `trpl::join` to `trpl::join3` to handle the additional future. -<Listing number="17-12" caption="Using multiple producers with async blocks" file-name="src/main.rs"> +<Listing number="17-13" caption="Using multiple producers with async blocks" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} ``` </Listing> diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 1ed95f14cc..d4dddb636e 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -5,13 +5,13 @@ also had to switch from using `join` to using `join3`. It would be annoying to have to call a different function every time we changed the number of futures we wanted to join. Happily, we have a macro form of `join` to which we can pass an arbitrary number of arguments. It also handles awaiting the futures itself. -Thus, we could rewrite the code from Listing 17-12 to use `join!` instead of -`join3`, as in Listing 17-13: +Thus, we could rewrite the code from Listing 17-13 to use `join!` instead of +`join3`, as in Listing 17-14: -<Listing number="17-13" caption="Using `join!` to wait for multiple futures" file-name="src/main.rs"> +<Listing number="17-14" caption="Using `join!` to wait for multiple futures" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} ``` </Listing> @@ -28,10 +28,10 @@ implements the `Iterator` trait, which we learned about back in Chapter 13, so it seems like just the ticket. Let’s try putting our futures in a vector, and replace `join!` with `join_all`. -<Listing number="17-14" caption="Storing anonymous futures in a vector and calling `join_all`"> +<Listing number="17-15" caption="Storing anonymous futures in a vector and calling `join_all`"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-16/src/main.rs:here}} ``` </Listing> @@ -39,7 +39,7 @@ replace `join!` with `join_all`. Unfortunately, this does not compile. Instead, we get this error: <!-- manual-regeneration -cd listings/ch17-async-await/listing-17-14/ +cd listings/ch17-async-await/listing-17-16/ cargo build copy just the compiler error --> @@ -98,12 +98,12 @@ implement the `Future` trait. > they will all be until runtime. We start by wrapping each of the futures in the `vec!` in a `Box::new`, as shown -in Listing 17-15. +in Listing 17-16. -<Listing number="17-15" caption="Trying to use `Box::new` to align the types of the futures in a `Vec`" file-name="src/main.rs"> +<Listing number="17-16" caption="Trying to use `Box::new` to align the types of the futures in a `Vec`" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-17/src/main.rs:here}} ``` </Listing> @@ -113,12 +113,12 @@ error we did before, but we get one for both the second and third `Box::new` calls, and we also get new errors referring to the `Unpin` trait. We will come back to the `Unpin` errors in a moment. First, let’s fix the type errors on the `Box::new` calls, by explicitly providing the type of `futures` as a trait -object (Listing 17-16). +object (Listing 17-17). -<Listing number="17-16" caption="Fixing the rest of the type mismatch errors by using an explicit type declaration" file-name="src/main.rs"> +<Listing number="17-17" caption="Fixing the rest of the type mismatch errors by using an explicit type declaration" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-16/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-18/src/main.rs:here}} ``` </Listing> @@ -136,7 +136,7 @@ the errors mentioning `Unpin`. Although there are three of them, notice that each is very similar in its contents. <!-- manual-regeneration -cd listings/ch17-async-await/listing-17-16 +cd listings/ch17-async-await/listing-17-18 cargo build copy *only* the errors --> @@ -207,14 +207,14 @@ tell us that the first async block (`src/main.rs:8:23: 20:10`) does not implement the `Unpin` trait, and suggests using `pin!` or `Box::pin` to resolve it. Later in the chapter, we will dig into a few more details about `Pin` and `Unpin`. For the moment, though, we can just follow the compiler’s advice to get -unstuck! In Listing 17-17, we start by updating the type annotation for +unstuck! In Listing 17-18, we start by updating the type annotation for `futures`, with a `Pin` wrapping each `Box`. Second, we use `Box::pin` to pin the futures themselves. -<Listing number="17-17" caption="Using `Pin` and `Box::pin` to make the `Vec` type check" file-name="src/main.rs"> +<Listing number="17-18" caption="Using `Pin` and `Box::pin` to make the `Vec` type check" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-17/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} ``` </Listing> @@ -251,25 +251,25 @@ However, we must still be explicit about the type of the pinned reference; otherwise Rust will still not know to interpret these as dynamic trait objects, which is what we need them to be in the `Vec`. We therefore `pin!` each future when we define it, and define `futures` as a `Vec` containing pinned mutable -references to the dynamic `Future` type, as in Listing 17-18. +references to the dynamic `Future` type, as in Listing 17-19. -<Listing number="17-18" caption="Using `Pin` directly with the `pin!` macro to avoid unnecessary heap allocations" file-name="src/main.rs"> +<Listing number="17-19" caption="Using `Pin` directly with the `pin!` macro to avoid unnecessary heap allocations" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-18/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} ``` </Listing> We got this far by ignoring the fact that we might have different `Output` -types. For example, in Listing 17-19, the anonymous future for `a` implements +types. For example, in Listing 17-20, the anonymous future for `a` implements `Future<Output = u32>`, the anonymous future for `b` implements `Future<Output = &str>`, and the anonymous future for `c` implements `Future<Output = bool>`. -<Listing number="17-19" caption="Three futures with distinct types" file-name="src/main.rs"> +<Listing number="17-20" caption="Three futures with distinct types" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:here}} ``` </Listing> @@ -299,16 +299,19 @@ that reason. > function can do a lot of things that `trpl::race` function cannot, but it also > has some additional complexity that we can skip over for now. -In Listing 17-20, we use `trpl::race` to run two futures, `slow` and `fast`, +In Listing 17-21, we use `trpl::race` to run two futures, `slow` and `fast`, against each other. Each one prints a message when it starts running, pauses for some amount of time by calling and awaiting `sleep`, and then prints another message when it finishes. Then we pass both to `trpl::race` and wait for one of -them to finish. (The outcome here won’t be too surprising: `fast` wins!) +them to finish. (The outcome here won’t be too surprising: `fast` wins!) Note +that unlike the first time we used `race` back in [Our First Async +Program][async-program], we just ignore the `Either` instance it returns here, +because all of the interesting behavior happens in the body of the async blocks. -<Listing number="17-20" caption="Using `race` to get the result of whichever future finishes first" file-name="src/main.rs"> +<Listing number="17-21" caption="Using `race` to get the result of whichever future finishes first" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:here}} ``` </Listing> @@ -344,28 +347,28 @@ But *how* would you hand control back to the runtime in those cases? ### Yielding -Let’s simulate a long-running operation. Listing 17-21 introduces a `slow` +Let’s simulate a long-running operation. Listing 17-22 introduces a `slow` function. It uses `std::thread::sleep` instead of `trpl::sleep` so that calling `slow` will block the current thread for some number of milliseconds. We can use `slow` to stand in for real-world operations which are both long-running and blocking. -<Listing number="17-21" caption="Using `thread::sleep` to simulate slow operations" file-name="src/main.rs"> +<Listing number="17-22" caption="Using `thread::sleep` to simulate slow operations" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:slow}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:slow}} ``` </Listing> -In Listing 17-22, we use `slow` to emulate doing this kind of CPU-bound work in +In Listing 17-23, we use `slow` to emulate doing this kind of CPU-bound work in a pair of futures. To begin, each future only hands control back to the runtime *after* carrying out a bunch of slow operations. -<Listing number="17-22" caption="Using `thread::sleep` to simulate slow operations" file-name="src/main.rs"> +<Listing number="17-23" caption="Using `thread::sleep` to simulate slow operations" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:slow-futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:slow-futures}} ``` </Listing> @@ -373,7 +376,7 @@ a pair of futures. To begin, each future only hands control back to the runtime If you run this, you will see this output: <!-- manual-regeneration -cd listings/ch17-async-await/listing-17-22/ +cd listings/ch17-async-await/listing-17-24/ cargo run copy just the output --> @@ -399,24 +402,24 @@ completes. To allow both futures to make progress between their slow tasks, we need await points so we can hand control back to the runtime. That means we need something we can await! -We can already see this kind of handoff happening in Listing 17-22: if we +We can already see this kind of handoff happening in Listing 17-23: if we removed the `trpl::sleep` at the end of the `a` future, it would complete without the `b` future running *at all*. Maybe we could use the `sleep` function as a starting point? -<Listing number="17-23" caption="Using `sleep` to let operations switch off making progress" file-name="src/main.rs"> +<Listing number="17-24" caption="Using `sleep` to let operations switch off making progress" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:here}} ``` </Listing> -In Listing 17-23, we add `trpl::sleep` calls with await points between each call +In Listing 17-24, we add `trpl::sleep` calls with await points between each call to `slow`. Now the two futures’ work is interleaved: <!-- manual-regeneration -cd listings/ch17-async-await/listing-17-23/ +cd listings/ch17-async-await/listing-17-25/ cargo run copy just the output --> @@ -441,13 +444,13 @@ however makes the most sense to us. We do not really want to *sleep* here, though: we want to make progress as fast as we can. We just need to hand back control to the runtime. We can do that -directly, using the `yield_now` function. In Listing 17-24, we replace all those +directly, using the `yield_now` function. In Listing 17-25, we replace all those `sleep` calls with `yield_now`. -<Listing number="17-24" caption="Using `yield_now` to let operations switch off making progress" file-name="src/main.rs"> +<Listing number="17-25" caption="Using `yield_now` to let operations switch off making progress" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:yields}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:yields}} ``` </Listing> @@ -460,17 +463,17 @@ example, will always sleep for at least a millisecond, even if we pass it a lot in one millisecond! You can see this for yourself by setting up a little benchmark, like the one in -Listing 17-25. (This is not an especially rigorous way to do performance +Listing 17-26. (This is not an especially rigorous way to do performance testing, but it suffices to show the difference here.) Here, we skip all the status printing, pass a one-nanosecond `Duration` to `trpl::sleep`, and let each future run by itself, with no switching between the futures. Then we run for 1,000 iterations and see how long the future using `trpl::sleep` takes compared to the future using `trpl::yield_now`. -<Listing number="17-25" caption="Comparing the performance of `sleep` and `yield_now`" file-name="src/main.rs"> +<Listing number="17-26" caption="Comparing the performance of `sleep` and `yield_now`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:here}} ``` </Listing> @@ -500,13 +503,13 @@ build a `timeout` function with async building blocks we already have. When we are done, the result will be another building block we could use to build up yet further async abstractions. -Listing 17-26 shows how we would expect this `timeout` to work with a slow +Listing 17-27 shows how we would expect this `timeout` to work with a slow future. -<Listing number="17-26" caption="Using our imagined `timeout` to run a slow operation with a time limit" file-name="src/main.rs"> +<Listing number="17-27" caption="Using our imagined `timeout` to run a slow operation with a time limit" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:here}} ``` </Listing> @@ -523,14 +526,14 @@ Let’s implement this! To begin, let’s think about the API for `timeout`: elapses first, the `Result` will be `Err` with the duration that the timeout waited for. -Listing 17-27 shows this declaration. +Listing 17-28 shows this declaration. <!-- This is not tested because it intentionally does not compile. --> -<Listing number="17-27" caption="Defining the signature of `timeout`" file-name="src/main.rs"> +<Listing number="17-28" caption="Defining the signature of `timeout`" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:declaration}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:declaration}} ``` </Listing> @@ -540,28 +543,6 @@ need: we want to race the future passed in against the duration. We can use `trpl::sleep` to make a timer future from the duration, and use `trpl::race` to run that timer with the future the caller passes in. -The `trpl::race` function returns a value to indicate which of the futures -passed to it finishes first. (When we saw `race` earlier in Listing 17-20, we -ignored its return value, because we were only interested in seeing the behavior -of `fast` and `slow` when we ran the program.) Either future can legitimately -“win,” so it does not make sense to return a `Result`. Instead, `race` returns a -type we have not seen before, `trpl::Either`. The `Either` type is somewhat like -a `Result`, in that it has two cases. Unlike `Result`, though, there is no -notion of success or failure baked into `Either`. Instead, it uses `Left` and -`Right` to indicate “one or the other”. - -```rust -enum Either<A, B> { - Left(A), - Right(B) -} -``` - -The `race` function returns `Left` if the first argument finishes first, with -that future’s output, and `Right` with the second future argument’s output if -*that* one finishes first. This matches the order the arguments appear when -calling the function: the first argument is to the left of the second argument. - We also know that `race` is not fair, and polls arguments in the order they are passed. Thus, we pass `future_to_try` to `race` first so it gets a chance to complete even if `max_time` is a very short duration. If `future_to_try` @@ -569,15 +550,15 @@ finishes first, `race` will return `Left` with the output from `future`. If `timer` finishes first, `race` will return `Right` with the timer’s output of `()`. -In Listing 17-28, we match on the result of awaiting `trpl::race`. If the +In Listing 17-29, we match on the result of awaiting `trpl::race`. If the `future_to_try` succeeded and we get a `Left(output)`, we return `Ok(output)`. If the sleep timer elapsed instead and we get a `Right(())`, we ignore the `()` with `_` and return `Err(max_time)` instead. -<Listing number="17-28" caption="Defining `timeout` with `race` and `sleep`" file-name="src/main.rs"> +<Listing number="17-29" caption="Defining `timeout` with `race` and `sleep`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:implementation}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-30/src/main.rs:implementation}} ``` </Listing> @@ -617,3 +598,4 @@ to consider first, though: [collections]: ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: ch12-03-improving-error-handling-and-modularity.html [futures]: ch17-01-futures-and-syntax.html#what-are-futures +[async-program]: ch17-01-futures-and-syntax.html#our-first-async-program diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 3510aa4164..674f52a7d5 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -20,12 +20,12 @@ though, a general-purpose stream API needs to be much more general: it will just provide the next item like `Iterator` does, but asynchronously. In fact, this is roughly how it works in Rust, so we can actually create a stream from any iterator. As with an iterator, we can work with a stream by calling its `next` -method, and then awaiting the output, as in Listing 17-29. +method, and then awaiting the output, as in Listing 17-30. -<Listing number="17-29" caption="Creating a stream from an iterator and printing its values" file-name="src/main.rs"> +<Listing number="17-30" caption="Creating a stream from an iterator and printing its values" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:stream}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs:stream}} ``` </Listing> @@ -40,7 +40,7 @@ can see in the output, it reports that there is no `next` method available. <!-- TODO: fix up the path here? --> <!-- manual-regeneration -cd listings/chapter-17-async-await/listing-17-29 +cd listings/chapter-17-async-await/listing-17-31 cargo build copy only the error output --> @@ -52,7 +52,7 @@ error[E0599]: no method named `next` found for struct `Iter` in the current scop 8 | while let Some(value) = stream.next().await { | ^^^^ | - = note: the full type name has been written to '/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-29/target/debug/deps/async_await-bbd5bb8f6851cb5f.long-type-18426562901668632191.txt' + = note: the full type name has been written to '/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-31/target/debug/deps/async_await-bbd5bb8f6851cb5f.long-type-18426562901668632191.txt' = note: consider using `--verbose` to print the full type name to the console = help: items from traits can only be used if the trait is in scope help: the following traits which provide `next` are implemented but not in scope; perhaps you want to import one of them @@ -89,25 +89,25 @@ return to the `Stream` and `StreamExt` traits in a bit more detail at the end of the chapter. For now, this is enough to let us keep moving. All we need to do here is add a `use` statement for `trpl::StreamExt`, as in -Listing 17-30. +Listing 17-31. -<Listing number="17-30" caption="Successfully using an iterator as the basis for a stream" file-name="src/main.rs"> +<Listing number="17-31" caption="Successfully using an iterator as the basis for a stream" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-30/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs}} ``` </Listing> With all those pieces put together, things work the way we want! What is more, now that we have `StreamExt` in scope, we can use all of its utility methods, -just like with iterators. For example, in Listing 17-31, we use the `filter` +just like with iterators. For example, in Listing 17-32, we use the `filter` method to filter out everything but multiples of three and five. -<Listing number="17-31" caption="Filtering a `Stream` with the `StreamExt::filter` method" file-name="src/main.rs"> +<Listing number="17-32" caption="Filtering a `Stream` with the `StreamExt::filter` method" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-33/src/main.rs}} ``` </Listing> @@ -129,7 +129,7 @@ avoid doing needless work. Let’s start by building a little stream of messages, similar to what we might see from a WebSocket or other real-time communication protocols. In Listing -17-32, we create a function `get_messages` which returns `impl Stream<Item = +17-33, we create a function `get_messages` which returns `impl Stream<Item = String>`. For its implementation, we create an async channel, loop over the first ten letters of the English alphabet, and send them across the channel. @@ -137,10 +137,10 @@ We also use a new type: `ReceiverStream`, which converts the `rx` receiver from the `trpl::channel` into a `Stream` with a `next` method. Back in `main`, we use a `while let` loop to print all the messages from the stream. -<Listing number="17-32" caption="Using the `rx` receiver as a `ReceiverStream`" file-name="src/main.rs"> +<Listing number="17-33" caption="Using the `rx` receiver as a `ReceiverStream`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-34/src/main.rs:all}} ``` </Listing> @@ -168,7 +168,7 @@ We could do this with the regular `Receiver` API, or even the regular `Iterator` API, though. Let’s add something that requires streams, like adding a timeout which applies to every item in the stream, and a delay on the items we emit. -In Listing 17-33, we start by adding a timeout to the stream with the `timeout` +In Listing 17-34, we start by adding a timeout to the stream with the `timeout` method, which comes from the `StreamExt` trait. Then we update the body of the `while let` loop, because the stream now returns a `Result`. The `Ok` variant indicates a message arrived in time; the `Err` variant indicates that the @@ -178,10 +178,10 @@ timeout. Finally, notice that we pin the messages after applying the timeout to them, because the timeout helper produces a future which needs to be pinned to be polled. -<Listing number="17-33" caption="Using the `StreamExt::timeout` method to set a time limit on the items in a stream" file-name="src/main.rs"> +<Listing number="17-34" caption="Using the `StreamExt::timeout` method to set a time limit on the items in a stream" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-33/src/main.rs:timeout}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-35/src/main.rs:timeout}} ``` </Listing> @@ -195,10 +195,10 @@ and a 300 millisecond delay to odd-index items, to simulate the different delays we might see from a stream of messages in the real world. Because our timeout is for 200 milliseconds, this should affect half of the messages. -<Listing number="17-34" caption="Sending messages through `tx` with an async delay without making `get_messages` an async function" file-name="src/main.rs"> +<Listing number="17-35" caption="Sending messages through `tx` with an async delay without making `get_messages` an async function" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-34/src/main.rs:messages}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-36/src/main.rs:messages}} ``` </Listing> @@ -230,7 +230,7 @@ Now our code has a much more interesting result! Between every other pair of messages, we see an error reported: `Problem: Elapsed(())`. <!-- manual-regeneration -cd listings/listing-17-34 +cd listings/listing-17-36 cargo run copy only the program output, *not* the compiler output --> @@ -274,7 +274,7 @@ are going to send back the count of intervals which has elapsed, so the return type will be `impl Stream<Item = u32>`, and we can call the function `get_intervals`. -In Listing 17-35, we start by defining a `count` in the task. (We could define +In Listing 17-36, we start by defining a `count` in the task. (We could define it outside the task, too, but it is clearer to limit the scope of any given variable.) Then we create a an infinite loop. Each iteration of the loop asynchronously sleeps for one millisecond, increments the count, and then sends @@ -282,10 +282,10 @@ it over the channel. Since this is all wrapped in the task created by `spawn_task`, all of it will get cleaned up along with the runtime, including the infinite loop. -<Listing number="17-35" caption="Creating a stream with a counter that will be emitted once every millisecond" file-name="src/main.rs"> +<Listing number="17-36" caption="Creating a stream with a counter that will be emitted once every millisecond" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-35/src/main.rs:intervals}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:intervals}} ``` </Listing> @@ -298,12 +298,12 @@ at least one await point in each iteration through the loop. Back in our main function’s async block, we start by calling `get_intervals`. Then we merge the `messages` and `intervals` streams with the `merge` method. Finally, we loop over that combined stream instead of over `messages` (Listing -17-36). +17-37). -<Listing number="17-36" caption="Attempting to merge streams of messages and intervals" file-name="src/main.rs"> +<Listing number="17-37" caption="Attempting to merge streams of messages and intervals" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-36/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-38/src/main.rs:main}} ``` </Listing> @@ -318,7 +318,7 @@ for a `timeout` call. Meanwhile, the `intervals` stream has the type `impl Stream<Item = u32>`. To merge these two streams, we need to transform one of them to match the other. -In Listing 17-37, we rework with the `intervals` stream, since `messages` is +In Listing 17-38, we rework with the `intervals` stream, since `messages` is already in the basic format we want and has to handle timeout errors. First, we can use the `map` helper method to transform the `intervals` into a string. Second, we need to match the `Timeout` from `messages`. Since we do not actually @@ -330,10 +330,10 @@ stream, and pin it so that it is safe to do so. <!-- We cannot directly test this one, because it never stops. --> -<Listing number="17-37" caption="Aligning the types of the the `intervals` stream with the type of the `messages` stream" file-name="src/main.rs"> +<Listing number="17-38" caption="Aligning the types of the the `intervals` stream with the type of the `messages` stream" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-39/src/main.rs:main}} ``` </Listing> @@ -361,7 +361,7 @@ Interval: 43 --snip-- ``` -Listing 17-38 shows one way to solve these last two problems. First, we use the +Listing 17-39 shows one way to solve these last two problems. First, we use the `throttle` method on the `intervals` stream, so that it does not overwhelm the `messages` stream. Throttling is a way of limiting the rate at which a function will be called—or, in this case, how often the stream will be polled. Once every @@ -372,10 +372,10 @@ To limit the number of items we will accept from a stream, we can use the `take` method. We apply it to the *merged* stream, because we want to limit the final output, not just one stream or the other. -<Listing number="17-38" caption="Using `throttle` and `take` to manage the merged streams" file-name="src/main.rs"> +<Listing number="17-39" caption="Using `throttle` and `take` to manage the merged streams" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-38/src/main.rs:throttle}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:throttle}} ``` </Listing> @@ -393,7 +393,7 @@ never produce those interval messages in the first place! This is the inherent performance characteristics. <!-- manual-regeneration -cd listings/listing-17-38 +cd listings/listing-17-40 cargo run copy and paste only the program output --> @@ -426,15 +426,15 @@ channel-based streams, the `send` calls could fail when the other side of the channel closes—and that is just a matter of how the runtime executes the futures which make up the stream. Up till now we have ignored this by calling `unwrap`, but in a well-behaved app, we should explicitly handle the error, at minimum by -ending the loop so we do not try to send any more messages! Listing 17-39 shows +ending the loop so we do not try to send any more messages! Listing 17-40 shows a simple error strategy: print the issue and then `break` from the loops. As usual, the correct way to handle a message send error will vary—just make sure you have a strategy. -<Listing number="17-39" caption="Handling errors and shutting down the loops"> +<Listing number="17-40" caption="Handling errors and shutting down the loops"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-39/src/main.rs:errors}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-41/src/main.rs:errors}} ``` </Listing> diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 9eb31d2fa4..0a5ee1f89e 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -115,11 +115,11 @@ it is not yet ready. <!-- TODO: get a *very* careful technical review of this section! --> -When we introduced the idea of pinning, while working on Listing 17-16, we ran +When we introduced the idea of pinning, while working on Listing 17-17, we ran into a very gnarly error message. Here is the relevant part of it again: <!-- manual-regeneration -cd listings/ch17-async-await/listing-17-16 +cd listings/ch17-async-await/listing-17-18 cargo build copy *only* the final `error` block from the errors --> diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index ad3a4d24da..3753120192 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -24,15 +24,15 @@ is managed by library-level code: the runtime. In the previous section, we saw that we could build a `Stream` by using an async channel and spawning an async task which we could call from synchronous code. We -could do the exact same thing with a thread! In Listing 17-39, we used -`trpl::spawn_task` and `trpl::sleep`. In Listing 17-40, we replace those with +could do the exact same thing with a thread! In Listing 17-40, we used +`trpl::spawn_task` and `trpl::sleep`. In Listing 17-41, we replace those with the `thread::spawn` and `thread::sleep` APIs from the standard library in the `get_intervals` function. -<Listing number="17-40" caption="Using the `std::thread` APIs instead of the async `trpl` APIs for the `get_intervals` function" file-name="src/main.rs"> +<Listing number="17-41" caption="Using the `std::thread` APIs instead of the async `trpl` APIs for the `get_intervals` function" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:threads}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-41/src/main.rs:threads}} ``` </Listing> From 573a6ca4bafb8f72ab867a2071ccece6478b8600 Mon Sep 17 00:00:00 2001 From: Chris Krycho <hello@chriskrycho.com> Date: Fri, 20 Sep 2024 15:42:27 -0600 Subject: [PATCH 24/25] Ch. 17: fix mdbook test output This gets CI working again. The problem was basically a mix of a few silly mistakes: - Using `include` instead of `rustdoc_include` in several places. - Having rewritten the listing numbers incorrectly. --- Cargo.lock | 1866 ++--------------- Cargo.toml | 2 +- README.md | 3 +- .../ch17-async-await/listing-17-01/Cargo.lock | 14 +- .../ch17-async-await/listing-17-01/Cargo.toml | 2 +- .../ch17-async-await/listing-17-02/Cargo.lock | 14 +- .../ch17-async-await/listing-17-02/Cargo.toml | 2 +- .../ch17-async-await/listing-17-03/Cargo.toml | 2 +- .../ch17-async-await/listing-17-04/Cargo.toml | 2 +- .../ch17-async-await/listing-17-05/Cargo.toml | 2 +- .../ch17-async-await/listing-17-42/Cargo.lock | 1860 ++++++++++++++++ .../ch17-async-await/listing-17-42/Cargo.toml | 8 + .../listing-17-42/src/main.rs | 22 + src/ch17-01-futures-and-syntax.md | 21 +- src/ch17-02-concurrency-with-async.md | 8 +- src/ch17-03-more-futures.md | 36 +- src/ch17-04-streams.md | 30 +- src/ch17-06-futures-tasks-threads.md | 21 +- 18 files changed, 2101 insertions(+), 1814 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-42/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-42/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-42/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 21c0d5e8a8..493ab8e687 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,1806 +2,278 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "cc" -version = "1.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" -dependencies = [ - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "crc32fast" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "cssparser" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "phf 0.11.2", - "smallvec", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "docopt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" -dependencies = [ - "lazy_static", - "regex", - "serde", - "strsim", -] - -[[package]] -name = "dtoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" - -[[package]] -name = "dtoa-short" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" -dependencies = [ - "dtoa", -] - -[[package]] -name = "ego-tree" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" - -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "fastrand" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" - -[[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", -] - -[[package]] -name = "flate2" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "getrandom" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "h2" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "html5ever" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" -dependencies = [ - "log", - "mac", - "markup5ever", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "ipnet" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.153" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] -name = "listing-scraper-01" -version = "0.1.0" -dependencies = [ - "trpl", -] - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - -[[package]] -name = "markup5ever" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" -dependencies = [ - "log", - "phf 0.11.2", - "phf_codegen 0.11.2", - "string_cache", - "string_cache_codegen", - "tendril", -] - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi", - "libc", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "object" -version = "0.36.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" - -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.4", - "smallvec", - "windows-targets", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_shared 0.10.0", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", -] - -[[package]] -name = "phf_codegen" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "proc-macro2" -version = "1.0.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" -dependencies = [ - "bitflags 2.5.0", -] - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - -[[package]] -name = "reqwest" -version = "0.12.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-registry", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rust-book-tools" -version = "0.0.1" -dependencies = [ - "docopt", - "flate2", - "lazy_static", - "regex", - "serde", - "tar", - "walkdir", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.23.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" -dependencies = [ - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" -dependencies = [ - "base64", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scraper" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" -dependencies = [ - "ahash", - "cssparser", - "ego-tree", - "getopts", - "html5ever", - "once_cell", - "selectors", - "tendril", -] - -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "selectors" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" -dependencies = [ - "bitflags 2.5.0", - "cssparser", - "derive_more", - "fxhash", - "log", - "new_debug_unreachable", - "phf 0.10.1", - "phf_codegen 0.10.0", - "precomputed-hash", - "servo_arc", - "smallvec", -] - -[[package]] -name = "serde" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "servo_arc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" -dependencies = [ - "stable_deref_trait", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared 0.10.0", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro2", - "quote", -] +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "strsim" -version = "0.10.0" +name = "aho-corasick" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] [[package]] -name = "subtle" -version = "2.6.1" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "syn" -version = "2.0.59" +name = "bitflags" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] -name = "sync_wrapper" -version = "1.0.1" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "system-configuration" -version = "0.6.1" +name = "crc32fast" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "system-configuration-sys", + "cfg-if", ] [[package]] -name = "system-configuration-sys" -version = "0.6.0" +name = "docopt" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" dependencies = [ - "core-foundation-sys", - "libc", + "lazy_static", + "regex", + "serde", + "strsim", ] [[package]] -name = "tar" -version = "0.4.40" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "filetime", "libc", - "xattr", + "windows-sys", ] [[package]] -name = "tempfile" -version = "3.12.0" +name = "filetime" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", - "fastrand", - "once_cell", - "rustix", - "windows-sys 0.59.0", + "libc", + "redox_syscall", + "windows-sys", ] [[package]] -name = "tendril" -version = "0.4.3" +name = "flate2" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ - "futf", - "mac", - "utf-8", + "crc32fast", + "miniz_oxide", ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "lazy_static" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "tinyvec_macros" -version = "0.1.1" +name = "libc" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "tokio" -version = "1.40.0" +name = "linux-raw-sys" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "windows-sys 0.52.0", -] +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "memchr" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] -name = "tokio-rustls" -version = "0.26.0" +name = "miniz_oxide" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", + "adler", ] [[package]] -name = "tokio-stream" -version = "0.1.16" +name = "proc-macro2" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "unicode-ident", ] [[package]] -name = "tokio-util" -version = "0.7.12" +name = "quote" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", + "proc-macro2", ] [[package]] -name = "tower" -version = "0.4.13" +name = "redox_syscall" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", + "bitflags 1.3.2", ] [[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.40" +name = "regex" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ - "pin-project-lite", - "tracing-core", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "tracing-core" -version = "0.1.32" +name = "regex-automata" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "trpl" -version = "0.1.0" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ - "futures", - "reqwest", - "scraper", - "tokio", - "tokio-stream", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.0" +name = "regex-syntax" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +name = "rust-book-tools" +version = "0.0.1" dependencies = [ - "tinyvec", + "docopt", + "flate2", + "lazy_static", + "regex", + "serde", + "tar", + "walkdir", ] [[package]] -name = "unicode-width" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" +name = "rustix" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "same-file", "winapi-util", ] [[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.93" +name = "serde" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", + "serde_derive", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" +name = "serde_derive" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ - "bumpalo", - "log", - "once_cell", "proc-macro2", "quote", "syn", - "wasm-bindgen-shared", ] [[package]] -name = "wasm-bindgen-futures" -version = "0.4.43" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" +name = "syn" +version = "2.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" dependencies = [ + "proc-macro2", "quote", - "wasm-bindgen-macro-support", + "unicode-ident", ] [[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" +name = "tar" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", + "filetime", + "libc", + "xattr", ] [[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" +name = "unicode-ident" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" [[package]] -name = "web-sys" -version = "0.3.70" +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ - "js-sys", - "wasm-bindgen", + "same-file", + "winapi-util", ] [[package]] @@ -1835,36 +307,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -1874,15 +316,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -1957,30 +390,3 @@ dependencies = [ "linux-raw-sys", "rustix", ] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 5b7ef40548..20fc14643d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = [ "listings/ch17-async-await/listing-scraper-01","packages/tools"] +members = ["packages/tools"] default-members = ["packages/tools"] resolver = "2" exclude = [ diff --git a/README.md b/README.md index 9648db0ae0..b4426bd492 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,8 @@ $ start chrome.exe .\book\index.html # Windows (Cmd) To run the tests: ```bash -$ mdbook test +$ cd packages/trpl +$ mdbook test --library-path packages/trpl/target/debug/deps ``` ## Contributing diff --git a/listings/ch17-async-await/listing-17-01/Cargo.lock b/listings/ch17-async-await/listing-17-01/Cargo.lock index 207879da8f..1109eb84f5 100644 --- a/listings/ch17-async-await/listing-17-01/Cargo.lock +++ b/listings/ch17-async-await/listing-17-01/Cargo.lock @@ -30,6 +30,13 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "async_await" +version = "0.1.0" +dependencies = [ + "trpl", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -579,13 +586,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "listing-scraper-01" -version = "0.1.0" -dependencies = [ - "trpl", -] - [[package]] name = "lock_api" version = "0.4.12" diff --git a/listings/ch17-async-await/listing-17-01/Cargo.toml b/listings/ch17-async-await/listing-17-01/Cargo.toml index 9fad6d6a96..57fe49bfe5 100644 --- a/listings/ch17-async-await/listing-17-01/Cargo.toml +++ b/listings/ch17-async-await/listing-17-01/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "listing-scraper-01" +name = "async_await" version = "0.1.0" edition = "2021" diff --git a/listings/ch17-async-await/listing-17-02/Cargo.lock b/listings/ch17-async-await/listing-17-02/Cargo.lock index cb7d407618..1bd5f08c34 100644 --- a/listings/ch17-async-await/listing-17-02/Cargo.lock +++ b/listings/ch17-async-await/listing-17-02/Cargo.lock @@ -30,6 +30,13 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "async_await" +version = "0.1.0" +dependencies = [ + "trpl", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -579,13 +586,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "listing-scraper-01" -version = "0.1.0" -dependencies = [ - "trpl", -] - [[package]] name = "lock_api" version = "0.4.12" diff --git a/listings/ch17-async-await/listing-17-02/Cargo.toml b/listings/ch17-async-await/listing-17-02/Cargo.toml index 9fad6d6a96..57fe49bfe5 100644 --- a/listings/ch17-async-await/listing-17-02/Cargo.toml +++ b/listings/ch17-async-await/listing-17-02/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "listing-scraper-01" +name = "async_await" version = "0.1.0" edition = "2021" diff --git a/listings/ch17-async-await/listing-17-03/Cargo.toml b/listings/ch17-async-await/listing-17-03/Cargo.toml index 9fad6d6a96..57fe49bfe5 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.toml +++ b/listings/ch17-async-await/listing-17-03/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "listing-scraper-01" +name = "async_await" version = "0.1.0" edition = "2021" diff --git a/listings/ch17-async-await/listing-17-04/Cargo.toml b/listings/ch17-async-await/listing-17-04/Cargo.toml index 9fad6d6a96..57fe49bfe5 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.toml +++ b/listings/ch17-async-await/listing-17-04/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "listing-scraper-01" +name = "async_await" version = "0.1.0" edition = "2021" diff --git a/listings/ch17-async-await/listing-17-05/Cargo.toml b/listings/ch17-async-await/listing-17-05/Cargo.toml index 9fad6d6a96..57fe49bfe5 100644 --- a/listings/ch17-async-await/listing-17-05/Cargo.toml +++ b/listings/ch17-async-await/listing-17-05/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "listing-scraper-01" +name = "async_await" version = "0.1.0" edition = "2021" diff --git a/listings/ch17-async-await/listing-17-42/Cargo.lock b/listings/ch17-async-await/listing-17-42/Cargo.lock new file mode 100644 index 0000000000..35391aee48 --- /dev/null +++ b/listings/ch17-async-await/listing-17-42/Cargo.lock @@ -0,0 +1,1860 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "async_await" +version = "0.1.0" +dependencies = [ + "trpl", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-42/Cargo.toml b/listings/ch17-async-await/listing-17-42/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-42/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "async_await" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +trpl = { path = "../../../packages/trpl" } diff --git a/listings/ch17-async-await/listing-17-42/src/main.rs b/listings/ch17-async-await/listing-17-42/src/main.rs new file mode 100644 index 0000000000..1a508bf582 --- /dev/null +++ b/listings/ch17-async-await/listing-17-42/src/main.rs @@ -0,0 +1,22 @@ +extern crate trpl; // for mdbook test + +// ANCHOR: all +use std::{thread, time::Duration}; + +fn main() { + let (tx, mut rx) = trpl::channel(); + + thread::spawn(move || { + for i in 1..11 { + tx.send(i).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + trpl::run(async { + while let Some(message) = rx.recv().await { + println!("{message}"); + } + }); +} +// ANCHOR_END: all diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index bf7e26bde0..a072263732 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -74,7 +74,7 @@ finishes that whole process first. <Listing number="17-1" file-name="src/main.rs" caption="Defining an async function to get the title element from an HTML page"> ```rust -{{#include ../listings/ch17-async-await/listing-17-01/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:all}} ``` </Listing> @@ -129,7 +129,7 @@ function calls together with `await` between them, as shown in Listing 17-2: <Listing number="17-2" file-name="src/main.rs" caption="Chaining with the `await` keyword"> ```rust -{{#include ../listings/ch17-async-await/listing-17-02/src/main.rs:chaining}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-02/src/main.rs:chaining}} ``` </Listing> @@ -150,7 +150,9 @@ page_title` in Listing 17-1, it is equivalent to a non-async function defined like this: ```rust +# extern crate trpl; // required for mdbook test use std::future::Future; +use trpl::Html; fn page_title(url: &str) -> impl Future<Output = Option<String>> + '_ { async move { @@ -172,7 +174,7 @@ Let’s walk through each part of the transformed version: * All of the code called in the body of the original function is wrapped in an `async move` block. Remember that blocks are expressions. This whole block is the expression returned from the function. -* This async block produces a value with the type `Option<String>`, as described +* This async block produces a value with the type `Option<String>`, as described above. That value matches the `Output` type in the return type. This is just like other blocks you have seen. * The new function body is an `async move` block because of how it uses the @@ -195,8 +197,8 @@ account for whether the page had a `<title>`. <Listing number="17-3" file-name="src/main.rs" caption="Calling the `page_title` function from `main` with a user-supplied argument"> -```rust -{{#include ../listings/ch17-async-await/listing-17-03/src/main.rs:main}} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-03/src/main.rs:main}} ``` </Listing> @@ -249,7 +251,9 @@ await the result of calling `page_title`, as in Listing 17-4. <Listing number="17-4" caption="Awaiting an async block with `trpl::run`" file-name="src/main.rs"> -```rust +<!-- should_panic,noplayground because mdbook does not pass args --> + +```rust,should_panic,noplayground {{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:run}} ``` @@ -275,6 +279,7 @@ it is ready to try advancing this one again. This is an invisible state machine, as if you wrote something like this: ```rust +# extern crate trpl; // required for mdbook test enum PageTitleFuture<'a> { GetAwaitPoint { url: &'a str, @@ -315,7 +320,9 @@ and racing it. <Listing number="17-5" caption="" file-name="src/main.rs"> -```rust +<!-- should_panic,noplayground because mdbook does not pass args --> + +```rust,should_panic,noplayground {{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:all}} ``` diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 9449910c3e..8f3ed136e2 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -223,7 +223,7 @@ between them, as shown in Listing 17-10: <Listing number="17-10" caption="Sending and receiving multiple messages over the async channel and sleeping with an `.await` between each message" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:many-messages}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:many-messages}} ``` </Listing> @@ -288,7 +288,7 @@ trying *not* to do. <Listing number="17-11" caption="Separating `send` and `recv` into their own `async` blocks and awaiting the futures for those blocks" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:futures}} ``` </Listing> @@ -333,7 +333,7 @@ it shuts down gracefully after the last message is sent and received. <Listing number="17-12" caption="A working example of sending and receiving messages between futures which correctly shuts down when complete" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:with-move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:with-move}} ``` </Listing> @@ -355,7 +355,7 @@ end up back in the same infinite loop we started out in. Finally, we switch from <Listing number="17-13" caption="Using multiple producers with async blocks" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} ``` </Listing> diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index d4dddb636e..2e9ac581ec 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -11,7 +11,7 @@ Thus, we could rewrite the code from Listing 17-13 to use `join!` instead of <Listing number="17-14" caption="Using `join!` to wait for multiple futures" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} ``` </Listing> @@ -31,7 +31,7 @@ replace `join!` with `join_all`. <Listing number="17-15" caption="Storing anonymous futures in a vector and calling `join_all`"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-16/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} ``` </Listing> @@ -103,7 +103,7 @@ in Listing 17-16. <Listing number="17-16" caption="Trying to use `Box::new` to align the types of the futures in a `Vec`" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-17/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-16/src/main.rs:here}} ``` </Listing> @@ -118,7 +118,7 @@ object (Listing 17-17). <Listing number="17-17" caption="Fixing the rest of the type mismatch errors by using an explicit type declaration" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-18/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-17/src/main.rs:here}} ``` </Listing> @@ -136,7 +136,7 @@ the errors mentioning `Unpin`. Although there are three of them, notice that each is very similar in its contents. <!-- manual-regeneration -cd listings/ch17-async-await/listing-17-18 +cd listings/ch17-async-await/listing-17-17 cargo build copy *only* the errors --> @@ -214,7 +214,7 @@ the futures themselves. <Listing number="17-18" caption="Using `Pin` and `Box::pin` to make the `Vec` type check" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-18/src/main.rs:here}} ``` </Listing> @@ -256,7 +256,7 @@ references to the dynamic `Future` type, as in Listing 17-19. <Listing number="17-19" caption="Using `Pin` directly with the `pin!` macro to avoid unnecessary heap allocations" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} ``` </Listing> @@ -269,7 +269,7 @@ types. For example, in Listing 17-20, the anonymous future for `a` implements <Listing number="17-20" caption="Three futures with distinct types" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} ``` </Listing> @@ -311,7 +311,7 @@ because all of the interesting behavior happens in the body of the async blocks. <Listing number="17-21" caption="Using `race` to get the result of whichever future finishes first" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:here}} ``` </Listing> @@ -356,7 +356,7 @@ blocking. <Listing number="17-22" caption="Using `thread::sleep` to simulate slow operations" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:slow}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:slow}} ``` </Listing> @@ -368,7 +368,7 @@ a pair of futures. To begin, each future only hands control back to the runtime <Listing number="17-23" caption="Using `thread::sleep` to simulate slow operations" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:slow-futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:slow-futures}} ``` </Listing> @@ -410,7 +410,7 @@ as a starting point? <Listing number="17-24" caption="Using `sleep` to let operations switch off making progress" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:here}} ``` </Listing> @@ -419,7 +419,7 @@ In Listing 17-24, we add `trpl::sleep` calls with await points between each call to `slow`. Now the two futures’ work is interleaved: <!-- manual-regeneration -cd listings/ch17-async-await/listing-17-25/ +cd listings/ch17-async-await/listing-17-24 cargo run copy just the output --> @@ -450,7 +450,7 @@ directly, using the `yield_now` function. In Listing 17-25, we replace all those <Listing number="17-25" caption="Using `yield_now` to let operations switch off making progress" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:yields}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:yields}} ``` </Listing> @@ -473,7 +473,7 @@ compared to the future using `trpl::yield_now`. <Listing number="17-26" caption="Comparing the performance of `sleep` and `yield_now`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:here}} ``` </Listing> @@ -509,7 +509,7 @@ future. <Listing number="17-27" caption="Using our imagined `timeout` to run a slow operation with a time limit" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:here}} ``` </Listing> @@ -533,7 +533,7 @@ Listing 17-28 shows this declaration. <Listing number="17-28" caption="Defining the signature of `timeout`" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:declaration}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:declaration}} ``` </Listing> @@ -558,7 +558,7 @@ with `_` and return `Err(max_time)` instead. <Listing number="17-29" caption="Defining `timeout` with `race` and `sleep`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-30/src/main.rs:implementation}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:implementation}} ``` </Listing> diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 674f52a7d5..439e0db2ff 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -25,7 +25,7 @@ method, and then awaiting the output, as in Listing 17-30. <Listing number="17-30" caption="Creating a stream from an iterator and printing its values" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs:stream}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-30/src/main.rs:stream}} ``` </Listing> @@ -40,7 +40,7 @@ can see in the output, it reports that there is no `next` method available. <!-- TODO: fix up the path here? --> <!-- manual-regeneration -cd listings/chapter-17-async-await/listing-17-31 +cd listings/chapter-17-async-await/listing-17-30 cargo build copy only the error output --> @@ -52,7 +52,7 @@ error[E0599]: no method named `next` found for struct `Iter` in the current scop 8 | while let Some(value) = stream.next().await { | ^^^^ | - = note: the full type name has been written to '/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-31/target/debug/deps/async_await-bbd5bb8f6851cb5f.long-type-18426562901668632191.txt' + = note: the full type name has been written to '/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-30/target/debug/deps/async_await-bbd5bb8f6851cb5f.long-type-18426562901668632191.txt' = note: consider using `--verbose` to print the full type name to the console = help: items from traits can only be used if the trait is in scope help: the following traits which provide `next` are implemented but not in scope; perhaps you want to import one of them @@ -94,7 +94,7 @@ Listing 17-31. <Listing number="17-31" caption="Successfully using an iterator as the basis for a stream" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs}} ``` </Listing> @@ -107,7 +107,7 @@ method to filter out everything but multiples of three and five. <Listing number="17-32" caption="Filtering a `Stream` with the `StreamExt::filter` method" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-33/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs}} ``` </Listing> @@ -140,7 +140,7 @@ a `while let` loop to print all the messages from the stream. <Listing number="17-33" caption="Using the `rx` receiver as a `ReceiverStream`" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-34/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-33/src/main.rs:all}} ``` </Listing> @@ -181,7 +181,7 @@ be polled. <Listing number="17-34" caption="Using the `StreamExt::timeout` method to set a time limit on the items in a stream" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-35/src/main.rs:timeout}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-34/src/main.rs:timeout}} ``` </Listing> @@ -198,7 +198,7 @@ for 200 milliseconds, this should affect half of the messages. <Listing number="17-35" caption="Sending messages through `tx` with an async delay without making `get_messages` an async function" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-36/src/main.rs:messages}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-35/src/main.rs:messages}} ``` </Listing> @@ -230,7 +230,7 @@ Now our code has a much more interesting result! Between every other pair of messages, we see an error reported: `Problem: Elapsed(())`. <!-- manual-regeneration -cd listings/listing-17-36 +cd listings/listing-17-35 cargo run copy only the program output, *not* the compiler output --> @@ -285,7 +285,7 @@ the infinite loop. <Listing number="17-36" caption="Creating a stream with a counter that will be emitted once every millisecond" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:intervals}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-36/src/main.rs:intervals}} ``` </Listing> @@ -303,7 +303,7 @@ Finally, we loop over that combined stream instead of over `messages` (Listing <Listing number="17-37" caption="Attempting to merge streams of messages and intervals" file-name="src/main.rs"> ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-38/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:main}} ``` </Listing> @@ -333,7 +333,7 @@ stream, and pin it so that it is safe to do so. <Listing number="17-38" caption="Aligning the types of the the `intervals` stream with the type of the `messages` stream" file-name="src/main.rs"> ```rust,ignore -{{#rustdoc_include ../listings/ch17-async-await/listing-17-39/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-38/src/main.rs:main}} ``` </Listing> @@ -375,7 +375,7 @@ output, not just one stream or the other. <Listing number="17-39" caption="Using `throttle` and `take` to manage the merged streams" file-name="src/main.rs"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:throttle}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-39/src/main.rs:throttle}} ``` </Listing> @@ -393,7 +393,7 @@ never produce those interval messages in the first place! This is the inherent performance characteristics. <!-- manual-regeneration -cd listings/listing-17-40 +cd listings/listing-17-39 cargo run copy and paste only the program output --> @@ -434,7 +434,7 @@ you have a strategy. <Listing number="17-40" caption="Handling errors and shutting down the loops"> ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-41/src/main.rs:errors}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:errors}} ``` </Listing> diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 3753120192..0832d058eb 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -103,27 +103,10 @@ common example of this kind of mix in real-world Rust code. <!-- TODO: extract into a listing file! --> -<Listing number="17-TODO" caption="Sending messages with blocking code in a thread and awaiting the messages in an async block" file-name="src/main.rs"> +<Listing number="17-42" caption="Sending messages with blocking code in a thread and awaiting the messages in an async block" file-name="src/main.rs"> ```rust -use std::thread; - -fn main() { - let (tx, mut rx) = trpl::channel(); - - thread::spawn(move || { - for i in 1..11 { - tx.send(i).unwrap(); - thread::sleep(Duration::from_secs(1)); - } - }); - - trpl::run(async { - while let Some(message) = rx.recv().await { - println!("{message}"); - } - }); -} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-42/src/main.rs}} ``` </Listing> From b265249e480d8120aed9f374c54d5aaa05227fd3 Mon Sep 17 00:00:00 2001 From: Chris Krycho <hello@chriskrycho.com> Date: Mon, 23 Sep 2024 09:03:05 -0600 Subject: [PATCH 25/25] Ch. 17: Fix spelling and internal links --- ci/dictionary.txt | 7 +++++++ src/ch17-02-concurrency-with-async.md | 4 ++-- src/ch17-03-more-futures.md | 11 +++++------ src/ch17-04-streams.md | 2 +- src/ch17-05-traits-for-async.md | 12 +++++++----- src/ch17-06-futures-tasks-threads.md | 4 ++-- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/ci/dictionary.txt b/ci/dictionary.txt index 9fd8e33e41..057d2a7f6e 100644 --- a/ci/dictionary.txt +++ b/ci/dictionary.txt @@ -152,6 +152,7 @@ ebook ebooks Edsger egular +ElementRef else's emoji encodings @@ -191,6 +192,8 @@ FrenchToast FromIterator FromResidual frontend +FuturesUnordered +GetAwaitPoint getrandom getter getters @@ -248,6 +251,7 @@ internet interoperate IntoFuture IntoIterator +intra InvalidDigit invariants ioerror @@ -295,6 +299,7 @@ lval macOS Matsakis mathematic +mdbook memoization metadata Metadata @@ -370,6 +375,7 @@ OurError OutlinePrint overloadable overread +PageTitleFuture PanicPayload parallelizable param @@ -521,6 +527,7 @@ TcpListener TcpStream templating test's +TextAwaitPoint TextField That'd there'd diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 8f3ed136e2..a302b5aa2e 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -152,7 +152,7 @@ what we saw with threads. That is because the `trpl::join` function is *fair*, meaning it checks each future equally often, alternating between them, and never lets one race ahead if the other is ready. With threads, the operating system decides which thread to check and how long to let it run. With async Rust, the -runtime decides which taks to check. (In practice, the details get complicated +runtime decides which task to check. (In practice, the details get complicated because an async runtime might use operating system threads under the hood as part of how it manages concurrency, so guaranteeing fairness can be more work for a runtime—but it is still possible!) Runtimes do not have to guarantee @@ -382,4 +382,4 @@ received 'you' This is a good start, but it limits us to just a handful of futures: two with `join`, or three with `join3`. Let’s see how we might work with more futures. -[streams]: /ch17-05-streams.md +[streams]: ch17-05-streams.html diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 2e9ac581ec..35e919249f 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -325,11 +325,11 @@ to poll first. Regardless of whether the implementation of race we are using is fair, though, *one* of the futures will run up to the first `.await` in its body before another task can start. -Recall from [“What Are Futures?”][futures] that at each await point, Rust gives -a runtime a chance to pause the task and switch to another one if the future -being awaited is not ready. The inverse is also true: Rust *only* pauses async -blocks and hands control back to a runtime at an await point. Everything between -await points is synchronous. +Recall from [Our First Async Program][async-program] that at each await point, +Rust gives a runtime a chance to pause the task and switch to another one if the +future being awaited is not ready. The inverse is also true: Rust *only* pauses +async blocks and hands control back to a runtime at an await point. Everything +between await points is synchronous. That means if you do a bunch of work in an async block without an await point, that future will block any other futures from making progress. You may sometimes @@ -597,5 +597,4 @@ to consider first, though: [collections]: ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: ch12-03-improving-error-handling-and-modularity.html -[futures]: ch17-01-futures-and-syntax.html#what-are-futures [async-program]: ch17-01-futures-and-syntax.html#our-first-async-program diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 439e0db2ff..b3e4cac9a7 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -443,4 +443,4 @@ That is a good note to turn to our final section and wrap up this walk through async in Rust, by discussing how futures (including streams), tasks, and threads relate to each other, and how you can use them together. -[17-02-messages]: ch17-02-concurrency-with-async.md#message-passing +[17-02-messages]: ch17-02-concurrency-with-async.html#message-passing diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 0a5ee1f89e..91193a4542 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -11,9 +11,9 @@ still leaving the *really* deep dive for other documentation! ### Future -Back in [Async Functions][async-functions], we noted that `Future` is a trait. -Let’s start by taking a closer look at how it works. Here is how Rust defines -a `Future`: +Back in [Futures and the Async Syntax][futures-syntax], we noted that `Future` +is a trait. Let’s start by taking a closer look at how it works. Here is how +Rust defines a `Future`: ```rust use std::pin::Pin; @@ -199,7 +199,7 @@ starts to explain the error message we saw above—but that was in terms of `Unpin`, not `Pin`. So what exactly are `Pin` and `Unpin`, how do they relate, and why does `Future` need `self` to be in a `Pin` type to call `poll`? -In [“What Are Futures”][what-are-futures], we described how a series of await +In [Our First Async Program][first-async], we described how a series of await points in a future get compiled into a state machine—and noted how the compiler helps make sure that state machine follows all of Rust’s normal rules around safety, including borrowing and ownership. To make that work, Rust looks at what @@ -379,10 +379,12 @@ even when you need to write your own streaming data type, you *only* have to implement `Stream`, and then anyone who uses your data type can use `StreamExt` and its methods with it automatically. -[counting]: /ch17-02-concurrency-with-async.md +[futures-syntax]: ch17-01-futures-and-syntax.html +[counting]: ch17-02-concurrency-with-async.html [async-book]: https://rust-lang.github.io/async-book/ [under-the-hood]: https://rust-lang.github.io/async-book/02_execution/01_chapter.html [pinning]: https://rust-lang.github.io/async-book/04_pinning/01_chapter.html +[first-async]: ch17-01-futures-and-syntax.html#our-first-async-program That’s all we’re going to cover for the lower-level details on these traits. To wrap up, let’s consider how futures (including streams), tasks, and threads all diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 0832d058eb..a10b391bf6 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -139,5 +139,5 @@ as your Rust programs get bigger. In addition, we’ll discuss how Rust’s idio relate to those you might be familiar with from object-oriented programming. -[combining-futures]: ch17-04-more-ways-of-combining-futures.md#building-our-own-async-abstractions -[streams]: ch17-05-streams.md#composing-streams +[combining-futures]: ch17-03-more-futures.html#building-our-own-async-abstractions +[streams]: ch17-04-streams.html#composing-streams