From 0ec7296ff72026f0880b7d2fe329996294c70cdd Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 15:32:03 -0600 Subject: [PATCH 001/249] Create crate for The Rust Programming Language --- .gitignore | 1 + CONTRIBUTING.md | 11 +++ Cargo.lock | 7 ++ Cargo.toml | 7 ++ LICENSE-APACHE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 25 ++++++ README.md | 9 +++ src/lib.rs | 14 ++++ 8 files changed, 275 insertions(+) create mode 100644 .gitignore create mode 100644 CONTRIBUTING.md create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..bd14bf21d7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing + +## 🚧 Under construction! 🚧 + +Thanks for your interesting in helping us with this! At the moment, we are not +ready for contributions, though. + +Once we stabilize the contents of the book, including the APIs we are +re-exporting here and the little bits of functionality implemented in that +crate, we will gladly take all the help we can get for maintaining this. We will +update this document once we are ready for contributions. diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..0858db7638 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "trpl" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..6b6ea9d5ad --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trpl" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000000..38634daab0 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2010 The Rust Project Developers + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000000..25597d5838 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2010 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..ddfc445a50 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# The Rust Programming Language Book Crate + +This repository is the home of the `trpl` crate used in _The Rust Programming +Language_ book materials. + +## Requirements + + +This crate currently requires at least Rust 1.77. diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000000..7d12d9af81 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} From fcd470c4a8bcd295414eff072c107ff24955ab9c Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 15:32:03 -0600 Subject: [PATCH 002/249] Add Tokio dependency We will primarily just be re-exporting this, though we may also have a couple cases where we choose to implement something small around it. --- Cargo.lock | 421 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + 2 files changed, 423 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 0858db7638..826cde189c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,427 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[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.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +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 = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[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 = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[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", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "trpl" version = "0.1.0" +dependencies = [ + "tokio", +] + +[[package]] +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/Cargo.toml b/Cargo.toml index 6b6ea9d5ad..fe35925a69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +tokio = { version = "1", features = ["full"] } From 3943e512f8f47050e6ca77d98a2386baa18d94d0 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 15:45:50 -0600 Subject: [PATCH 003/249] Re-export `tokio::main` as `trpl::async_main` and test it. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Introduce an integration tests crate. Structure it the way people *should* for large crates (although this is not that) and document why, including linking to a relevant post. 2. Add a basic integration test that verifies the re-export works as it should. (This is not exactly rocket science, but we want to make sure these things don’t just stop working on accident.) An open question that remains here: do we want some structure to the crate beyond the top level re-exports? My inclination at this moment is: no, because we don’t have any *motivation* for that, and naming things is difficult. (We cannot do `trpl::async`, for example, because `async` is a keyword!) --- src/lib.rs | 15 +-------------- tests/integration/main.rs | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 tests/integration/main.rs diff --git a/src/lib.rs b/src/lib.rs index 7d12d9af81..766a9a7e68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +pub use tokio::main as async_main; diff --git a/tests/integration/main.rs b/tests/integration/main.rs new file mode 100644 index 0000000000..81653f155b --- /dev/null +++ b/tests/integration/main.rs @@ -0,0 +1,24 @@ +//! Integration tests for the crate. +//! +//! These all live in a *single* integration test crate, `tests/integration`, +//! because each integration test is a dedicated binary crate which has to be +//! compiled separately. While that is not really a problem for a crate this +//! small, we have chosen to follow this “best practice” here as a good example. +//! +//! For more details on why you might prefer this pattern see [this post][post]. +//! +//! [post]: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html + +use trpl::async_main; + +#[test] +fn re_exported_macro_works() { + #[async_main] + async fn demo() -> &'static str { + let val = async { "Hello" }.await; + assert_eq!(val, "Hello", "Async is usable in async_main function"); + val + } + + assert_eq!(demo(), "Hello", "value returns correctly"); +} From e51828957d05fbb1bbd2961f122f53288d601247 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 16:13:12 -0600 Subject: [PATCH 004/249] Add more crate-level docs and matching README materials. --- README.md | 12 ++++++++++++ src/lib.rs | 14 ++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/README.md b/README.md index ddfc445a50..a074e05a6e 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,18 @@ This repository is the home of the `trpl` crate used in _The Rust Programming Language_ book materials. +This crate mostly just re-exports items from *other* crates. It exists for two +main reasons: + +1. So that as you read along in _The Rust Programming Language_, you can add + just one dependency, rather than however many we end up with, and likewise + use only one set of imports. + +2. So that we can more easily guarantee it keeps building and working. Since we + control the contents of this crate and when it changes, readers will never be + broken by upstream changes, e.g. if Tokio does a breaking 2.0 release at some + point. + ## Requirements diff --git a/src/lib.rs b/src/lib.rs index 766a9a7e68..a0fddb1b09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,15 @@ +//! A support crate for _The Rust Programming Language_. +//! +//! This crate mostly just re-exports items from *other* crates. It exists for +//! two main reasons: +//! +//! 1. So that as you read along in _The Rust Programming Language_, you can +//! add just one dependency, rather than however many we end up with, and +//! likewise use only one set of imports. +//! +//! 2. So that we can more easily guarantee it keeps building and working. Since +//! we control the contents of this crate and when it changes, readers will +//! never be broken by upstream changes, e.g. if Tokio does a breaking 2.0 +//! release at some point. + pub use tokio::main as async_main; From 608c35b52f8cc9a24b47b159eff35740e55281b9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 16:13:12 -0600 Subject: [PATCH 005/249] Document the first test so people can understand it. --- tests/integration/main.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/integration/main.rs b/tests/integration/main.rs index 81653f155b..fd232ccc7e 100644 --- a/tests/integration/main.rs +++ b/tests/integration/main.rs @@ -11,14 +11,19 @@ use trpl::async_main; +/// This test makes sure the re-exported version of the `tokio::main` macro, +/// which is applied like `#[tokio::main] async fn some_fn() { … }`, continues +/// to work. However, tests cannot use `async fn`, so to test it, we need to +/// have a non-`async` test function, which then applies the macro to an `async` +/// function in its body, and invokes *that*. #[test] fn re_exported_macro_works() { #[async_main] - async fn demo() -> &'static str { + async fn internal() -> &'static str { let val = async { "Hello" }.await; assert_eq!(val, "Hello", "Async is usable in async_main function"); val } - assert_eq!(demo(), "Hello", "value returns correctly"); + assert_eq!(internal(), "Hello", "value returns correctly"); } From 71ea12e43041c2b135dabb6a461c3c50b7eb67e1 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 16:27:04 -0600 Subject: [PATCH 006/249] Add CI for `main` and PRs against `main` --- .github/workflows/main.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..0642f451b8 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,23 @@ +name: CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + integration_test: + name: Integration Tests + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose From 4255d87df5337ae1ed0e533eee4ddfc6cfacf7a2 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 16:55:47 -0600 Subject: [PATCH 007/249] Add a CI status badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a074e05a6e..3906da15a4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # The Rust Programming Language Book Crate +![Build Status](https://github.com/chriskrycho/trpl-crate/workflows/CI/badge.svg) + This repository is the home of the `trpl` crate used in _The Rust Programming Language_ book materials. From 7c40849115d92e165c37609d0251f1b12945cb0b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 16 Apr 2024 15:36:29 -0600 Subject: [PATCH 008/249] Add new Chapter 17: Async and Await --- src/SUMMARY.md | 42 ++++++++++--------- src/ch17-00-async-await.md | 2 + src/{ch17-00-oop.md => ch18-00-oop.md} | 0 ...01-what-is-oo.md => ch18-01-what-is-oo.md} | 0 ...it-objects.md => ch18-02-trait-objects.md} | 0 ...terns.md => ch18-03-oo-design-patterns.md} | 0 ...h18-00-patterns.md => ch19-00-patterns.md} | 0 ...=> ch19-01-all-the-places-for-patterns.md} | 0 ...efutability.md => ch19-02-refutability.md} | 0 ...rn-syntax.md => ch19-03-pattern-syntax.md} | 0 ...atures.md => ch20-00-advanced-features.md} | 0 ...-unsafe-rust.md => ch20-01-unsafe-rust.md} | 0 ...d-traits.md => ch20-03-advanced-traits.md} | 0 ...ced-types.md => ch20-04-advanced-types.md} | 0 ...h20-05-advanced-functions-and-closures.md} | 0 src/{ch19-06-macros.md => ch20-06-macros.md} | 0 ... => ch21-00-final-project-a-web-server.md} | 0 ...threaded.md => ch21-01-single-threaded.md} | 0 ...tithreaded.md => ch21-02-multithreaded.md} | 0 ... ch21-03-graceful-shutdown-and-cleanup.md} | 0 20 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 src/ch17-00-async-await.md rename src/{ch17-00-oop.md => ch18-00-oop.md} (100%) rename src/{ch17-01-what-is-oo.md => ch18-01-what-is-oo.md} (100%) rename src/{ch17-02-trait-objects.md => ch18-02-trait-objects.md} (100%) rename src/{ch17-03-oo-design-patterns.md => ch18-03-oo-design-patterns.md} (100%) rename src/{ch18-00-patterns.md => ch19-00-patterns.md} (100%) rename src/{ch18-01-all-the-places-for-patterns.md => ch19-01-all-the-places-for-patterns.md} (100%) rename src/{ch18-02-refutability.md => ch19-02-refutability.md} (100%) rename src/{ch18-03-pattern-syntax.md => ch19-03-pattern-syntax.md} (100%) rename src/{ch19-00-advanced-features.md => ch20-00-advanced-features.md} (100%) rename src/{ch19-01-unsafe-rust.md => ch20-01-unsafe-rust.md} (100%) rename src/{ch19-03-advanced-traits.md => ch20-03-advanced-traits.md} (100%) rename src/{ch19-04-advanced-types.md => ch20-04-advanced-types.md} (100%) rename src/{ch19-05-advanced-functions-and-closures.md => ch20-05-advanced-functions-and-closures.md} (100%) rename src/{ch19-06-macros.md => ch20-06-macros.md} (100%) rename src/{ch20-00-final-project-a-web-server.md => ch21-00-final-project-a-web-server.md} (100%) rename src/{ch20-01-single-threaded.md => ch21-01-single-threaded.md} (100%) rename src/{ch20-02-multithreaded.md => ch21-02-multithreaded.md} (100%) rename src/{ch20-03-graceful-shutdown-and-cleanup.md => ch21-03-graceful-shutdown-and-cleanup.md} (100%) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index b4b58afdee..a004483b1e 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -101,29 +101,31 @@ - [Shared-State Concurrency](ch16-03-shared-state.md) - [Extensible Concurrency with the `Sync` and `Send` Traits](ch16-04-extensible-concurrency-sync-and-send.md) -- [Object Oriented Programming Features of Rust](ch17-00-oop.md) - - [Characteristics of Object-Oriented Languages](ch17-01-what-is-oo.md) - - [Using Trait Objects That Allow for Values of Different Types](ch17-02-trait-objects.md) - - [Implementing an Object-Oriented Design Pattern](ch17-03-oo-design-patterns.md) +- [Async and Await](ch17-00-async-await.md) + +- [Object Oriented Programming Features of Rust](ch18-00-oop.md) + - [Characteristics of Object-Oriented Languages](ch18-01-what-is-oo.md) + - [Using Trait Objects That Allow for Values of Different Types](ch18-02-trait-objects.md) + - [Implementing an Object-Oriented Design Pattern](ch18-03-oo-design-patterns.md) ## Advanced Topics -- [Patterns and Matching](ch18-00-patterns.md) - - [All the Places Patterns Can Be Used](ch18-01-all-the-places-for-patterns.md) - - [Refutability: Whether a Pattern Might Fail to Match](ch18-02-refutability.md) - - [Pattern Syntax](ch18-03-pattern-syntax.md) - -- [Advanced Features](ch19-00-advanced-features.md) - - [Unsafe Rust](ch19-01-unsafe-rust.md) - - [Advanced Traits](ch19-03-advanced-traits.md) - - [Advanced Types](ch19-04-advanced-types.md) - - [Advanced Functions and Closures](ch19-05-advanced-functions-and-closures.md) - - [Macros](ch19-06-macros.md) - -- [Final Project: Building a Multithreaded Web Server](ch20-00-final-project-a-web-server.md) - - [Building a Single-Threaded Web Server](ch20-01-single-threaded.md) - - [Turning Our Single-Threaded Server into a Multithreaded Server](ch20-02-multithreaded.md) - - [Graceful Shutdown and Cleanup](ch20-03-graceful-shutdown-and-cleanup.md) +- [Patterns and Matching](ch19-00-patterns.md) + - [All the Places Patterns Can Be Used](ch19-01-all-the-places-for-patterns.md) + - [Refutability: Whether a Pattern Might Fail to Match](ch19-02-refutability.md) + - [Pattern Syntax](ch19-03-pattern-syntax.md) + +- [Advanced Features](ch20-00-advanced-features.md) + - [Unsafe Rust](ch20-01-unsafe-rust.md) + - [Advanced Traits](ch20-03-advanced-traits.md) + - [Advanced Types](ch20-04-advanced-types.md) + - [Advanced Functions and Closures](ch20-05-advanced-functions-and-closures.md) + - [Macros](ch20-06-macros.md) + +- [Final Project: Building a Multithreaded Web Server](ch21-00-final-project-a-web-server.md) + - [Building a Single-Threaded Web Server](ch21-01-single-threaded.md) + - [Turning Our Single-Threaded Server into a Multithreaded Server](ch21-02-multithreaded.md) + - [Graceful Shutdown and Cleanup](ch21-03-graceful-shutdown-and-cleanup.md) - [Appendix](appendix-00.md) - [A - Keywords](appendix-01-keywords.md) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md new file mode 100644 index 0000000000..7f216e6f3a --- /dev/null +++ b/src/ch17-00-async-await.md @@ -0,0 +1,2 @@ +## Async and Await + diff --git a/src/ch17-00-oop.md b/src/ch18-00-oop.md similarity index 100% rename from src/ch17-00-oop.md rename to src/ch18-00-oop.md diff --git a/src/ch17-01-what-is-oo.md b/src/ch18-01-what-is-oo.md similarity index 100% rename from src/ch17-01-what-is-oo.md rename to src/ch18-01-what-is-oo.md diff --git a/src/ch17-02-trait-objects.md b/src/ch18-02-trait-objects.md similarity index 100% rename from src/ch17-02-trait-objects.md rename to src/ch18-02-trait-objects.md diff --git a/src/ch17-03-oo-design-patterns.md b/src/ch18-03-oo-design-patterns.md similarity index 100% rename from src/ch17-03-oo-design-patterns.md rename to src/ch18-03-oo-design-patterns.md diff --git a/src/ch18-00-patterns.md b/src/ch19-00-patterns.md similarity index 100% rename from src/ch18-00-patterns.md rename to src/ch19-00-patterns.md diff --git a/src/ch18-01-all-the-places-for-patterns.md b/src/ch19-01-all-the-places-for-patterns.md similarity index 100% rename from src/ch18-01-all-the-places-for-patterns.md rename to src/ch19-01-all-the-places-for-patterns.md diff --git a/src/ch18-02-refutability.md b/src/ch19-02-refutability.md similarity index 100% rename from src/ch18-02-refutability.md rename to src/ch19-02-refutability.md diff --git a/src/ch18-03-pattern-syntax.md b/src/ch19-03-pattern-syntax.md similarity index 100% rename from src/ch18-03-pattern-syntax.md rename to src/ch19-03-pattern-syntax.md diff --git a/src/ch19-00-advanced-features.md b/src/ch20-00-advanced-features.md similarity index 100% rename from src/ch19-00-advanced-features.md rename to src/ch20-00-advanced-features.md diff --git a/src/ch19-01-unsafe-rust.md b/src/ch20-01-unsafe-rust.md similarity index 100% rename from src/ch19-01-unsafe-rust.md rename to src/ch20-01-unsafe-rust.md diff --git a/src/ch19-03-advanced-traits.md b/src/ch20-03-advanced-traits.md similarity index 100% rename from src/ch19-03-advanced-traits.md rename to src/ch20-03-advanced-traits.md diff --git a/src/ch19-04-advanced-types.md b/src/ch20-04-advanced-types.md similarity index 100% rename from src/ch19-04-advanced-types.md rename to src/ch20-04-advanced-types.md diff --git a/src/ch19-05-advanced-functions-and-closures.md b/src/ch20-05-advanced-functions-and-closures.md similarity index 100% rename from src/ch19-05-advanced-functions-and-closures.md rename to src/ch20-05-advanced-functions-and-closures.md diff --git a/src/ch19-06-macros.md b/src/ch20-06-macros.md similarity index 100% rename from src/ch19-06-macros.md rename to src/ch20-06-macros.md diff --git a/src/ch20-00-final-project-a-web-server.md b/src/ch21-00-final-project-a-web-server.md similarity index 100% rename from src/ch20-00-final-project-a-web-server.md rename to src/ch21-00-final-project-a-web-server.md diff --git a/src/ch20-01-single-threaded.md b/src/ch21-01-single-threaded.md similarity index 100% rename from src/ch20-01-single-threaded.md rename to src/ch21-01-single-threaded.md diff --git a/src/ch20-02-multithreaded.md b/src/ch21-02-multithreaded.md similarity index 100% rename from src/ch20-02-multithreaded.md rename to src/ch21-02-multithreaded.md diff --git a/src/ch20-03-graceful-shutdown-and-cleanup.md b/src/ch21-03-graceful-shutdown-and-cleanup.md similarity index 100% rename from src/ch20-03-graceful-shutdown-and-cleanup.md rename to src/ch21-03-graceful-shutdown-and-cleanup.md From c1a0d1434e304b2673cc2729598cfc19e922b60a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 16 Apr 2024 15:36:29 -0600 Subject: [PATCH 009/249] Ch. 17: introduction section --- src/ch17-00-async-await.md | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 7f216e6f3a..219fbeecca 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -1,2 +1,48 @@ ## Async and Await +In Chapter 16, we saw one of Rust’s approaches to concurrency: using threads. +Since Rust 1.39, there has been another option for concurrency: the async-await +model. + +In the async-await model, concurrent operations do not require their own +threads. Instead, they can run on *tasks*. A task is a bit like a thread, but +instead of being managed by the operating system, it is managed by a runtime. +The job of a runtime is to schedule Some languages, including Go, Kotlin, +Erlang, and Swift, ship runtimes with the language. In Rust, there are many +different runtimes, because the things a runtime for a high-throughput web +server should do are very different from the things a runtime for a +microcontroller should do. + +In the rest of chapter, we will: + +* see how to use Rust’s `async` and `.await` syntax +* explore how to use the async-await model to solve some of the same challenges + we looked at in Chapter 16 +* look at how multithreading and async provide complementary solutions, which + you can even use together in many cases + +First, though, let’s explore what async-await gives us. + +### Why async-await + +Many operations we ask the computer to do can take a while to finish. For +example, if you used a video editor to create a video of a family celebration, +exporting it could take anywhere from minutes to hours. Similarly, when you +upload that video to some service to share it with your family, that upload +process might take a long time. + +It would be nice if we could do something else while we are waiting for those +long-running processes to complete. + +As we saw in the previous chapter, threads provide one approach to concurrency, +and they let us solve some of these issues. However, they also have some +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 +multiple threads. While mainstream desktop and mobile operating systems have all +had threading for many years, many embedded operating systems used on +microcontrollers do not. + + + +The async-await model provides a different, complementary set of tradeoffs. From d17c7129822a689b9a23472c9019836235dd56c9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 19 Apr 2024 15:45:51 -0600 Subject: [PATCH 010/249] Ch. 17: Expand introduction and add stub for tasks chapter --- src/ch17-00-async-await.md | 75 ++++++++++++++++++++++++++------------ src/ch17-01-tasks.md | 21 +++++++++++ 2 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 src/ch17-01-tasks.md diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 219fbeecca..94a0c3b04c 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -4,22 +4,13 @@ In Chapter 16, we saw one of Rust’s approaches to concurrency: using threads. Since Rust 1.39, there has been another option for concurrency: the async-await model. -In the async-await model, concurrent operations do not require their own -threads. Instead, they can run on *tasks*. A task is a bit like a thread, but -instead of being managed by the operating system, it is managed by a runtime. -The job of a runtime is to schedule Some languages, including Go, Kotlin, -Erlang, and Swift, ship runtimes with the language. In Rust, there are many -different runtimes, because the things a runtime for a high-throughput web -server should do are very different from the things a runtime for a -microcontroller should do. - In the rest of chapter, we will: * see how to use Rust’s `async` and `.await` syntax * explore how to use the async-await model to solve some of the same challenges we looked at in Chapter 16 -* look at how multithreading and async provide complementary solutions, which - you can even use together in many cases +* look at how multithreading and async-await provide complementary solutions, + which you can even use together in many cases First, though, let’s explore what async-await gives us. @@ -29,20 +20,58 @@ Many operations we ask the computer to do can take a while to finish. For example, if you used a video editor to create a video of a family celebration, exporting it could take anywhere from minutes to hours. Similarly, when you upload that video to some service to share it with your family, that upload -process might take a long time. +process might take a long time. It would be nice if we could do something else +while we are waiting for those long-running processes to complete. + +In the previous chapter we treated parallelism and concurrency as +interchangeable. Now we need to distinguish between the two a little more: + +* *Parallelism* is when operations can happen simultaneously. + +* *Concurrency* is when operations can make progress without having to wait for + all other operations to complete. + +On a machine with multiple CPU cores, we can actually do work in parallel. One +core can be doing thing while another core does something completely unrelated, +and those actually happen at the same time. On a machine with a single CPU core, +the CPU can only do one operation at a time, but we can still have concurrency. +Using tools like threads, processes, and async-await, the computer can pause one +activity and switch to others before eventually cycling back to that first +activity again. So all parallel operations are also concurrent, but not all +concurrent operations happen in parallel! + +> Note: When working with async-await in Rust, we need to think in terms of +> *concurrency*. Depending on the hardware, the operating system, and the async +> runtime we are using, that concurrency may use some degree of parallelism +> under the hood, or it may not. -It would be nice if we could do something else while we are waiting for those -long-running processes to complete. +One common analogy for thinking about the difference between concurrency and +parallelism is cooking in a kitchen. Parallelism is like having two cooks: one +working on cooking eggs, and the other working on preparing fruit bowls. Those +can happen at the same time, without either affecting the other. Concurrency is +like having a single cook who can start cooking some eggs, start dicing up some +vegetables to use in the omelette, adding seasoning and whatever vegetables are +ready to the eggs at certain points, and switching back and forth between those +tasks. -As we saw in the previous chapter, threads provide one approach to concurrency, -and they let us solve some of these issues. However, they also have some -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 -multiple threads. While mainstream desktop and mobile operating systems have all -had threading for many years, many embedded operating systems used on -microcontrollers do not. +(This analogy breaks down if you think about it too hard. The eggs keep cooking +while the cook is chopping up the vegetables, after all. That is parallelism, +not concurrency! The focus of the analogy is the *cook*, not the food, though, +and as long as you keep that in mind, it mostly works.) +Consider again the examples of exporting a video file and waiting on the video +file to finish uploading. 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, so +instead your computer could invisibly interrupt the export often enough to let +you get other small amounts of work done along the way. +The file upload is different. That does not take up that much CPU time. Mostly, +you are waiting on data to transfer across the network. -The async-await model provides a different, complementary set of tradeoffs. +A big difference between the cooking analogy and Rust’s async-await model for +concurrency is that in the cooking example, the cook makes the decision about +when to switch tasks. In Rust’s async-await model, the tasks are in control of +that. To see how, let’s look at diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md new file mode 100644 index 0000000000..bef9b40cba --- /dev/null +++ b/src/ch17-01-tasks.md @@ -0,0 +1,21 @@ +## Tasks + +As we saw in the previous chapter, threads provide one approach to concurrency, +and they let us solve some of these issues. However, they also have some +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 +multiple threads. While mainstream desktop and mobile operating systems have all +had threading for many years, many embedded operating systems used on +microcontrollers do not. + +The async-await model provides a different, complementary set of tradeoffs. + +In the async-await model, concurrent operations do not require their own +threads. Instead, they can run on *tasks*. A task is a bit like a thread, but +instead of being managed by the operating system, it is managed by a runtime. +The job of a runtime is to schedule Some languages, including Go, Kotlin, +Erlang, and Swift, ship runtimes with the language. In Rust, there are many +different runtimes, because the things a runtime for a high-throughput web +server should do are very different from the things a runtime for a +microcontroller should do. From 4ce722d6ca8a95c4c709c55fb80818145fa535bb Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 19 Apr 2024 16:39:59 -0600 Subject: [PATCH 011/249] Ch. 17: Fix a couple typos and incomplete sentences --- src/ch17-00-async-await.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 94a0c3b04c..0f6c7e9980 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -32,13 +32,13 @@ interchangeable. Now we need to distinguish between the two a little more: all other operations to complete. On a machine with multiple CPU cores, we can actually do work in parallel. One -core can be doing thing while another core does something completely unrelated, -and those actually happen at the same time. On a machine with a single CPU core, -the CPU can only do one operation at a time, but we can still have concurrency. -Using tools like threads, processes, and async-await, the computer can pause one -activity and switch to others before eventually cycling back to that first -activity again. So all parallel operations are also concurrent, but not all -concurrent operations happen in parallel! +core can be doing one thing while another core does something completely +unrelated, and those actually happen at the same time. On a machine with a +single CPU core, the CPU can only do one operation at a time, but we can still +have concurrency. Using tools like threads, processes, and async-await, the +computer can pause one activity and switch to others before eventually cycling +back to that first activity again. So all parallel operations are also +concurrent, but not all concurrent operations happen in parallel! > Note: When working with async-await in Rust, we need to think in terms of > *concurrency*. Depending on the hardware, the operating system, and the async @@ -56,8 +56,8 @@ tasks. (This analogy breaks down if you think about it too hard. The eggs keep cooking while the cook is chopping up the vegetables, after all. That is parallelism, -not concurrency! The focus of the analogy is the *cook*, not the food, though, -and as long as you keep that in mind, it mostly works.) +not just concurrency! The focus of the analogy is the *cook*, not the food, +though, and as long as you keep that in mind, it mostly works.) Consider again the examples of exporting a video file and waiting on the video file to finish uploading. The video export will use as much CPU and GPU power as @@ -74,4 +74,4 @@ here --> A big difference between the cooking analogy and Rust’s async-await model for concurrency is that in the cooking example, the cook makes the decision about when to switch tasks. In Rust’s async-await model, the tasks are in control of -that. To see how, let’s look at +that. To see how, let’s look at how Rust actually uses async-await. From 71d92ecc1a9e870a3b12f3559e7ad565753a06f5 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 22 Apr 2024 12:08:04 -0600 Subject: [PATCH 012/249] Ch. 17: Add some introductory material about async/await MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 17.00: Introduction to the conceptual machinery. This is very nascent but has some decent bones. - 17.01: Trying to get at the foundations for tasks, laziness, etc.; this is *especially* incomplete. - 17.02: Just a paragraph I do not want to lose, which I think *will* be useful… eventually. --- src/ch16-01-threads.md | 3 +- src/ch17-00-async-await.md | 52 ++++---- src/ch17-01-tasks.md | 239 +++++++++++++++++++++++++++++++++++-- src/ch17-02.md | 4 + 4 files changed, 270 insertions(+), 28 deletions(-) create mode 100644 src/ch17-02.md diff --git a/src/ch16-01-threads.md b/src/ch16-01-threads.md index cfdd0c7066..a26a18dc03 100644 --- a/src/ch16-01-threads.md +++ b/src/ch16-01-threads.md @@ -30,7 +30,8 @@ operating systems provide an API the language can call for creating new threads. The Rust standard library uses a *1:1* model of thread implementation, whereby a program uses one operating system thread per one language thread. There are crates that implement other models of threading that make different -tradeoffs to the 1:1 model. +tradeoffs to the 1:1 model. (Rust’s async-await system, which we will see in the +next chapter, provides another approach to concurrency as well.) ### Creating a New Thread with `spawn` diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 0f6c7e9980..a5bd2eb6e4 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -31,20 +31,6 @@ interchangeable. Now we need to distinguish between the two a little more: * *Concurrency* is when operations can make progress without having to wait for all other operations to complete. -On a machine with multiple CPU cores, we can actually do work in parallel. One -core can be doing one thing while another core does something completely -unrelated, and those actually happen at the same time. On a machine with a -single CPU core, the CPU can only do one operation at a time, but we can still -have concurrency. Using tools like threads, processes, and async-await, the -computer can pause one activity and switch to others before eventually cycling -back to that first activity again. So all parallel operations are also -concurrent, but not all concurrent operations happen in parallel! - -> Note: When working with async-await in Rust, we need to think in terms of -> *concurrency*. Depending on the hardware, the operating system, and the async -> runtime we are using, that concurrency may use some degree of parallelism -> under the hood, or it may not. - One common analogy for thinking about the difference between concurrency and parallelism is cooking in a kitchen. Parallelism is like having two cooks: one working on cooking eggs, and the other working on preparing fruit bowls. Those @@ -59,17 +45,43 @@ while the cook is chopping up the vegetables, after all. That is parallelism, not just concurrency! The focus of the analogy is the *cook*, not the food, though, and as long as you keep that in mind, it mostly works.) +On a machine with multiple CPU cores, we can actually do work in parallel. One +core can be doing one thing while another core does something completely +unrelated, and those actually happen at the same time. On a machine with a +single CPU core, the CPU can only do one operation at a time, but we can still +have concurrency. Using tools like threads, processes, and async-await, the +computer can pause one activity and switch to others before eventually cycling +back to that first activity again. So all parallel operations are also +concurrent, but not all concurrent operations happen in parallel! + +> Note: When working with async-await in Rust, we need to think in terms of +> *concurrency*. Depending on the hardware, the operating system, and the async +> runtime we are using, that concurrency may use some degree of parallelism +> under the hood, or it may not. More about async runtimes in a later section! + Consider again the examples of exporting a video file and waiting on the video file to finish uploading. 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, so -instead your computer could invisibly interrupt the export often enough to let -you get other small amounts of work done along the way. - -The file upload is different. That does not take up that much CPU time. Mostly, -you are waiting on data to transfer across the network. +instead your computer can (and does!) invisibly interrupt the export often +enough to let you get other small amounts of work done along the way. + +The file upload is different. It does not take up very much CPU time. Instead, +you are mostly waiting on data to transfer across the network. If you only have +a single CPU core, you might write a bunch of data to a network socket and then +wait for it to finish getting sent by the network controller. You could choose +to wait for all the data to get “flushed” from the socket and actually sent over +the network, but if there is a busy network connection, you might be waiting for +a while… with your CPU doing not much! Thus, even if you make a blocking call to +write to a socket, your computer probably does other things while the network +operation is happening. + +In both of these cases, it might be useful for *your program* to participate in +the same kind of concurrency the computer is providing for the rest of the +system. One way to do this is the approach we saw last chapter: using threads, +which are provided and managed by the operating system. Another way to get +access to concurrency is using language-specific capabilities—like async-await. A big difference between the cooking analogy and Rust’s async-await model for concurrency is that in the cooking example, the cook makes the decision about diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index bef9b40cba..701a720bb1 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -1,4 +1,6 @@ -## Tasks +## Futures and the Async-Await Syntax + +### Tasks As we saw in the previous chapter, threads provide one approach to concurrency, and they let us solve some of these issues. However, they also have some @@ -9,13 +11,236 @@ multiple threads. While mainstream desktop and mobile operating systems have all had threading for many years, many embedded operating systems used on microcontrollers do not. -The async-await model provides a different, complementary set of tradeoffs. +The async-await model provides a different, complementary set of tradeoffs. In + + In the async-await model, concurrent operations do not require their own threads. Instead, they can run on *tasks*. A task is a bit like a thread, but instead of being managed by the operating system, it is managed by a runtime. -The job of a runtime is to schedule Some languages, including Go, Kotlin, -Erlang, and Swift, ship runtimes with the language. In Rust, there are many -different runtimes, because the things a runtime for a high-throughput web -server should do are very different from the things a runtime for a -microcontroller should do. + + + +### + +Like many other languages with first-class support for the async-await +programming model, Rust uses the `async` and `await` keywords—though with some +important differences from other languages like C# or JavaScript. 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. + +Let’s write our first async function: + +```rust +fn main() { + hello_async(); +} + +async fn hello_async() { + println!("Hello, async!"); +} +``` + +If we compile and run this… nothing happens, and we get a compiler warning: + +```console +$ cargo run +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: `hello-async` (bin "hello-async") generated 1 warning + Finished dev [unoptimized + debuginfo] target(s) in 1.50s + Running `target/debug/hello-async` +``` + +The warning tells us why nothing happened. Calling `hello_async()` itself was +not enough: we need to `.await`or poll the “future” it returns. That might be a +bit surprising: we did not write a return type on the function. However, we +*did* mark it as an `async fn`. In Rust, `async fn` is equivalent to writing a +function which returns a *future* of the return type, using the `impl Trait` +syntax we discussed back in the [“Traits as Parameters”][impl-trait] section in +Chapter 10. So these two are roughly equivalent: + + +```rust +fn hello_async() -> impl Future { + println!("Hello, async!"); +} +``` + +```rust +async fn hello_async() { + println!("Hello, async!"); +} +``` + +That explains why we got the `unused_must_use` warning. The other part of the +warning was the note that we need to `.await` or poll the future. Rust's `await` +keyword is a postfix keyword, meaning it goes *after* the expression you are +awaiting. (As of now, `await` is the only postfix keyword in the language.) +Let’s try that here: + +```rust +fn main() { + hello_async().await; +} +``` + +Now we actually have a compiler error! + +```text +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> src/main.rs:2:19 + | +1 | fn main() { + | ---- this is not `async` +2 | hello_async().await; + | ^^^^^ only allowed inside `async` functions and blocks +``` + +Okay, so we cannot actually use `.await` in `main`, because it is not an `async` +function itself—and it cannot be. To understand why, we need to pause to see +what a `Future` actually is and why it needs to be `.await`-ed or polled to do +anything. + +### Understanding `Future` + +Since `async fn` compiles to a return type with `impl Future`, we +know that `Future` is a trait, with an associated type `Output`. The other part +of the trait is its one method: `poll`. The `poll` method returns a fairly +simple type: + +```rust +enum Poll { + Ready(T), + Pending +} +``` + +(You might have noticed that this `Poll` type is a lot like an `Option`. Having +a dedicated type lets Rust treat `Poll` differently from `Option`, though, which +is important since they have very different meanings!) + +Under the hood, when you call `.await`, Rust compiles that to code which calls +`poll` instead, kind of like this: + + +```rust +match hello_async().poll() { + Ready(_) => { + // We’re done! + } + Pending => { + // But what goes here? + } +} +``` + +As you can see from this sample, though, there is a question: what happens when +the `Future` is still `Pending`? We need some way to try again. We would need to +have something like this instead: + + +```rust +let hello_async_fut = hello_async(); +loop { + match hello_async_fut.poll() { + Ready(_) => { + break; + } + Pending => { + // continue + } + } +} +``` + +If we wrote that code, though, we would block the computer from doing anything +else, though—the opposite of what we were going for. It also wouldn’t compile +for three other reasons, though: + +1. The `poll` method actually requires an argument: a `Context` that carries + along a way to say when to call it again, to avoid exactly the problem of + blocking other operations from making progress. + +2. The `Future` returned by our `async fn` is not actually ready to use here, + because `poll` requires that the future be “pinned”—guaranteed not to get + moved around in memory, so that any references to the future can be checked + for memory safety. + +3. Even if we pinned the future, this code would move `hello_async_fut` in the + first iteration through the `loop`. After the first time through the loop, we + would not be able to call it again. + +When we use the `async fn` form with `.await`, Rust compiles it to something +smarter than the `loop` above, in conjunction with a *runtime* responsible for +executing that loop. + +Some languages, including Go, Kotlin, Erlang, and Swift, ship runtimes with the +language. In Rust, there are many different runtimes, because the things a +runtime for a high-throughput web server with dozens of CPU cores and terabytes +of RAM should do are very different from the things a runtime for a +microcontroller with a single core and one gigabyte of RAM should do. + + + +The other thing to notice here is that futures in Rust are *lazy*. They do not +do anything until you explicitly ask them to—whether by calling `poll` or by +using `.await` to do so. This is different from the behavior we saw when using +`thread::spawn` in the previous chapter, and it is different from how many other +languages approach async-await. This allows Rust to avoid running async code +unless it is actually needed, and supports some of the memory safety features +Rust brings to async-await. (The details are beyond the scope of this book, but +are well worth digging into.) + +### Running Async Code + + + +Going back to `main`, this explains why we cannot have an `async fn main`: what +would execute the async code? We need to pick a runtime and executor. We can get +started with that easily by using the simple one that comes bundled with the +`futures` crate, an official home for Rust experimentation for async code. Since +we will be using a bunch of tools from that crate for the rest of the chapter, +let’s go ahead and add it to the dependencies for our test project: + +``` +cargo add futures@0.3 +``` + +Now we can use the executor which comes with `futures` to run the code. The +`futures::executor::block_on` function takes in a `Future` and runs it until it +completes. + +```rust +use futures::executor; + +fn main() { + executor::block_on(hello_async()); +} + +async fn hello_async() { + println!("Hello, async!"); +} +``` + +Now when we run this, we get the behavior we might have expected initially: + +```console +$ cargo run + Compiling hello-async v0.1.0 (/Users/chris/dev/chriskrycho/async-trpl-fun/hello-async) + Finished dev [unoptimized + debuginfo] target(s) in 4.89s + Running `target/debug/hello-async` +Hello, async! +``` + +Now, that’s a lot of work to just print a string, but we have laid some key +foundations for working with async and await in Rust. + +[impl-trait]: ch10-02-traits.html#traits-as-parameters diff --git a/src/ch17-02.md b/src/ch17-02.md new file mode 100644 index 0000000000..75d4dcaa65 --- /dev/null +++ b/src/ch17-02.md @@ -0,0 +1,4 @@ +The executor from `futures` we used in the previous section is intentionally +quite limited. It works well, but if you are going to build a real-world +application, you will want to use the executor from one of the *other* runtimes +in the Rust ecosystem. From fdb3794e2af67a037493e54259be98442b908f59 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 23 Apr 2024 17:26:07 -0600 Subject: [PATCH 013/249] Ch. 17: Introduce runtimes and the `trpl` crate Add a fair bit more material about the `futures` executor and why we might prefer to use something else. With that motivation in place, have the readers add our `trpl` crate. (We can of course rename that crate, but it does the job for now.) Use it to get the equivalent of `#[tokio::main]` equivalent and incorporate it into an example. --- src/ch17-01-tasks.md | 3 ++- src/ch17-02.md | 51 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 701a720bb1..70ed2f2647 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -241,6 +241,7 @@ Hello, async! ``` Now, that’s a lot of work to just print a string, but we have laid some key -foundations for working with async and await in Rust. +foundations for working with async-await in Rust! Now that you know the basics +of how futures work, and the [impl-trait]: ch10-02-traits.html#traits-as-parameters diff --git a/src/ch17-02.md b/src/ch17-02.md index 75d4dcaa65..80c1a6f582 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -1,4 +1,49 @@ The executor from `futures` we used in the previous section is intentionally -quite limited. It works well, but if you are going to build a real-world -application, you will want to use the executor from one of the *other* runtimes -in the Rust ecosystem. +quite limited. It works quite well, but if you are going to build a real-world +application, you will likely want to use the executor from one of the *other* +runtimes in the Rust ecosystem. + +For the rest of the chapter, we will be using [Tokio][tokio], which is the most +widely used async runtime, especially (but not only!) for web applications. + +> Note: There are other great options out there, too, and they may be more +> suitable for your purposes, so this is not at all saying Tokio is better than +> the alternatives. + +To keep this chapter focused on learning async-await, 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, and in a couple cases wires up a few things for you which are +less relevant to the subject of the book. There is no magic involved, though! 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 handful of +helper functions we supply are doing. + +For now, go ahead and add the dependency to your `hello-async` project: + +```console +$ cargo add trpl +``` + +Okay, now let’s start exploring . Going forward, we will use a new `async_main` +macro so that we can use `async fn` with a `main` function. Under the hood, this +little utility macro from Tokio sets up the Tokio runtime and wires up a call +kind of like we saw with `futures::executor::block_on` in the previous section. + +```rust +use trpl::async_main; + +#[async_main] +async fn main() { + async { + println!("Hello, world!"); + }.await; +} +``` + +Now we can use `async` blocks directly in `main` and not worry about wiring up +the runtime ourselves. + +[tokio]: https://tokio.rs +[crate-source]: TODO From cf00f054baeda0b0fd43fa3905129eec5da5f76e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 1 May 2024 10:07:55 -0600 Subject: [PATCH 014/249] =?UTF-8?q?Use=20=E2=80=9Casynchronous=20programmi?= =?UTF-8?q?ng=E2=80=9D=20or=20=E2=80=9Casync=E2=80=9D,=20not=20=E2=80=9Cas?= =?UTF-8?q?ync-await=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch16-01-threads.md | 12 ++++++------ src/ch17-00-async-await.md | 34 +++++++++++++++++----------------- src/ch17-01-tasks.md | 32 ++++++++++++++++---------------- src/ch17-02.md | 12 ++++++------ 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/ch16-01-threads.md b/src/ch16-01-threads.md index a26a18dc03..f3cdbff907 100644 --- a/src/ch16-01-threads.md +++ b/src/ch16-01-threads.md @@ -26,12 +26,12 @@ a code structure that is different from that in programs running in a single thread. Programming languages implement threads in a few different ways, and many -operating systems provide an API the language can call for creating new -threads. The Rust standard library uses a *1:1* model of thread implementation, -whereby a program uses one operating system thread per one language thread. -There are crates that implement other models of threading that make different -tradeoffs to the 1:1 model. (Rust’s async-await system, which we will see in the -next chapter, provides another approach to concurrency as well.) +operating systems provide an API the language can call for creating new threads. +The Rust standard library uses a *1:1* model of thread implementation, whereby a +program uses one operating system thread per one language thread. There are +crates that implement other models of threading that make different tradeoffs to +the 1:1 model. (Rust’s async system, which we will see in the next chapter, +provides another approach to concurrency as well.) ### Creating a New Thread with `spawn` diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index a5bd2eb6e4..f34caf2e66 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -1,20 +1,20 @@ ## Async and Await In Chapter 16, we saw one of Rust’s approaches to concurrency: using threads. -Since Rust 1.39, there has been another option for concurrency: the async-await -model. +Since Rust 1.39, there has been another option for concurrency: asynchronous +programming, or *async*. In the rest of chapter, we will: * see how to use Rust’s `async` and `.await` syntax -* explore how to use the async-await model to solve some of the same challenges - we looked at in Chapter 16 -* look at how multithreading and async-await provide complementary solutions, - which you can even use together in many cases +* explore how to use the async model to solve some of the same challenges we + looked at in Chapter 16 +* look at how multithreading and async provide complementary solutions, which + you can even use together in many cases -First, though, let’s explore what async-await gives us. +First, though, let’s explore what async gives us. -### Why async-await +### Why Async? Many operations we ask the computer to do can take a while to finish. For example, if you used a video editor to create a video of a family celebration, @@ -49,12 +49,12 @@ On a machine with multiple CPU cores, we can actually do work in parallel. One core can be doing one thing while another core does something completely unrelated, and those actually happen at the same time. On a machine with a single CPU core, the CPU can only do one operation at a time, but we can still -have concurrency. Using tools like threads, processes, and async-await, the -computer can pause one activity and switch to others before eventually cycling -back to that first activity again. So all parallel operations are also -concurrent, but not all concurrent operations happen in parallel! +have concurrency. Using tools like threads, processes, and async, the computer +can pause one activity and switch to others before eventually cycling back to +that first activity again. So all parallel operations are also concurrent, but +not all concurrent operations happen in parallel! -> Note: When working with async-await in Rust, we need to think in terms of +> Note: When working with async in Rust, we need to think in terms of > *concurrency*. Depending on the hardware, the operating system, and the async > runtime we are using, that concurrency may use some degree of parallelism > under the hood, or it may not. More about async runtimes in a later section! @@ -81,9 +81,9 @@ In both of these cases, it might be useful for *your program* to participate in the same kind of concurrency the computer is providing for the rest of the system. One way to do this is the approach we saw last chapter: using threads, which are provided and managed by the operating system. Another way to get -access to concurrency is using language-specific capabilities—like async-await. +access to concurrency is using language-specific capabilities—like async. -A big difference between the cooking analogy and Rust’s async-await model for +A big difference between the cooking analogy and Rust’s async model for concurrency is that in the cooking example, the cook makes the decision about -when to switch tasks. In Rust’s async-await model, the tasks are in control of -that. To see how, let’s look at how Rust actually uses async-await. +when to switch tasks. In Rust’s async model, the tasks are in control of that. +To see how, let’s look at how Rust actually uses async. diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 70ed2f2647..632638d60d 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -1,4 +1,4 @@ -## Futures and the Async-Await Syntax +## Futures and the Async Syntax ### Tasks @@ -11,23 +11,23 @@ multiple threads. While mainstream desktop and mobile operating systems have all had threading for many years, many embedded operating systems used on microcontrollers do not. -The async-await model provides a different, complementary set of tradeoffs. In +The async model provides a different, complementary set of tradeoffs. In -In the async-await model, concurrent operations do not require their own -threads. Instead, they can run on *tasks*. A task is a bit like a thread, but -instead of being managed by the operating system, it is managed by a runtime. +In the async model, concurrent operations do not require their own threads. +Instead, they can run on *tasks*. A task is a bit like a thread, but instead of +being managed by the operating system, it is managed by a runtime. ### -Like many other languages with first-class support for the async-await -programming model, Rust uses the `async` and `await` keywords—though with some -important differences from other languages like C# or JavaScript. 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. +Like many other languages with first-class support for the async programming +model, Rust uses the `async` and `await` keywords—though with some important +differences from other languages like C# or JavaScript. 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. Let’s write our first async function: @@ -194,10 +194,10 @@ The other thing to notice here is that futures in Rust are *lazy*. They do not do anything until you explicitly ask them to—whether by calling `poll` or by using `.await` to do so. This is different from the behavior we saw when using `thread::spawn` in the previous chapter, and it is different from how many other -languages approach async-await. This allows Rust to avoid running async code -unless it is actually needed, and supports some of the memory safety features -Rust brings to async-await. (The details are beyond the scope of this book, but -are well worth digging into.) +languages approach async. This allows Rust to avoid running async code unless it +is actually needed, and supports some of the memory safety features Rust brings +to async. (The details are beyond the scope of this book, but are well worth +digging into.) ### Running Async Code @@ -241,7 +241,7 @@ Hello, async! ``` Now, that’s a lot of work to just print a string, but we have laid some key -foundations for working with async-await in Rust! Now that you know the basics -of how futures work, and the +foundations for working with async in Rust! Now that you know the basics of how +futures work, and the [impl-trait]: ch10-02-traits.html#traits-as-parameters diff --git a/src/ch17-02.md b/src/ch17-02.md index 80c1a6f582..c1cff2e869 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -10,12 +10,12 @@ widely used async runtime, especially (but not only!) for web applications. > suitable for your purposes, so this is not at all saying Tokio is better than > the alternatives. -To keep this chapter focused on learning async-await, 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, and in a couple cases wires up a few things for you which are -less relevant to the subject of the book. There is no magic involved, though! If -you want to understand what the crate does, we encourage you to check out [its +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, and in a couple cases wires up a few things for you which are less +relevant to the subject of the book. There is no magic involved, though! 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 handful of helper functions we supply are doing. From 02b0bd195ce3306f85749dbdb72a3e70b7911e55 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 1 May 2024 10:12:48 -0600 Subject: [PATCH 015/249] Add note about Async Book ch. 4: Pinning --- src/ch17-01-tasks.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 632638d60d..c20bb5bdb8 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -197,7 +197,8 @@ using `.await` to do so. This is different from the behavior we saw when using languages approach async. This allows Rust to avoid running async code unless it is actually needed, and supports some of the memory safety features Rust brings to async. (The details are beyond the scope of this book, but are well worth -digging into.) +digging into. In particular, see [Chapter 4: Pinning][pinning] in the official +[_Asynchronous Programming in Rust_][async-book] book.) ### Running Async Code @@ -245,3 +246,5 @@ foundations for working with async in Rust! Now that you know the basics of how futures work, and the [impl-trait]: ch10-02-traits.html#traits-as-parameters +[pinning]: https://rust-lang.github.io/async-book/04_pinning/01_chapter.html +[async-book]: https://rust-lang.github.io/async-book/ From 94d95c6e6bffe8f6976e3cd8a2d0e7a9b9da0a2d Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 1 May 2024 10:18:23 -0600 Subject: [PATCH 016/249] Ch. 17: Explain what `Poll::Pending` and `Poll::Ready(T)` mean. --- src/ch17-01-tasks.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index c20bb5bdb8..13ceb1b960 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -123,9 +123,17 @@ enum Poll { } ``` -(You might have noticed that this `Poll` type is a lot like an `Option`. Having -a dedicated type lets Rust treat `Poll` differently from `Option`, though, which -is important since they have very different meanings!) +You might have noticed that this `Poll` type is a lot like an `Option`. Having a +dedicated type lets Rust treat `Poll` differently from `Option`, though, which +is important since they have very different meanings! 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 future, the caller should not call `poll()` again after the +> future has returned `Ready`. Many futures will panic if polled 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` instead, kind of like this: From b4bcb2cb3e431199ad6013723519dbfcefeeed83 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 1 May 2024 11:02:42 -0600 Subject: [PATCH 017/249] Ch. 17: add a TODO for the `async fn` desugaring --- src/ch17-01-tasks.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 13ceb1b960..561a5a10eb 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -67,15 +67,17 @@ function which returns a *future* of the return type, using the `impl Trait` syntax we discussed back in the [“Traits as Parameters”][impl-trait] section in Chapter 10. So these two are roughly equivalent: - ```rust -fn hello_async() -> impl Future { +async fn hello_async() { println!("Hello, async!"); } ``` + + + ```rust -async fn hello_async() { +fn hello_async() -> impl Future { println!("Hello, async!"); } ``` @@ -171,7 +173,7 @@ loop { If we wrote that code, though, we would block the computer from doing anything else, though—the opposite of what we were going for. It also wouldn’t compile -for three other reasons, though: +for three other reasons: 1. The `poll` method actually requires an argument: a `Context` that carries along a way to say when to call it again, to avoid exactly the problem of From 63baf226c424ba265220eee6ab66e679d20f8c6f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 1 May 2024 11:32:15 -0600 Subject: [PATCH 018/249] Ch. 17: fix a misplaced period --- src/ch17-02.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-02.md b/src/ch17-02.md index c1cff2e869..57b002d415 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -11,7 +11,7 @@ widely used async runtime, especially (but not only!) for web applications. > the alternatives. 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 +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, and in a couple cases wires up a few things for you which are less relevant to the subject of the book. There is no magic involved, though! If you From c31d308f1836a69d6784bc623b68603c52d919bd Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 1 May 2024 11:32:15 -0600 Subject: [PATCH 019/249] Ch. 17: get to working async code sooner Move up the installation of the futures crate: get the initial example compiling as soon as possible (even though it is just "Hello, world!") and *then* explain what was going on. --- src/ch17-01-tasks.md | 143 ++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 62 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 561a5a10eb..32f8bf3120 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -7,11 +7,12 @@ and they let us solve some of these issues. However, they also have some 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 -multiple threads. While mainstream desktop and mobile operating systems have all -had threading for many years, many embedded operating systems used on -microcontrollers do not. +them! While mainstream desktop and mobile operating systems have all had +threading for many years, many embedded operating systems, like those used on +some microcontrollers, do not. -The async model provides a different, complementary set of tradeoffs. In +The async model provides a different—and ultimately complementary—set of +tradeoffs. In @@ -65,7 +66,10 @@ bit surprising: we did not write a return type on the function. However, we *did* mark it as an `async fn`. In Rust, `async fn` is equivalent to writing a function which returns a *future* of the return type, using the `impl Trait` syntax we discussed back in the [“Traits as Parameters”][impl-trait] section in -Chapter 10. So these two are roughly equivalent: +Chapter 10, and an `async` block compiles to an anonymous struct which +implements the `Future` trait. + +So these two are roughly equivalent: ```rust async fn hello_async() { @@ -73,28 +77,41 @@ async fn hello_async() { } ``` - - - ```rust fn hello_async() -> impl Future { - println!("Hello, async!"); + async { + println!("Hello, async!"); + } } ``` -That explains why we got the `unused_must_use` warning. The other part of the -warning was the note that we need to `.await` or poll the future. Rust's `await` -keyword is a postfix keyword, meaning it goes *after* the expression you are -awaiting. (As of now, `await` is the only postfix keyword in the language.) -Let’s try that here: - + + +That explains why we got the `unused_must_use` warning: writing `async fn` meant +we were actually returning an anonymous `Future`. Just like with `Result`, Rust +will let us know if we don’t use a `Future`. It is often a mistake to ignore an +error in an operation your program performed. With a `Future`, it is even more +significant. To see why, let’s look at the other part of the warning. It told us +that “futures do nothing unless you `.await` or poll them”. That is, futures are +*lazy*: they don’t do anything until you ask them to. The compiler is telling us +that ignoring a `Future` makes it completely useless! We will see why that is +later on. For now, let’s start by awaiting the future returned by `hello_async` +to actually have it run. + +> Note: Rust’s `await` keyword goes *after* the expression you are awaiting—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 async and non-async methods much nicer to work +> with. As of now, `await` is the only postfix keyword in the language. + + ```rust fn main() { hello_async().await; } ``` -Now we actually have a compiler error! +Oh no! We have gone from a compiler warning ton an actual error: ```text error[E0728]: `await` is only allowed inside `async` functions and blocks @@ -106,12 +123,48 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks | ^^^^^ only allowed inside `async` functions and blocks ``` -Okay, so we cannot actually use `.await` in `main`, because it is not an `async` -function itself—and it cannot be. To understand why, we need to pause to see -what a `Future` actually is and why it needs to be `.await`-ed or polled to do -anything. +This time, the compiler is informing us we cannot actually use `.await` in +`main`, because `main` is not an `async` function. As of today, it cannot be +without some extra help: it needs a *runtime* to execute the asynchronous code. +For now, we can solve that by adding the runtime built into the `futures` crate, +an official home for Rust experimentation for async code. Since we will be using +a bunch of tools from that crate for the rest of the chapter, let’s go ahead and +add it to the dependencies for our test project: + +``` +cargo add futures@0.3 +``` + +Now we can use the executor which comes with `futures` to run the code. The +`futures::executor::block_on` function takes in a `Future` and runs it until it +completes. + +```rust +use futures::executor; + +fn main() { + executor::block_on(hello_async()); +} + +async fn hello_async() { + println!("Hello, async!"); +} +``` + +Now when we run this, we get the behavior we might have expected initially: + +```console +$ cargo run + Compiling hello-async v0.1.0 (/Users/chris/dev/chriskrycho/async-trpl-fun/hello-async) + Finished dev [unoptimized + debuginfo] target(s) in 4.89s + Running `target/debug/hello-async` +Hello, async! +``` + +Phew: we finally have some working async code! To understand why we needed this, +let’s dig in a little more into what a `Future` actually is. -### Understanding `Future` +### Futures and runtimes Since `async fn` compiles to a return type with `impl Future`, we know that `Future` is a trait, with an associated type `Output`. The other part @@ -132,7 +185,7 @@ 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 future, 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 after becoming > ready! Futures which are safe to poll again will say so explicitly in their > documentation. @@ -192,11 +245,11 @@ When we use the `async fn` form with `.await`, Rust compiles it to something smarter than the `loop` above, in conjunction with a *runtime* responsible for executing that loop. -Some languages, including Go, Kotlin, Erlang, and Swift, ship runtimes with the -language. In Rust, there are many different runtimes, because the things a -runtime for a high-throughput web server with dozens of CPU cores and terabytes -of RAM should do are very different from the things a runtime for a -microcontroller with a single core and one gigabyte of RAM should do. +> Note: Some languages, including Go, Kotlin, Erlang, and Swift, ship runtimes +> with the language. In Rust, there are many different runtimes, because a +> runtime might need to do very different things to support a high-throughput +> web server with dozens of CPU cores and terabytes of RAM than it would for a +> microcontroller with a single core and one gigabyte of RAM should do. @@ -215,41 +268,7 @@ digging into. In particular, see [Chapter 4: Pinning][pinning] in the official Going back to `main`, this explains why we cannot have an `async fn main`: what -would execute the async code? We need to pick a runtime and executor. We can get -started with that easily by using the simple one that comes bundled with the -`futures` crate, an official home for Rust experimentation for async code. Since -we will be using a bunch of tools from that crate for the rest of the chapter, -let’s go ahead and add it to the dependencies for our test project: - -``` -cargo add futures@0.3 -``` - -Now we can use the executor which comes with `futures` to run the code. The -`futures::executor::block_on` function takes in a `Future` and runs it until it -completes. - -```rust -use futures::executor; - -fn main() { - executor::block_on(hello_async()); -} - -async fn hello_async() { - println!("Hello, async!"); -} -``` - -Now when we run this, we get the behavior we might have expected initially: - -```console -$ cargo run - Compiling hello-async v0.1.0 (/Users/chris/dev/chriskrycho/async-trpl-fun/hello-async) - Finished dev [unoptimized + debuginfo] target(s) in 4.89s - Running `target/debug/hello-async` -Hello, async! -``` +would execute the async code? We need to pick a runtime and executor. Now, that’s a lot of work to just print a string, but we have laid some key foundations for working with async in Rust! Now that you know the basics of how From dee72208b8384ec164642e43fe76fba25a3b9112 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 9 May 2024 16:35:28 -0600 Subject: [PATCH 020/249] Ch. 17: add to table of contents so `mdbook serve` is useful --- src/SUMMARY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index a004483b1e..daa9a07af7 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -102,6 +102,8 @@ - [Extensible Concurrency with the `Sync` and `Send` Traits](ch16-04-extensible-concurrency-sync-and-send.md) - [Async and Await](ch17-00-async-await.md) + - [Futures and the Async Syntax](ch17-01-tasks.md) + - [something something tokio?!?](ch17-02.md) - [Object Oriented Programming Features of Rust](ch18-00-oop.md) - [Characteristics of Object-Oriented Languages](ch18-01-what-is-oo.md) From 5b3c27eb4ac60291e808b9f90798cf39709b86ef Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 9 May 2024 16:51:16 -0600 Subject: [PATCH 021/249] Ch. 17: clarify language about Tokio --- src/ch17-02.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ch17-02.md b/src/ch17-02.md index 57b002d415..bb0306ff2f 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -7,8 +7,8 @@ For the rest of the chapter, we will be using [Tokio][tokio], which is the most widely used async runtime, especially (but not only!) for web applications. > Note: There are other great options out there, too, and they may be more -> suitable for your purposes, so this is not at all saying Tokio is better than -> the alternatives. +> suitable for your purposes. We are using Tokio because it is the most widely +> used runtime—not as a judgment call on whether it is the *best* runtime! 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 From ebebf8c166ad7026ab4d3840fea455283b8837f9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 9 May 2024 16:54:09 -0600 Subject: [PATCH 022/249] Ch. 17: use `trpl`, not `futures`, even for initial code samples - Update the instructions to install `trpl` instead of `futures`, and move the introductory text there. - Update the note about Tokio in 17.02 to describe both `futures` and `tokio`. --- src/ch17-01-tasks.md | 30 ++++++++++++++++++------------ src/ch17-02.md | 40 ++++++++++++++++------------------------ 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 32f8bf3120..be642fcec2 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -126,24 +126,29 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks This time, the compiler is informing us we cannot actually use `.await` in `main`, because `main` is not an `async` function. As of today, it cannot be without some extra help: it needs a *runtime* to execute the asynchronous code. -For now, we can solve that by adding the runtime built into the `futures` crate, -an official home for Rust experimentation for async code. Since we will be using -a bunch of tools from that crate for the rest of the chapter, let’s go ahead and -add it to the dependencies for our test project: -``` -cargo add futures@0.3 +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, and in a couple cases wires up a few things for you which are less +relevant to the subject of the book. There is no magic involved, though! 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 handful of +helper functions we supply are doing. + +For now, go ahead and add the dependency to your `hello-async` project: + +```console +$ cargo add trpl ``` -Now we can use the executor which comes with `futures` to run the code. The -`futures::executor::block_on` function takes in a `Future` and runs it until it -completes. +Now we can get our code working by using the `trpl::block_on` function, which +takes in a `Future` and runs it until it completes. ```rust -use futures::executor; - fn main() { - executor::block_on(hello_async()); + trpl::block_on(hello_async()); } async fn hello_async() { @@ -153,6 +158,7 @@ async fn hello_async() { Now when we run this, we get the behavior we might have expected initially: + ```console $ cargo run Compiling hello-async v0.1.0 (/Users/chris/dev/chriskrycho/async-trpl-fun/hello-async) diff --git a/src/ch17-02.md b/src/ch17-02.md index bb0306ff2f..fc650165df 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -3,30 +3,21 @@ quite limited. It works quite well, but if you are going to build a real-world application, you will likely want to use the executor from one of the *other* runtimes in the Rust ecosystem. -For the rest of the chapter, we will be using [Tokio][tokio], which is the most -widely used async runtime, especially (but not only!) for web applications. - -> Note: There are other great options out there, too, and they may be more -> suitable for your purposes. We are using Tokio because it is the most widely -> used runtime—not as a judgment call on whether it is the *best* runtime! - -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, and in a couple cases wires up a few things for you which are less -relevant to the subject of the book. There is no magic involved, though! 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 handful of -helper functions we supply are doing. - -For now, go ahead and add the dependency to your `hello-async` project: - -```console -$ cargo add trpl -``` - -Okay, now let’s start exploring . Going forward, we will use a new `async_main` +> ### The `futures` and `tokio` Crates +> +> Whenever you see code from the `trpl` crate throughout the rest of the +> chapter, it will be re-exporting code from the `futures` 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 options out there, +> too, and they may be more suitable for your purposes. We are using Tokio +> because it is the most widely-used runtime—not as a judgment call on whether +> it is the *best* runtime! + +Okay, now let’s start exploring. Going forward, we will use a new `async_main` macro so that we can use `async fn` with a `main` function. Under the hood, this little utility macro from Tokio sets up the Tokio runtime and wires up a call kind of like we saw with `futures::executor::block_on` in the previous section. @@ -45,5 +36,6 @@ async fn main() { Now we can use `async` blocks directly in `main` and not worry about wiring up the runtime ourselves. + [tokio]: https://tokio.rs [crate-source]: TODO From ee0704d4736c9aebb2f7808f2c5816504312de38 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 9 May 2024 16:54:09 -0600 Subject: [PATCH 023/249] Ch. 17: text/code ordering fix in 17.02 --- src/ch17-02.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ch17-02.md b/src/ch17-02.md index fc650165df..9dfa186927 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -21,6 +21,8 @@ Okay, now let’s start exploring. Going forward, we will use a new `async_main` macro so that we can use `async fn` with a `main` function. Under the hood, this little utility macro from Tokio sets up the Tokio runtime and wires up a call kind of like we saw with `futures::executor::block_on` in the previous section. +Now we can use `async` blocks directly in `main` and not worry about wiring up +the runtime ourselves: ```rust use trpl::async_main; @@ -33,8 +35,6 @@ async fn main() { } ``` -Now we can use `async` blocks directly in `main` and not worry about wiring up -the runtime ourselves. [tokio]: https://tokio.rs From 40df04923b9750ae2e72132898759460f2eb482f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Apr 2024 16:57:00 -0600 Subject: [PATCH 024/249] Prepare to integrate into TRPL repo --- CONTRIBUTING.md => packages/trpl/CONTRIBUTING.md | 0 Cargo.lock => packages/trpl/Cargo.lock | 0 Cargo.toml => packages/trpl/Cargo.toml | 0 LICENSE-APACHE => packages/trpl/LICENSE-APACHE | 0 LICENSE-MIT => packages/trpl/LICENSE-MIT | 0 README.md => packages/trpl/README.md | 0 {src => packages/trpl/src}/lib.rs | 0 {tests => packages/trpl/tests}/integration/main.rs | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTING.md => packages/trpl/CONTRIBUTING.md (100%) rename Cargo.lock => packages/trpl/Cargo.lock (100%) rename Cargo.toml => packages/trpl/Cargo.toml (100%) rename LICENSE-APACHE => packages/trpl/LICENSE-APACHE (100%) rename LICENSE-MIT => packages/trpl/LICENSE-MIT (100%) rename README.md => packages/trpl/README.md (100%) rename {src => packages/trpl/src}/lib.rs (100%) rename {tests => packages/trpl/tests}/integration/main.rs (100%) diff --git a/CONTRIBUTING.md b/packages/trpl/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to packages/trpl/CONTRIBUTING.md diff --git a/Cargo.lock b/packages/trpl/Cargo.lock similarity index 100% rename from Cargo.lock rename to packages/trpl/Cargo.lock diff --git a/Cargo.toml b/packages/trpl/Cargo.toml similarity index 100% rename from Cargo.toml rename to packages/trpl/Cargo.toml diff --git a/LICENSE-APACHE b/packages/trpl/LICENSE-APACHE similarity index 100% rename from LICENSE-APACHE rename to packages/trpl/LICENSE-APACHE diff --git a/LICENSE-MIT b/packages/trpl/LICENSE-MIT similarity index 100% rename from LICENSE-MIT rename to packages/trpl/LICENSE-MIT diff --git a/README.md b/packages/trpl/README.md similarity index 100% rename from README.md rename to packages/trpl/README.md diff --git a/src/lib.rs b/packages/trpl/src/lib.rs similarity index 100% rename from src/lib.rs rename to packages/trpl/src/lib.rs diff --git a/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs similarity index 100% rename from tests/integration/main.rs rename to packages/trpl/tests/integration/main.rs From 8f6bcc72404a121c51f2bf9636fa3d917f6a8198 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 10 May 2024 09:09:43 -0600 Subject: [PATCH 025/249] Ch. 17: expand, clarify, and restructure 17.01 - Explicitly section out the discussions of async functions and blocks and the associated `async` and `.await` syntax from defining `Future` and explaining how it works. - Also a bunch of small phrasing tweaks. --- src/ch17-01-tasks.md | 49 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index be642fcec2..9c379c45fb 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -1,7 +1,5 @@ ## Futures and the Async Syntax -### Tasks - As we saw in the previous chapter, threads provide one approach to concurrency, and they let us solve some of these issues. However, they also have some tradeoffs. On many operating systems, they use a fair bit of memory for each @@ -22,15 +20,12 @@ being managed by the operating system, it is managed by a runtime. -### - -Like many other languages with first-class support for the async programming -model, Rust uses the `async` and `await` keywords—though with some important -differences from other languages like C# or JavaScript. 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. +Like other languages with async, Rust uses the `async` and `await` +keywords—though with some important differences, as we will see. 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. -Let’s write our first async function: +Let’s write our first async function, and call it: ```rust fn main() { @@ -60,16 +55,21 @@ warning: `hello-async` (bin "hello-async") generated 1 warning Running `target/debug/hello-async` ``` -The warning tells us why nothing happened. Calling `hello_async()` itself was -not enough: we need to `.await`or poll the “future” it returns. That might be a -bit surprising: we did not write a return type on the function. However, we -*did* mark it as an `async fn`. In Rust, `async fn` is equivalent to writing a -function which returns a *future* of the return type, using the `impl Trait` -syntax we discussed back in the [“Traits as Parameters”][impl-trait] section in -Chapter 10, and an `async` block compiles to an anonymous struct which -implements the `Future` trait. +The warning tells us that just calling `hello_async()` was not enough: we also +need to `.await` or poll the future it returns. This raises two important +questions: + +- Given there is no return type on the function, how is it returning a future? +- What is a future? + +### Async functions + +In Rust, `async fn` is equivalent to writing a function which returns a +future of the return type, using the `impl Trait` syntax we discussed back in +the [“Traits as Parameters”][impl-trait] section in Chapter 10. An `async` +block compiles to an anonymous struct which implements the `Future` trait. -So these two are roughly equivalent: +That means these two are roughly equivalent: ```rust async fn hello_async() { @@ -137,7 +137,7 @@ 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 handful of helper functions we supply are doing. -For now, go ahead and add the dependency to your `hello-async` project: +For now, go ahead and add the `trpl` crate to your `hello-async` project: ```console $ cargo add trpl @@ -167,10 +167,11 @@ $ cargo run Hello, async! ``` -Phew: we finally have some working async code! To understand why we needed this, -let’s dig in a little more into what a `Future` actually is. +Phew: we finally have some working async code! Now we can answer that second +question: what is a future anyway? That will also help us understand why we need +a runtime to make this work. -### Futures and runtimes +### Futures Since `async fn` compiles to a return type with `impl Future`, we know that `Future` is a trait, with an associated type `Output`. The other part @@ -184,7 +185,7 @@ enum Poll { } ``` -You might have noticed that this `Poll` type is a lot like an `Option`. Having a +You may notice that this `Poll` type is a lot like an `Option`. Having a dedicated type lets Rust treat `Poll` differently from `Option`, though, which is important since they have very different meanings! The `Pending` variant indicates that the future still has work to do, so the caller will need to check From 0c00b174d455c1fe15bed0b69e766901c844c8f4 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 10 May 2024 14:06:44 -0600 Subject: [PATCH 026/249] Ch. 17: reorganize 17.01 and get a useable intro to Future --- src/ch17-01-tasks.md | 139 ++++++++++++++++++++++++------------------- src/ch17-02.md | 7 ++- 2 files changed, 82 insertions(+), 64 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 9c379c45fb..b634c052f7 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -91,12 +91,16 @@ That explains why we got the `unused_must_use` warning: writing `async fn` meant we were actually returning an anonymous `Future`. Just like with `Result`, Rust will let us know if we don’t use a `Future`. It is often a mistake to ignore an error in an operation your program performed. With a `Future`, it is even more -significant. To see why, let’s look at the other part of the warning. It told us -that “futures do nothing unless you `.await` or poll them”. That is, futures are -*lazy*: they don’t do anything until you ask them to. The compiler is telling us -that ignoring a `Future` makes it completely useless! We will see why that is -later on. For now, let’s start by awaiting the future returned by `hello_async` -to actually have it run. +significant. The compiler also warned us that “futures do nothing unless you +`.await` or poll them”. That is, futures are *lazy*: they don’t do anything +until you ask them to. + +The compiler is telling us that ignoring a `Future` makes it completely useless! +This is different from the behavior we saw when using `thread::spawn` in the +previous chapter, and it is different from how many other languages approach +async. This allows Rust to avoid running async code unless it is actually +needed. We will see why that is later on. For now, let’s start by awaiting the +future returned by `hello_async` to actually have it run. > Note: Rust’s `await` keyword goes *after* the expression you are awaiting—that > is, it is a *postfix keyword*. This is different from what you might be used @@ -111,7 +115,7 @@ fn main() { } ``` -Oh no! We have gone from a compiler warning ton an actual error: +Oh no! We have gone from a compiler warning to an actual error: ```text error[E0728]: `await` is only allowed inside `async` functions and blocks @@ -123,9 +127,19 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks | ^^^^^ only allowed inside `async` functions and blocks ``` -This time, the compiler is informing us we cannot actually use `.await` in -`main`, because `main` is not an `async` function. As of today, it cannot be -without some extra help: it needs a *runtime* to execute the asynchronous code. +This time, the compiler is informing us we cannot use `.await` in `main`, +because `main` is not an `async` function. That is because async code needs a +*runtime*: a Rust crate which manages the details of executing the asynchronous +code, including whether or not to use threads for it, scheduling different async +operations, and so on. + +Most languages which support async, including C#, JavaScript, Go, Kotlin, +Erlang, and Swift, bundle a runtime with the language. At least for now, 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 dozens of CPU cores and terabytes of +RAM has very different different needs than a microcontroller with a single +core, one gigabyte of RAM, and no ability to do heap allocations. 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 @@ -143,8 +157,9 @@ For now, go ahead and add the `trpl` crate to your `hello-async` project: $ cargo add trpl ``` -Now we can get our code working by using the `trpl::block_on` function, which -takes in a `Future` and runs it until it completes. +In our `main` function, let’s wrap the call to `hello_async` with the +`trpl::block_on` function, which takes in a `Future` and runs it until it +completes. ```rust fn main() { @@ -156,7 +171,7 @@ async fn hello_async() { } ``` -Now when we run this, we get the behavior we might have expected initially: +When we run this, we get the behavior we might have expected initially: ```console @@ -169,14 +184,31 @@ Hello, async! Phew: we finally have some working async code! Now we can answer that second question: what is a future anyway? That will also help us understand why we need -a runtime to make this work. +that `trpl::block_on` call to make this work. ### Futures -Since `async fn` compiles to a return type with `impl Future`, we -know that `Future` is a trait, with an associated type `Output`. The other part -of the trait is its one method: `poll`. The `poll` method returns a fairly -simple type: +A *future* is a data structure which represents the state of some async +operation. More precisely, a Rust `Future` is a trait; it allows many different +data structures to represent different async operations in different ways, but +with a common interface. Here is the definition of the trait: + +```rust +pub trait Future { + type Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} +``` + +`Future` has an associated type, `Output`, which says what the result of the +future will be when it resolves. (This is analogous to the `Item` associated +type for the `Iterator` trait, which we saw back in Chapter 13.) Beyond that, +`Future` has only one method: `poll`, which takes a special `Pin` reference for +its `self` parameter and a mutable reference to some `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 { @@ -198,7 +230,7 @@ work and the `T` value is available. > documentation. Under the hood, when you call `.await`, Rust compiles that to code which calls -`poll` instead, kind of like this: +`poll`, kind of like this: ```rust @@ -231,51 +263,33 @@ loop { } ``` -If we wrote that code, though, we would block the computer from doing anything -else, though—the opposite of what we were going for. It also wouldn’t compile -for three other reasons: - -1. The `poll` method actually requires an argument: a `Context` that carries - along a way to say when to call it again, to avoid exactly the problem of - blocking other operations from making progress. - -2. The `Future` returned by our `async fn` is not actually ready to use here, - because `poll` requires that the future be “pinned”—guaranteed not to get - moved around in memory, so that any references to the future can be checked - for memory safety. - -3. Even if we pinned the future, this code would move `hello_async_fut` in the - first iteration through the `loop`. After the first time through the loop, we - would not be able to call it again. - -When we use the `async fn` form with `.await`, Rust compiles it to something -smarter than the `loop` above, in conjunction with a *runtime* responsible for -executing that loop. - -> Note: Some languages, including Go, Kotlin, Erlang, and Swift, ship runtimes -> with the language. In Rust, there are many different runtimes, because a -> runtime might need to do very different things to support a high-throughput -> web server with dozens of CPU cores and terabytes of RAM than it would for a -> microcontroller with a single core and one gigabyte of RAM should do. - - - -The other thing to notice here is that futures in Rust are *lazy*. They do not -do anything until you explicitly ask them to—whether by calling `poll` or by -using `.await` to do so. This is different from the behavior we saw when using -`thread::spawn` in the previous chapter, and it is different from how many other -languages approach async. This allows Rust to avoid running async code unless it -is actually needed, and supports some of the memory safety features Rust brings -to async. (The details are beyond the scope of this book, but are well worth -digging into. In particular, see [Chapter 4: Pinning][pinning] in the official -[_Asynchronous Programming in Rust_][async-book] book.) +And in fact, when we use `.await`, Rust compiles it to something very similar to +that `loop`. However, if Rust compiled it to *only* that code, every `.await` +would block the computer from doing anything else—the opposite of what we were +going for! -### Running Async Code +> Note: It also wouldn’t compile, because it doesn’t actually satisfy the +> contract for a `Future`. In particular, `hello_async_fut` is not *pinned* with +> the `Pin` type and we did not pass along a `Context` argument. The details are +> beyond the scope of this book, but are well worth digging into. In particular, +> see [Chapter 4: Pinning][pinning] in the official [_Asynchronous Programming +> in Rust_][async-book] book. + + - +What is more, eventually we end up back in some non-async function. At that point, something needs to “translate” between the async +and sync worlds. That “something” is a *runtime*, a crate which handles the +top-level `poll()` call, scheduling and handing off between the different async +operations which may be in flight, and often providing async versions of +functionality like file I/O. -Going back to `main`, this explains why we cannot have an `async fn main`: what -would execute the async code? We need to pick a runtime and executor. +Now we can understand what is happening in Listing 17-XX. The `main` function is +not `async`—and it really cannot be: if it were, something would need to call +`poll()` on whatever `main` returned! Instead, we use the `trpl::block_on` +function, which polls the `Future` returned by `hello_async` until it returns +`Ready`. + +### Running Async Code Now, that’s a lot of work to just print a string, but we have laid some key foundations for working with async in Rust! Now that you know the basics of how @@ -284,3 +298,6 @@ futures work, and the [impl-trait]: ch10-02-traits.html#traits-as-parameters [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 + + diff --git a/src/ch17-02.md b/src/ch17-02.md index 9dfa186927..0eeb815d7b 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -6,11 +6,12 @@ runtimes in the Rust ecosystem. > ### The `futures` and `tokio` Crates > > Whenever you see code from the `trpl` crate throughout the rest of the -> chapter, it will be re-exporting code from the `futures` and [`tokio`][tokio] crates. +> chapter, it will be re-exporting code from the `futures` 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 options out there, > too, and they may be more suitable for your purposes. We are using Tokio @@ -38,4 +39,4 @@ async fn main() { [tokio]: https://tokio.rs -[crate-source]: TODO + From 23027cb6ece4fb200c612003f7cc23387b143ddb Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 10 May 2024 14:15:44 -0600 Subject: [PATCH 027/249] Ch. 17: wording and formatting in 17.01 --- src/ch17-01-tasks.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index b634c052f7..26237f901e 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -64,10 +64,10 @@ questions: ### Async functions -In Rust, `async fn` is equivalent to writing a function which returns a -future of the return type, using the `impl Trait` syntax we discussed back in -the [“Traits as Parameters”][impl-trait] section in Chapter 10. An `async` -block compiles to an anonymous struct which implements the `Future` trait. +In Rust, `async fn` is equivalent to writing a function which returns a future +of the return type, using the `impl Trait` syntax we discussed back in the +[“Traits as Parameters”][impl-trait] section in Chapter 10. An `async` block +compiles to an anonymous struct which implements the `Future` trait. That means these two are roughly equivalent: @@ -102,12 +102,6 @@ async. This allows Rust to avoid running async code unless it is actually needed. We will see why that is later on. For now, let’s start by awaiting the future returned by `hello_async` to actually have it run. -> Note: Rust’s `await` keyword goes *after* the expression you are awaiting—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 async and non-async methods much nicer to work -> with. As of now, `await` is the only postfix keyword in the language. - ```rust fn main() { @@ -115,6 +109,12 @@ fn main() { } ``` +> Note: Rust’s `await` keyword goes *after* the expression you are awaiting—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 async and non-async methods much nicer to work +> with. As of now, `await` is the only postfix keyword in the language. + Oh no! We have gone from a compiler warning to an actual error: ```text @@ -277,11 +277,11 @@ going for! -What is more, eventually we end up back in some non-async function. At that point, something needs to “translate” between the async -and sync worlds. That “something” is a *runtime*, a crate which handles the -top-level `poll()` call, scheduling and handing off between the different async -operations which may be in flight, and often providing async versions of -functionality like file I/O. +What is more, eventually we end up back in some non-async function. At that +point, something needs to “translate” between the async and sync worlds. That +“something” is a *runtime*, a crate which handles the top-level `poll()` call, +scheduling and handing off between the different async operations which may be +in flight, and often providing async versions of functionality like file I/O. Now we can understand what is happening in Listing 17-XX. The `main` function is not `async`—and it really cannot be: if it were, something would need to call @@ -293,7 +293,7 @@ function, which polls the `Future` returned by `hello_async` until it returns Now, that’s a lot of work to just print a string, but we have laid some key foundations for working with async in Rust! Now that you know the basics of how -futures work, and the +futures and runtimes work, we can see some of the things we can *do* with async. [impl-trait]: ch10-02-traits.html#traits-as-parameters [pinning]: https://rust-lang.github.io/async-book/04_pinning/01_chapter.html From 3cf4faeeca93731b0b37aa831608922d5290a48c Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 10 May 2024 16:27:15 -0600 Subject: [PATCH 028/249] Ch. 17: corrections/discussion on runtimes, mostly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tie off the discussion about needing a runtime so that it is clear what is needed in `main` and therefore why `main` cannot natively be `async` itself. - Correct the description of what `.await` compiles to. - Extend the note about the “under the hood” bits: mention generators so people know what to go looking for if they are curious. - Rewrite the existing introduction of the `#[async_main]` macro to lean on the material now covered in the previous chapter. --- src/ch17-01-tasks.md | 49 +++++++++++++++++++++++++------------------- src/ch17-02.md | 19 +++++++++-------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 26237f901e..2d747a0448 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -264,38 +264,45 @@ loop { ``` And in fact, when we use `.await`, Rust compiles it to something very similar to -that `loop`. However, if Rust compiled it to *only* that code, every `.await` -would block the computer from doing anything else—the opposite of what we were -going for! - -> Note: It also wouldn’t compile, because it doesn’t actually satisfy the -> contract for a `Future`. In particular, `hello_async_fut` is not *pinned* with -> the `Pin` type and we did not pass along a `Context` argument. The details are -> beyond the scope of this book, but are well worth digging into. In particular, -> see [Chapter 4: Pinning][pinning] in the official [_Asynchronous Programming -> in Rust_][async-book] book. - - - -What is more, eventually we end up back in some non-async function. At that -point, something needs to “translate” between the async and sync worlds. That -“something” is a *runtime*, a crate which handles the top-level `poll()` call, -scheduling and handing off between the different async operations which may be -in flight, and often providing async versions of functionality like file I/O. +that loop. If Rust compiled it to *exactly* that code, every `.await` would +block the computer from doing anything else—the opposite of what we were going +for! Instead, Rust internally makes sure that the loop can hand back control to +the the context of the code where which is awaiting this little bit of code. + +When we follow that chain far enough, eventually we end up back in some +non-async function. At that point, something needs to “translate” between the +async and sync worlds. That “something” is a *runtime*, a crate which handles +the top-level `poll()` call, scheduling and handing off between the different +async operations which may be in flight, and often providing async versions of +functionality like file I/O. Now we can understand what is happening in Listing 17-XX. The `main` function is not `async`—and it really cannot be: if it were, something would need to call `poll()` on whatever `main` returned! Instead, we use the `trpl::block_on` function, which polls the `Future` returned by `hello_async` until it returns -`Ready`. - -### Running Async Code +`Ready`. Every async program in Rust has at least one place where it sets up an +executor and executes code. + +> Note: Under the hood, Rust uses *generators* so that it can hand off control +> between different functions. These are an implementation detail, though, and +> you never have to think about it when writing Rust. +> +> The loop as written also wouldn’t compile, because it doesn’t actually satisfy +> the contract for a `Future`. In particular, `hello_async_fut` is not *pinned* +> with the `Pin` type and we did not pass along a `Context` argument. +> +> More details here are beyond the scope of this book, but are well worth +> digging into if you want to understand how things work “under the hood.” In +> particular, see [Chapter 2: Under the Hood: Executing Futures and +> Tasks][under-the-hood] and [Chapter 4: Pinning][pinning] in the official +> [_Asynchronous Programming in Rust_][async-book] book. Now, that’s a lot of work to just print a string, but we have laid some key foundations for working with async in Rust! Now that you know the basics of how futures and runtimes work, we can see some of the things we can *do* with async. [impl-trait]: ch10-02-traits.html#traits-as-parameters +[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 diff --git a/src/ch17-02.md b/src/ch17-02.md index 0eeb815d7b..0cf64d42a3 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -1,7 +1,9 @@ The executor from `futures` we used in the previous section is intentionally -quite limited. It works quite well, but if you are going to build a real-world -application, you will likely want to use the executor from one of the *other* -runtimes in the Rust ecosystem. +quite limited. It works well, but it requires you to set it up yourself, as we +did in the previous chapter, and it it is not tuned for any particular use case. +Accordingly, if you are going to build a real-world application, you will likely +want to use the executor from one of the *other* runtimes in the Rust +ecosystem. Once again, we will use code from the `trpl` crate to set things up. > ### The `futures` and `tokio` Crates > @@ -18,12 +20,10 @@ runtimes in the Rust ecosystem. > because it is the most widely-used runtime—not as a judgment call on whether > it is the *best* runtime! -Okay, now let’s start exploring. Going forward, we will use a new `async_main` -macro so that we can use `async fn` with a `main` function. Under the hood, this -little utility macro from Tokio sets up the Tokio runtime and wires up a call -kind of like we saw with `futures::executor::block_on` in the previous section. -Now we can use `async` blocks directly in `main` and not worry about wiring up -the runtime ourselves: +This time, it uses a macro, `async_main`, which allows us to use `async fn` with +a `main` function. The macro just rewrites the function to do something similar +to what we wrote by hand in the previous chapter, but lets us skip writing it +out by hand. Now we can write that `async` block and `.await` it in `main`: ```rust use trpl::async_main; @@ -36,6 +36,7 @@ async fn main() { } ``` +Okay, now let’s start exploring. [tokio]: https://tokio.rs From c3ebabeea464e03c986e341b25868968f29590d7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 10 May 2024 16:28:39 -0600 Subject: [PATCH 029/249] Ch. 17: pull disconnected material out of 17.01 --- src/ch17-01-tasks.md | 20 -------------------- src/ch17-03-vs-threads.md | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 20 deletions(-) create mode 100644 src/ch17-03-vs-threads.md diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 2d747a0448..48ee45f4a5 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -1,25 +1,5 @@ ## Futures and the Async Syntax -As we saw in the previous chapter, threads provide one approach to concurrency, -and they let us solve some of these issues. However, they also have some -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! While mainstream desktop and mobile operating systems have all had -threading for many years, many embedded operating systems, like those used on -some microcontrollers, do not. - -The async model provides a different—and ultimately complementary—set of -tradeoffs. In - - - -In the async model, concurrent operations do not require their own threads. -Instead, they can run on *tasks*. A task is a bit like a thread, but instead of -being managed by the operating system, it is managed by a runtime. - - - Like other languages with async, Rust uses the `async` and `await` keywords—though with some important differences, as we will see. Blocks and functions can be marked `async`, and you can wait on the result of an `async` diff --git a/src/ch17-03-vs-threads.md b/src/ch17-03-vs-threads.md new file mode 100644 index 0000000000..63f270522f --- /dev/null +++ b/src/ch17-03-vs-threads.md @@ -0,0 +1,23 @@ + + +As we saw in the previous chapter, threads provide one approach to concurrency, +and they let us solve some of these issues. However, they also have some +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! While mainstream desktop and mobile operating systems have all had +threading for many years, many embedded operating systems, like those used on +some microcontrollers, do not. + +The async model provides a different—and ultimately complementary—set of +tradeoffs. In the async model, concurrent operations do not require their own +threads. Instead, they can run on *tasks*. A task is a bit like a thread, but +instead of being managed by the operating system, it is managed by code that +lives at the level of libraries. + + From 5657a4907186ff85194190dd92c044e0e6436269 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 10 May 2024 16:41:42 -0600 Subject: [PATCH 030/249] Ch. 17: minor wording improvement --- src/ch17-01-tasks.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 48ee45f4a5..75411528dc 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -1,9 +1,10 @@ ## Futures and the Async Syntax Like other languages with async, Rust uses the `async` and `await` -keywords—though with some important differences, as we will see. 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. +keywords—though with some important differences from how other languages do +things, as we will see. 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. Let’s write our first async function, and call it: From b4e30305b72b6f48a0111bb43bd6778e28e27845 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 14 May 2024 12:25:48 -0600 Subject: [PATCH 031/249] Ch. 17: eliminate duplicate runtime description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep both references, but make the first one a simple definition, and the second one the “ah, now we can make sense of that definition”. --- src/ch17-01-tasks.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index c045d1cd26..7ce057fcd9 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -112,13 +112,10 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks | ^^^^^ only allowed inside `async` functions and blocks ``` - - This time, the compiler is informing us we cannot use `.await` in `main`, because `main` is not an `async` function. That is because async code needs a -*runtime*: a Rust crate which manages the details of executing the asynchronous -code, including whether or not to use threads for it, scheduling different async -operations, and so on. +*runtime*: a Rust crate which manages the details of executing asynchronous +code. Most languages which support async, including C#, JavaScript, Go, Kotlin, Erlang, and Swift, bundle a runtime with the language. At least for now, Rust @@ -266,10 +263,10 @@ of code. When we follow that chain far enough, eventually we end up back in some non-async function. At that point, something needs to “translate” between the -async and sync worlds. That “something” is a *runtime*, a crate which handles -the top-level `poll()` call, scheduling and handing off between the different -async operations which may be in flight, and often providing async versions of -functionality like file I/O. +async and sync worlds. That “something” is the runtime! Whatever runtime you use +is what handles the top-level `poll()` call, scheduling and handing off between +the different async operations which may be in flight, and often also providing +async versions of functionality like file I/O. Now we can understand why the compiler was blocking us in Listing 17-2 (before we added the `trpl::block_on` function). The `main` function is not `async`—and From 95105d23d7da27abc7deadb541a539ccb83a1b83 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 14 May 2024 15:59:10 -0600 Subject: [PATCH 032/249] Ch. 17: Add `futures` to `trpl` crate for re-exports --- Cargo.lock | 36 +++++++++++++++++++++++++ packages/trpl/Cargo.toml | 1 + packages/trpl/src/lib.rs | 1 + packages/trpl/tests/integration/main.rs | 8 +++++- 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5203a716e4..03c7ee8b62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -501,6 +501,21 @@ dependencies = [ "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" @@ -517,6 +532,23 @@ 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" @@ -546,10 +578,13 @@ 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", @@ -1908,6 +1943,7 @@ dependencies = [ name = "trpl" version = "0.1.0" dependencies = [ + "futures", "tokio", ] diff --git a/packages/trpl/Cargo.toml b/packages/trpl/Cargo.toml index fe35925a69..046f95da5b 100644 --- a/packages/trpl/Cargo.toml +++ b/packages/trpl/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +futures = "0.3.30" tokio = { version = "1", features = ["full"] } diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index a0fddb1b09..4d8c08fcab 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -12,4 +12,5 @@ //! never be broken by upstream changes, e.g. if Tokio does a breaking 2.0 //! release at some point. +pub use futures::executor::block_on; pub use tokio::main as async_main; diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index fd232ccc7e..8f091d5df4 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -9,7 +9,7 @@ //! //! [post]: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html -use trpl::async_main; +use trpl::{async_main, block_on}; /// This test makes sure the re-exported version of the `tokio::main` macro, /// which is applied like `#[tokio::main] async fn some_fn() { … }`, continues @@ -27,3 +27,9 @@ fn re_exported_macro_works() { assert_eq!(internal(), "Hello", "value returns correctly"); } + +#[test] +fn re_exported_block_on_works() { + let val = block_on(async { "Hello" }); + assert_eq!(val, "Hello"); +} From f418ceba2e3f7d805b297519c356a34effcac7b8 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 14 May 2024 15:59:10 -0600 Subject: [PATCH 033/249] Ch. 17: abandon attempt to re-export `tokio::main` Re-exporting the macro does not work unless you have `tokio` as a direct dependency, because its expansion is in terms of Tokio doc-hidden items. --- packages/trpl/src/lib.rs | 22 ++++++++++-- packages/trpl/tests/integration/main.rs | 42 +++++++++++++--------- src/ch17-01-tasks.md | 16 +++++++++ src/ch17-02.md | 48 +------------------------ 4 files changed, 62 insertions(+), 66 deletions(-) diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 4d8c08fcab..521aa28cb1 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -12,5 +12,23 @@ //! never be broken by upstream changes, e.g. if Tokio does a breaking 2.0 //! release at some point. -pub use futures::executor::block_on; -pub use tokio::main as async_main; +use std::future::Future; + +pub use futures::future::join; +pub use tokio::{runtime::Runtime, task::spawn as spawn_task, time::sleep}; + +/// Run a single future to completion on a bespoke Tokio `Runtime`. +/// +/// Every time you call this, a new instance of `tokio::runtime::Runtime` will +/// be created (see the implementation for details: it is trivial). This is: +/// +/// - Reasonable for teaching purposes, in that you do not generally need to set +/// up more than one runtime anyway, and especially do not in basic code like +/// we are showing! +/// +/// - 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 { + 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 8f091d5df4..e55aea5703 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -9,27 +9,35 @@ //! //! [post]: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html -use trpl::{async_main, block_on}; +use trpl::{block_on, sleep, spawn_task}; -/// This test makes sure the re-exported version of the `tokio::main` macro, -/// which is applied like `#[tokio::main] async fn some_fn() { … }`, continues -/// to work. However, tests cannot use `async fn`, so to test it, we need to -/// have a non-`async` test function, which then applies the macro to an `async` -/// function in its body, and invokes *that*. +/// This test is foundational for all the others, as they depend on `block_on`. +/// +/// 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_macro_works() { - #[async_main] - async fn internal() -> &'static str { - let val = async { "Hello" }.await; - assert_eq!(val, "Hello", "Async is usable in async_main function"); - val - } +fn re_exported_block_on_works() { + let val = block_on(async { "Hello" }); + assert_eq!(val, "Hello"); +} - assert_eq!(internal(), "Hello", "value returns correctly"); +#[test] +fn re_exported_spawn_works() { + let result = block_on(async { + let handle_a = spawn_task(async { "Hello" }); + let handle_b = spawn_task(async { "Goodbye" }); + vec![handle_a.await.unwrap(), handle_b.await.unwrap()] + }); + + assert_eq!(result, vec!["Hello", "Goodbye"]); } #[test] -fn re_exported_block_on_works() { - let val = block_on(async { "Hello" }); - assert_eq!(val, "Hello"); +fn re_exported_sleep_works() { + let val = block_on(async { + sleep(std::time::Duration::from_micros(1)).await; + "Done!" + }); + assert_eq!(val, "Done!"); } diff --git a/src/ch17-01-tasks.md b/src/ch17-01-tasks.md index 7ce057fcd9..0654274fe3 100644 --- a/src/ch17-01-tasks.md +++ b/src/ch17-01-tasks.md @@ -135,6 +135,21 @@ 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 handful of helper functions we supply are doing. +> ### The `futures` and `tokio` Crates +> +> Whenever you see code from the `trpl` crate throughout the rest of the +> chapter, it will be re-exporting code from the `futures` 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 options out there, +> too, and they may be more suitable for your purposes. We are using Tokio +> because it is the most widely-used runtime—not as a judgment call on whether +> it is the *best* runtime! + For now, go ahead and add the `trpl` crate to your `hello-async` project: ```console @@ -299,5 +314,6 @@ futures and runtimes work, we can see some of the things we can *do* with async. [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 +[tokio]: https://tokio.rs diff --git a/src/ch17-02.md b/src/ch17-02.md index 116c5040f6..2ff1a880d6 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -1,47 +1 @@ -The executor from `futures` we used in the previous section is intentionally -quite limited. It works well, but it requires you to set it up yourself, as we -did in the previous chapter, and it it is not tuned for any particular use case. -Accordingly, if you are going to build a real-world application, you will likely -want to use the executor from one of the *other* runtimes in the Rust -ecosystem. Once again, we will use code from the `trpl` crate to set things up. - -> ### The `futures` and `tokio` Crates -> -> Whenever you see code from the `trpl` crate throughout the rest of the -> chapter, it will be re-exporting code from the `futures` 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 options out there, -> too, and they may be more suitable for your purposes. We are using Tokio -> because it is the most widely-used runtime—not as a judgment call on whether -> it is the *best* runtime! - -This time, it uses a macro, `async_main`, which allows us to use `async fn` with -a `main` function. The macro just rewrites the function to do something similar -to what we wrote by hand in the previous chapter, but lets us skip writing it -out by hand. Now we can write that `async` block and `.await` it in `main`: - -- -```rust -use trpl::async_main; - -#[async_main] -async fn main() { - async { - println!("Hello, world!"); - }.await; -} -``` - - - -Okay, now let’s start exploring. - - -[tokio]: https://tokio.rs - +## TODO: Section Title From 8e7420e2a18747d8760398a3caea161ce6bc3cee Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 14 May 2024 15:59:10 -0600 Subject: [PATCH 034/249] =?UTF-8?q?Ch.=2017:=20start=20in=20earnest=20on?= =?UTF-8?q?=20=C2=A72,=20showing=20relation=20to=20threads?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some listings which I can actually run, with `TODO` paths in them since I do not know what the numbers will be, since I have not actually finished with §0 or §1 yet! --- .../listing-TODO-01/Cargo.lock | 540 ++++++++++++++++++ .../listing-TODO-01/Cargo.toml | 9 + .../listing-TODO-01/src/main.rs | 17 + .../listing-TODO-02/Cargo.lock | 540 ++++++++++++++++++ .../listing-TODO-02/Cargo.toml | 9 + .../listing-TODO-02/src/main.rs | 19 + .../listing-TODO-03/Cargo.lock | 540 ++++++++++++++++++ .../listing-TODO-03/Cargo.toml | 9 + .../listing-TODO-03/src/main.rs | 21 + src/ch17-02.md | 110 ++++ 10 files changed, 1814 insertions(+) create mode 100644 listings/ch17-async-await/listing-TODO-01/Cargo.lock create mode 100644 listings/ch17-async-await/listing-TODO-01/Cargo.toml create mode 100644 listings/ch17-async-await/listing-TODO-01/src/main.rs create mode 100644 listings/ch17-async-await/listing-TODO-02/Cargo.lock create mode 100644 listings/ch17-async-await/listing-TODO-02/Cargo.toml create mode 100644 listings/ch17-async-await/listing-TODO-02/src/main.rs create mode 100644 listings/ch17-async-await/listing-TODO-03/Cargo.lock create mode 100644 listings/ch17-async-await/listing-TODO-03/Cargo.toml create mode 100644 listings/ch17-async-await/listing-TODO-03/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-01/Cargo.lock b/listings/ch17-async-await/listing-TODO-01/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-01/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-TODO-01/Cargo.toml b/listings/ch17-async-await/listing-TODO-01/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-01/Cargo.toml @@ -0,0 +1,9 @@ +[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-TODO-01/src/main.rs b/listings/ch17-async-await/listing-TODO-01/src/main.rs new file mode 100644 index 0000000000..4af024741e --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-01/src/main.rs @@ -0,0 +1,17 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + trpl::spawn_task(async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }); + + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }); +} diff --git a/listings/ch17-async-await/listing-TODO-02/Cargo.lock b/listings/ch17-async-await/listing-TODO-02/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-02/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-TODO-02/Cargo.toml b/listings/ch17-async-await/listing-TODO-02/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-02/Cargo.toml @@ -0,0 +1,9 @@ +[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-TODO-02/src/main.rs b/listings/ch17-async-await/listing-TODO-02/src/main.rs new file mode 100644 index 0000000000..71cb24e34c --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-02/src/main.rs @@ -0,0 +1,19 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let handle = trpl::spawn_task(async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }); + + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + + handle.await; + }); +} diff --git a/listings/ch17-async-await/listing-TODO-03/Cargo.lock b/listings/ch17-async-await/listing-TODO-03/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-03/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-TODO-03/Cargo.toml b/listings/ch17-async-await/listing-TODO-03/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-03/Cargo.toml @@ -0,0 +1,9 @@ +[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-TODO-03/src/main.rs b/listings/ch17-async-await/listing-TODO-03/src/main.rs new file mode 100644 index 0000000000..8797b5d634 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-03/src/main.rs @@ -0,0 +1,21 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let fut1 = async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }; + + let fut2 = async { + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }; + + trpl::join(fut1, fut2).await; + }); +} diff --git a/src/ch17-02.md b/src/ch17-02.md index 2ff1a880d6..eeb335866e 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -1 +1,111 @@ ## TODO: Section Title + +Back in Chapter 16, we saw an example of counting up on multiple threads. Given +that threads allow us to implement a form of concurrency, we might expect that +async APIs can substitute fairly directly for the threading APIs. 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: + + + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs}} +``` + + + +This does something very similar to what the thread-base implementation did, as +we can see from the output: + +```text +hi number 1 from the second task! +hi number 1 from the first task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +``` + +Just like with the threading example, you may see a different order in your own +terminal output when you run this. And, just like the threading example, if you +want to run all the way to the completion of the first 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. Here, we can use +`await` to do the same thing: + + + +```rust +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let handle = trpl::spawn_task(async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }); + + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + + handle.join().await + }); +} +``` + +Now the output again matches + +```text +hi number 1 from the second task! +hi number 1 from the first task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +hi number 6 from the first task! +hi number 7 from the first task! +hi number 8 from the first task! +hi number 9 from the first task! +``` + + + + + +```text +hi number 1 from the first task! +hi number 1 from the second task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +hi number 6 from the first task! +hi number 7 from the first task! +hi number 8 from the first task! +hi number 9 from the first task! +``` + +Here, at least with the implementation we are using in `trpl`, you will see +the exact same order every time, which is *very* different from what we saw with +threads. + From 1ee7975b247d0c00dace93257f7cd15355687d48 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 15 May 2024 09:31:53 -0600 Subject: [PATCH 035/249] =?UTF-8?q?Ch.=2017:=20add=20more=20examples=20and?= =?UTF-8?q?=20explanation=20to=20=C2=A702.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-TODO-01/src/main.rs | 8 ++ src/ch17-02.md | 98 ++++++++++++------- 2 files changed, 72 insertions(+), 34 deletions(-) diff --git a/listings/ch17-async-await/listing-TODO-01/src/main.rs b/listings/ch17-async-await/listing-TODO-01/src/main.rs index 4af024741e..e766efdf18 100644 --- a/listings/ch17-async-await/listing-TODO-01/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-01/src/main.rs @@ -1,7 +1,11 @@ +// ANCHOR: all use std::time::Duration; +// ANCHOR: block_on fn main() { trpl::block_on(async { + // ANCHOR_END: block_on + // ANCHOR: task trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); @@ -13,5 +17,9 @@ fn main() { println!("hi number {i} from the second task!"); trpl::sleep(Duration::from_millis(1)).await; } + // ANCHOR_END: task + // ANCHOR: block_on }); } +// ANCHOR_END: block_on +// ANCHOR_END: all diff --git a/src/ch17-02.md b/src/ch17-02.md index eeb335866e..0200abe2ce 100644 --- a/src/ch17-02.md +++ b/src/ch17-02.md @@ -6,23 +6,36 @@ async APIs can substitute fairly directly for the threading APIs. 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: +example as with threads. - +To start, we will set up our `main` function with `trpl::block_on`: + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:block_on}} +``` + +Then we can write two loops within that block, each with a `trpl::sleep` call in +them. Similar to the threading example, we put one in the body of a +`trpl::spawn_task`, just like we did with `thread::spawn`, and the other in a +top-level `for` loop. Notice that we also need to add a `.await` after the +`sleep` calls. + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:task}} +``` + +Putting that all together, we end up with the code in Listing 17-TODO: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:all}} ``` This does something very similar to what the thread-base implementation did, as -we can see from the output: +we can see from the output when we run it: ```text hi number 1 from the second task! @@ -43,31 +56,15 @@ 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. Here, we can use `await` to do the same thing: - + ```rust -use std::time::Duration; - -fn main() { - trpl::block_on(async { - let handle = trpl::spawn_task(async { - for i in 1..10 { - println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - }); - - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - - handle.join().await - }); -} +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-02/src/main.rs}} ``` -Now the output again matches + + +Now the output again looks like what we saw in the threading example. ```text hi number 1 from the second task! @@ -85,9 +82,30 @@ hi number 8 from the first task! hi number 9 from the first task! ``` - +So far, it looks like async and threads basically give us the same basic +behavior. However, there are a few important differences already. One was using +`.await` instead of calling `join` on the join handle. Another is that we needed +to await both `sleep` calls. Most importantly, though, we did not need to spawn +another operating system thread to do this. We were able to get concurrency for +just the cost of a task, which has much faster startup time and uses much less +memory than an OS thread. - + + +What is more, we actually do not need the `spawn_task` call at all to get +concurrency here. Remember that each async block compiles to an anonymous +future. That means we can put each of these two loops in an async block and then +ask the runtime to run them both to completion using `trpl::join`: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-03/src/main.rs}} +``` + + + +When we run this, we see both futures run to completion: ```text hi number 1 from the first task! @@ -105,7 +123,19 @@ hi number 8 from the first task! hi number 9 from the first task! ``` -Here, at least with the implementation we are using in `trpl`, you will see -the exact same order every time, which is *very* different from what we saw with -threads. - +Here, at least with the implementation we are using in `trpl`, you will see the +exact same order every time, which is very different from what we saw with +threads. That is because the `trpl::join` function is *fair*, meaning it checks +both futures at an equal rate. With threads, the operating system decides which +thread to check, and that is ultimately out of our control. With an async +runtime, the runtime itself decides which future to check, so it has the final +say. 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, +but a well-designed runtime can still guarantee fairness. + +Try combining different places to await the futures and see what they do. See if you can figure out what the output will be *before* running the code! + +* Remove the async block from around either or both of the loops. +* Await each async block immediately after defining it. +* Wrap only the first loop in an async block, and await the resulting future + after the body of second loop. From 9c1f4c8cd6712594924e17a58f3cecd63562bdfa Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 15 May 2024 16:44:01 -0600 Subject: [PATCH 036/249] Ch. 17: Finish 'Counting', start on 'Async Move Blocks' Also rename the files to match their actual titles now that I know them. Or at least: know a good first pass for them. --- src/SUMMARY.md | 4 +- ...tasks.md => ch17-01-futures-and-syntax.md} | 0 src/ch17-02-concurrency-with-async.md | 191 ++++++++++++++++++ src/ch17-02.md | 141 ------------- 4 files changed, 193 insertions(+), 143 deletions(-) rename src/{ch17-01-tasks.md => ch17-01-futures-and-syntax.md} (100%) create mode 100644 src/ch17-02-concurrency-with-async.md delete mode 100644 src/ch17-02.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index daa9a07af7..60680d1983 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -102,8 +102,8 @@ - [Extensible Concurrency with the `Sync` and `Send` Traits](ch16-04-extensible-concurrency-sync-and-send.md) - [Async and Await](ch17-00-async-await.md) - - [Futures and the Async Syntax](ch17-01-tasks.md) - - [something something tokio?!?](ch17-02.md) + - [Futures and the Async Syntax](ch17-01-futures-and-syntax.md) + - [Concurrency With Async](ch17-02-concurrency-with-async.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-tasks.md b/src/ch17-01-futures-and-syntax.md similarity index 100% rename from src/ch17-01-tasks.md rename to src/ch17-01-futures-and-syntax.md diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md new file mode 100644 index 0000000000..5e86b00fde --- /dev/null +++ b/src/ch17-02-concurrency-with-async.md @@ -0,0 +1,191 @@ +## Concurrency With Async + +In this section, we will apply async to some of the same concurrency challenges +we tackled with threads in chapter 16. Since we already talked about a lot of +the key ideas there, in this section we will focus on what is different between +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. + +### Counting + +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. + +To start, we will set up our `main` function with `trpl::block_on`: + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:block_on}} +``` + +Then we can write two loops within that block, each with a `trpl::sleep` call in +them. Similar to the threading example, we put one in the body of a +`trpl::spawn_task`, just like we did with `thread::spawn`, and the other in a +top-level `for` loop. Notice that we also need to add a `.await` after the +`sleep` calls. + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:task}} +``` + +Putting that all together, we end up with the code in Listing 17-TODO: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:all}} +``` + + + +This does something very similar to what the thread-base implementation did, as +we can see from the output when we run it. (As with the threading example, you +may see a different order in your own terminal output when you run this.) + +```text +hi number 1 from the second task! +hi number 1 from the first task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +``` + +This 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—just like threads are. Thus, 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. Here, we can use `await` to do the same thing: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-02/src/main.rs}} +``` + + + +Now the output again looks like what we saw in the threading example. + +```text +hi number 1 from the second task! +hi number 1 from the first task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +hi number 6 from the first task! +hi number 7 from the first task! +hi number 8 from the first task! +hi number 9 from the first task! +``` + +So far, it looks like async and threads basically give us the same basic +behavior. However, there are a few important differences already. One was using +`.await` instead of calling `join` on the join handle. Another is that we needed +to await both `sleep` calls. Most importantly, though, we did not need to spawn +another operating system thread to do this. We were able to get concurrency for +just the cost of a task, which has much faster startup time and uses much less +memory than an OS thread. + +What is more, we actually do not need the `spawn_task` call at all to get +concurrency here. Remember that each async block compiles to an anonymous +future. That means we can put each of these two loops in an async block and then +ask the runtime to run them both to completion using `trpl::join`: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-03/src/main.rs}} +``` + + + +When we run this, we see both futures run to completion: + +```text +hi number 1 from the first task! +hi number 1 from the second task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +hi number 6 from the first task! +hi number 7 from the first task! +hi number 8 from the first task! +hi number 9 from the first task! +``` + +Here, you will see the exact same order every time, which is very different from +what we saw with threads. That is because the `trpl::join` function is *fair*, +meaning it checks both futures equally, rather than letting one race ahead. With +threads, the operating system decides which thread to check, and that is +ultimately out of our control. With an async runtime, the runtime itself decides +which future to check, so it has the final say. 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, but a runtime can still choose +to guarantee fairness even so. However, runtimes do not have to guarantee +fairness for any given operation, and even within a given runtime, different +APIs sometimes exist to let you choose whether fairness is something you care +about as a caller. + +Try some of these different variations on awaiting the futures and see what they +do. For an extra challenge, see if you can figure out what the output will be +*before* running the code! + +* Remove the async block from around either or both of the loops. +* Await each async block immediately after defining it. +* Wrap only the first loop in an async block, and await the resulting future + after the body of second loop. + +### Tasks vs. Threads + + + +### Async Move Blocks + +In Chapter 13, we learned how to use the `move` keyword with closures, and in +Chapter 16, we saw that we often need to use closures marked with `move` when +working with threads. The `move` keyword also works with async blocks, which +also sometimes need to take ownership of the data they reference. Remember, any +time you write a future, a runtime is ultimately responsible for executing it. +That means that an async block might outlive the function where you write it, the +same way a closure does—even if you do not pass it to a closure explicitly. + +> Note: the `async` keyword does not yet work with closures directly, so you +> cannot write code like these function calls: +> +> ```rust,ignore +> example_1(async || { ... }); +> example_2(async move || { ... }); +> ``` +> +> However, since async blocks themselves can be marked with `move`, this ends up +> not being a problem. Remember that `async` blocks compile to anonymous +> futures. That means you can write calls like this instead: +> +> ```rust,ignore +> example_1(|| async { ... }); +> example_2(|| async move { ... }); +> ``` +> +> These closures now return anonymous futures, meaning they work basically the +> same way that an async function does. + +### Message Passing + +Sharing data between futures will look familiar. We can again use async versions +of Rust’s types for diff --git a/src/ch17-02.md b/src/ch17-02.md deleted file mode 100644 index 0200abe2ce..0000000000 --- a/src/ch17-02.md +++ /dev/null @@ -1,141 +0,0 @@ -## TODO: Section Title - -Back in Chapter 16, we saw an example of counting up on multiple threads. Given -that threads allow us to implement a form of concurrency, we might expect that -async APIs can substitute fairly directly for the threading APIs. 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. - -To start, we will set up our `main` function with `trpl::block_on`: - -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:block_on}} -``` - -Then we can write two loops within that block, each with a `trpl::sleep` call in -them. Similar to the threading example, we put one in the body of a -`trpl::spawn_task`, just like we did with `thread::spawn`, and the other in a -top-level `for` loop. Notice that we also need to add a `.await` after the -`sleep` calls. - -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:task}} -``` - -Putting that all together, we end up with the code in Listing 17-TODO: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:all}} -``` - - - -This does something very similar to what the thread-base implementation did, as -we can see from the output when we run it: - -```text -hi number 1 from the second task! -hi number 1 from the first task! -hi number 2 from the first task! -hi number 2 from the second task! -hi number 3 from the first task! -hi number 3 from the second task! -hi number 4 from the first task! -hi number 4 from the second task! -hi number 5 from the first task! -``` - -Just like with the threading example, you may see a different order in your own -terminal output when you run this. And, just like the threading example, if you -want to run all the way to the completion of the first 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. Here, we can use -`await` to do the same thing: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-02/src/main.rs}} -``` - - - -Now the output again looks like what we saw in the threading example. - -```text -hi number 1 from the second task! -hi number 1 from the first task! -hi number 2 from the first task! -hi number 2 from the second task! -hi number 3 from the first task! -hi number 3 from the second task! -hi number 4 from the first task! -hi number 4 from the second task! -hi number 5 from the first task! -hi number 6 from the first task! -hi number 7 from the first task! -hi number 8 from the first task! -hi number 9 from the first task! -``` - -So far, it looks like async and threads basically give us the same basic -behavior. However, there are a few important differences already. One was using -`.await` instead of calling `join` on the join handle. Another is that we needed -to await both `sleep` calls. Most importantly, though, we did not need to spawn -another operating system thread to do this. We were able to get concurrency for -just the cost of a task, which has much faster startup time and uses much less -memory than an OS thread. - - - -What is more, we actually do not need the `spawn_task` call at all to get -concurrency here. Remember that each async block compiles to an anonymous -future. That means we can put each of these two loops in an async block and then -ask the runtime to run them both to completion using `trpl::join`: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-03/src/main.rs}} -``` - - - -When we run this, we see both futures run to completion: - -```text -hi number 1 from the first task! -hi number 1 from the second task! -hi number 2 from the first task! -hi number 2 from the second task! -hi number 3 from the first task! -hi number 3 from the second task! -hi number 4 from the first task! -hi number 4 from the second task! -hi number 5 from the first task! -hi number 6 from the first task! -hi number 7 from the first task! -hi number 8 from the first task! -hi number 9 from the first task! -``` - -Here, at least with the implementation we are using in `trpl`, you will see the -exact same order every time, which is very different from what we saw with -threads. That is because the `trpl::join` function is *fair*, meaning it checks -both futures at an equal rate. With threads, the operating system decides which -thread to check, and that is ultimately out of our control. With an async -runtime, the runtime itself decides which future to check, so it has the final -say. 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, -but a well-designed runtime can still guarantee fairness. - -Try combining different places to await the futures and see what they do. See if you can figure out what the output will be *before* running the code! - -* Remove the async block from around either or both of the loops. -* Await each async block immediately after defining it. -* Wrap only the first loop in an async block, and await the resulting future - after the body of second loop. From c1c3c7fac80b38112054659e9da8ca6fc1d77b8b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 16 May 2024 14:06:15 -0600 Subject: [PATCH 037/249] =?UTF-8?q?Ch.=2017:=20start=20on=20message-passin?= =?UTF-8?q?g=20and=20`async=20move`=20in=20=C2=A72?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduce the relevant supporting features in `trpl`. - Add a couple listings to show how things do or do not work. --- .../listing-TODO-04/Cargo.lock | 540 ++++++++++++++++++ .../listing-TODO-04/Cargo.toml | 9 + .../listing-TODO-04/src/main.rs | 29 + .../listing-TODO-05/Cargo.lock | 540 ++++++++++++++++++ .../listing-TODO-05/Cargo.toml | 9 + .../listing-TODO-05/src/main.rs | 31 + packages/trpl/src/lib.rs | 21 +- packages/trpl/tests/integration/main.rs | 22 +- src/ch17-02-concurrency-with-async.md | 38 +- 9 files changed, 1233 insertions(+), 6 deletions(-) create mode 100644 listings/ch17-async-await/listing-TODO-04/Cargo.lock create mode 100644 listings/ch17-async-await/listing-TODO-04/Cargo.toml create mode 100644 listings/ch17-async-await/listing-TODO-04/src/main.rs create mode 100644 listings/ch17-async-await/listing-TODO-05/Cargo.lock create mode 100644 listings/ch17-async-await/listing-TODO-05/Cargo.toml create mode 100644 listings/ch17-async-await/listing-TODO-05/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-04/Cargo.lock b/listings/ch17-async-await/listing-TODO-04/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-TODO-04/Cargo.toml b/listings/ch17-async-await/listing-TODO-04/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04/Cargo.toml @@ -0,0 +1,9 @@ +[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-TODO-04/src/main.rs b/listings/ch17-async-await/listing-TODO-04/src/main.rs new file mode 100644 index 0000000000..2bd9e3353f --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04/src/main.rs @@ -0,0 +1,29 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + async { + let (tx, mut rx) = trpl::channel(); + + let tx_fut = async { + println!("Sending 'Hello'"); + tx.send("Hello").unwrap(); + println!("Sleeping!"); + trpl::sleep(Duration::from_millis(1)).await; + println!("Sending 'Goodbye'"); + tx.send("Goodbye").unwrap(); + }; + + let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; + } + .await; + }); + + println!("Done!"); +} diff --git a/listings/ch17-async-await/listing-TODO-05/Cargo.lock b/listings/ch17-async-await/listing-TODO-05/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-05/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-TODO-05/Cargo.toml b/listings/ch17-async-await/listing-TODO-05/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-05/Cargo.toml @@ -0,0 +1,9 @@ +[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-TODO-05/src/main.rs b/listings/ch17-async-await/listing-TODO-05/src/main.rs new file mode 100644 index 0000000000..8780297b10 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-05/src/main.rs @@ -0,0 +1,31 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + async { + let (tx, mut rx) = trpl::channel(); + + // ANCHOR: move + let tx_fut = async move { + // ANCHOR_END: move + println!("Sending 'Hello'"); + tx.send("Hello").unwrap(); + println!("Sleeping!"); + trpl::sleep(Duration::from_millis(1)).await; + println!("Sending 'Goodbye'"); + tx.send("Goodbye").unwrap(); + }; + + let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; + } + .await; + }); + + println!("Done!"); +} diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 521aa28cb1..d49290f111 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -15,7 +15,26 @@ use std::future::Future; pub use futures::future::join; -pub use tokio::{runtime::Runtime, task::spawn as spawn_task, time::sleep}; +pub use tokio::{ + runtime::Runtime, + // We use the `unbounded` variants because they most closely match the APIs + // from `std::sync::mpsc::channel`. Tokio's API choices are interesting: + // + // | `tokio::sync::mpsc` | `std::sync::mpsc` | + // | ------------------- | ----------------- | + // | `channel` | `sync_channel` | + // | `unbounded_channel` | `channel` | + // + // The book collapses these differences for pedagogical simplicity, so that + // readers are not asking why `unbounded` is now important and can focus on + // the more important differences between sync and async APIs. + sync::mpsc::{ + unbounded_channel as channel, UnboundedReceiver as Receiver, + UnboundedSender as Sender, + }, + task::spawn as spawn_task, + time::sleep, +}; /// Run a single future to completion on a bespoke Tokio `Runtime`. /// diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index e55aea5703..17dc7e2e15 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -9,7 +9,9 @@ //! //! [post]: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html -use trpl::{block_on, sleep, spawn_task}; +use std::time::Duration; + +use trpl::{block_on, channel, sleep, spawn_task, Receiver, Sender}; /// This test is foundational for all the others, as they depend on `block_on`. /// @@ -36,8 +38,24 @@ fn re_exported_spawn_works() { #[test] fn re_exported_sleep_works() { let val = block_on(async { - sleep(std::time::Duration::from_micros(1)).await; + sleep(Duration::from_micros(1)).await; "Done!" }); assert_eq!(val, "Done!"); } + +#[test] +fn re_exported_channel_apis_work() { + block_on(async { + let (tx, mut rx) = channel(); + + tx.send("Hello").unwrap(); + trpl::sleep(Duration::from_millis(1)).await; + tx.send("Goodbye").unwrap(); + drop(tx); + + assert_eq!(rx.recv().await, Some("Hello")); + assert_eq!(rx.recv().await, Some("Goodbye")); + assert_eq!(rx.recv().await, None); + }); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 5e86b00fde..a8c29fe834 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -5,7 +5,10 @@ we tackled with threads in chapter 16. Since we already talked about a lot of the key ideas there, in this section we will focus on what is different between 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. +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. ### Counting @@ -165,7 +168,10 @@ time you write a future, a runtime is ultimately responsible for executing it. That means that an async block might outlive the function where you write it, the same way a closure does—even if you do not pass it to a closure explicitly. -> Note: the `async` keyword does not yet work with closures directly, so you + + +> Note: the `async` keyword does not yet work with closures directly—that is, +> there is no direct equivalent to `async fn` for anonymous functions—so you > cannot write code like these function calls: > > ```rust,ignore @@ -187,5 +193,31 @@ same way a closure does—even if you do not pass it to a closure explicitly. ### Message Passing + + Sharing data between futures will look familiar. We can again use async versions -of Rust’s types for +of Rust’s types for message-passing. Instead of `std::sync:mpsc::channel`, we +will use a `tprl::channel`, for example. The `Receiver::recv()` method in the +`std` channel blocks until it receives a message. The `trpl::Receiver::recv()` +method, by contrast, is an `async` function. Instead of blocking, it sleeps +until a message is received or the send side of the channel closes. + + + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04/src/main.rs}} +``` + + + +If we run this, though, it never stops! We can see that `rx` receives and prints all the messages, but + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-05/src/main.rs:move}} +``` + + From 4b7886e09245e9e39677f8796f5458368970d60b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 17 May 2024 15:18:21 -0600 Subject: [PATCH 038/249] Ch. 17: Finish a pass on Message Passing example - Incorporate a good discusion of the need to make sure that the `tx` in this example gets dropped. - Add more listings which show borrowing vs. moving a `tx`, covering the full territory in that example. - Add and test more re-exports in `trpl`. I made a conscious choice here *not* to use `future::join_all()` because that ends up getting into a discussion of `Pin`. I left a TODO item here for now because I think it is probably worth getting into, and that could be a good thing to transition to *after* this section. --- .../listing-TODO-04/src/main.rs | 39 +- .../listing-TODO-04b/Cargo.lock | 540 ++++++++++++++++++ .../listing-TODO-04b/Cargo.toml | 9 + .../listing-TODO-04b/src/main.rs | 38 ++ .../listing-TODO-05/src/main.rs | 37 +- packages/trpl/src/lib.rs | 2 +- packages/trpl/tests/integration/main.rs | 40 +- src/ch17-02-concurrency-with-async.md | 103 +++- 8 files changed, 752 insertions(+), 56 deletions(-) create mode 100644 listings/ch17-async-await/listing-TODO-04b/Cargo.lock create mode 100644 listings/ch17-async-await/listing-TODO-04b/Cargo.toml create mode 100644 listings/ch17-async-await/listing-TODO-04b/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-04/src/main.rs b/listings/ch17-async-await/listing-TODO-04/src/main.rs index 2bd9e3353f..d0e76ecd45 100644 --- a/listings/ch17-async-await/listing-TODO-04/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-04/src/main.rs @@ -1,29 +1,32 @@ +// ANCHOR: all use std::time::Duration; fn main() { trpl::block_on(async { - async { - let (tx, mut rx) = trpl::channel(); + let (tx, mut rx) = trpl::channel(); - let tx_fut = async { - println!("Sending 'Hello'"); - tx.send("Hello").unwrap(); - println!("Sleeping!"); - trpl::sleep(Duration::from_millis(1)).await; - println!("Sending 'Goodbye'"); - tx.send("Goodbye").unwrap(); - }; + let tx_fut = async { + println!("Sending 'Hello'"); + tx.send("Hello").unwrap(); - let rx_fut = async { - while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); - } - }; + println!("Sleeping!"); + trpl::sleep(Duration::from_millis(1)).await; - trpl::join(tx_fut, rx_fut).await; - } - .await; + println!("Sending 'Goodbye'"); + tx.send("Goodbye").unwrap(); + }; + + // ANCHOR: loop + let rx_fut = async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; + // ANCHOR_END: loop }); println!("Done!"); } +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-TODO-04b/Cargo.lock b/listings/ch17-async-await/listing-TODO-04b/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04b/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-TODO-04b/Cargo.toml b/listings/ch17-async-await/listing-TODO-04b/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04b/Cargo.toml @@ -0,0 +1,9 @@ +[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-TODO-04b/src/main.rs b/listings/ch17-async-await/listing-TODO-04b/src/main.rs new file mode 100644 index 0000000000..7fb7c9ce86 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04b/src/main.rs @@ -0,0 +1,38 @@ +use std::{boxed::Box, future::Future, pin::Pin, time::Duration}; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx_fut = async { + println!("Sending 'Hello'"); + tx.send("Hello").unwrap(); + + println!("Sleeping!"); + trpl::sleep(Duration::from_millis(1)).await; + + println!("Sending 'Goodbye'"); + tx.send("Goodbye").unwrap(); + }; + + let rx_fut = async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + }; + + // ANCHOR: updated + let tx_fut2 = async { + println!("Sending 'Extra'"); + tx.send("Extra").unwrap(); + + println!("Sleeping from tx_fut2"); + trpl::sleep(Duration::from_millis(1)).await; + }; + + trpl::join3(tx_fut, tx_fut2, rx_fut).await; + // ANCHOR_END: updated + }); + + println!("Done!"); +} diff --git a/listings/ch17-async-await/listing-TODO-05/src/main.rs b/listings/ch17-async-await/listing-TODO-05/src/main.rs index 8780297b10..6f24a19cff 100644 --- a/listings/ch17-async-await/listing-TODO-05/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-05/src/main.rs @@ -2,29 +2,26 @@ use std::time::Duration; fn main() { trpl::block_on(async { - async { - let (tx, mut rx) = trpl::channel(); + let (tx, mut rx) = trpl::channel(); - // ANCHOR: move - let tx_fut = async move { - // ANCHOR_END: move - println!("Sending 'Hello'"); - tx.send("Hello").unwrap(); - println!("Sleeping!"); - trpl::sleep(Duration::from_millis(1)).await; - println!("Sending 'Goodbye'"); - tx.send("Goodbye").unwrap(); - }; + // ANCHOR: move + let tx_fut = async move { + // ANCHOR_END: move + println!("Sending 'Hello'"); + tx.send("Hello").unwrap(); + println!("Sleeping!"); + trpl::sleep(Duration::from_millis(1)).await; + println!("Sending 'Goodbye'"); + tx.send("Goodbye").unwrap(); + }; - let rx_fut = async { - while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); - } - }; + let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; - trpl::join(tx_fut, rx_fut).await; - } - .await; + trpl::join(tx_fut, rx_fut).await; }); println!("Done!"); diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index d49290f111..43764b97e9 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -14,7 +14,7 @@ use std::future::Future; -pub use futures::future::join; +pub use futures::future::{join, join3}; pub use tokio::{ runtime::Runtime, // We use the `unbounded` variants because they most closely match the APIs diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index 17dc7e2e15..c0fa703562 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -11,7 +11,7 @@ use std::time::Duration; -use trpl::{block_on, channel, sleep, spawn_task, Receiver, Sender}; +use trpl::{Receiver, Sender}; /// This test is foundational for all the others, as they depend on `block_on`. /// @@ -20,15 +20,15 @@ use trpl::{block_on, channel, sleep, spawn_task, Receiver, Sender}; /// others will likely start working again. #[test] fn re_exported_block_on_works() { - let val = block_on(async { "Hello" }); + let val = trpl::block_on(async { "Hello" }); assert_eq!(val, "Hello"); } #[test] fn re_exported_spawn_works() { - let result = block_on(async { - let handle_a = spawn_task(async { "Hello" }); - let handle_b = spawn_task(async { "Goodbye" }); + let result = trpl::block_on(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()] }); @@ -37,8 +37,8 @@ fn re_exported_spawn_works() { #[test] fn re_exported_sleep_works() { - let val = block_on(async { - sleep(Duration::from_micros(1)).await; + let val = trpl::block_on(async { + trpl::sleep(Duration::from_micros(1)).await; "Done!" }); assert_eq!(val, "Done!"); @@ -46,8 +46,9 @@ fn re_exported_sleep_works() { #[test] fn re_exported_channel_apis_work() { - block_on(async { - let (tx, mut rx) = channel(); + trpl::block_on(async { + // Explicitly naming the type to confirm the re-exports are aligned. + let (tx, mut rx): (Sender<&str>, Receiver<&str>) = trpl::channel(); tx.send("Hello").unwrap(); trpl::sleep(Duration::from_millis(1)).await; @@ -59,3 +60,24 @@ fn re_exported_channel_apis_work() { assert_eq!(rx.recv().await, None); }); } + +#[test] +fn re_exported_join_apis_work() { + let result = trpl::block_on(async { + let a = async { 1 }; + let b = async { 2 }; + trpl::join(a, b).await + }); + + assert_eq!(result, (1, 2)); + + let result = trpl::block_on(async { + let a = async { 1 }; + let b = async { 2 }; + let c = async { 3 }; + + trpl::join3(a, b, c).await + }); + + assert_eq!(result, (1, 2, 3)); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index a8c29fe834..132acd9635 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -165,8 +165,8 @@ Chapter 16, we saw that we often need to use closures marked with `move` when working with threads. The `move` keyword also works with async blocks, which also sometimes need to take ownership of the data they reference. Remember, any time you write a future, a runtime is ultimately responsible for executing it. -That means that an async block might outlive the function where you write it, the -same way a closure does—even if you do not pass it to a closure explicitly. +That means that an async block might outlive the function where you write it, +the same way a closure does—even if you do not pass it to a closure explicitly. @@ -197,22 +197,100 @@ same way a closure does—even if you do not pass it to a closure explicitly. Sharing data between futures will look familiar. We can again use async versions of Rust’s types for message-passing. Instead of `std::sync:mpsc::channel`, we -will use a `tprl::channel`, for example. The `Receiver::recv()` method in the -`std` channel blocks until it receives a message. The `trpl::Receiver::recv()` -method, by contrast, is an `async` function. Instead of blocking, it sleeps -until a message is received or the send side of the channel closes. +will use a `tprl::channel`, for example. + +The `Receiver::recv()` method in the `std` channel blocks until it receives a +message. The `trpl::Receiver::recv()` method, by contrast, is an `async` +function. Instead of blocking, it sleeps until a message is received or the send +side of the channel closes. One other difference with this particular `recv()` +implementation is that it returns an `Option` of the type sent over the channel +instead of a `Result`. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04/src/main.rs:all}} +``` + + + +If we run this, though, it never stops! You will need to shut it down using +ctrl-c. We can see that `tx` sends all the +messages,and `rx` receives and prints them, but we never see the “Done!” +message, and the program never stops running. That’s because of the combination +of the `while let` loop and the `trpl::join` call: + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04/src/main.rs:loop}} +``` + +Let’s consider the way this loop works: + +* The `trpl::join` future only completes once *both* futures passed to it + have completed. +* The `tx` future completes after sending the second message. +* The `rx` future will not complete until the `while let` loop ends, though. +* 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, + `tx`, is dropped. +* We do not call `rx.close()` anywhere, and `tx` will not be dropped until the + function exits. +* The function cannot exit because it is blocked on `trpl::join` completing, + which takes us back to the top of the list! + +To solve this, then, we need to make sure the channel gets closed so that +`trpl::join` will complete. We could manually close `rx` somewhere by calling +`rx.close()`, but that does not make much sense in this case. The idea is that +`rx` should keep listening until `tx` is done sending. Stopping after handling +some arbitrary number of messages would make the program shut down, but it would +mean we could miss messages if the sending side changed. Given that we cannot +use `rx.close()`, we need to make sure that `tx` gets dropped *before* the end +of the function. + +Right now, the async block only borrows `tx`. We can confirm this by adding +another async block which uses `tx`, and using `trpl::join3` to wait for all +three futures to complete: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04b/src/main.rs:updated}} ``` -If we run this, though, it never stops! We can see that `rx` receives and prints all the messages, but +Now both blocks borrow `tx`, so they are both able to use it to send messages, +which `rx` can then receive. When we run that code, we see the extra output from +the new `async` block, and the message it sends being received by the +`rx.recv()`: + +```text +Sending 'Hello' +Sleeping! +Sending 'Extra' +Sleeping from tx_fut2 +received 'Hello' +received 'Extra' +Sending 'Goodbye' +received 'Goodbye' +``` + +As before, we also see that the program does not shut down on its own and requires a ctrl-c. Now that we have seen how `async` blocks borrow the items they reference from their outer scope, we can go ahead and remove the extra block we just added, and switch back to using `trpl::join` instead of `trpl::join3`. + +We now know enough to solve the original issue here. We need to move `tx` into +the async block. Once that block ends, `tx` will be dropped. We can do that by +making the first async block an `async move` block: + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-05/src/main.rs:move}} +``` + +The result is Listing 17-TODO, and when we run *this* version of the code, it +shuts down gracefully after the last message is sent. @@ -221,3 +299,12 @@ If we run this, though, it never stops! We can see that `rx` receives and prints ``` + + + + From 548329994b2b1c35cf929ea03e1cc880cddcd3c7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 22 May 2024 13:44:36 -0600 Subject: [PATCH 039/249] Exclude `trpl` from workspace It should manage its own dependencies. --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 2bddb66f9f..b65d859e5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ exclude = [ "linkchecker", # linkchecker is part of the CI workflow "listings", # these are intentionally distinct from the workspace "tmp", # listings are built here when updating output via tools/update-rustc.sh + "trpl", # manages its own dependencies as a standalone crate # These are used as path dependencies in `rust-lang/rust` (since we are not # publishing them to crates.io), so they cannot be part of this workspace, From acde825992ac8a9b5f1a6ff4b5d132fdf983b264 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 22 May 2024 13:45:06 -0600 Subject: [PATCH 040/249] Ch. 17: skip `main` and `trpl::block_on` in some listings Wherever it makes sense to elide these for the sake of clarity, do so! --- listings/ch17-async-await/listing-TODO-01/src/main.rs | 4 ++-- listings/ch17-async-await/listing-TODO-02/src/main.rs | 2 ++ listings/ch17-async-await/listing-TODO-03/src/main.rs | 2 ++ src/ch17-01-futures-and-syntax.md | 8 ++------ src/ch17-02-concurrency-with-async.md | 8 ++++++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/listings/ch17-async-await/listing-TODO-01/src/main.rs b/listings/ch17-async-await/listing-TODO-01/src/main.rs index e766efdf18..62b08cf5e9 100644 --- a/listings/ch17-async-await/listing-TODO-01/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-01/src/main.rs @@ -1,8 +1,8 @@ // ANCHOR: all use std::time::Duration; -// ANCHOR: block_on fn main() { + // ANCHOR: block_on trpl::block_on(async { // ANCHOR_END: block_on // ANCHOR: task @@ -20,6 +20,6 @@ fn main() { // ANCHOR_END: task // ANCHOR: block_on }); + // ANCHOR_END: block_on } -// ANCHOR_END: block_on // ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-TODO-02/src/main.rs b/listings/ch17-async-await/listing-TODO-02/src/main.rs index 71cb24e34c..079cbe06a9 100644 --- a/listings/ch17-async-await/listing-TODO-02/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-02/src/main.rs @@ -2,6 +2,7 @@ use std::time::Duration; fn main() { trpl::block_on(async { + // ANCHOR: handle let handle = trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); @@ -15,5 +16,6 @@ fn main() { } handle.await; + // ANCHOR_END: handle }); } diff --git a/listings/ch17-async-await/listing-TODO-03/src/main.rs b/listings/ch17-async-await/listing-TODO-03/src/main.rs index 8797b5d634..60889f3aed 100644 --- a/listings/ch17-async-await/listing-TODO-03/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-03/src/main.rs @@ -2,6 +2,7 @@ use std::time::Duration; fn main() { trpl::block_on(async { + // ANCHOR: join let fut1 = async { for i in 1..10 { println!("hi number {i} from the first task!"); @@ -17,5 +18,6 @@ fn main() { }; trpl::join(fut1, fut2).await; + // ANCHOR_END: join }); } diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 0654274fe3..e299f1b5d2 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -236,9 +236,7 @@ work and the `T` value is available. Under the hood, when you call `.await`, Rust compiles that to code which calls `poll`, kind of like this: - - -```rust +```rust,ignore match hello_async().poll() { Ready(_) => { // We’re done! @@ -253,9 +251,7 @@ As you can see from this sample, though, there is a question: what happens when the `Future` is still `Pending`? We need some way to try again. We would need to have something like this instead: - - -```rust +```rust,ignore let hello_async_fut = hello_async(); loop { match hello_async_fut.poll() { diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 132acd9635..f08907084d 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -24,6 +24,10 @@ To start, we will set up our `main` function with `trpl::block_on`: {{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:block_on}} ``` +> Note: From this point forward in the chapter, every example will include this +> exact same code, so we will often skip it just like we do with `main`. Don’t +> forget to include it in your own code! + Then we can write two loops within that block, each with a `trpl::sleep` call in them. Similar to the threading example, we put one in the body of a `trpl::spawn_task`, just like we did with `thread::spawn`, and the other in a @@ -70,7 +74,7 @@ thread was done running. Here, we can use `await` to do the same thing: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-02/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-02/src/main.rs:handle}} ``` @@ -109,7 +113,7 @@ ask the runtime to run them both to completion using `trpl::join`: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-03/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-03/src/main.rs:join}} ``` From 7b14d7dbde929b8c037779f3986e6b500b024a5f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 22 May 2024 13:45:06 -0600 Subject: [PATCH 041/249] Ch. 17: inline some note content and fix some phrasing --- src/ch17-02-concurrency-with-async.md | 44 +++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index f08907084d..028d7fc14c 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -48,7 +48,7 @@ Putting that all together, we end up with the code in Listing 17-TODO: -This does something very similar to what the thread-base implementation did, as +This does something very similar to what the thread-based implementation did, as we can see from the output when we run it. (As with the threading example, you may see a different order in your own terminal output when you run this.) @@ -170,30 +170,30 @@ working with threads. The `move` keyword also works with async blocks, which also sometimes need to take ownership of the data they reference. Remember, any time you write a future, a runtime is ultimately responsible for executing it. That means that an async block might outlive the function where you write it, -the same way a closure does—even if you do not pass it to a closure explicitly. +the same way a closure can. -> Note: the `async` keyword does not yet work with closures directly—that is, -> there is no direct equivalent to `async fn` for anonymous functions—so you -> cannot write code like these function calls: -> -> ```rust,ignore -> example_1(async || { ... }); -> example_2(async move || { ... }); -> ``` -> -> However, since async blocks themselves can be marked with `move`, this ends up -> not being a problem. Remember that `async` blocks compile to anonymous -> futures. That means you can write calls like this instead: -> -> ```rust,ignore -> example_1(|| async { ... }); -> example_2(|| async move { ... }); -> ``` -> -> These closures now return anonymous futures, meaning they work basically the -> same way that an async function does. +The `async` keyword does not yet work with closures directly. That is, there is +no direct equivalent to `async fn` for anonymous functions. As a result, you +cannot write code like these function calls: + +```rust,ignore +example_1(async || { ... }); +example_2(async move || { ... }); +``` + +However, since async blocks themselves can be marked with `move`, this ends up +not being a problem. Remember that `async` blocks compile to anonymous futures. +That means you can write calls like this instead: + +```rust,ignore +example_1(|| async { ... }); +example_2(|| async move { ... }); +``` + +These closures now return anonymous futures, meaning they work basically the +same way that an async function does. ### Message Passing From 1d7c987288d6e6313ec4fd1c32d6466ed306da90 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 22 May 2024 15:55:59 -0600 Subject: [PATCH 042/249] Ch. 17: Rewrite listings to be more similar to Ch. 16 --- .../listing-TODO-04/src/main.rs | 19 ++++---- .../listing-TODO-04b/src/main.rs | 43 +++++++++++-------- .../listing-TODO-05/src/main.rs | 19 ++++---- src/ch17-02-concurrency-with-async.md | 16 +++---- 4 files changed, 54 insertions(+), 43 deletions(-) diff --git a/listings/ch17-async-await/listing-TODO-04/src/main.rs b/listings/ch17-async-await/listing-TODO-04/src/main.rs index d0e76ecd45..0c364f43dd 100644 --- a/listings/ch17-async-await/listing-TODO-04/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-04/src/main.rs @@ -6,14 +6,17 @@ fn main() { let (tx, mut rx) = trpl::channel(); let tx_fut = async { - println!("Sending 'Hello'"); - tx.send("Hello").unwrap(); + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("future"), + ]; - println!("Sleeping!"); - trpl::sleep(Duration::from_millis(1)).await; - - println!("Sending 'Goodbye'"); - tx.send("Goodbye").unwrap(); + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_secs(1)).await; + } }; // ANCHOR: loop @@ -26,7 +29,5 @@ fn main() { trpl::join(tx_fut, rx_fut).await; // ANCHOR_END: loop }); - - println!("Done!"); } // ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-TODO-04b/src/main.rs b/listings/ch17-async-await/listing-TODO-04b/src/main.rs index 7fb7c9ce86..e5d8f86066 100644 --- a/listings/ch17-async-await/listing-TODO-04b/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-04b/src/main.rs @@ -1,38 +1,45 @@ -use std::{boxed::Box, future::Future, pin::Pin, time::Duration}; +use std::time::Duration; fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); let tx_fut = async { - println!("Sending 'Hello'"); - tx.send("Hello").unwrap(); - - println!("Sleeping!"); - trpl::sleep(Duration::from_millis(1)).await; - - println!("Sending 'Goodbye'"); - tx.send("Goodbye").unwrap(); + 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_secs(1)).await; + } }; let rx_fut = async { - while let Some(value) = rx.recv().await { - println!("received '{value}'"); + while let Some(received) = rx.recv().await { + println!("Got: {received}"); } }; // ANCHOR: updated let tx_fut2 = async { - println!("Sending 'Extra'"); - tx.send("Extra").unwrap(); - - println!("Sleeping from tx_fut2"); - trpl::sleep(Duration::from_millis(1)).await; + 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; + } }; trpl::join3(tx_fut, tx_fut2, rx_fut).await; // ANCHOR_END: updated }); - - println!("Done!"); } diff --git a/listings/ch17-async-await/listing-TODO-05/src/main.rs b/listings/ch17-async-await/listing-TODO-05/src/main.rs index 6f24a19cff..b88571997e 100644 --- a/listings/ch17-async-await/listing-TODO-05/src/main.rs +++ b/listings/ch17-async-await/listing-TODO-05/src/main.rs @@ -7,12 +7,17 @@ fn main() { // ANCHOR: move let tx_fut = async move { // ANCHOR_END: move - println!("Sending 'Hello'"); - tx.send("Hello").unwrap(); - println!("Sleeping!"); - trpl::sleep(Duration::from_millis(1)).await; - println!("Sending 'Goodbye'"); - tx.send("Goodbye").unwrap(); + 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_secs(1)).await; + } }; let rx_fut = async { @@ -23,6 +28,4 @@ fn main() { trpl::join(tx_fut, rx_fut).await; }); - - println!("Done!"); } diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 028d7fc14c..7002919027 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -273,14 +273,14 @@ the new `async` block, and the message it sends being received by the `rx.recv()`: ```text -Sending 'Hello' -Sleeping! -Sending 'Extra' -Sleeping from tx_fut2 -received 'Hello' -received 'Extra' -Sending 'Goodbye' -received 'Goodbye' +Got: hi +Got: more +Got: from +Got: messages +Got: the +Got: for +Got: future +Got: you ``` As before, we also see that the program does not shut down on its own and requires a ctrl-c. Now that we have seen how `async` blocks borrow the items they reference from their outer scope, we can go ahead and remove the extra block we just added, and switch back to using `trpl::join` instead of `trpl::join3`. From 1db4ee255afb14141399056a002b3ac8c941fff7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 22 May 2024 15:55:59 -0600 Subject: [PATCH 043/249] Ch. 17: wording and structure tweaks --- src/ch17-01-futures-and-syntax.md | 2 +- src/ch17-02-concurrency-with-async.md | 94 +++++++++++++++------------ 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index e299f1b5d2..8e943e3b4a 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -279,7 +279,7 @@ is what handles the top-level `poll()` call, scheduling and handing off between the different async operations which may be in flight, and often also providing async versions of functionality like file I/O. -Now we can understand why the compiler was blocking us in Listing 17-2 (before +Now we can understand why the compiler was stopping us in Listing 17-2 (before we added the `trpl::block_on` function). The `main` function is not `async`—and it really cannot be: if it were, something would need to call `poll()` on whatever `main` returned! Instead, we use the `trpl::block_on` function, which diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 7002919027..ea865e45d1 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -29,8 +29,8 @@ To start, we will set up our `main` function with `trpl::block_on`: > forget to include it in your own code! Then we can write two loops within that block, each with a `trpl::sleep` call in -them. Similar to the threading example, we put one in the body of a -`trpl::spawn_task`, just like we did with `thread::spawn`, and the other in a +them. Similar to the threading example, we put one loop in the body of a +`trpl::spawn_task`, the same way we did with `thread::spawn`, and the other in a top-level `for` loop. Notice that we also need to add a `.await` after the `sleep` calls. @@ -150,50 +150,19 @@ APIs sometimes exist to let you choose whether fairness is something you care about as a caller. Try some of these different variations on awaiting the futures and see what they -do. For an extra challenge, see if you can figure out what the output will be -*before* running the code! +do: * Remove the async block from around either or both of the loops. * Await each async block immediately after defining it. * Wrap only the first loop in an async block, and await the resulting future after the body of second loop. -### Tasks vs. Threads +For an extra challenge, see if you can figure out what the output will be in +each case *before* running the code! - - -### Async Move Blocks - -In Chapter 13, we learned how to use the `move` keyword with closures, and in -Chapter 16, we saw that we often need to use closures marked with `move` when -working with threads. The `move` keyword also works with async blocks, which -also sometimes need to take ownership of the data they reference. Remember, any -time you write a future, a runtime is ultimately responsible for executing it. -That means that an async block might outlive the function where you write it, -the same way a closure can. - - - -The `async` keyword does not yet work with closures directly. That is, there is -no direct equivalent to `async fn` for anonymous functions. As a result, you -cannot write code like these function calls: +### Futures, Tasks, and Threads -```rust,ignore -example_1(async || { ... }); -example_2(async move || { ... }); -``` - -However, since async blocks themselves can be marked with `move`, this ends up -not being a problem. Remember that `async` blocks compile to anonymous futures. -That means you can write calls like this instead: - -```rust,ignore -example_1(|| async { ... }); -example_2(|| async move { ... }); -``` - -These closures now return anonymous futures, meaning they work basically the -same way that an async function does. + ### Message Passing @@ -283,11 +252,29 @@ Got: future Got: you ``` -As before, we also see that the program does not shut down on its own and requires a ctrl-c. Now that we have seen how `async` blocks borrow the items they reference from their outer scope, we can go ahead and remove the extra block we just added, and switch back to using `trpl::join` instead of `trpl::join3`. +As before, we also see that the program does not shut down on its own and +requires a ctrl-c. Now that we have seen how +`async` blocks borrow the items they reference from their outer scope, we can go +ahead and remove the extra block we just added, and switch back to using +`trpl::join` instead of `trpl::join3`. -We now know enough to solve the original issue here. We need to move `tx` into -the async block. Once that block ends, `tx` will be dropped. We can do that by -making the first async block an `async move` block: +This little exploration makes the original issue much clearer: it is ultimately +about *ownership*. We need to move `tx` into the async block so that once that +block ends, `tx` will be dropped. + +In Chapter 13, we learned how to use the `move` keyword with closures, and in +Chapter 16, we saw that we often need to use closures marked with `move` when +working with threads. As we have discovered, the same dynamics apply to async +blocks—so the `move` keyword also works with async blocks, allowing them to take +ownership of the data they reference. + + +Remember, any time you write a future, a runtime is ultimately responsible for +executing it. That means that an async block might outlive the function where +you write it, the same way a closure can. + + +We can do that by making the first async block an `async move` block. ```rust {{#rustdoc_include ../listings/ch17-async-await/listing-TODO-05/src/main.rs:move}} @@ -312,3 +299,26 @@ shuts down gracefully after the last message is sent. --> + + +The `async` keyword does not yet work with closures directly. That is, there is +no direct equivalent to `async fn` for anonymous functions. As a result, you +cannot write code like these function calls: + +```rust,ignore +example_1(async || { ... }); +example_2(async move || { ... }); +``` + +However, since async blocks themselves can be marked with `move`, this ends up +not being a problem. Remember that `async` blocks compile to anonymous futures. +That means you can write calls like this instead: + +```rust,ignore +example_1(|| async { ... }); +example_2(|| async move { ... }); +``` + +These closures now return anonymous futures, meaning they work basically the +same way that an async function does. + From af18d2b969311846e8648b4b566fe6ee2452f080 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 22 May 2024 15:55:59 -0600 Subject: [PATCH 044/249] Ch. 17: show multiple producers working with `clone` --- .../listing-TODO-04b2/Cargo.lock | 540 ++++++++++++++++++ .../listing-TODO-04b2/Cargo.toml | 9 + .../listing-TODO-04b2/src/main.rs | 46 ++ src/ch17-02-concurrency-with-async.md | 22 + 4 files changed, 617 insertions(+) create mode 100644 listings/ch17-async-await/listing-TODO-04b2/Cargo.lock create mode 100644 listings/ch17-async-await/listing-TODO-04b2/Cargo.toml create mode 100644 listings/ch17-async-await/listing-TODO-04b2/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-04b2/Cargo.lock b/listings/ch17-async-await/listing-TODO-04b2/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04b2/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-TODO-04b2/Cargo.toml b/listings/ch17-async-await/listing-TODO-04b2/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04b2/Cargo.toml @@ -0,0 +1,9 @@ +[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-TODO-04b2/src/main.rs b/listings/ch17-async-await/listing-TODO-04b2/src/main.rs new file mode 100644 index 0000000000..4c5e65da9b --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-04b2/src/main.rs @@ -0,0 +1,46 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + // ANCHOR: here + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + trpl::join3(tx1_fut, tx_fut, rx_fut).await; + // ANCHOR_END: here + }); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index ea865e45d1..4a9102866a 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -179,6 +179,8 @@ side of the channel closes. One other difference with this particular `recv()` implementation is that it returns an `Option` of the type sent over the channel instead of a `Result`. +We can start by introducing an async version of the `channel` + @@ -291,6 +293,26 @@ shuts down gracefully after the last message is sent. +### Multiple Producers with Async + +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. For example, we can +make the code from Listing 17-TODO work by cloning the `tx` before moving it +into the first async block, moving the original `tx` into the second async +block, and switchign back to `join3`. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04b2/src/main.rs:here}} +``` + + + + +Both of these blocks need to be `async move` blocks, or else we will end up back +in the same infinite loop we started out in. + + +### Parallelism and Concurrency + In the previous chapter we treated parallelism and concurrency as interchangeable. Now we need to distinguish between the two a little more: @@ -54,34 +140,10 @@ can pause one activity and switch to others before eventually cycling back to that first activity again. So all parallel operations are also concurrent, but not all concurrent operations happen in parallel! -> Note: When working with async in Rust, we need to think in terms of -> *concurrency*. Depending on the hardware, the operating system, and the async -> runtime we are using, that concurrency may use some degree of parallelism -> under the hood, or it may not. More about async runtimes in a later section! - -Consider again the examples of exporting a video file and waiting on the video -file to finish uploading. 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, so -instead your computer can (and does!) invisibly interrupt the export often -enough to let you get other small amounts of work done along the way. - -The file upload is different. It does not take up very much CPU time. Instead, -you are mostly waiting on data to transfer across the network. If you only have -a single CPU core, you might write a bunch of data to a network socket and then -wait for it to finish getting sent by the network controller. You could choose -to wait for all the data to get “flushed” from the socket and actually sent over -the network, but if there is a busy network connection, you might be waiting for -a while… with your CPU doing not much! Thus, even if you make a blocking call to -write to a socket, your computer probably does other things while the network -operation is happening. - -In both of these cases, it might be useful for *your program* to participate in -the same kind of concurrency the computer is providing for the rest of the -system. One way to do this is the approach we saw last chapter: using threads, -which are provided and managed by the operating system. Another way to get -access to concurrency is using language-specific capabilities—like async. +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, that concurrency may use some degree of parallelism under the hood, or it +may not. (More about async runtimes later!) A big difference between the cooking analogy and Rust’s async model for concurrency is that in the cooking example, the cook makes the decision about diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 4a9102866a..f1684622a0 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -166,8 +166,6 @@ each case *before* running the code! ### Message Passing - - Sharing data between futures will look familiar. We can again use async versions of Rust’s types for message-passing. Instead of `std::sync:mpsc::channel`, we will use a `tprl::channel`, for example. From 1010b1fc51e910ea3c939576bb1f99b1750979b1 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 24 May 2024 11:22:22 -0600 Subject: [PATCH 046/249] Ch. 17: further motivation for async w/examples I am not 100% sure we will keep these, but right now they feel useful for helping see how `async` can help solve some of these problems. --- src/ch17-00-async-await.md | 96 +++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index dd56ec2a9f..2892948f93 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -4,7 +4,7 @@ In Chapter 16, we saw one of Rust’s approaches to concurrency: using threads. Since Rust 1.39, there has been another option for concurrency: asynchronous programming, or *async*. -In the rest of chapter, we will: +In the rest of this chapter, we will: * see how to use Rust’s `async` and `.await` syntax * explore how to use the async model to solve some of the same challenges we @@ -23,15 +23,12 @@ upload that video to some service to share it with your family, that upload process might take a long time. It would be nice if we could do something else while we are waiting for those long-running processes to complete. - - -Consider again the examples of exporting a video file and waiting on the video -file to finish uploading. 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, so -instead your computer can (and does!) invisibly interrupt the export often -enough to let you get other small amounts of work done along the way. +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, so instead your computer +can (and does!) invisibly interrupt the export often enough to let you get other +small amounts of work done along the way. The file upload is different. It does not take up very much CPU time. Instead, you are mostly waiting on data to transfer across the network. If you only have @@ -74,38 +71,81 @@ dedicated thread which handles the write operation, it will *not* block the rest of the program. But in many ways, it would be nicer if the call were not blocking in the first place. + + One way to accomplish that would be to use an API built around callbacks. For each blocking operation, we could pass in a function to call once the operation completes: ```rust,ignore -network_socket.non_blocking_send(data).and_then(|result| { +network_socket.non_blocking_send(data, |result| { + // ... +}); +``` + +Or we could register callbacks to run when events happen: + +```rust,ignore +network_socket.add_listener(Event::DoneSending, || { // ... }); ``` -This is the basic design of most event-based APIs. It is also the basic mechanic -used when working directly with promises in JavaScript. Historically, it was -also the way that Rust implemented async! This can make the control flow for the -program much more complicated, though. In particular, you can end up with many -nested callbacks, and debugging those can be very painful. Even with chains of -function calls, this can get laborious: +Or we could have our functions return a type with an `and_then` method on it, +which in turn accepts a callback which can do more work of the same sort: ```rust,ignore -network_socket - .non_blocking_send(data) - .and_then(|first_result| { /* another non_blocking operation */ }) - .and_then(|next_result| { /* another non_blocking operation */ }) - .and_then(|yet_another_result| { /* finish things up */ }); +network_socket.non_blocking_send(data) + .and_then(|result| { /* another non_blocking operation */ }) + .and_then(|next_result| { /* ... */ }); +``` + +Historically, this last choice was the way that Rust did async! Each of these +can make the control flow for the program more complicated, though. You can end +up with many nested callbacks, or long chains of callbacks, and understanding +the flow of data through the program can become more difficult as a result. + +With other common types in Rust, we often use pattern-matching in scenarios like +this. When we are using callbacks we do not yet have the data at the time we +call `non_blocking_send`—and we will not have it until the callback gets called. +That means that there is no way to match on the data it will return: it is not +here yet! + +There are also no particularly good ways to get data out of those callbacks. We +might try something like this, imagining a `read_to_string_non_blocking` which +has eaxctly the kind of `and_then` method described above. If we were to try to +use that, with code something like this, it would not compile: + +```rust,ignore,does_not_compile +let mut data = None; +read_to_string_non_blocking(some_path).and_then(|result| { + data = Some(result); +}); +println!("{data:?}"); ``` -With other common types in Rust, we often use pattern-matching on operations -like this. However, when we are using callbacks like these to avoid blocking, we -cannot use pattern matching, because we do not yet have the data at the time we -call `non_blocking_send`—and we will not have it until the callback gets -called. +The callback passed to `and_then` needs a mutable reference to `data`, but the +`load` function tries to return `data` to the caller. Rust would helpfully tell +us that we cannot borrow `data` immutably to print it because it is still +borrowed mutably for the `and_then` callback. This is not just Rust being fussy, +either: the result of this would normally always just print the `None` value and +exit, but if the read *happened* to go fast enough, it is possible it could +sometimes print some string data instead. That is *definitely* not what we +want! + +We also cannot cancel `read_to_string_non_blocking`: once it has started, it +will run till it finishes unless the whole program stops. + +What we really want to be able to write is something much simpler, like we would +in blocking code, but in a way that + +```rust,ignore,does_not_compile +let data = read_to_string_non_blocking(&path).await; +printl!("{data}"); +``` - +That is exactly what Rust’s async abstraction gives us. It is designed to help +us solve all of these issues. ### Parallelism and Concurrency From 8ce6c8a5442396e864b6e199a2655a8994264797 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 24 May 2024 17:13:10 -0600 Subject: [PATCH 047/249] =?UTF-8?q?Ch.=2017:=20rework=20=C2=A700=20to=20ta?= =?UTF-8?q?lk=20about=20reads=20instead=20of=20writes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets me combine the examples of trying to get data “out” with the existing network socket example, rather than introducing yet another imaginary API, and gives us a final API that looks much closer to what users will actually see with a real world socket. --- src/ch17-00-async-await.md | 82 ++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 2892948f93..296dae8bb0 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -19,9 +19,9 @@ First, though, let’s explore what async gives us. Many operations we ask the computer to do can take a while to finish. For example, if you used a video editor to create a video of a family celebration, exporting it could take anywhere from minutes to hours. Similarly, when you -upload that video to some service to share it with your family, that upload -process might take a long time. It would be nice if we could do something else -while we are waiting for those long-running processes to complete. +download a video shared by someone in your family, that download process might +take a long time. It would be nice if we could do something else while we are +waiting for those long-running 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 @@ -30,32 +30,35 @@ That would be a pretty frustrating experience, though, so instead your computer can (and does!) invisibly interrupt the export often enough to let you get other small amounts of work done along the way. -The file upload is different. It does not take up very much CPU time. Instead, -you are mostly waiting on data to transfer across the network. If you only have -a single CPU core, you might write a bunch of data to a network socket and then -wait for it to finish getting sent by the network controller. You could choose -to wait for all the data to get “flushed” from the socket and actually sent over -the network, but if there is a busy network connection, you might be waiting for -a while… with your CPU doing not much! Thus, even if your program cannot do -anything until it finishes writing data to a network socket, your computer -probably still does other things while the network operation is happening. +The file download is different. It does not take up very much CPU time. Instead, +you are mostly waiting on data to transfer across the network. You can start +reading from a network socket, but it might take a while for all the data to +arrive and be fed into the socket by the network controller. Moreover, 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 socket. Even if “some time” here is just a second +or two, that is a very long time for a modern processor, which can do billions +of operations every second. You could choose to wait for all of that to finish, +but you might be waiting for a while… with your CPU doing not much! Thus, even +if your specific program cannot do anything until it finishes reading data from +a network socket, your computer will once again invisibly interrupt your +program so other things can happen at the same time as the network operation. > Note: The video export is the kind of operation which is often described as > “CPU-bound”. It is limited by the speed of the computer’s CPU (and GPU), and -> how much of that power it can use. The video upload is the kind of operation +> how much of that power it can use. The video download is the kind of operation > which is often described as “IO-bound,” because it is limited by the speed of > the computer’s *input and output*. It can only go as fast as the data can be > sent across the network, which means that it can only go as fast as the data -> can be written to the socket. +> can be written to the socket by the network controller. In both of these examples, the concurrency happens at the level of the whole program. The operating system decides to interrupt the 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 lots of opportunities for concurrency that the operating system cannot see. For example, -if we are building a tool to manage file uploads, it is important that the user -interface stay responsive while an upload is happening. In fact, we should even -be able to start multiple uploads at the same time. +if we are building a tool to manage file downloads, it is important that the +user interface stay responsive while a download is happening. In fact, we should +even be able to start multiple downloads at the same time. However, many operating system APIs for interacting with network sockets are *blocking*. That is, the function calls block further progress in the program @@ -65,20 +68,18 @@ function calls which interact with files, network sockets, or other resources on the computer, because those are the places where an individual program would benefit from the operation being *non*-blocking. -When doing file uploads, we could work around the fact that the call to write to +When doing file downloads, we could work around the fact that the call to write to a network socket is blocking using threads. If we move the data over to a dedicated thread which handles the write operation, it will *not* block the rest of the program. But in many ways, it would be nicer if the call were not blocking in the first place. - - One way to accomplish that would be to use an API built around callbacks. For each blocking operation, we could pass in a function to call once the operation completes: ```rust,ignore -network_socket.non_blocking_send(data, |result| { +network_socket.read_non_blocking(|result| { // ... }); ``` @@ -86,18 +87,18 @@ network_socket.non_blocking_send(data, |result| { Or we could register callbacks to run when events happen: ```rust,ignore -network_socket.add_listener(Event::DoneSending, || { +network_socket.add_listener(Event::ReadFinished, |data| { // ... }); ``` -Or we could have our functions return a type with an `and_then` method on it, -which in turn accepts a callback which can do more work of the same sort: +Or we could have our functions return a type with `and_then` method, which in +turn accepts a callback which can do more work of the same sort: ```rust,ignore -network_socket.non_blocking_send(data) - .and_then(|result| { /* another non_blocking operation */ }) - .and_then(|next_result| { /* ... */ }); +network_socket.read_non_blocking().and_then(|result| { + /* another non_blocking operation */ +}); ``` Historically, this last choice was the way that Rust did async! Each of these @@ -107,18 +108,18 @@ the flow of data through the program can become more difficult as a result. With other common types in Rust, we often use pattern-matching in scenarios like this. When we are using callbacks we do not yet have the data at the time we -call `non_blocking_send`—and we will not have it until the callback gets called. +call `read_non_blocking`—and we will not have it until the callback gets called. That means that there is no way to match on the data it will return: it is not here yet! There are also no particularly good ways to get data out of those callbacks. We -might try something like this, imagining a `read_to_string_non_blocking` which -has eaxctly the kind of `and_then` method described above. If we were to try to -use that, with code something like this, it would not compile: +might try something like this, imagining a `read_non_blocking` which has exactly +the kind of `and_then` method described above. If we were to try to use that, +with code something like this, it would not compile: ```rust,ignore,does_not_compile let mut data = None; -read_to_string_non_blocking(some_path).and_then(|result| { +network_socket.read_non_blocking().and_then(|result| { data = Some(result); }); println!("{data:?}"); @@ -133,19 +134,20 @@ exit, but if the read *happened* to go fast enough, it is possible it could sometimes print some string data instead. That is *definitely* not what we want! -We also cannot cancel `read_to_string_non_blocking`: once it has started, it -will run till it finishes unless the whole program stops. +We also cannot cancel `read_non_blocking`: once it has started, it will run till +it finishes unless the whole program stops. -What we really want to be able to write is something much simpler, like we would -in blocking code, but in a way that +What we really want to be able to write is something much more direct, like we +would write in blocking code, but with the benefits of getting the data when it +is available and *not* blocking the rest of the program while waiting for the +data to arrive—something like this: ```rust,ignore,does_not_compile -let data = read_to_string_non_blocking(&path).await; -printl!("{data}"); +let data = network_socket.read(&path).await; +println!("{data}"); ``` That is exactly what Rust’s async abstraction gives us. It is designed to help -us solve all of these issues. ### Parallelism and Concurrency @@ -189,3 +191,5 @@ A big difference between the cooking analogy and Rust’s async model for concurrency is that in the cooking example, the cook makes the decision about when to switch tasks. In Rust’s async model, the tasks are in control of that. To see how, let’s look at how Rust actually uses async. +us solve all of these issues. In the next section, we will see how this works in +practice. From 52bf9e49a1652c9d4bb819bf02cba77e2b0ecb66 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 24 May 2024 17:13:10 -0600 Subject: [PATCH 048/249] =?UTF-8?q?Ch.=2017:=20extract=20parallelism=20dis?= =?UTF-8?q?cussion=20from=20=C2=A700=20to=20=C2=A703?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §03 is the current place I expect to tackle the distinctions between threads, tasks, and futures, and is therefore a reasonable home for a brief discussion on these two big ideas, I think? --- src/ch17-00-async-await.md | 43 ------------------------------------ src/ch17-03-vs-threads.md | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 296dae8bb0..7f97432f95 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -148,48 +148,5 @@ println!("{data}"); ``` That is exactly what Rust’s async abstraction gives us. It is designed to help - -### Parallelism and Concurrency - -In the previous chapter we treated parallelism and concurrency as -interchangeable. Now we need to distinguish between the two a little more: - -* *Parallelism* is when operations can happen simultaneously. - -* *Concurrency* is when operations can make progress without having to wait for - all other operations to complete. - -One common analogy for thinking about the difference between concurrency and -parallelism is cooking in a kitchen. Parallelism is like having two cooks: one -working on cooking eggs, and the other working on preparing fruit bowls. Those -can happen at the same time, without either affecting the other. Concurrency is -like having a single cook who can start cooking some eggs, start dicing up some -vegetables to use in the omelette, adding seasoning and whatever vegetables are -ready to the eggs at certain points, and switching back and forth between those -tasks. - -(This analogy breaks down if you think about it too hard. The eggs keep cooking -while the cook is chopping up the vegetables, after all. That is parallelism, -not just concurrency! The focus of the analogy is the *cook*, not the food, -though, and as long as you keep that in mind, it mostly works.) - -On a machine with multiple CPU cores, we can actually do work in parallel. One -core can be doing one thing while another core does something completely -unrelated, and those actually happen at the same time. On a machine with a -single CPU core, the CPU can only do one operation at a time, but we can still -have concurrency. Using tools like threads, processes, and async, the computer -can pause one activity and switch to others before eventually cycling back to -that first activity again. So all parallel operations are also concurrent, but -not all concurrent operations happen in parallel! - -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, that concurrency may use some degree of parallelism under the hood, or it -may not. (More about async runtimes later!) - -A big difference between the cooking analogy and Rust’s async model for -concurrency is that in the cooking example, the cook makes the decision about -when to switch tasks. In Rust’s async model, the tasks are in control of that. -To see how, let’s look at how Rust actually uses async. us solve all of these issues. In the next section, we will see how this works in practice. diff --git a/src/ch17-03-vs-threads.md b/src/ch17-03-vs-threads.md index 63f270522f..357213a174 100644 --- a/src/ch17-03-vs-threads.md +++ b/src/ch17-03-vs-threads.md @@ -21,3 +21,48 @@ lives at the level of libraries. task primitive to run (and there are runtimes which do *not* use tasks!) so it might make more sense to find another common, appropriate term for it instead. --> + +### Parallelism and Concurrency + +First, though, we need to dig a little deeper into the differences between +parallelism and concurrency. In the previous chapter we treated them as mostly +interchangeable. Now we need to distinguish between the two a little more, +because the differences will show up as we start working: + +* *Parallelism* is when operations can happen simultaneously. + +* *Concurrency* is when operations can make progress without having to wait for + all other operations to complete. + +One common analogy for thinking about the difference between concurrency and +parallelism is cooking in a kitchen. Parallelism is like having two cooks: one +working on cooking eggs, and the other working on preparing fruit bowls. Those +can happen at the same time, without either affecting the other. Concurrency is +like having a single cook who can start cooking some eggs, start dicing up some +vegetables to use in the omelette, adding seasoning and whatever vegetables are +ready to the eggs at certain points, and switching back and forth between those +tasks. + +(This analogy breaks down if you think about it too hard. The eggs keep cooking +while the cook is chopping up the vegetables, after all. That is parallelism, +not just concurrency! The focus of the analogy is the *cook*, not the food, +though, and as long as you keep that in mind, it mostly works.) + +On a machine with multiple CPU cores, we can actually do work in parallel. One +core can be doing one thing while another core does something completely +unrelated, and those actually happen at the same time. On a machine with a +single CPU core, the CPU can only do one operation at a time, but we can still +have concurrency. Using tools like threads, processes, and async, the computer +can pause one activity and switch to others before eventually cycling back to +that first activity again. So all parallel operations are also concurrent, but +not all concurrent operations happen in parallel! + +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, that concurrency may use some degree of parallelism under the hood, or it +may not. (More about async runtimes later!) + +A big difference between the cooking analogy and Rust’s async model for +concurrency is that in the cooking example, the cook makes the decision about +when to switch tasks. In Rust’s async model, the tasks are in control of that. +To see how, let’s look at how Rust actually uses async. From 3224ceba42e2ac9e78667989d771ad0bc5f44c10 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 27 May 2024 09:38:04 -0600 Subject: [PATCH 049/249] =?UTF-8?q?Ch.=2017:=20dedicate=20=C2=A703=20to=20?= =?UTF-8?q?'Futures,=20Tasks,=20and=20Threads'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move the heading out from §03. - Add this to the summary. --- src/SUMMARY.md | 1 + src/ch17-02-concurrency-with-async.md | 4 ---- ...ch17-03-vs-threads.md => ch17-03-futures-tasks-threads.md} | 4 +++- 3 files changed, 4 insertions(+), 5 deletions(-) rename src/{ch17-03-vs-threads.md => ch17-03-futures-tasks-threads.md} (97%) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 60680d1983..18c89533a5 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -104,6 +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) + - [Futures, Tasks, and Threads](ch17-03-futures-tasks-threads.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-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index f1684622a0..c829d18336 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -160,10 +160,6 @@ do: For an extra challenge, see if you can figure out what the output will be in each case *before* running the code! -### Futures, Tasks, and Threads - - - ### Message Passing Sharing data between futures will look familiar. We can again use async versions diff --git a/src/ch17-03-vs-threads.md b/src/ch17-03-futures-tasks-threads.md similarity index 97% rename from src/ch17-03-vs-threads.md rename to src/ch17-03-futures-tasks-threads.md index 357213a174..ca27ce27be 100644 --- a/src/ch17-03-vs-threads.md +++ b/src/ch17-03-futures-tasks-threads.md @@ -1,4 +1,6 @@ - +## Futures, Tasks, and Threads + + As we saw in the previous chapter, threads provide one approach to concurrency, and they let us solve some of these issues. However, they also have some From 82f47c3459c80c48f3e7dc29aea1ae8e4af47bbd Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 27 May 2024 11:48:42 -0600 Subject: [PATCH 050/249] Ch. 17: Listings are all `17-*`! --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 2 ++ .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 src/ch17-02-concurrency-with-async.md | 22 +++++++++---------- 22 files changed, 13 insertions(+), 11 deletions(-) rename listings/ch17-async-await/{listing-TODO-01 => listing-17-01}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-TODO-01 => listing-17-01}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-TODO-01 => listing-17-01}/src/main.rs (100%) rename listings/ch17-async-await/{listing-TODO-02 => listing-17-02}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-TODO-02 => listing-17-02}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-TODO-02 => listing-17-02}/src/main.rs (100%) rename listings/ch17-async-await/{listing-TODO-03 => listing-17-03}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-TODO-03 => listing-17-03}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-TODO-03 => listing-17-03}/src/main.rs (100%) rename listings/ch17-async-await/{listing-TODO-04 => listing-17-04}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-TODO-04 => listing-17-04}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-TODO-04 => listing-17-04}/src/main.rs (92%) rename listings/ch17-async-await/{listing-TODO-04b => listing-17-04b}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-TODO-04b => listing-17-04b}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-TODO-04b => listing-17-04b}/src/main.rs (100%) rename listings/ch17-async-await/{listing-TODO-04b2 => listing-17-04b2}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-TODO-04b2 => listing-17-04b2}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-TODO-04b2 => listing-17-04b2}/src/main.rs (100%) rename listings/ch17-async-await/{listing-TODO-05 => listing-17-05}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-TODO-05 => listing-17-05}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-TODO-05 => listing-17-05}/src/main.rs (100%) diff --git a/listings/ch17-async-await/listing-TODO-01/Cargo.lock b/listings/ch17-async-await/listing-17-01/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-TODO-01/Cargo.lock rename to listings/ch17-async-await/listing-17-01/Cargo.lock diff --git a/listings/ch17-async-await/listing-TODO-01/Cargo.toml b/listings/ch17-async-await/listing-17-01/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-TODO-01/Cargo.toml rename to listings/ch17-async-await/listing-17-01/Cargo.toml diff --git a/listings/ch17-async-await/listing-TODO-01/src/main.rs b/listings/ch17-async-await/listing-17-01/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-TODO-01/src/main.rs rename to listings/ch17-async-await/listing-17-01/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-02/Cargo.lock b/listings/ch17-async-await/listing-17-02/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-TODO-02/Cargo.lock rename to listings/ch17-async-await/listing-17-02/Cargo.lock diff --git a/listings/ch17-async-await/listing-TODO-02/Cargo.toml b/listings/ch17-async-await/listing-17-02/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-TODO-02/Cargo.toml rename to listings/ch17-async-await/listing-17-02/Cargo.toml diff --git a/listings/ch17-async-await/listing-TODO-02/src/main.rs b/listings/ch17-async-await/listing-17-02/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-TODO-02/src/main.rs rename to listings/ch17-async-await/listing-17-02/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-03/Cargo.lock b/listings/ch17-async-await/listing-17-03/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-TODO-03/Cargo.lock rename to listings/ch17-async-await/listing-17-03/Cargo.lock diff --git a/listings/ch17-async-await/listing-TODO-03/Cargo.toml b/listings/ch17-async-await/listing-17-03/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-TODO-03/Cargo.toml rename to listings/ch17-async-await/listing-17-03/Cargo.toml diff --git a/listings/ch17-async-await/listing-TODO-03/src/main.rs b/listings/ch17-async-await/listing-17-03/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-TODO-03/src/main.rs rename to listings/ch17-async-await/listing-17-03/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-04/Cargo.lock b/listings/ch17-async-await/listing-17-04/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-TODO-04/Cargo.lock rename to listings/ch17-async-await/listing-17-04/Cargo.lock diff --git a/listings/ch17-async-await/listing-TODO-04/Cargo.toml b/listings/ch17-async-await/listing-17-04/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-TODO-04/Cargo.toml rename to listings/ch17-async-await/listing-17-04/Cargo.toml diff --git a/listings/ch17-async-await/listing-TODO-04/src/main.rs b/listings/ch17-async-await/listing-17-04/src/main.rs similarity index 92% rename from listings/ch17-async-await/listing-TODO-04/src/main.rs rename to listings/ch17-async-await/listing-17-04/src/main.rs index 0c364f43dd..7e0546bbb3 100644 --- a/listings/ch17-async-await/listing-TODO-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -3,7 +3,9 @@ use std::time::Duration; fn main() { trpl::block_on(async { + // ANCHOR: add-channel let (tx, mut rx) = trpl::channel(); + // ANCHOR_END: add-channel let tx_fut = async { let vals = vec![ diff --git a/listings/ch17-async-await/listing-TODO-04b/Cargo.lock b/listings/ch17-async-await/listing-17-04b/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-TODO-04b/Cargo.lock rename to listings/ch17-async-await/listing-17-04b/Cargo.lock diff --git a/listings/ch17-async-await/listing-TODO-04b/Cargo.toml b/listings/ch17-async-await/listing-17-04b/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-TODO-04b/Cargo.toml rename to listings/ch17-async-await/listing-17-04b/Cargo.toml diff --git a/listings/ch17-async-await/listing-TODO-04b/src/main.rs b/listings/ch17-async-await/listing-17-04b/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-TODO-04b/src/main.rs rename to listings/ch17-async-await/listing-17-04b/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-04b2/Cargo.lock b/listings/ch17-async-await/listing-17-04b2/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-TODO-04b2/Cargo.lock rename to listings/ch17-async-await/listing-17-04b2/Cargo.lock diff --git a/listings/ch17-async-await/listing-TODO-04b2/Cargo.toml b/listings/ch17-async-await/listing-17-04b2/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-TODO-04b2/Cargo.toml rename to listings/ch17-async-await/listing-17-04b2/Cargo.toml diff --git a/listings/ch17-async-await/listing-TODO-04b2/src/main.rs b/listings/ch17-async-await/listing-17-04b2/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-TODO-04b2/src/main.rs rename to listings/ch17-async-await/listing-17-04b2/src/main.rs diff --git a/listings/ch17-async-await/listing-TODO-05/Cargo.lock b/listings/ch17-async-await/listing-17-05/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-TODO-05/Cargo.lock rename to listings/ch17-async-await/listing-17-05/Cargo.lock diff --git a/listings/ch17-async-await/listing-TODO-05/Cargo.toml b/listings/ch17-async-await/listing-17-05/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-TODO-05/Cargo.toml rename to listings/ch17-async-await/listing-17-05/Cargo.toml diff --git a/listings/ch17-async-await/listing-TODO-05/src/main.rs b/listings/ch17-async-await/listing-17-05/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-TODO-05/src/main.rs rename to listings/ch17-async-await/listing-17-05/src/main.rs diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index c829d18336..be5561624f 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -21,7 +21,7 @@ to implement the same counting example as with threads. To start, we will set up our `main` function with `trpl::block_on`: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:block_on}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:block_on}} ``` > Note: From this point forward in the chapter, every example will include this @@ -35,7 +35,7 @@ top-level `for` loop. Notice that we also need to add a `.await` after the `sleep` calls. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:task}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:task}} ``` Putting that all together, we end up with the code in Listing 17-TODO: @@ -43,7 +43,7 @@ Putting that all together, we end up with the code in Listing 17-TODO: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-01/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:all}} ``` @@ -74,7 +74,7 @@ thread was done running. Here, we can use `await` to do the same thing: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-02/src/main.rs:handle}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-02/src/main.rs:handle}} ``` @@ -113,7 +113,7 @@ ask the runtime to run them both to completion using `trpl::join`: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-03/src/main.rs:join}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-03/src/main.rs:join}} ``` @@ -180,7 +180,7 @@ We can start by introducing an async version of the `channel` ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:all}} ``` @@ -192,7 +192,7 @@ message, and the program never stops running. That’s because of the combinatio of the `while let` loop and the `trpl::join` call: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04/src/main.rs:loop}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:loop}} ``` Let’s consider the way this loop works: @@ -227,7 +227,7 @@ three futures to complete: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04b/src/main.rs:updated}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04b/src/main.rs:updated}} ``` @@ -273,7 +273,7 @@ you write it, the same way a closure can. We can do that by making the first async block an `async move` block. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-05/src/main.rs:move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:move}} ``` The result is Listing 17-TODO, and when we run *this* version of the code, it @@ -282,7 +282,7 @@ shuts down gracefully after the last message is sent. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-05/src/main.rs:move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:move}} ``` @@ -298,7 +298,7 @@ block, and switchign back to `join3`. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-TODO-04b2/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04b2/src/main.rs:here}} ``` From 91ffec833c6426fb3aa5ff16e7369e615a024fee Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 27 May 2024 11:48:42 -0600 Subject: [PATCH 051/249] Ch. 17: Fill out message-passing example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Gradually build up to the full thing, rather than dumping it all at once at the start. - Show several more “false starts” along the way, using them to teach a couple key ideas about async and control flow. - Update the listings to have their actual expected numbers. --- .../listing-17-04/src/main.rs | 30 +- .../listing-17-05/src/main.rs | 42 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-06/src/main.rs | 33 ++ .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-08/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-08/Cargo.toml | 9 + .../listing-17-08/src/main.rs | 34 ++ .../ch17-async-await/listing-17-09/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-09/Cargo.toml | 9 + .../src/main.rs | 0 src/ch17-02-concurrency-with-async.md | 175 ++++-- 15 files changed, 1327 insertions(+), 85 deletions(-) rename listings/ch17-async-await/{listing-17-04b => listing-17-06}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-04b => listing-17-06}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-06/src/main.rs rename listings/ch17-async-await/{listing-17-04b2 => listing-17-07}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-04b2 => listing-17-07}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-04b => listing-17-07}/src/main.rs (100%) create mode 100644 listings/ch17-async-await/listing-17-08/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-08/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-08/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-09/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-09/Cargo.toml rename listings/ch17-async-await/{listing-17-04b2 => listing-17-09}/src/main.rs (100%) 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 7e0546bbb3..a6033e5994 100644 --- a/listings/ch17-async-await/listing-17-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -1,35 +1,17 @@ // ANCHOR: all -use std::time::Duration; - fn main() { trpl::block_on(async { // ANCHOR: add-channel let (tx, mut rx) = trpl::channel(); // ANCHOR_END: add-channel - let tx_fut = async { - 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_secs(1)).await; - } - }; - - // ANCHOR: loop - let rx_fut = async { - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - }; + // ANCHOR: send-and-receive + let val = String::from("hi"); + tx.send(val).unwrap(); - trpl::join(tx_fut, rx_fut).await; - // ANCHOR_END: loop + let received = rx.recv().await.unwrap(); + println!("Got: {received}"); + // ANCHOR_END: send-and-receive }); } // ANCHOR_END: all 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 b88571997e..c1b62d8e66 100644 --- a/listings/ch17-async-await/listing-17-05/src/main.rs +++ b/listings/ch17-async-await/listing-17-05/src/main.rs @@ -1,31 +1,31 @@ +// ANCHOR: all +// ANCHOR: many-messages use std::time::Duration; +// ANCHOR_END: many-messages fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - // ANCHOR: move - let tx_fut = async move { - // ANCHOR_END: move - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; + // ANCHOR: many-messages + 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_secs(1)).await; - } - }; + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_secs(1)).await; + } + // ANCHOR_END: many-messages - let rx_fut = async { - while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); - } - }; - - trpl::join(tx_fut, rx_fut).await; + // ANCHOR: loop + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + // ANCHOR_END: loop }); } +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-04b/Cargo.lock b/listings/ch17-async-await/listing-17-06/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-04b/Cargo.lock rename to listings/ch17-async-await/listing-17-06/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-04b/Cargo.toml b/listings/ch17-async-await/listing-17-06/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-04b/Cargo.toml rename to listings/ch17-async-await/listing-17-06/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-06/src/main.rs b/listings/ch17-async-await/listing-17-06/src/main.rs new file mode 100644 index 0000000000..aeeacc5462 --- /dev/null +++ b/listings/ch17-async-await/listing-17-06/src/main.rs @@ -0,0 +1,33 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + 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"), + ]; + + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_secs(1)).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 + }); +} diff --git a/listings/ch17-async-await/listing-17-04b2/Cargo.lock b/listings/ch17-async-await/listing-17-07/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-04b2/Cargo.lock rename to listings/ch17-async-await/listing-17-07/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-04b2/Cargo.toml b/listings/ch17-async-await/listing-17-07/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-04b2/Cargo.toml rename to listings/ch17-async-await/listing-17-07/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-04b/src/main.rs b/listings/ch17-async-await/listing-17-07/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-04b/src/main.rs rename to listings/ch17-async-await/listing-17-07/src/main.rs diff --git a/listings/ch17-async-await/listing-17-08/Cargo.lock b/listings/ch17-async-await/listing-17-08/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-08/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-08/Cargo.toml b/listings/ch17-async-await/listing-17-08/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-08/Cargo.toml @@ -0,0 +1,9 @@ +[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-08/src/main.rs b/listings/ch17-async-await/listing-17-08/src/main.rs new file mode 100644 index 0000000000..fa02e21a87 --- /dev/null +++ b/listings/ch17-async-await/listing-17-08/src/main.rs @@ -0,0 +1,34 @@ +// ANCHOR: all +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + // ANCHOR: move + let tx_fut = async move { + // ANCHOR_END: move + + 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_secs(1)).await; + } + }; + + let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; + }); +} +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-09/Cargo.lock b/listings/ch17-async-await/listing-17-09/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-09/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-09/Cargo.toml b/listings/ch17-async-await/listing-17-09/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-09/Cargo.toml @@ -0,0 +1,9 @@ +[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-04b2/src/main.rs b/listings/ch17-async-await/listing-17-09/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-04b2/src/main.rs rename to listings/ch17-async-await/listing-17-09/src/main.rs diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index be5561624f..bad5699359 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -173,52 +173,147 @@ side of the channel closes. One other difference with this particular `recv()` implementation is that it returns an `Option` of the type sent over the channel instead of a `Result`. -We can start by introducing an async version of the `channel` +We can start by introducing an async version of the multiple-producer, +single-consumer channel channel API we used with threads back in Chapter 16: - + -+```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:add-channel}} +``` + + + +Now we can send messages from the sender to the receiver. Unlike in Chapter 16, +where we needed to spawn a separate thread to allow the message passing to +happen asynchronously, here we opt into async behavior on the receiver side by +using `.await` on the `rx.recv()` call. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:send-and-receive}} +``` + + + +The `send` call does not block, since the channel we are sending it into is +unbounded. That was true with our threading example back in Chapter 16, too, +though. The difference here is that the `rx.recv()` call here does not block the +rest of the program, whereas the one in Chapter 16 *did* block the main thread. +Instead, once the program hits the `.await` on the `rx.recv()` call, it hands +control back to the runtime, which can go on scheduling other operations until a +message arrives. It might be hard to see that from this code, though, since the +message will arrive right away! + +> 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 +> transition between sync and async code. However, *within* this block, the +> `.await` does not block further operations—as we will see! + +Let’s go ahead and send a whole series of messages, and sleep in between them, +as shown in Listing 17-TODO: + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:many-messages}} ``` -If we run this, though, it never stops! You will need to shut it down using -ctrl-c. We can see that `tx` sends all the -messages,and `rx` receives and prints them, but we never see the “Done!” -message, and the program never stops running. That’s because of the combination -of the `while let` loop and the `trpl::join` call: +Then we can wait on each of those messages in a loop. Here, we need to use a +`while let` loop rather than a `for` loop, because Rust does not yet have an +async version of `Iterator`, which is what the `for` loop does. In TODO: SECTION +TITLE, we will see more about two related traits the community has been working +on, `AsyncIterator` and `Stream`. For now, we can stick with `while let`, as in +Listing 17-TODO, and the loop will end when `rx.recv().await` produces a `None`. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:loop}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:loop}} ``` -Let’s consider the way this loop works: + + +This code does not do what we want. It does successfully send and receive the +messages, but instead of seeing the messages received at one-second intervals, +we see them arrive all at once, four seconds after we start the program. It +also never stops! 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. This highlights an +important point about the way that async works in Rust. Within any given async +block, the await points are sequential: each one happens one after another. That +is, after all, one of the big motivations for using this syntax instead of +callbacks, event handlers, or chains of methods: the flow through the program is +much easier to follow, because having the order that `.await` keywords appear in +the *code* is also the order they happen when running the *program*. + +With that in mind, we can see why this code behaves the way it does by looking +at the whole thing all together. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:all}} +``` + + + +There is just one async block here, so everything here will proceed linearly. +Every one of the `.await` points for the `trpl::sleep` calls appears before the +`.await` points on the `rx.recv()`, so all the `tx.send` calls happen, +interspersed with all of the `trpl::sleep` calls. Only then does the `while let` +loop get to go through all of the `.await` points on the `recv` calls. + +To get the behavior we actually want, where the delay happens in between +receiving each message, rather than before receiving any message, we need to +give put the `tx` and `rx` operations in their own async blocks, so the runtime +can execute each of them separately. We also need to tell the runtime to +actually run them using `trpl::join`, just like we did for the counting example +above. Listing 17-TODO shows how that looks. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-06/src/main.rs:futures}} +``` + + + +With these changes made, the messages get printed at one-second intervals, +rather than all in a rush after four seconds. + +The program still never stops running, though. That’s because of the combination +of the `while let` loop and the `trpl::join` call. Let’s consider the way this +loop works: * The `trpl::join` future only completes once *both* futures passed to it have completed. -* The `tx` future completes after sending the second message. -* The `rx` future will not complete until the `while let` loop ends, though. +* 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, `tx`, is dropped. * We do not call `rx.close()` anywhere, and `tx` will not be dropped until the - function exits. -* The function cannot exit because it is blocked on `trpl::join` completing, - which takes us back to the top of the list! - -To solve this, then, we need to make sure the channel gets closed so that -`trpl::join` will complete. We could manually close `rx` somewhere by calling -`rx.close()`, but that does not make much sense in this case. The idea is that -`rx` should keep listening until `tx` is done sending. Stopping after handling -some arbitrary number of messages would make the program shut down, but it would -mean we could miss messages if the sending side changed. Given that we cannot -use `rx.close()`, we need to make sure that `tx` gets dropped *before* the end -of the function. + 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 need to make sure the channel gets closed so that `trpl::join` will complete. +We could manually close `rx` somewhere by calling `rx.close()`, but that does +not make much sense in this case. The idea is that `rx` should keep listening +until `tx` is done sending. Stopping after handling some arbitrary number of +messages would make the program shut down, but it would mean we could miss +messages if the sending side changed. Given that we cannot use `rx.close()`, we +need to make sure that `tx` gets dropped *before* the end of the function. Right now, the async block only borrows `tx`. We can confirm this by adding another async block which uses `tx`, and using `trpl::join3` to wait for all @@ -227,7 +322,7 @@ three futures to complete: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04b/src/main.rs:updated}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-07/src/main.rs:updated}} ``` @@ -262,27 +357,22 @@ In Chapter 13, we learned how to use the `move` keyword with closures, and in Chapter 16, we saw that we often need to use closures marked with `move` when working with threads. As we have discovered, the same dynamics apply to async blocks—so the `move` keyword also works with async blocks, allowing them to take -ownership of the data they reference. +ownership of the data they reference. We can do that by change the first async +block from an `async` block to an `async move` block, as in Listing 17-TODO: - -Remember, any time you write a future, a runtime is ultimately responsible for -executing it. That means that an async block might outlive the function where -you write it, the same way a closure can. - - -We can do that by making the first async block an `async move` block. + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:move}} ``` The result is Listing 17-TODO, and when we run *this* version of the code, it shuts down gracefully after the last message is sent. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:all}} ``` @@ -293,17 +383,16 @@ 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. For example, we can make the code from Listing 17-TODO work by cloning the `tx` before moving it into the first async block, moving the original `tx` into the second async -block, and switchign back to `join3`. +block, and switching back to `join3`. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04b2/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:here}} ``` - Both of these blocks need to be `async move` blocks, or else we will end up back in the same infinite loop we started out in. @@ -338,3 +427,9 @@ example_2(|| async move { ... }); These closures now return anonymous futures, meaning they work basically the same way that an async function does. + + +Remember, any time you write a future, a runtime is ultimately responsible for +executing it. That means that an async block might outlive the function where +you write it, the same way a closure can. + From 91348caaeb4ce424474f82293b057ea0ba48a263 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 27 May 2024 16:06:20 -0600 Subject: [PATCH 052/249] Ch. 17: A minor wording improvement --- src/ch17-02-concurrency-with-async.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index bad5699359..88f992adf9 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -416,8 +416,8 @@ example_2(async move || { ... }); ``` However, since async blocks themselves can be marked with `move`, this ends up -not being a problem. Remember that `async` blocks compile to anonymous futures. -That means you can write calls like this instead: +not being a problem. Because `async` blocks compile to anonymous futures, you +can write calls like this instead: ```rust,ignore example_1(|| async { ... }); From 068f30b4061c223f6a3580582e7454f27cdc83a7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 27 May 2024 16:06:20 -0600 Subject: [PATCH 053/249] Ch 17.02: motivating `futures::join!` and `Box::pin` Up to this point, the chapter has stuck to `join` and `join3`, as simple function-based APIs. The `join_all` API is obviously more convenient than those *if you can use it*, but being able to use it requires having something which `impl Iterator` of a given type, and therefore demands a homogeneous type, which motivates introducing `Box::pin`. That in turn is quite annoying to work with and requires `Output = ` for all the futures in the collection, because of how `join_all` is typed (Rust does not have the ability to do do variadic types, which is what would be necessary for `join_all` to work the way we might want). Thus, we get a motivation for `futures::join!`, which unlike `join_all` *can* work with heterogeneous types. This fills out a fair bit of the text here and adds a lot of the listing support, and outlines what remains to do text-wise. --- Cargo.toml | 2 +- .../ch17-async-await/listing-17-10/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-10/Cargo.toml | 9 + .../listing-17-10/src/main.rs | 47 ++ .../ch17-async-await/listing-17-11/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-11/Cargo.toml | 9 + .../listing-17-11/src/main.rs | 49 ++ .../ch17-async-await/listing-17-12/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-12/Cargo.toml | 9 + .../listing-17-12/src/main.rs | 53 ++ .../ch17-async-await/listing-17-13/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-13/Cargo.toml | 9 + .../listing-17-13/src/main.rs | 53 ++ packages/trpl/Cargo.lock | 533 +++++++++++++++++ packages/trpl/src/lib.rs | 5 +- packages/trpl/tests/integration/main.rs | 81 ++- src/ch17-02-concurrency-with-async.md | 184 +++++- 17 files changed, 3168 insertions(+), 35 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-10/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-10/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-10/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-11/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-11/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-11/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-12/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-12/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-12/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-13/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-13/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-13/src/main.rs create mode 100644 packages/trpl/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index b65d859e5b..20fc14643d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ exclude = [ "linkchecker", # linkchecker is part of the CI workflow "listings", # these are intentionally distinct from the workspace "tmp", # listings are built here when updating output via tools/update-rustc.sh - "trpl", # manages its own dependencies as a standalone crate + "packages/trpl", # manages its own dependencies as a standalone crate # These are used as path dependencies in `rust-lang/rust` (since we are not # publishing them to crates.io), so they cannot be part of this workspace, diff --git a/listings/ch17-async-await/listing-17-10/Cargo.lock b/listings/ch17-async-await/listing-17-10/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-10/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-10/Cargo.toml b/listings/ch17-async-await/listing-17-10/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-10/Cargo.toml @@ -0,0 +1,9 @@ +[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-10/src/main.rs b/listings/ch17-async-await/listing-17-10/src/main.rs new file mode 100644 index 0000000000..78e17a3846 --- /dev/null +++ b/listings/ch17-async-await/listing-17-10/src/main.rs @@ -0,0 +1,47 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + // ANCHOR: here + 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-11/Cargo.lock b/listings/ch17-async-await/listing-17-11/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-11/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-11/Cargo.toml b/listings/ch17-async-await/listing-17-11/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-11/Cargo.toml @@ -0,0 +1,9 @@ +[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-11/src/main.rs b/listings/ch17-async-await/listing-17-11/src/main.rs new file mode 100644 index 0000000000..f96fecb929 --- /dev/null +++ b/listings/ch17-async-await/listing-17-11/src/main.rs @@ -0,0 +1,49 @@ +use std::{future::Future, time::Duration}; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + // ANCHOR: here + let futures: Vec>> = + vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; + + trpl::join_all(futures).await; + // ANCHOR_END: here + }); +} diff --git a/listings/ch17-async-await/listing-17-12/Cargo.lock b/listings/ch17-async-await/listing-17-12/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-12/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-12/Cargo.toml b/listings/ch17-async-await/listing-17-12/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-12/Cargo.toml @@ -0,0 +1,9 @@ +[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-12/src/main.rs b/listings/ch17-async-await/listing-17-12/src/main.rs new file mode 100644 index 0000000000..6320a17a71 --- /dev/null +++ b/listings/ch17-async-await/listing-17-12/src/main.rs @@ -0,0 +1,53 @@ +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = pin!(async move { + 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; + } + }); + + let rx_fut = pin!(async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + }); + + let tx_fut = pin!(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_secs(1)).await; + } + }); + + // ANCHOR: here + let futures: Vec>>> = + vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; + + trpl::join_all(futures).await; + // ANCHOR_END: here + }); +} diff --git a/listings/ch17-async-await/listing-17-13/Cargo.lock b/listings/ch17-async-await/listing-17-13/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-13/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-13/Cargo.toml b/listings/ch17-async-await/listing-17-13/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-13/Cargo.toml @@ -0,0 +1,9 @@ +[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-13/src/main.rs b/listings/ch17-async-await/listing-17-13/src/main.rs new file mode 100644 index 0000000000..20c7627a3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-13/src/main.rs @@ -0,0 +1,53 @@ +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = pin!(async move { + 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; + } + }); + + let rx_fut = pin!(async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + }); + + let tx_fut = pin!(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_secs(1)).await; + } + }); + + // ANCHOR: here + let futures: Vec>> = + vec![tx1_fut, rx_fut, tx_fut]; + + trpl::join_all(futures).await; + // ANCHOR_END: here + }); +} diff --git a/packages/trpl/Cargo.lock b/packages/trpl/Cargo.lock new file mode 100644 index 0000000000..20893eeaaa --- /dev/null +++ b/packages/trpl/Cargo.lock @@ -0,0 +1,533 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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 = "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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.5", +] + +[[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.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 = "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" +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 = "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.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 43764b97e9..9d53d86ddf 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -14,7 +14,10 @@ use std::future::Future; -pub use futures::future::{join, join3}; +pub use futures::{ + future::{join, join3, join_all}, + join, +}; pub use tokio::{ runtime::Runtime, // We use the `unbounded` variants because they most closely match the APIs diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index c0fa703562..106deb152d 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -9,8 +9,9 @@ //! //! [post]: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html -use std::time::Duration; +use std::{pin::Pin, time::Duration}; +use futures::Future; use trpl::{Receiver, Sender}; /// This test is foundational for all the others, as they depend on `block_on`. @@ -61,23 +62,71 @@ fn re_exported_channel_apis_work() { }); } -#[test] -fn re_exported_join_apis_work() { - let result = trpl::block_on(async { - let a = async { 1 }; - let b = async { 2 }; - trpl::join(a, b).await - }); +mod re_exported_join_apis_work { + use super::*; - assert_eq!(result, (1, 2)); + #[test] + fn join_fn() { + let result = trpl::block_on(async { + let a = async { 1 }; + let b = async { 2 }; + trpl::join(a, b).await + }); - let result = trpl::block_on(async { - let a = async { 1 }; - let b = async { 2 }; - let c = async { 3 }; + assert_eq!(result, (1, 2)); + } - trpl::join3(a, b, c).await - }); + #[test] + fn join3_fn() { + let result = trpl::block_on(async { + let a = async { 1 }; + let b = async { 2 }; + let c = async { 3 }; + + trpl::join3(a, b, c).await + }); + + assert_eq!(result, (1, 2, 3)); + } + + #[test] + fn join_all_fn() { + let result = trpl::block_on(async { + let a = async { format!("{}", 1) }; + + let b = async { format!("Hello") }; + + let outer = String::from("World"); + let c = async move { format!("{outer}") }; + + let futures: Vec>>> = + vec![Box::pin(a), Box::pin(b), Box::pin(c)]; + + trpl::join_all(futures).await + }); + + assert_eq!( + result, + vec![ + String::from("1"), + String::from("Hello"), + String::from("World") + ] + ); + } + + #[test] + fn join_macro() { + let result = trpl::block_on(async { + let a = async { 1 }; + let b = async { "Hello" }; + + let outer = vec![String::from("World")]; + let c = async move { outer }; + + trpl::join!(a, b, c) + }); - assert_eq!(result, (1, 2, 3)); + assert_eq!(result, (1, "Hello", vec![String::from("World")])); + } } diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 88f992adf9..622154bdfd 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -38,16 +38,6 @@ top-level `for` loop. Notice that we also need to add a `.await` after the {{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:task}} ``` -Putting that all together, we end up with the code in Listing 17-TODO: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:all}} -``` - - - This does something very similar to what the thread-based implementation did, as we can see from the output when we run it. (As with the threading example, you may see a different order in your own terminal output when you run this.) @@ -377,8 +367,6 @@ shuts down gracefully after the last message is sent. -### Multiple Producers with Async - 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. For example, we can make the code from Listing 17-TODO work by cloning the `tx` before moving it @@ -396,14 +384,173 @@ block, and switching back to `join3`. Both of these blocks need to be `async move` blocks, or else we will end up back in the same infinite loop we started out in. +### Working with More Futures + +When we switched from using two futures to three, we also had to switch from +using `join` to using `join3`. It would be annoying to do this every time we +changed our code. + + + +However, both the function nor macro forms of `join` only work for cases where +we know the number of futures ahead of time. If instead we have a dynamic number +of futures, we need a function which works with a collection type which can grow +and shrink dynamically at runtime, such as a vector. In real-world Rust, pushing +futures into a collection and then waiting on some or all the futures in that +collection to complete is a very common pattern. + +The `trpl::join_all` function accepts any type which 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, so we can swap out our +`join3` call and replace it with `join_all`. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:here}} +``` + + + +Unfortunately, this does not compile. Instead, we get this error: + + + +```text +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}` +``` + +This error message is admittedly not the most helpful! It only tells us that it +expected one async block and found another—but why is it looking for the async +blocks that it names here, and why does it only reference them by where they +appear in the code? + +One clue is the format of this message. Notice that it is exactly the same as if +we had tried to create a `Vec` with a a number and a string in it: + + + +```rust +let a = 1; +let b = "Hello"; +let vals = vec![a, b]; +``` + +The output there would be: + +```text +error[E0308]: mismatched types + --> src/main.rs:4:24 + | +4 | let vals = vec![a, b]; + | ^ expected integer, found `&str` +``` + +Saying “expected *something*, found *something else*” is Rust’s standard format +for telling us about a type mismatch. As we saw with vectors in [Using an Enum +to Store Multiple Types][collections] back in Chapter 8, we need the type of +each item in a collection to be the same—and `tx1_fut`, `rx_fut`, and `tx_fut` +do not have the same type. + +The underlying issue here is what we learned in the previous section: async +blocks compile to anonymous futures. Under the hood, there is a data structure +corresponding to each of these blocks, and it has its own unique type. This +might be surprising. After all, none of them returns anything, so the `Future` +type in each case is `Future`. However, `Future` is a trait, not a +concrete type. The actual types here are invisible from our point of view as the +person writing the code. + +In Chapter 8, we discussed one way to include multiple types in a single vector: +using an enum to represent each of the different types which can appear in the +vector. We cannot do that here, though. For one thing, we do not even have a way +to name the different types, because they are anonymous. For another, the reason +we reached for a vector and `join_all` in the first place was to be able to work +with a dynamic collection of futures where we do not know what they will all be +until runtime. + +To make this work, we need to use *trait objects*, just as we did for returning +different kinds of errors from the same function in [Returning Errors from the +run function][dyn] back in Chapter 12. Again, we will cover trait objects in +detail in Chapter 17. Here, it just lets us use + +Back in Chapter 13, we saw that we can use `Box` to provide enough indirection +to tell Rust what *size* a type will be at runtime and avoid having types which +are infinitely large. We can use `Box` in a similar way here to represent these +different futures as the same type: a pointer to a *trait object*. We will talk +more about trait objects later in the book. For now, it is enough to know that +we can wrap a trait-based type like this in a `Box`, with the keyword `dyn` to +tell the compiler that this is a + + + ++ +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:here}} + + + + + ++ +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} + + + +This 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. It +would be nice if we could make this + +This keeps everything on the stack, and that is a nice little performance win, +but it is still a lot of explicit types, which is quite unusual for Rust! There +is another problem, too. We got this far by ignoring the fact that we might have + + + ++ +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} + + + - + + + +> Note: This is how closures work, too, but we did not have to talk about it +> back in Chapter 13, because the details did not bubble up to the surface the +> way they do here! + The `async` keyword does not yet work with closures directly. That is, there is @@ -433,3 +580,6 @@ Remember, any time you write a future, a runtime is ultimately responsible for executing it. That means that an async block might outlive the function where you write it, the same way a closure can. + +[collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types +[dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html From 7a5bdb298da6c6cf0d07f4030722c64cb7b61df1 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 28 May 2024 13:41:10 -0600 Subject: [PATCH 054/249] Ch. 17: finish motivating `Pin` and `pin!` This does not yet actually *explain* either of them, but it gets us to the point where an explanation is well-motivated and can make some sense, and it (more or less successfully) covers the set of errors that gets us to that point. --- .../listing-17-11/src/main.rs | 4 +- .../listing-17-12/src/main.rs | 24 +- .../listing-17-13/src/main.rs | 4 +- .../ch17-async-await/listing-17-14/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-14/Cargo.toml | 9 + .../listing-17-14/src/main.rs | 53 ++ src/ch17-02-concurrency-with-async.md | 97 +++- 7 files changed, 701 insertions(+), 30 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-14/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-14/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-14/src/main.rs 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 f96fecb929..beff676dbe 100644 --- a/listings/ch17-async-await/listing-17-11/src/main.rs +++ b/listings/ch17-async-await/listing-17-11/src/main.rs @@ -1,4 +1,4 @@ -use std::{future::Future, time::Duration}; +use std::time::Duration; fn main() { trpl::block_on(async { @@ -40,7 +40,7 @@ fn main() { }; // ANCHOR: here - let futures: Vec>> = + let futures = vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; trpl::join_all(futures).await; 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 6320a17a71..b712d344c0 100644 --- a/listings/ch17-async-await/listing-17-12/src/main.rs +++ b/listings/ch17-async-await/listing-17-12/src/main.rs @@ -1,15 +1,11 @@ -use std::{ - future::Future, - pin::{pin, Pin}, - time::Duration, -}; +use std::{future::Future, time::Duration}; fn main() { trpl::block_on(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"), @@ -21,15 +17,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"), @@ -41,13 +37,13 @@ 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; - // ANCHOR_END: here }); } 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 20c7627a3f..6320a17a71 100644 --- a/listings/ch17-async-await/listing-17-13/src/main.rs +++ b/listings/ch17-async-await/listing-17-13/src/main.rs @@ -44,8 +44,8 @@ fn main() { }); // ANCHOR: here - let futures: Vec>> = - vec![tx1_fut, rx_fut, tx_fut]; + let futures: Vec>>> = + vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; trpl::join_all(futures).await; // ANCHOR_END: here diff --git a/listings/ch17-async-await/listing-17-14/Cargo.lock b/listings/ch17-async-await/listing-17-14/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-14/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-14/Cargo.toml b/listings/ch17-async-await/listing-17-14/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-14/Cargo.toml @@ -0,0 +1,9 @@ +[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-14/src/main.rs b/listings/ch17-async-await/listing-17-14/src/main.rs new file mode 100644 index 0000000000..20c7627a3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-14/src/main.rs @@ -0,0 +1,53 @@ +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = pin!(async move { + 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; + } + }); + + let rx_fut = pin!(async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + }); + + let tx_fut = pin!(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_secs(1)).await; + } + }); + + // ANCHOR: here + let futures: Vec>> = + vec![tx1_fut, rx_fut, tx_fut]; + + trpl::join_all(futures).await; + // ANCHOR_END: here + }); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 622154bdfd..66755292f8 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -496,29 +496,99 @@ until runtime. To make this work, we need to use *trait objects*, just as we did for returning different kinds of errors from the same function in [Returning Errors from the run function][dyn] back in Chapter 12. Again, we will cover trait objects in -detail in Chapter 17. Here, it just lets us use +detail in Chapter 17. Here, it lets us treat each of the anonymous futures +produced by these types as interchangeable, since all of them by definition +implement the `Future` trait. -Back in Chapter 13, we saw that we can use `Box` to provide enough indirection -to tell Rust what *size* a type will be at runtime and avoid having types which -are infinitely large. We can use `Box` in a similar way here to represent these -different futures as the same type: a pointer to a *trait object*. We will talk -more about trait objects later in the book. For now, it is enough to know that -we can wrap a trait-based type like this in a `Box`, with the keyword `dyn` to -tell the compiler that this is a - - +We can start by wrapping each of the futures in the `vec!` in a `Box::new()`. +Unfortunately, the initial way we might try this, as shown in Listing 17-TODO, +still does not compile. +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:here}} +``` - +In fact, we have the same basic 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 can start by fixing the type error around the `Box::new` calls, by telling +the compiler explicitly that we want to use these types as trait objects. The +clearest way to do that here is by adding a type annotation to the declaration +of `futures`, as we see in Listing 17-TODO. The type we have to write here is a +little involved, so let’s walk through each part of 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`. +- Then we annotate the trait with `dyn` to mark it as dynamic. +- The entire trait is wrapped in a `Box`. +- Finally, we state explicitly that `futures` is a `Vec` containing these items. +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} +``` + + + +That already made a big difference. Now when we run the compiler, we only have +the errors mentioning `Unpin`, each of which is a variation on this same output: + + + +```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}>: 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 `Future` +note: required by a bound in `futures_util::future::join_all::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` +``` + +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 is generic over a `Future`, and `Future` itself requires the `Unpin` +trait. + +`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 certain context. Just like `Send` and `Sync`, `Unpin` is automatically +implemented for all types where the compiler can prove it should be. You may +also recall that there is an opposite for each of `Send` and `Sync`: `?Send` and +`?Sync`, which tell the compiler that the types in question *might* be `Send` or +`Sync` but are not guaranteed to. `Unpin`, as its name implies, is similarly the +opposite of `Pin`, which we saw as part of the signature of the `Future::poll` +method when we covered the API of `Future` in the [Futures][futures] section +earlier in this chapter. + +### The Pin Trait and Pinning + + + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} +``` @@ -534,7 +604,9 @@ is another problem, too. We got this far by ignoring the fact that we might have -{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} +``` @@ -583,3 +655,4 @@ you write it, the same way a closure can. [collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html +[futures]: /ch17-01-futures-and-syntax.html#futures From 626aec8b40d7882b22f0217599cdb317b59810a2 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 28 May 2024 16:36:24 -0600 Subject: [PATCH 055/249] =?UTF-8?q?Ch.=2017:=20A=20small=20wording=20tweak?= =?UTF-8?q?=20about=20`JoinAll`=20in=20=C2=A703?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-02-concurrency-with-async.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 66755292f8..b1b00ff571 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -561,12 +561,12 @@ note: required by a bound in `futures_util::future::join_all::JoinAll` | ^^^^^^ required by this bound in `JoinAll` ``` -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 is generic over a `Future`, and `Future` itself requires the `Unpin` -trait. +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, which is itself a `Future`, is also +generic over a `Future`, and `Future` itself requires the `Unpin` trait. `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 From b3827671518caef5ff8b7914480f8745317ba3f5 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 28 May 2024 16:44:28 -0600 Subject: [PATCH 056/249] Ch. 17: Start building out explanation of `Pin` --- src/ch17-02-concurrency-with-async.md | 70 ++++++++++++++++++++------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index b1b00ff571..b10a639205 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -561,12 +561,51 @@ note: required by a bound in `futures_util::future::join_all::JoinAll` | ^^^^^^ required by this bound in `JoinAll` ``` -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, which is itself a `Future`, is also -generic over a `Future`, and `Future` itself requires the `Unpin` trait. +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, which is itself a `Future`, is also generic over a `Future`, and +`Future` itself requires 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 + +When we introduced the `Future` trait in the previous chapter, we saw that the +definition of its `poll` method has an unusual way of specifying the `self` +parameter. To review, here is the full definition of `Future`: + +```rust +pub trait Future { + type Output; + + // Required method + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} +``` + +We have not seen a method definition like this before, where `self` has a type +annotation rather than simply being named like `self`, `mut self`, `&self`, or +`&mut self`. This syntax means that the method can only be called when the +instance of the type which implements `Future` is behind a `Pin` pointer type. +This syntax is not specific to `Pin`; it also works with `Box` and other smart +pointer types, and we will see it again in Chapter 18. + +Here, the signature tells us that if we want to poll a future to check whether +it is `Pending` or `Ready(Output)`, the type which implements `Future` has to be +behind a `Pin` smart 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`? + + + +Remember that any time you write a future, a runtime is ultimately responsible +for executing it. That means that an async block might outlive the function +where you write it, the same way a closure can. `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 @@ -580,10 +619,10 @@ opposite of `Pin`, which we saw as part of the signature of the `Future::poll` method when we covered the API of `Future` in the [Futures][futures] section earlier in this chapter. -### The Pin Trait and Pinning - +Now we know enough to understand the error message from above. The problem + ```rust,ignore,does_not_compile @@ -596,10 +635,6 @@ This 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. It would be nice if we could make this -This keeps everything on the stack, and that is a nice little performance win, -but it is still a lot of explicit types, which is quite unusual for Rust! There -is another problem, too. We got this far by ignoring the fact that we might have - @@ -610,6 +645,11 @@ is another problem, too. We got this far by ignoring the fact that we might have +This keeps everything on the stack, and that is a nice little performance win, +but it is still a lot of explicit types, which is quite unusual for Rust! There +is another problem, too. We got this far by ignoring the fact that we might have +different `Output` types from the `Future`. + - -Remember, any time you write a future, a runtime is ultimately responsible for -executing it. That means that an async block might outlive the function where -you write it, the same way a closure can. - - [collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html [futures]: /ch17-01-futures-and-syntax.html#futures From e000ea332f2ab358058ae385a0e53a455c867643 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 29 May 2024 10:17:28 -0600 Subject: [PATCH 057/249] Ch. 17: Iterate on explanation of `Pin` and `Unpin` This is (a) far from perfect and (b) far from done, but it represents a useful increment of work and includes a bunch of notes for where to go next with this quite tricky section. listings/ch17-async-await/listing-17-13/src/main.rs JJ: M listings/ch17-async-await/listing-17-14/src/main.rs JJ: M src/ch17-02-concurrency-with-async.md --- .../listing-17-13/src/main.rs | 2 +- .../listing-17-14/src/main.rs | 17 ++++- src/ch17-02-concurrency-with-async.md | 65 ++++++++++++++++--- 3 files changed, 73 insertions(+), 11 deletions(-) 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 6320a17a71..5520a58ca5 100644 --- a/listings/ch17-async-await/listing-17-13/src/main.rs +++ b/listings/ch17-async-await/listing-17-13/src/main.rs @@ -46,8 +46,8 @@ fn main() { // 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; - // 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 20c7627a3f..a22c9570f7 100644 --- a/listings/ch17-async-await/listing-17-14/src/main.rs +++ b/listings/ch17-async-await/listing-17-14/src/main.rs @@ -9,7 +9,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"), @@ -21,15 +24,25 @@ 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 }); + // ANCHOR_END: here + // ANCHOR: here let tx_fut = pin!(async move { + // snip... + // ANCHOR_END: here let vals = vec![ String::from("more"), String::from("messages"), @@ -41,13 +54,13 @@ 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 trpl::join_all(futures).await; - // ANCHOR_END: here }); } diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index b10a639205..ed5e9342c0 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -621,9 +621,31 @@ earlier in this chapter. -Now we know enough to understand the error message from above. The problem - -+ + +Now we know enough to understand the error message from above. The problem is +that the futures produced by an async block are *not* pinned by default. +Strictly: they implement `!Unpin` to opt out of being copyable by default the +way most types are. We need to pin them explicitly. + +Now that we have an idea what that error message was telling us, we can finally +get our `join_all` call to compile! First, we need to explicitly annotate +`futures` as referring to a pinned `Box` of futures. Second, we actually need to +pin the futures, which we can do using the handy `Box::pin` API, which exists +for exactly this. Putting that together, we end up with the code in Listing +17-TODO. + + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} @@ -631,13 +653,40 @@ Now we know enough to understand the error message from above. The problem -This 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. It -would be nice if we could make this +If we compile and run this, we finally get the output we hoped for: - + -+```text +received 'hi' +received 'more' +received 'from' +received 'messages' +received 'the' +received 'for' +received 'future' +received 'you' +``` + +Phew! + +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 +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 +instead. + +The `std::pin::pin` macro exists to do just that for values. 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. + + ```rust {{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} From 0032e07f80289dbe3b80d83cf5b2e35452f1f646 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 29 May 2024 16:46:36 -0600 Subject: [PATCH 058/249] =?UTF-8?q?Ch.=2017:=20iterate=20on=20=C2=A702=20e?= =?UTF-8?q?xamples,=20extract=20=E2=80=9Cextra=E2=80=9D=20material?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch17-async-await/listing-17-15/Cargo.lock | 540 ++++++++++++++++++ .../ch17-async-await/listing-17-15/Cargo.toml | 9 + .../listing-17-15/src/main.rs | 12 + src/ch17-02-concurrency-with-async.md | 74 ++- src/ch17-03-futures-tasks-threads.md | 32 ++ 5 files changed, 629 insertions(+), 38 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-15/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-15/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-15/src/main.rs diff --git a/listings/ch17-async-await/listing-17-15/Cargo.lock b/listings/ch17-async-await/listing-17-15/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-15/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-15/Cargo.toml b/listings/ch17-async-await/listing-17-15/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-15/Cargo.toml @@ -0,0 +1,9 @@ +[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-15/src/main.rs b/listings/ch17-async-await/listing-17-15/src/main.rs new file mode 100644 index 0000000000..24845f0887 --- /dev/null +++ b/listings/ch17-async-await/listing-17-15/src/main.rs @@ -0,0 +1,12 @@ +fn main() { + trpl::block_on(async { + // ANCHOR: here + let a = async { 1u32 }; + let b = async { "Hello!" }; + let c = async { true }; + // ANCHOR_END: here + + let (a_result, b_result, c_result) = trpl::join!(a, b, c); + println!("{a_result}, {b_result}, {c_result}"); + }); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index ed5e9342c0..772418ad5e 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -610,14 +610,12 @@ need for pinning. --> `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 certain context. Just like `Send` and `Sync`, `Unpin` is automatically -implemented for all types where the compiler can prove it should be. You may -also recall that there is an opposite for each of `Send` and `Sync`: `?Send` and -`?Sync`, which tell the compiler that the types in question *might* be `Send` or -`Sync` but are not guaranteed to. `Unpin`, as its name implies, is similarly the -opposite of `Pin`, which we saw as part of the signature of the `Future::poll` -method when we covered the API of `Future` in the [Futures][futures] section -earlier in this chapter. +in certain context. Just like `Send` and `Sync`, the compiler implements `Unpin` +automatically for most types. + +`Unpin`’s job is to tell the compiler that a given type does *not* need to +uphold any particular guarantees about whether the value in question can be +moved. For example, if a future @@ -697,44 +695,44 @@ dynamic `Future` type. This keeps everything on the stack, and that is a nice little performance win, but it is still a lot of explicit types, which is quite unusual for Rust! There is another problem, too. We got this far by ignoring the fact that we might have -different `Output` types from the `Future`. - - +different `Output` types. For example, in Listing 17-TODO, the anonymous future +type for `a` implements `Future` and the anonymous future type for +`b` implements `Future`. + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} +``` - -> Note: This is how closures work, too, but we did not have to talk about it -> back in Chapter 13, because the details did not bubble up to the surface the -> way they do here! - + - -The `async` keyword does not yet work with closures directly. That is, there is -no direct equivalent to `async fn` for anonymous functions. As a result, you -cannot write code like these function calls: +We can use `trpl::join!` to await them together, since it accepts two different +future types, but we cannot use `trpl::join_all` with these futures, because we +will never be able to make them have the same type. (This is the same as working +with any other type in Rust, though: futures are not special, even though we +have some nice syntax for working with them, and that is a good thing!) We have +a basic tradeoff here: 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 with a +static number of futures with `join!`, and so on, -```rust,ignore -example_1(async || { ... }); -example_2(async move || { ... }); -``` + +In practice, you will usually work directly with `async` and `.await`, and only +as a secondary tool reach for the functions like `join` or `join_all`, or their +corresponding macro equivalents. These kinds of tools are really handy for +building frameworks, or especially when you are building a runtime itself. -However, since async blocks themselves can be marked with `move`, this ends up -not being a problem. Because `async` blocks compile to anonymous futures, you -can write calls like this instead: +### Select -```rust,ignore -example_1(|| async { ... }); -example_2(|| async move { ... }); -``` +Thus far, we have only used the `join` family of functions and macros. When we +“join” on some collection of futures, 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. -These closures now return anonymous futures, meaning they work basically the -same way that an async function does. - + [collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html diff --git a/src/ch17-03-futures-tasks-threads.md b/src/ch17-03-futures-tasks-threads.md index ca27ce27be..230289d086 100644 --- a/src/ch17-03-futures-tasks-threads.md +++ b/src/ch17-03-futures-tasks-threads.md @@ -68,3 +68,35 @@ A big difference between the cooking analogy and Rust’s async model for concurrency is that in the cooking example, the cook makes the decision about when to switch tasks. In Rust’s async model, the tasks are in control of that. To see how, let’s look at how Rust actually uses async. + +## Misc. other stuff + + +The `async` keyword does not yet work with closures directly. That is, there is +no direct equivalent to `async fn` for anonymous functions. As a result, you +cannot write code like these function calls: + +```rust,ignore +example_1(async || { ... }); +example_2(async move || { ... }); +``` + +However, since async blocks themselves can be marked with `move`, this ends up +not being a problem. Because `async` blocks compile to anonymous futures, you +can write calls like this instead: + +```rust,ignore +example_1(|| async { ... }); +example_2(|| async move { ... }); +``` + +These closures now return anonymous futures, meaning they work basically the +same way that an async function does. + + + +> Note: This is how closures work, too, but we did not have to talk about it +> back in Chapter 13, because the details did not bubble up to the surface the +> way they do here! + + From 42363712e801ae23d5fa6ff6baa08cae8ba04ff4 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 30 May 2024 11:42:49 -0600 Subject: [PATCH 059/249] =?UTF-8?q?Ch.=2017:=20Explain=20`join!`=20in=20?= =?UTF-8?q?=C2=A702?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-09b/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-09b/Cargo.toml | 9 + .../listing-17-09b/src/main.rs | 46 ++ src/ch17-02-concurrency-with-async.md | 26 +- 4 files changed, 613 insertions(+), 8 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-09b/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-09b/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-09b/src/main.rs diff --git a/listings/ch17-async-await/listing-17-09b/Cargo.lock b/listings/ch17-async-await/listing-17-09b/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-09b/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-09b/Cargo.toml b/listings/ch17-async-await/listing-17-09b/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-09b/Cargo.toml @@ -0,0 +1,9 @@ +[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-09b/src/main.rs b/listings/ch17-async-await/listing-17-09b/src/main.rs new file mode 100644 index 0000000000..945442dd8a --- /dev/null +++ b/listings/ch17-async-await/listing-17-09b/src/main.rs @@ -0,0 +1,46 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + // ANCHOR: here + trpl::join!(tx1_fut, tx_fut, rx_fut); + // ANCHOR_END: here + }); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 772418ad5e..e33b854c97 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -388,16 +388,26 @@ in the same infinite loop we started out in. When we switched from using two futures to three, we also had to switch from using `join` to using `join3`. It would be annoying to do this every time we -changed our code. +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-TODO to use `join!` instead of `join3`, as in Listing 17-TODO: - + -However, both the function nor macro forms of `join` only work for cases where -we know the number of futures ahead of time. If instead we have a dynamic number -of futures, we need a function which works with a collection type which can grow -and shrink dynamically at runtime, such as a vector. In real-world Rust, pushing -futures into a collection and then waiting on some or all the futures in that -collection to complete is a very common pattern. +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-09b/src/main.rs:here}} +``` + + + +This is definitely a nice improvement over needing to swap between `join` and +`join3` and `join4` and so on! However, both the function nor macro forms of +`join` only work for cases where we know the number of futures ahead of time. If +instead we have a dynamic number of futures, we need a function which works with +a collection type which can grow and shrink dynamically at runtime, such as a +vector. In real-world Rust, pushing futures into a collection and then waiting +on some or all the futures in that collection to complete is a very common +pattern. The `trpl::join_all` function accepts any type which implements the `Iterator` trait, which we learned about back in Chapter 13, so it seems like just the From 97f5bcc4d54fc3f39f718e51b9a216cc58218ace Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 30 May 2024 11:49:00 -0600 Subject: [PATCH 060/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20Clarify=20the=20?= =?UTF-8?q?`move`=20discussion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-02-concurrency-with-async.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index e33b854c97..b95a0cf542 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -320,7 +320,7 @@ three futures to complete: Now both blocks borrow `tx`, so they are both able to use it to send messages, which `rx` can then receive. When we run that code, we see the extra output from the new `async` block, and the message it sends being received by the -`rx.recv()`: +`rx.recv()`. ```text Got: hi @@ -334,21 +334,21 @@ Got: you ``` As before, we also see that the program does not shut down on its own and -requires a ctrl-c. Now that we have seen how -`async` blocks borrow the items they reference from their outer scope, we can go -ahead and remove the extra block we just added, and switch back to using -`trpl::join` instead of `trpl::join3`. - -This little exploration makes the original issue much clearer: it is ultimately -about *ownership*. We need to move `tx` into the async block so that once that -block ends, `tx` will be dropped. +requires a ctrl-c, though. This little +exploration helps us understand why: it is ultimately about *ownership*. We need +to move `tx` into the async block so that once that block ends, `tx` will be +dropped. In Chapter 13, we learned how to use the `move` keyword with closures, and in Chapter 16, we saw that we often need to use closures marked with `move` when working with threads. As we have discovered, the same dynamics apply to async blocks—so the `move` keyword also works with async blocks, allowing them to take -ownership of the data they reference. We can do that by change the first async -block from an `async` block to an `async move` block, as in Listing 17-TODO: +ownership of the data they reference. + +Since we have seen how `async` blocks borrow the items they reference from their +outer scope, we can go ahead and remove the extra block we just added for now, +and switch back from `join3` to `join`. Then we can change the first async block +from an `async` block to an `async move` block, as in Listing 17-TODO: From c6965ca05715256016feb9a17737c1d221e22e4c Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 30 May 2024 12:44:38 -0600 Subject: [PATCH 061/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20Start=20showing?= =?UTF-8?q?=20timeouts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also has the setup for showing `select`, but currently jumps ahead to showing a `timeout` example. --- .../listing-17-timeout/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-timeout/Cargo.toml | 9 + .../listing-17-timeout/src/main.rs | 20 + packages/trpl/src/lib.rs | 19 +- packages/trpl/tests/integration/main.rs | 23 + src/ch17-02-concurrency-with-async.md | 16 + 6 files changed, 626 insertions(+), 1 deletion(-) create mode 100644 listings/ch17-async-await/listing-17-timeout/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-timeout/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-timeout/src/main.rs diff --git a/listings/ch17-async-await/listing-17-timeout/Cargo.lock b/listings/ch17-async-await/listing-17-timeout/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-timeout/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-timeout/Cargo.toml b/listings/ch17-async-await/listing-17-timeout/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-timeout/Cargo.toml @@ -0,0 +1,9 @@ +[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-timeout/src/main.rs b/listings/ch17-async-await/listing-17-timeout/src/main.rs new file mode 100644 index 0000000000..6e06ef7e42 --- /dev/null +++ b/listings/ch17-async-await/listing-17-timeout/src/main.rs @@ -0,0 +1,20 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + // ANCHOR: here + let limit = Duration::from_secs(2); + let slow = async { + trpl::sleep(Duration::from_secs(5)).await; + "Finally finished" + }; + + match trpl::timeout(limit, slow).await { + Ok(message) => println!("Succeded with '{message}'"), + Err(duration) => { + println!("Failed after {} seconds", duration.as_secs()) + } + } + // ANCHOR_END: here + }); +} diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 9d53d86ddf..4ab3c6d352 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -12,7 +12,8 @@ //! never be broken by upstream changes, e.g. if Tokio does a breaking 2.0 //! release at some point. -use std::future::Future; +use std::{future::Future, time::Duration}; +use tokio::time::{self, Timeout}; pub use futures::{ future::{join, join3, join_all}, @@ -54,3 +55,19 @@ pub fn block_on(future: F) -> F::Output { let rt = Runtime::new().unwrap(); rt.block_on(future) } + +/// Race a future against a specified timeout duration. +/// +/// Under the hood, this uses `tokio::time::timeout`, but instead of returning +/// Tokio's internal error type in the case of a failure, this simply returns +/// the duration which had elapsed. (It actually provides strictly *more* info +/// than Tokio's error does, though it does not `impl Error`.) +pub async fn timeout( + duration: Duration, + future: F, +) -> Result +where + F: Future, +{ + time::timeout(duration, future).await.map_err(|_| duration) +} diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index 106deb152d..477691b30f 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -130,3 +130,26 @@ mod re_exported_join_apis_work { assert_eq!(result, (1, "Hello", vec![String::from("World")])); } } + +#[test] +fn re_exported_timeout_works() { + let val = trpl::block_on(async { + let winner = async { + trpl::sleep(Duration::from_millis(1)).await; + String::from("Hello") + }; + trpl::timeout(Duration::from_millis(2), winner).await + }); + + assert_eq!(val, Ok(String::from("Hello"))); + + let val = trpl::block_on(async { + let loser = async { + trpl::sleep(Duration::from_millis(2)).await; + String::from("Hello") + }; + trpl::timeout(Duration::from_millis(1), loser).await + }); + + assert!(val.is_err()); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index b95a0cf542..776710e0bc 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -744,6 +744,22 @@ before we move on. +Many of these patterns are common enough to warrant abstracting over. For +example, the `trpl::timeout` function takes a `Duration` for the maximum time to +run, but also takes a future to run, and produces a new future you can await, +whose `Output` type is a `Result`. Listing 17-TODO shows how we can use it. If +the passed-in future finishes first, the output result will be `Ok`, with the +result of that passed-in future. If the duration elapses before the passed-in +future finishes, the result will be `Err` with the duration that elapsed. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout/src/main.rs:here}} +``` + + + [collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html [futures]: /ch17-01-futures-and-syntax.html#futures From c58f94376c30d3795edf4ede527666776b193779 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 30 May 2024 12:44:38 -0600 Subject: [PATCH 062/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20Start=20on=20exa?= =?UTF-8?q?mple=20of=20select.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-select-a/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-select-a/Cargo.toml | 9 + .../listing-17-select-a/src/main.rs | 5 + packages/trpl/src/lib.rs | 4 +- packages/trpl/tests/integration/main.rs | 33 +- src/ch17-02-concurrency-with-async.md | 10 +- 6 files changed, 597 insertions(+), 4 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-select-a/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-select-a/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-select-a/src/main.rs diff --git a/listings/ch17-async-await/listing-17-select-a/Cargo.lock b/listings/ch17-async-await/listing-17-select-a/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-select-a/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-select-a/Cargo.toml b/listings/ch17-async-await/listing-17-select-a/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-select-a/Cargo.toml @@ -0,0 +1,9 @@ +[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-select-a/src/main.rs b/listings/ch17-async-await/listing-17-select-a/src/main.rs new file mode 100644 index 0000000000..3ed5bec9d0 --- /dev/null +++ b/listings/ch17-async-await/listing-17-select-a/src/main.rs @@ -0,0 +1,5 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { trpl::select!(todo!()) }); +} diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 4ab3c6d352..4a9c970756 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -13,10 +13,10 @@ //! release at some point. use std::{future::Future, time::Duration}; -use tokio::time::{self, Timeout}; +use tokio::time; pub use futures::{ - future::{join, join3, join_all}, + future::{join, join3, join_all, select}, join, }; pub use tokio::{ diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index 477691b30f..ff800b2d7c 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -9,7 +9,10 @@ //! //! [post]: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html -use std::{pin::Pin, time::Duration}; +use std::{ + pin::{pin, Pin}, + time::Duration, +}; use futures::Future; use trpl::{Receiver, Sender}; @@ -153,3 +156,31 @@ fn re_exported_timeout_works() { assert!(val.is_err()); } + +#[test] +fn re_exported_select_macro() { + #[derive(Debug, PartialEq)] + enum Output { + Fast, + Slow, + } + + let result: Result = trpl::block_on(async { + // 1 second is 1,000 times slower than 1 millisecond, so this should + // reliably lose to the `fast` version. + let slow = pin!(async { + trpl::sleep(Duration::from_secs(1)).await; + Ok(Output::Slow) + }); + + let fast = pin!(async { + trpl::sleep(Duration::from_millis(1)).await; + Ok(Output::Fast) + }); + + trpl::select(slow, fast).await.factor_first().0 + }); + + let val = result.unwrap(); + assert_eq!(val, Output::Fast); +} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 776710e0bc..2fe5c01716 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -740,7 +740,15 @@ building frameworks, or especially when you are building a runtime itself. Thus far, we have only used the `join` family of functions and macros. When we “join” on some collection of futures, 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. +before we move on—kind of like racing one future against another. This operation +is usually called “select” after the name of a Unix system call used to check +the status of IO operations after a time delay. Just like with `join`, there are +both function and macro versions of `select`. For this example, we will use the +function version. + + From 7da440af2e2a098bccf6a3ddcca4608171dd83d0 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 4 Jun 2024 19:13:41 -0600 Subject: [PATCH 063/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20Implement=20`tim?= =?UTF-8?q?eout`=20example=20and=20building=20blocks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a `trpl::race` function which simplifies the `select` API by ignoring the future which resolves second. Use the `race` function to show how you can implement an even simpler `timeout` function on top of it, i.e. showing how futures can compose nicely. With that in place, there is enough to be able to “work up to it” in the body of the text. --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-timeout-final/src/main.rs | 29 +++++++++++++++ .../listing-17-timeout/src/main.rs | 20 ----------- packages/trpl/src/lib.rs | 32 +++++++++++++++-- packages/trpl/tests/integration/main.rs | 35 +++++++++---------- src/ch17-02-concurrency-with-async.md | 10 +++--- 7 files changed, 80 insertions(+), 46 deletions(-) rename listings/ch17-async-await/{listing-17-timeout => listing-17-timeout-final}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-timeout => listing-17-timeout-final}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-timeout-final/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-timeout/src/main.rs diff --git a/listings/ch17-async-await/listing-17-timeout/Cargo.lock b/listings/ch17-async-await/listing-17-timeout-final/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-timeout/Cargo.lock rename to listings/ch17-async-await/listing-17-timeout-final/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-timeout/Cargo.toml b/listings/ch17-async-await/listing-17-timeout-final/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-timeout/Cargo.toml rename to listings/ch17-async-await/listing-17-timeout-final/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-timeout-final/src/main.rs b/listings/ch17-async-await/listing-17-timeout-final/src/main.rs new file mode 100644 index 0000000000..dc40b89329 --- /dev/null +++ b/listings/ch17-async-await/listing-17-timeout-final/src/main.rs @@ -0,0 +1,29 @@ +use std::{future::Future, time::Duration}; + +use trpl::Either; + +fn main() { + trpl::block_on(async { + let slow = async { + trpl::sleep(Duration::from_secs(5)).await; + "Finally finished" + }; + + match timeout(Duration::from_secs(2), slow).await { + Ok(message) => println!("Succeeded with '{message}'"), + Err(duration) => { + println!("Failed after {} seconds", duration.as_secs()) + } + } + }); +} + +async fn timeout( + max_time: Duration, + future: F, +) -> Result { + match trpl::race(future, trpl::sleep(max_time)).await { + Either::Left(output) => Ok(output), + Either::Right(_) => Err(max_time), + } +} diff --git a/listings/ch17-async-await/listing-17-timeout/src/main.rs b/listings/ch17-async-await/listing-17-timeout/src/main.rs deleted file mode 100644 index 6e06ef7e42..0000000000 --- a/listings/ch17-async-await/listing-17-timeout/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - // ANCHOR: here - let limit = Duration::from_secs(2); - let slow = async { - trpl::sleep(Duration::from_secs(5)).await; - "Finally finished" - }; - - match trpl::timeout(limit, slow).await { - Ok(message) => println!("Succeded with '{message}'"), - Err(duration) => { - println!("Failed after {} seconds", duration.as_secs()) - } - } - // ANCHOR_END: here - }); -} diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 4a9c970756..fa7efba50c 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -12,11 +12,11 @@ //! never be broken by upstream changes, e.g. if Tokio does a breaking 2.0 //! release at some point. -use std::{future::Future, time::Duration}; +use std::{future::Future, pin::pin, time::Duration}; use tokio::time; pub use futures::{ - future::{join, join3, join_all, select}, + future::{self, join, join3, join_all}, join, }; pub use tokio::{ @@ -71,3 +71,31 @@ where { time::timeout(duration, future).await.map_err(|_| duration) } + +///Run two futures +pub async fn race(f1: F1, f2: F2) -> Either +where + F1: Future, + F2: Future, +{ + let f1 = pin!(f1); + let f2 = pin!(f2); + match future::select(f1, f2).await { + future::Either::Left((a, _f2)) => Either::Left(a), + future::Either::Right((b, _f1)) => Either::Right(b), + } +} + +/// A type which represents a simple choice between two options. +/// +/// You can think of this as being like [`Result`], but where `Result` gives +/// specific meaning to the two types (success with `Ok`, failure with `Err`), +/// `Either` does not. +/// +/// Here, we use it with [`race`] because the point of `select` is to choose +/// whichever type finishes first, but neither is more “correct” than the other. +#[derive(Debug, PartialEq)] +pub enum Either { + Left(A), + Right(B), +} diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index ff800b2d7c..bb8d763d17 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -15,7 +15,7 @@ use std::{ }; use futures::Future; -use trpl::{Receiver, Sender}; +use trpl::{Either, Receiver, Sender}; /// This test is foundational for all the others, as they depend on `block_on`. /// @@ -158,29 +158,26 @@ fn re_exported_timeout_works() { } #[test] -fn re_exported_select_macro() { +fn race() { #[derive(Debug, PartialEq)] - enum Output { - Fast, - Slow, - } + struct Slow; - let result: Result = trpl::block_on(async { - // 1 second is 1,000 times slower than 1 millisecond, so this should - // reliably lose to the `fast` version. - let slow = pin!(async { - trpl::sleep(Duration::from_secs(1)).await; - Ok(Output::Slow) - }); + #[derive(Debug, PartialEq)] + struct Fast; + + let val = trpl::block_on(async { + let slow = async { + trpl::sleep(Duration::from_millis(1_000)).await; + Slow + }; - let fast = pin!(async { + let fast = async { trpl::sleep(Duration::from_millis(1)).await; - Ok(Output::Fast) - }); + Fast + }; - trpl::select(slow, fast).await.factor_first().0 + trpl::race(slow, fast).await }); - let val = result.unwrap(); - assert_eq!(val, Output::Fast); + assert_eq!(val, Either::Right(Fast)); } diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 2fe5c01716..8e85971769 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -625,13 +625,13 @@ automatically for most types. `Unpin`’s job is to tell the compiler that a given type does *not* need to uphold any particular guarantees about whether the value in question can be -moved. For example, if a future +moved. For example, if a future - - +However, we do not actually need to sleep to accomplish this. We just +need to hand back control to the runtime. We can actually *yield* +control back to the runtime, using a function named `yield_now`. It does +just what it says: hands control back to the runtime, so that the +runtime can check whether any other tasks are ready to make progress. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-b/src/main.rs:futures}} +``` + + + +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 comparing what happens +if you change Listings 17-TODO and 17-TODO to both do 100 or 1,000 iterations +instead of just 5. You will see that the version with `yield_now` is *way* faster! + + Many of these patterns are common enough to warrant abstracting over. For example, the `trpl::timeout` function takes a `Duration` for the maximum time to @@ -768,6 +831,9 @@ future finishes, the result will be `Err` with the duration that elapsed. +Here we were using the `timeout` supplied by `trpl`, but we do not have to. We +can implement it ourselves using the + [collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html [futures]: /ch17-01-futures-and-syntax.html#futures From 5a0fb4233bf2239b0d579d69f21ca7e13ef532ff Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 6 Jun 2024 11:41:32 -0600 Subject: [PATCH 067/249] =?UTF-8?q?Ch.=2017:=20Split=20the=20over-long=20?= =?UTF-8?q?=C2=A702=20into=20two=20parts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …and fix a bunch of the listing references and make some word choice and sentence structure improvements along the way to boot. --- .../listing-17-select-a/Cargo.lock | 540 ------------------ .../listing-17-select-a/Cargo.toml | 9 - .../listing-17-select-a/src/main.rs | 5 - .../listing-17-timeout-a/src/main.rs | 4 +- .../listing-17-yield-a-sleep/src/main.rs | 2 +- src/SUMMARY.md | 4 +- src/ch17-02-concurrency-with-async.md | 454 +-------------- src/ch17-03-more-futures.md | 351 ++++++++++++ src/ch17-04-TODO.md | 107 ++++ ...ds.md => ch17-05-futures-tasks-threads.md} | 0 10 files changed, 465 insertions(+), 1011 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-select-a/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-select-a/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-select-a/src/main.rs create mode 100644 src/ch17-03-more-futures.md create mode 100644 src/ch17-04-TODO.md rename src/{ch17-03-futures-tasks-threads.md => ch17-05-futures-tasks-threads.md} (100%) diff --git a/listings/ch17-async-await/listing-17-select-a/Cargo.lock b/listings/ch17-async-await/listing-17-select-a/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-select-a/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-select-a/Cargo.toml b/listings/ch17-async-await/listing-17-select-a/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-select-a/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-select-a/src/main.rs b/listings/ch17-async-await/listing-17-select-a/src/main.rs deleted file mode 100644 index 3ed5bec9d0..0000000000 --- a/listings/ch17-async-await/listing-17-select-a/src/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { trpl::select!(todo!()) }); -} diff --git a/listings/ch17-async-await/listing-17-timeout-a/src/main.rs b/listings/ch17-async-await/listing-17-timeout-a/src/main.rs index 3272806fd8..5e702a2edc 100644 --- a/listings/ch17-async-await/listing-17-timeout-a/src/main.rs +++ b/listings/ch17-async-await/listing-17-timeout-a/src/main.rs @@ -2,12 +2,11 @@ use std::time::Duration; fn main() { trpl::block_on(async { - // ANCHOR: slow + // ANCHOR: here let slow = async { trpl::sleep(Duration::from_secs(5)).await; "I finished!" }; - // ANCHOR_END: slow match trpl::timeout(Duration::from_secs(2), slow).await { Ok(message) => println!("Succeeded with '{message}'"), @@ -15,5 +14,6 @@ fn main() { println!("Failed after {} seconds", duration.as_secs()) } } + // ANCHOR_END: here }); } diff --git a/listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs b/listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs index 78a3d2c885..97480fbab8 100644 --- a/listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs +++ b/listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs @@ -22,7 +22,7 @@ fn main() { } println!("'b' finished."); }; - // ANCHOR_end: here + // ANCHOR_END: here trpl::race(a, b).await; }); diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 18c89533a5..e34b10da22 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -104,7 +104,9 @@ - [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) - - [Futures, Tasks, and Threads](ch17-03-futures-tasks-threads.md) + - [Working With More Futures](ch17-03-more-futures.md) + - [TODO](ch17-04-TODO.md) + - [Futures, Tasks, and Threads](ch17-05-futures-tasks-threads.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-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index a8938877ea..e80b7605d4 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -384,456 +384,4 @@ block, and switching back to `join3`. Both of these blocks need to be `async move` blocks, or else we will end up back in the same infinite loop we started out in. -### Working with More Futures - -When we switched from using two futures to three, 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-TODO to use `join!` instead of `join3`, as in Listing 17-TODO: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-09b/src/main.rs:here}} -``` - - - -This is definitely a nice improvement over needing to swap between `join` and -`join3` and `join4` and so on! However, both the function nor macro forms of -`join` only work for cases where we know the number of futures ahead of time. If -instead we have a dynamic number of futures, we need a function which works with -a collection type which can grow and shrink dynamically at runtime, such as a -vector. In real-world Rust, pushing futures into a collection and then waiting -on some or all the futures in that collection to complete is a very common -pattern. - -The `trpl::join_all` function accepts any type which 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, so we can swap out our -`join3` call and replace it with `join_all`. - -- -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:here}} -``` - - - -Unfortunately, this does not compile. Instead, we get this error: - - - -```text -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}` -``` - -This error message is admittedly not the most helpful! It only tells us that it -expected one async block and found another—but why is it looking for the async -blocks that it names here, and why does it only reference them by where they -appear in the code? - -One clue is the format of this message. Notice that it is exactly the same as if -we had tried to create a `Vec` with a a number and a string in it: - - - -```rust -let a = 1; -let b = "Hello"; -let vals = vec![a, b]; -``` - -The output there would be: - -```text -error[E0308]: mismatched types - --> src/main.rs:4:24 - | -4 | let vals = vec![a, b]; - | ^ expected integer, found `&str` -``` - -Saying “expected *something*, found *something else*” is Rust’s standard format -for telling us about a type mismatch. As we saw with vectors in [Using an Enum -to Store Multiple Types][collections] back in Chapter 8, we need the type of -each item in a collection to be the same—and `tx1_fut`, `rx_fut`, and `tx_fut` -do not have the same type. - -The underlying issue here is what we learned in the previous section: async -blocks compile to anonymous futures. Under the hood, there is a data structure -corresponding to each of these blocks, and it has its own unique type. This -might be surprising. After all, none of them returns anything, so the `Future` -type in each case is `Future`. However, `Future` is a trait, not a -concrete type. The actual types here are invisible from our point of view as the -person writing the code. - -In Chapter 8, we discussed one way to include multiple types in a single vector: -using an enum to represent each of the different types which can appear in the -vector. We cannot do that here, though. For one thing, we do not even have a way -to name the different types, because they are anonymous. For another, the reason -we reached for a vector and `join_all` in the first place was to be able to work -with a dynamic collection of futures where we do not know what they will all be -until runtime. - -To make this work, we need to use *trait objects*, just as we did for returning -different kinds of errors from the same function in [Returning Errors from the -run function][dyn] back in Chapter 12. Again, we will cover trait objects in -detail in Chapter 17. Here, it lets us treat each of the anonymous futures -produced by these types as interchangeable, since all of them by definition -implement the `Future` trait. - -We can start by wrapping each of the futures in the `vec!` in a `Box::new()`. -Unfortunately, the initial way we might try this, as shown in Listing 17-TODO, -still does not compile. - -- -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:here}} -``` - - - -In fact, we have the same basic 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 can start by fixing the type error around the `Box::new` calls, by telling -the compiler explicitly that we want to use these types as trait objects. The -clearest way to do that here is by adding a type annotation to the declaration -of `futures`, as we see in Listing 17-TODO. The type we have to write here is a -little involved, so let’s walk through each part of 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`. -- Then we annotate the trait with `dyn` to mark it as dynamic. -- The entire trait is wrapped in a `Box`. -- Finally, we state explicitly that `futures` is a `Vec` containing these items. - -- -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} -``` - - - -That already made a big difference. Now when we run the compiler, we only have -the errors mentioning `Unpin`, each of which is a variation on this same output: - - - -```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}>: 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 `Future` -note: required by a bound in `futures_util::future::join_all::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` -``` - -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, which is itself a `Future`, is also generic over a `Future`, and -`Future` itself requires 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 - -When we introduced the `Future` trait in the previous chapter, we saw that the -definition of its `poll` method has an unusual way of specifying the `self` -parameter. To review, here is the full definition of `Future`: - -```rust -pub trait Future { - type Output; - - // Required method - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; -} -``` - -We have not seen a method definition like this before, where `self` has a type -annotation rather than simply being named like `self`, `mut self`, `&self`, or -`&mut self`. This syntax means that the method can only be called when the -instance of the type which implements `Future` is behind a `Pin` pointer type. -This syntax is not specific to `Pin`; it also works with `Box` and other smart -pointer types, and we will see it again in Chapter 18. - -Here, the signature tells us that if we want to poll a future to check whether -it is `Pending` or `Ready(Output)`, the type which implements `Future` has to be -behind a `Pin` smart 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`? - - - -Remember that any time you write a future, a runtime is ultimately responsible -for executing it. That means that an async block might outlive the function -where you write it, the same way a closure can. - -`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 certain context. Just like `Send` and `Sync`, the compiler implements `Unpin` -automatically for most types. - -`Unpin`’s job is to tell the compiler that a given type does *not* need to -uphold any particular guarantees about whether the value in question can be -moved. For example, if a future - - - - - -Now we know enough to understand the error message from above. The problem is -that the futures produced by an async block are *not* pinned by default. -Strictly: they implement `!Unpin` to opt out of being copyable by default the -way most types are. We need to pin them explicitly. - -Now that we have an idea what that error message was telling us, we can finally -get our `join_all` call to compile! First, we need to explicitly annotate -`futures` as referring to a pinned `Box` of futures. Second, we actually need to -pin the futures, which we can do using the handy `Box::pin` API, which exists -for exactly this. Putting that together, we end up with the code in Listing -17-TODO. - -- -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} -``` - - - -If we compile and run this, we finally get the output we hoped for: - - - -```text -received 'hi' -received 'more' -received 'from' -received 'messages' -received 'the' -received 'for' -received 'future' -received 'you' -``` - -Phew! - -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 -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 -instead. - -The `std::pin::pin` macro exists to do just that for values. 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. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} -``` - - - -This keeps everything on the stack, and that is a nice little performance win, -but it is still a lot of explicit types, which is quite unusual for Rust! There -is another problem, too. We got this far by ignoring the fact that we might have -different `Output` types. For example, in Listing 17-TODO, the anonymous future -type for `a` implements `Future` and the anonymous future type for -`b` implements `Future`. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} -``` - - - -We can use `trpl::join!` to await them together, since it accepts two different -future types, but we cannot use `trpl::join_all` with these futures, because we -will never be able to make them have the same type. (This is the same as working -with any other type in Rust, though: futures are not special, even though we -have some nice syntax for working with them, and that is a good thing!) We have -a basic tradeoff here: 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 with a -static number of futures with `join!`, and so on, - - -In practice, you will usually work directly with `async` and `.await`, and only -as a secondary tool reach for the functions like `join` or `join_all`, or their -corresponding macro equivalents. These kinds of tools are really handy for -building frameworks, or especially when you are building a runtime itself. - -### Race - -Thus far, we have only used the `join` family of functions and macros. When we -“join” on some collection of futures, 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-TODO, we use `race` to run two futures, `slow` and `fast` against -each other. First, we introduce the two futures. 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-race/src/main.rs:futures}} -``` - - - -One other thing to notice: if you flip the order of the arguments to `race`, the -order of the start messages changes, but 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. That means everything up to the first `.await` in a given future will -run before *any* of the other future gets a chance to run. Other implementations -*are* fair, and will randomly choose which future to start first. - -This dynamic is important to keep in mind! An async runtime can only -switch which future it is executing at await points. That means if you -load up a bunch of really expensive work in an async function, it will -block any other futures from making progress. (You may sometimes hear -this referred to as one future *starving* other futures. The same thing -applies to threads, too!) We can work around this using the `sleep` -function, as in Listing 17-TODO. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs:futures}} -``` - - - - - -However, we do not actually need to sleep to accomplish this. We just -need to hand back control to the runtime. We can actually *yield* -control back to the runtime, using a function named `yield_now`. It does -just what it says: hands control back to the runtime, so that the -runtime can check whether any other tasks are ready to make progress. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-b/src/main.rs:futures}} -``` - - - -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 comparing what happens -if you change Listings 17-TODO and 17-TODO to both do 100 or 1,000 iterations -instead of just 5. You will see that the version with `yield_now` is *way* faster! - - - -Many of these patterns are common enough to warrant abstracting over. For -example, the `trpl::timeout` function takes a `Duration` for the maximum time to -run, but also takes a future to run, and produces a new future you can await, -whose `Output` type is a `Result`. Listing 17-TODO shows how we can use it. If -the passed-in future finishes first, the output result will be `Ok`, with the -result of that passed-in future. If the duration elapses before the passed-in -future finishes, the result will be `Err` with the duration that elapsed. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout/src/main.rs:here}} -``` - - - -Here we were using the `timeout` supplied by `trpl`, but we do not have to. We -can implement it ourselves using the - -[collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types -[dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html -[futures]: /ch17-01-futures-and-syntax.html#futures + diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md new file mode 100644 index 0000000000..c8f1a63f65 --- /dev/null +++ b/src/ch17-03-more-futures.md @@ -0,0 +1,351 @@ +## Working With More 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-TODO to use +`join!` instead of `join3`, as in Listing 17-TODO: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-09b/src/main.rs:here}} +``` + + + +This is definitely a nice improvement over needing to swap between `join` and +`join3` and `join4` and so on! However, both the function nor macro forms of +`join` only work for cases where we know the number of futures ahead of time. If +instead we have a dynamic number of futures, we need a function which works with +a collection type which can grow and shrink dynamically at runtime, such as a +vector. In real-world Rust, pushing futures into a collection and then waiting +on some or all the futures in that collection to complete is a very common +pattern. + +The `trpl::join_all` function accepts any type which 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, so we can swap out our +`join3` call and replace it with `join_all`. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:here}} +``` + + + +Unfortunately, this does not compile. Instead, we get this error: + + + +```text +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}` +``` + +This error message is admittedly not the most helpful! It only tells us that it +expected one async block and found another—but why is it looking for the async +blocks that it names here, and why does it only reference them by where they +appear in the code? + +One clue is the format of this message. Notice that it is exactly the same as if +we had tried to create a `Vec` with a a number and a string in it: + + + +```rust +let a = 1; +let b = "Hello"; +let vals = vec![a, b]; +``` + +The output there would be: + +```text +error[E0308]: mismatched types + --> src/main.rs:4:24 + | +4 | let vals = vec![a, b]; + | ^ expected integer, found `&str` +``` + +Saying “expected *something*, found *something else*” is Rust’s standard format +for telling us about a type mismatch. As we saw with vectors in [Using an Enum +to Store Multiple Types][collections] back in Chapter 8, we need the type of +each item in a collection to be the same—and `tx1_fut`, `rx_fut`, and `tx_fut` +do not have the same type. + +The underlying issue here is what we learned in the previous section: async +blocks compile to anonymous futures. Under the hood, there is a data structure +corresponding to each of these blocks, and it has its own unique type. This +might be surprising. After all, none of them returns anything, so the `Future` +type in each case is `Future`. However, `Future` is a trait, not a +concrete type. The actual types here are invisible from our point of view as the +person writing the code. + +In Chapter 8, we discussed one way to include multiple types in a single vector: +using an enum to represent each of the different types which can appear in the +vector. We cannot do that here, though. For one thing, we do not even have a way +to name the different types, because they are anonymous. For another, the reason +we reached for a vector and `join_all` in the first place was to be able to work +with a dynamic collection of futures where we do not know what they will all be +until runtime. + +To make this work, we need to use *trait objects*, just as we did for returning +different kinds of errors from the same function in [Returning Errors from the +run function][dyn] back in Chapter 12. Again, we will cover trait objects in +detail in Chapter 17. Here, it lets us treat each of the anonymous futures +produced by these types as interchangeable, since all of them by definition +implement the `Future` trait. + +We can start by wrapping each of the futures in the `vec!` in a `Box::new()`. +Unfortunately, the initial way we might try this, as shown in Listing 17-TODO, +still does not compile. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:here}} +``` + + + +In fact, we have the same basic 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 can start by fixing the type error around the `Box::new` calls, by telling +the compiler explicitly that we want to use these types as trait objects. The +clearest way to do that here is by adding a type annotation to the declaration +of `futures`, as we see in Listing 17-TODO. The type we have to write here is a +little involved, so let’s walk through each part of 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`. +- Then we annotate the trait with `dyn` to mark it as dynamic. +- The entire trait is wrapped in a `Box`. +- Finally, we state explicitly that `futures` is a `Vec` containing these items. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} +``` + + + +That already made a big difference. Now when we run the compiler, we only have +the errors mentioning `Unpin`, each of which is a variation on this same output: + + + +```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}>: 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 `Future` +note: required by a bound in `futures_util::future::join_all::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` +``` + +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, which is itself a `Future`, is also generic over a `Future`, and +`Future` itself requires 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 + +When we introduced the `Future` trait in the previous chapter, we saw that the +definition of its `poll` method has an unusual way of specifying the `self` +parameter. To review, here is the full definition of `Future`: + +```rust +pub trait Future { + type Output; + + // Required method + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} +``` + +We have not seen a method definition like this before, where `self` has a type +annotation rather than simply being named like `self`, `mut self`, `&self`, or +`&mut self`. This syntax means that the method can only be called when the +instance of the type which implements `Future` is behind a `Pin` pointer type. +This syntax is not specific to `Pin`; it also works with `Box` and other smart +pointer types, and we will see it again in Chapter 18. + +Here, the signature tells us that if we want to poll a future to check whether +it is `Pending` or `Ready(Output)`, the type which implements `Future` has to be +behind a `Pin` smart 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`? + + + +Remember that any time you write a future, a runtime is ultimately responsible +for executing it. That means that an async block might outlive the function +where you write it, the same way a closure can. + +`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 certain context. Just like `Send` and `Sync`, the compiler implements `Unpin` +automatically for most types. + +`Unpin`’s job is to tell the compiler that a given type does *not* need to +uphold any particular guarantees about whether the value in question can be +moved. For example, if a future + + + + + +Now we know enough to understand the error message from above. The problem is +that the futures produced by an async block are *not* pinned by default. +Strictly: they implement `!Unpin` to opt out of being copyable by default the +way most types are. We need to pin them explicitly. + +Now that we have an idea what that error message was telling us, we can finally +get our `join_all` call to compile! First, we need to explicitly annotate +`futures` as referring to a pinned `Box` of futures. Second, we actually need to +pin the futures, which we can do using the handy `Box::pin` API, which exists +for exactly this. Putting that together, we end up with the code in Listing +17-TODO. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} +``` + + + +If we compile and run this, we finally get the output we hoped for: + + + +```text +received 'hi' +received 'more' +received 'from' +received 'messages' +received 'the' +received 'for' +received 'future' +received 'you' +``` + +Phew! + +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 +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 +instead. + +The `std::pin::pin` macro exists to do just that for values. 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. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} +``` + + + +This keeps everything on the stack, and that is a nice little performance win, +but it is still a lot of explicit types, which is quite unusual for Rust! There +is another problem, too. We got this far by ignoring the fact that we might have +different `Output` types. For example, in Listing 17-TODO, the anonymous future +type for `a` implements `Future` and the anonymous future type for +`b` implements `Future`. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} +``` + + + +We can use `trpl::join!` to await them together, since it accepts two different +future types, but we cannot use `trpl::join_all` with these futures, because we +will never be able to make them have the same type. (This is the same as working +with any other type in Rust, though: futures are not special, even though we +have some nice syntax for working with them, and that is a good thing!) We have +a basic tradeoff here: 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 with a +static number of futures with `join!`, and so on, + + +In practice, you will usually work directly with `async` and `.await`, and only +as a secondary tool reach for the functions like `join` or `join_all`, or their +corresponding macro equivalents. These kinds of tools are really handy for +building frameworks, or especially when you are building a runtime itself. diff --git a/src/ch17-04-TODO.md b/src/ch17-04-TODO.md new file mode 100644 index 0000000000..6ef578bdf2 --- /dev/null +++ b/src/ch17-04-TODO.md @@ -0,0 +1,107 @@ +## TODO: Title This Section! + +### Race + +Thus far, we have only used the `join` family of functions and macros. When we +“join” on some collection of futures, 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-TODO, we use `race` to run two futures, `slow` and `fast` against +each other. First, we introduce the two futures. 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-race/src/main.rs:here}} +``` + + + +One other thing to notice: if you flip the order of the arguments to `race`, the +order of the start messages changes, but 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. That means everything up to the first `.await` in a given future will +run before *any* of the other future gets a chance to run. Other implementations +*are* fair, and will randomly choose which future to start first. + +This dynamic is important to keep in mind! An async runtime can only switch +which future it is executing at await points. That means if you load up a bunch +of really expensive work in an async function, it will block any other futures +from making progress. (You may sometimes hear this referred to as one future +*starving* other futures. The same thing applies to threads, too!) We can work +around this using the `sleep` function, as in Listing 17-TODO. + + + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs:here}} +``` + + + +However, we do not actually need to sleep to accomplish this. We just need to +hand back control to the runtime. We can actually *yield* control back to the +runtime, using a function named `yield_now`. It does just what it says: hands +control back to the runtime, so that the runtime can check whether any other +tasks are ready to make progress. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-b-yield/src/main.rs:here}} +``` + + + +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 comparing what happens if you change Listings +17-TODO and 17-TODO to both do 100 or 1,000 iterations instead of just 5. The +version with `yield_now` is *way* faster! + + + + + +Many of these patterns are common enough to warrant abstracting over. For +example, the `trpl::timeout` function takes a `Duration` for the maximum time to +run, but also takes a future to run, and produces a new future you can await, +whose `Output` type is a `Result`. Listing 17-TODO shows how we can use it. If +the passed-in future finishes first, the output result will be `Ok`, with the +result of that passed-in future. If the duration elapses before the passed-in +future finishes, the result will be `Err` with the duration that elapsed. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-a/src/main.rs:here}} +``` + + + +Here we were using the `timeout` supplied by `trpl`, but we do not have to. We +can implement it ourselves using the + +[collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types +[dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html +[futures]: /ch17-01-futures-and-syntax.html#futures diff --git a/src/ch17-03-futures-tasks-threads.md b/src/ch17-05-futures-tasks-threads.md similarity index 100% rename from src/ch17-03-futures-tasks-threads.md rename to src/ch17-05-futures-tasks-threads.md From 86835d655b4a80097fba8e17ffa72884647ede85 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 6 Jun 2024 11:59:17 -0600 Subject: [PATCH 068/249] Ch. 17: Show worked example of implementing `timeout` --- .../listing-17-timeout-final/src/main.rs | 5 ++ src/ch17-04-TODO.md | 81 +++++++++++++++++-- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/listings/ch17-async-await/listing-17-timeout-final/src/main.rs b/listings/ch17-async-await/listing-17-timeout-final/src/main.rs index dc40b89329..7d8ad2ca47 100644 --- a/listings/ch17-async-await/listing-17-timeout-final/src/main.rs +++ b/listings/ch17-async-await/listing-17-timeout-final/src/main.rs @@ -18,12 +18,17 @@ fn main() { }); } +// ANCHOR: timeout + +// ANCHOR: declaration async fn timeout( max_time: Duration, future: F, ) -> Result { + // ANCHOR_END: declaration match trpl::race(future, trpl::sleep(max_time)).await { Either::Left(output) => Ok(output), Either::Right(_) => Err(max_time), } } +// ANCHOR_END: timeout diff --git a/src/ch17-04-TODO.md b/src/ch17-04-TODO.md index 6ef578bdf2..f934008366 100644 --- a/src/ch17-04-TODO.md +++ b/src/ch17-04-TODO.md @@ -79,9 +79,7 @@ version with `yield_now` is *way* faster! - +### Building Our Own Async Abstractions Many of these patterns are common enough to warrant abstracting over. For example, the `trpl::timeout` function takes a `Duration` for the maximum time to @@ -91,7 +89,7 @@ the passed-in future finishes first, the output result will be `Ok`, with the result of that passed-in future. If the duration elapses before the passed-in future finishes, the result will be `Err` with the duration that elapsed. -+ ```rust {{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-a/src/main.rs:here}} @@ -100,7 +98,80 @@ future finishes, the result will be `Err` with the duration that elapsed. Here we were using the `timeout` supplied by `trpl`, but we do not have to. We -can implement it ourselves using the +can implement it ourselves using `race` and `sleep`! To begin, let’s think about +the API of `timeout`: + +- Its first parameter is a `std::time::Duration` which specifies the maximum + time to wait. +- Its second parameter is the future to run. +- It returns a `Result`. If the future completes successfully, the `Result` will + be `Ok` with the value produced by the future. If the timeout happens, the + `Result` will be `Err` with the duration that the timeout waited for. + +We can write the same signature ourselves, as in Listing 17-TODO. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-final/src/main.rs:declaration}} +``` + + + +What about the body of the function? Here, we can `race` whatever future the +caller passes with a `sleep` future. + +When we saw `race` earlier in Listing 17-TODO, 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`. Like `Result`, +`Either` can be one of two types, but unlike `Result`, there is no notion of +success or failure baked into the type. Instead, it uses `Left` and `Right` to +indicate “one or the other”. Its implementation looks like this: + +```rust +enum Either { + Left(A), + Right(B) +} +``` + +In the case of `race` specifically, it 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. + +```rust,ignore +match race(future_a, future_b).await { + Either::Left(output_from_future_a) => /* ... */, + Either::Right(output_from_future_b) => /* ... */, +} +``` + +That gives us enough to be able to implement `timeout` ourselves using `race` +and `sleep`. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-final/src/main.rs:timeout}} +``` + + + +Let’s walk through the details. Since we know from earlier that `race` is not +fair, and will prefer the first argument to the second, we pass it the future +first so it gets a chance to complete even if the caller passes in a very short +value for `max_time`. Then we match on the result of awaiting the `race`. If the +future passed in by the caller finished first, we will have +`Either::Left(output)`, which we can return as a success with `Ok`. If the sleep +finished first, we will have `Either::Right(())` instead, since `timeout` +returns the unit type `()` if it succeeds. We can ignore that `()` by using `_` +and return `Err` with the duration the user passed in instead. And that’s it! + +Back in `main`, we can call this new `timeout` function exactly like we called +`trpl::timeout` before. [collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html From a364865195cc252fcebcccdc21c1c867bdcc7b84 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 6 Jun 2024 14:09:24 -0600 Subject: [PATCH 069/249] =?UTF-8?q?Ch.=2017=20=C2=A704:=20Show=20perforanc?= =?UTF-8?q?e=20of=20`sleep`=20vs.=20`yield=5Fnow`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-yield-c-performance/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-yield-c-performance/Cargo.toml | 9 + .../src/main.rs | 34 ++ src/ch17-04-TODO.md | 25 +- 4 files changed, 602 insertions(+), 6 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-yield-c-performance/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-yield-c-performance/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-yield-c-performance/src/main.rs diff --git a/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.lock b/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-yield-c-performance/Cargo.toml b/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.toml @@ -0,0 +1,9 @@ +[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-yield-c-performance/src/main.rs b/listings/ch17-async-await/listing-17-yield-c-performance/src/main.rs new file mode 100644 index 0000000000..ef99235640 --- /dev/null +++ b/listings/ch17-async-await/listing-17-yield-c-performance/src/main.rs @@ -0,0 +1,34 @@ +use std::time::{Duration, Instant}; + +fn main() { + trpl::block_on(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() + ); + + 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/src/ch17-04-TODO.md b/src/ch17-04-TODO.md index f934008366..3ebab93361 100644 --- a/src/ch17-04-TODO.md +++ b/src/ch17-04-TODO.md @@ -73,11 +73,24 @@ 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 comparing what happens if you change Listings -17-TODO and 17-TODO to both do 100 or 1,000 iterations instead of just 5. The -version with `yield_now` is *way* faster! +You can see this for yourself by setting up a little benchmark, like the one in +Listing 17-TODO. (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-TODO and 17-TODO. Then we run for 1,000 iterations and see how long +`sleep` takes vs. `yield_now`. - ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-c-performance/src/main.rs:here}} +``` + + + +The version with `yield_now` is *way* faster! ### Building Our Own Async Abstractions @@ -118,8 +131,8 @@ We can write the same signature ourselves, as in Listing 17-TODO. -What about the body of the function? Here, we can `race` whatever future the -caller passes with a `sleep` future. +Then, in the body of the function, we can `race` whatever future the caller +passes with a `sleep` future. When we saw `race` earlier in Listing 17-TODO, we ignored its return type, because we were just interested in seeing the behavior of `fast` and `slow` when From f4cd9d2bb6c28dd0643f51df9fa6686db4f0df15 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 7 Jun 2024 07:43:20 -0600 Subject: [PATCH 070/249] =?UTF-8?q?Ch.=2017=20=C2=A701:=20rephrase=20note?= =?UTF-8?q?=20about=20the=20details=20we=20don=E2=80=99t=20get=20into?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-01-futures-and-syntax.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 8e943e3b4a..66242dbaa1 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -293,13 +293,16 @@ executes code. > > The loop as written also wouldn’t compile, because it doesn’t actually satisfy > the contract for a `Future`. In particular, `hello_async_fut` is not *pinned* -> with the `Pin` type and we did not pass along a `Context` argument. +> with the `Pin` type and we did not pass along a `Context` argument. We will +> see a little more about `Pin` later in the chapter, but we will not dig into +> `Context` because you will not normally need them for working with futures in +> day-to-day Rust code. > -> More details here are beyond the scope of this book, but are well worth -> digging into if you want to understand how things work “under the hood.” In -> particular, see [Chapter 2: Under the Hood: Executing Futures and -> Tasks][under-the-hood] and [Chapter 4: Pinning][pinning] in the official -> [_Asynchronous Programming in Rust_][async-book] book. +> 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]. Now, that’s a lot of work to just print a string, but we have laid some key foundations for working with async in Rust! Now that you know the basics of how From b5010d1cdde5e9ae6a1220068e3c31d9dc132108 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 7 Jun 2024 07:43:20 -0600 Subject: [PATCH 071/249] =?UTF-8?q?Ch.=2017=20=C2=A701:=20Add=20necessary?= =?UTF-8?q?=20background=20for=20=C2=A704=20to=20make=20sense?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix some infelicitous wording along the way, and leave a TODO item to come back to for making more sense out of the text as it stands at the conclusion of the chapter. --- src/ch17-01-futures-and-syntax.md | 60 +++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 66242dbaa1..983c4e25e8 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -221,12 +221,14 @@ enum Poll { } ``` -You may notice that this `Poll` type is a lot like an `Option`. Having a -dedicated type lets Rust treat `Poll` differently from `Option`, though, which -is important since they have very different meanings! 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. +You may notice that this `Poll` type is a lot like an `Option`: it has one +variant which has a value (`Ready(T)` and `Some(T)`), and one which does not +(`Pending` and `None`). Having a dedicated type lets Rust treat `Poll` +differently from `Option`, though, which is important since they have very +different meanings! 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 after becoming @@ -265,19 +267,47 @@ loop { } ``` -When we use `.await`, Rust actually does compile it to something very similar to -that loop. If Rust compiled it to *exactly* that code, though, every `.await` -would block the computer from doing anything else—the opposite of what we were -going for! Instead, Rust internally makes sure that the loop can hand back -control to the the context of the code where which is awaiting this little bit -of code. +When we use `.await`, Rust compiles it to something fairly similar to that loop. +If Rust compiled it to *exactly* that code, though, every `.await` would block +the computer from doing anything else—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. + +Every *await point*—that is, every place where the code explicitly calls +`.await`—represents one of those places 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 after the first await point */), + SecondAwaitPoint(/* the state used after the second await point */), + // etc. for each `.await` point... +} +``` + +Writing that out by hand would be tedious and error-prone—especially when making +changes to code later. Async Rust creates that state machine for us, and it +really is an `enum` like this, just an anonymous one you don’t have to name. As +a result, the normal rules around data structures all apply, including for +borrowing and ownership. Happily, the compiler also handles checking that for +us, and has good error messages. We will work through a few of those later in +the chapter! This is enough information to let us keep following the chain back +up to the root of our original problem with running async functions. + + When we follow that chain far enough, eventually we end up back in some non-async function. At that point, something needs to “translate” between the -async and sync worlds. That “something” is the runtime! Whatever runtime you use +async and sync worlds. That “something” is also the runtime! Whatever runtime you use is what handles the top-level `poll()` call, scheduling and handing off between -the different async operations which may be in flight, and often also providing -async versions of functionality like file I/O. +the different async operations which may be in flight as they hand back control +at await points, and often also providing async versions of functionality like +file I/O. Now we can understand why the compiler was stopping us in Listing 17-2 (before we added the `trpl::block_on` function). The `main` function is not `async`—and From 13adef4cfd2d563765876073bcaf395667ed643a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 7 Jun 2024 07:43:20 -0600 Subject: [PATCH 072/249] =?UTF-8?q?Ch.=2017=20=C2=A704:=20Explain=20the=20?= =?UTF-8?q?*implications*=20of=20yielding=20to=20motivate=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-timeout-final/src/main.rs | 2 + src/ch17-04-TODO.md | 83 ++++++++++++++----- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/listings/ch17-async-await/listing-17-timeout-final/src/main.rs b/listings/ch17-async-await/listing-17-timeout-final/src/main.rs index 7d8ad2ca47..eaee49d51b 100644 --- a/listings/ch17-async-await/listing-17-timeout-final/src/main.rs +++ b/listings/ch17-async-await/listing-17-timeout-final/src/main.rs @@ -9,7 +9,9 @@ fn main() { "Finally finished" }; + // ANCHOR: main match timeout(Duration::from_secs(2), slow).await { + // ANCHOR_END: main Ok(message) => println!("Succeeded with '{message}'"), Err(duration) => { println!("Failed after {} seconds", duration.as_secs()) diff --git a/src/ch17-04-TODO.md b/src/ch17-04-TODO.md index 3ebab93361..ca525619e7 100644 --- a/src/ch17-04-TODO.md +++ b/src/ch17-04-TODO.md @@ -1,7 +1,5 @@ ## TODO: Title This Section! -### Race - Thus far, we have only used the `join` family of functions and macros. When we “join” on some collection of futures, we require *all* of them to finish before we move on. Sometimes, though, we only need *some* future from a set to finish @@ -24,19 +22,50 @@ surprising: `fast` wins!) One other thing to notice: if you flip the order of the arguments to `race`, the -order of the start messages changes, but 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. That means everything up to the first `.await` in a given future will -run before *any* of the other future gets a chance to run. Other implementations -*are* fair, and will randomly choose which future to start first. - -This dynamic is important to keep in mind! An async runtime can only switch -which future it is executing at await points. That means if you load up a bunch -of really expensive work in an async function, it will block any other futures -from making progress. (You may sometimes hear this referred to as one future -*starving* other futures. The same thing applies to threads, too!) We can work -around this using the `sleep` function, as in Listing 17-TODO. +order of the start 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 start 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. + +To see why, recall from our discussion of [Futures][futures that Rust compiles +async blocks in a way that hands control back to the async runtime at each await +point. That has an important corollary: async runtimes can only switch which +future they are executing at await points. Everything in between await points is +just normal synchronous Rust code. That means if you do a bunch of really +expensive work in an async function without an `.await`, that future will block +any other futures from making progress. + +> Note: You may sometimes hear this referred to as one future *starving* other +> futures. The same thing applies to threads, too! + +That has another important consequence for using `race`, `join`, or other tools +like them. *Some* future is going to run first, and everything up to the first +await point in that future will run before any part of any other futures gets a +chance to run. For simple code, 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. + +### Yielding + +Let’s consider a long-running operation. Here, we will simulate it using `sleep` +inside the function, but in the real world it could be a network call or +really any operation which might take a while. + + + +Since we know that we hand off control at await points, we also know that we +need a future to await. As a starting point, we could use the `sleep` function, +as in Listing 17-TODO. -Since we know that we hand off control at await points, we also know that we -need a future to await. As a starting point, we could use the `sleep` function, -as in Listing 17-TODO. + - +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-0-blocked/src/main.rs:slow}} +``` + + + +In Listing 17-TODO we have this kind of slow work in a pair of futures which +only hand control back to the runtime *after* carrying out a bunch of slow +operations, represented by calls to `slow`: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-0-blocked/src/main.rs:slow-futures}} +``` + + + +If you run this, you will see this output: + + + +```text +'a' started. +'a' ran for 300ms +'a' ran for 100ms +'a' ran for 200ms +'a' ran for 900ms +'b' started. +'b' ran for 750ms +'b' ran for 100ms +'b' ran for 150ms +'b' ran for 350ms +'b' ran for 150ms +'a' finished. +``` + +As with our earlier example, `race` still finishes when `a` finishes. 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. It would be better if both futures could make progress between their +slow tasks. We need some way to hand control back to the runtime there—and we +know that await points are the way to do that. However, that means we need +something we can await! + +However, we can also see the handoff happening in this very example: if we +removed the `trpl::sleep` at the end of the `a` future, it would complete +without the `b` future running *at all*. Given that, maybe we could use the +`sleep` function as a starting point, as in Listing 17-TODO. @@ -81,6 +126,12 @@ as in Listing 17-TODO. +Now the two futures’ work is interleaved. The `a` future still runs for a bit +before handing off control to `b`, because it has some expensive work to do up +front, but after that they just swap back and forth every time one of them hits +an await point. In this case, we have done that after ever call to `slow`, but +we could break up the work however makes the most sense to us. + However, we do not actually need to sleep to accomplish this. We just need to hand back control to the runtime. We can actually *yield* control back to the runtime, using a function named `yield_now`. It does just what it says: hands From e56e906d7e919228946243f628818f233a8b4f50 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 7 Jun 2024 13:39:05 -0600 Subject: [PATCH 074/249] =?UTF-8?q?Ch.=2017=20=C2=A704:=20Add=20a=20good?= =?UTF-8?q?=20transition=20sentence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-04-TODO.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ch17-04-TODO.md b/src/ch17-04-TODO.md index 8a5180c0e8..332df00b1a 100644 --- a/src/ch17-04-TODO.md +++ b/src/ch17-04-TODO.md @@ -172,6 +172,10 @@ Listings 17-TODO and 17-TODO. Then we run for 1,000 iterations and see how long The version with `yield_now` is *way* faster! +In real-world code, you will not usually be alternative regular 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 Many of these patterns are common enough to warrant abstracting over. For From 95422ab0118cf5e273a59dd52ec86f8ecfd1ea3e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 7 Jun 2024 13:40:21 -0600 Subject: [PATCH 075/249] =?UTF-8?q?Ch.=2017=20=C2=A704:=20add=20a=20Note?= =?UTF-8?q?=20about=20cooperative=20multitasking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-04-TODO.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ch17-04-TODO.md b/src/ch17-04-TODO.md index 332df00b1a..1b886dc72f 100644 --- a/src/ch17-04-TODO.md +++ b/src/ch17-04-TODO.md @@ -59,12 +59,6 @@ function “slow” will just take a number of milliseconds to run, and sleep t thread for that long. This is intentionally not an async function, because the idea is to represent work that is *not* async. - - ```rust @@ -172,6 +166,14 @@ Listings 17-TODO and 17-TODO. Then we run for 1,000 iterations and see how long The version with `yield_now` is *way* faster! +> Note: This also means that async can be a useful tool 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 and +> therefore also the *responsibility* to avoid blocking for too long. This is +> how some Rust-based embedded operating systems work! + In real-world code, you will not usually be alternative regular function calls with await points on every single line, of course. The underlying dynamic is an important one to keep in mind, though! From b3931efad3ecc482ab45e814b340f29f327122e6 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 7 Jun 2024 13:40:21 -0600 Subject: [PATCH 076/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20Add=20more=20exp?= =?UTF-8?q?lanatory=20material=20on=20`Pin`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is far from complete, but at least takes another reasonable step toward an explanation, while keeping the level of detail relatively manageable, I think. --- src/ch17-03-more-futures.md | 82 ++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index c8f1a63f65..2ec7d2e221 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -26,8 +26,8 @@ pattern. The `trpl::join_all` function accepts any type which 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, so we can swap out our -`join3` call and replace it with `join_all`. +ticket. Let’s try putting our futures in a vector, and replace `join3` with +`join_all`. @@ -227,6 +227,82 @@ type to call `poll`? + + +In [Futures and Syntax: 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. Consider code like this: + + + +```rust +async { + let mut strings = vec![]; + + let a = trpl::read_to_string("test-data/hello.txt").await.unwrap(); + strings.push(a.trim()); + + let b = trpl::read_to_string("test-data/world.txt").await.unwrap(); + strings.push(b.trim()); + + let combined = strings.join(" "); + println!("{combined}"); +} +``` + +If we think about the state machine that would get compiled to, it might be +something kind of like this: + +```rust,ignore +enum AsyncStateMachine<'a> { + FirstAwait(&'a mut Vec), + SecondAwait(&'a mut Vec), +} +``` + +This could actually be fine, on its own—Rust would keep track of those mutable +references, and if we got something wrong, the borrow checker would tell us. It +gets a bit tricky, though, if we want to move around the future that corresponds +to that block. Remember, we could always do something like this: + +```rust,ignore +let file_reads_future = async { + // snip... +}; + +let some_other_future = async { + // snip... +}; + +trpl::join(file_reads_future, some_other_future).await; +``` + +If we pass those futures into `join`, or return them from a function, or put +them in a data structure to keep track of for some reason, we move the state +machine as well, and that means the `Vec` for the values we read in with +`trpl::read_to_string` moves. But the state machine Rust generated for us has +references to it. Since references point to the actual memory address of the +`Vec`, Rust needs some way to either update them so they are still valid after +the `Vec` moves, or it needs some way to keep `Vec` from getting moved around so +that the references do not need to be updated. Updating all the references to an +object every time it moves could be quite a lot of work for the compiler to add, +especially since there can be a whole web of references that need updating. On +the other hand, making sure the underlying item *does not move in memory* can be +“free” at runtime in exchange for keeping some promises at compile time. That is +where `Pin` and `Unpin` come in. + + + +> Note: This allows a whole class of complex types to be safe in Rust which are +> otherwise difficult to implement. + Remember that any time you write a future, a runtime is ultimately responsible for executing it. That means that an async block might outlive the function where you write it, the same way a closure can. +> Note: 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 fundamentally, that is a great place to start. +> Those details are not at all necessary for working with async Rust day to day, +> though. Here, we will stick to the parts you *do* need to understand to work +> with them in everyday Rust! + +`Pin` is a smart pointer, which only works with *other pointer types*, including +references, `Box`, `Rc`, and so on. (Technically, it works with any type which +implements the `Deref` trait, which we covered in Chapter 15; you can think of +this restriction as equivalent to only working with pointers, though, since +implementing `Deref` means your type behaves like a pointer type.) Wrapping a +pointer type in `Pin` enforces the exact guarantee we need: the value *behind* +the pointer we wrap in `Pin` cannot move. It is “pinned” in its current spot by +the `Pin` wrapper. -> Note: This allows a whole class of complex types to be safe in Rust which are -> otherwise difficult to implement. + Remember that any time you write a future, a runtime is ultimately responsible for executing it. That means that an async block might outlive the function where you write it, the same way a closure can. +need for pinning, or switch to connecting it to *moving*. --> `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 @@ -332,6 +345,14 @@ moved. For example, if a future My head hurts. --> +> 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*. That is, they are data structures where one part +> of the structure refers to another internally. As we have seen, futures can +> match that description, so self-referential types which require `Pin` show up +> *most* commonly in async Rust today, but you might see it come up in other +> contexts, too. + Now we know enough to understand the error message from above. The problem is that the futures produced by an async block are *not* pinned by default. Strictly: they implement `!Unpin` to opt out of being copyable by default the From a97358e0c1d3933f6b2dcee832caa6d4967facc8 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 10 Jun 2024 14:25:58 -0600 Subject: [PATCH 079/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20Finish=20a=20fir?= =?UTF-8?q?st=20pass=20on=20explaining=20`Pin`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-02-concurrency-with-async.md | 23 ++++-- src/ch17-03-more-futures.md | 107 +++++++++++++------------- 2 files changed, 69 insertions(+), 61 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index e80b7605d4..d6189a565d 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -339,16 +339,23 @@ exploration helps us understand why: it is ultimately about *ownership*. We need to move `tx` into the async block so that once that block ends, `tx` will be dropped. -In Chapter 13, we learned how to use the `move` keyword with closures, and in -Chapter 16, we saw that we often need to use closures marked with `move` when -working with threads. As we have discovered, the same dynamics apply to async -blocks—so the `move` keyword also works with async blocks, allowing them to take -ownership of the data they reference. - Since we have seen how `async` blocks borrow the items they reference from their outer scope, we can go ahead and remove the extra block we just added for now, -and switch back from `join3` to `join`. Then we can change the first async block -from an `async` block to an `async move` block, as in Listing 17-TODO: +and switch back from `join3` to `join`. + +The last step here is to figure out how to get ownership of the data instead of +just borrowing it. In Chapter 13, we learned how to use the `move` keyword with +closures, and in Chapter 16, we saw that we often need to use closures marked +with `move` when working with threads. As we have discovered, the same dynamics +apply to async blocks! Hopefully this will make sense if you remember that any +time you write a future, a runtime is ultimately responsible for executing it. +That means that an async block might outlive the function where you write it, +the same way a closure can. When a future takes ownership of the data it +references this way, it needs to move that data into the future—so the `move` +keyword works with async blocks just like it does with closures. + +Thus, we can change the first async block from an `async` block to an `async +move` block, as in Listing 17-TODO: diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index f2be660261..14b0435e57 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -305,53 +305,54 @@ where `Pin` and `Unpin` come in. > though. Here, we will stick to the parts you *do* need to understand to work > with them in everyday Rust! -`Pin` is a smart pointer, which only works with *other pointer types*, including -references, `Box`, `Rc`, and so on. (Technically, it works with any type which -implements the `Deref` trait, which we covered in Chapter 15; you can think of -this restriction as equivalent to only working with pointers, though, since -implementing `Deref` means your type behaves like a pointer type.) Wrapping a -pointer type in `Pin` enforces the exact guarantee we need: the value *behind* -the pointer we wrap in `Pin` cannot move. It is “pinned” in its current spot by -the `Pin` wrapper. - - - -Remember that any time you write a future, a runtime is ultimately responsible -for executing it. That means that an async block might outlive the function -where you write it, the same way a closure can. - -`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 certain context. Just like `Send` and `Sync`, the compiler implements `Unpin` -automatically for most types. - -`Unpin`’s job is to tell the compiler that a given type does *not* need to -uphold any particular guarantees about whether the value in question can be -moved. For example, if a future - - - - +`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. including references, +other smart pointers, and so on. + +Wrapping a pointer type in `Pin` enforces the exact guarantee we need: the value +*behind* the pointer we wrap in `Pin` cannot move. It is “pinned” in its current +spot by the `Pin` wrapper. 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. Remember: the problem `Pin` addresses is when data +structures have internal references which need to maintained when the structure +moves around, as happens with internal references in futures. 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. But what happens if +you have a `Pin` or a `Pin>`? + +We need a way to tell the compiler that it is actually just fine to move items +around in cases like these where there is nothing to worry about. 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 +most types, and implementing it manually is unsafe. That is because you have to +make sure that the type for which you are implementing `Unsafe` *never* moves +data out from a reference that *needs* to be stable. > 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*. That is, they are data structures where one part > of the structure refers to another internally. As we have seen, futures can > match that description, so self-referential types which require `Pin` show up -> *most* commonly in async Rust today, but you might see it come up in other -> contexts, too. +> *most* commonly in async Rust today, but you might—very rarely!—see it in +> other contexts, too. Now we know enough to understand the error message from above. The problem is that the futures produced by an async block are *not* pinned by default. @@ -431,20 +432,20 @@ type for `a` implements `Future` and the anonymous future type for We can use `trpl::join!` to await them together, since it accepts two different future types, but we cannot use `trpl::join_all` with these futures, because we -will never be able to make them have the same type. (This is the same as working -with any other type in Rust, though: futures are not special, even though we -have some nice syntax for working with them, and that is a good thing!) We have -a basic tradeoff here: 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 with a -static number of futures with `join!`, and so on, +will never be able to make them have the same type. We have a basic tradeoff +here: 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 with a set number of futures +with the `join` functions or the `join!` macro, even if they have different +types. This is the same as working with any other type 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 only as a secondary tool reach for the functions like `join` or `join_all`, or their -corresponding macro equivalents. These kinds of tools are really handy for -building frameworks, or especially when you are building a runtime itself. +corresponding macro equivalents. Likewise, you will only need to reach for `pin` +now and again to use them *with* those APIs. These kinds of tools are mostly +handy for building frameworks, or especially 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! [what-are-futures]: /ch17-01-futures-and-syntax.html#what-are-futures From 644bc54d0fc189e9f81da2244cb47c7e798d4eb6 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 10 Jun 2024 16:57:22 -0600 Subject: [PATCH 080/249] =?UTF-8?q?Ch.=2017=20=C2=A704:=20Code=20sample=20?= =?UTF-8?q?and=20incomplete=20sentence=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-04-TODO.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ch17-04-TODO.md b/src/ch17-04-TODO.md index 83b74ed876..8c12f079d7 100644 --- a/src/ch17-04-TODO.md +++ b/src/ch17-04-TODO.md @@ -242,7 +242,7 @@ finishes first, with that future’s output, and `Right` with the second future argument’s output if *that* one finishes first. ```rust,ignore -match race(future_a, future_b).await { +match trpl::race(future_a, future_b).await { Either::Left(output_from_future_a) => /* ... */, Either::Right(output_from_future_b) => /* ... */, } @@ -282,7 +282,9 @@ Back in `main`, we can call this new `timeout` function exactly like we called This pattern is quite common and useful. Futures compose with other futures, so you can build really powerful tools using smaller async building blocks. For -example, you can use this same approach to +example, you can use this same approach to combine timeouts with retries, and +in turn use those with things like network calls—the exact example we started +out with at the beginning of the chapter! [collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html From f7861623a15f8d447f4a228bb631337aa101899a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 11 Jun 2024 12:51:35 -0600 Subject: [PATCH 081/249] =?UTF-8?q?Ch.=2017=20=C2=A704:=20Give=20the=20sec?= =?UTF-8?q?tion=20a=20reasonable=20title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SUMMARY.md | 2 +- ...h17-04-TODO.md => ch17-04-more-ways-of-combining-futures.md} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/{ch17-04-TODO.md => ch17-04-more-ways-of-combining-futures.md} (99%) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index e34b10da22..f161db9097 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -105,7 +105,7 @@ - [Futures and the Async Syntax](ch17-01-futures-and-syntax.md) - [Concurrency With Async](ch17-02-concurrency-with-async.md) - [Working With More Futures](ch17-03-more-futures.md) - - [TODO](ch17-04-TODO.md) + - [More Ways of Combining Futures](ch17-04-more-ways-of-combining-futures.md) - [Futures, Tasks, and Threads](ch17-05-futures-tasks-threads.md) - [Object Oriented Programming Features of Rust](ch18-00-oop.md) diff --git a/src/ch17-04-TODO.md b/src/ch17-04-more-ways-of-combining-futures.md similarity index 99% rename from src/ch17-04-TODO.md rename to src/ch17-04-more-ways-of-combining-futures.md index 8c12f079d7..c5d5fd9c30 100644 --- a/src/ch17-04-TODO.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -1,4 +1,4 @@ -## TODO: Title This Section! +## More Ways of Combining Futures Thus far, we have only used the `join` family of functions and macros. When we “join” on some collection of futures, we require *all* of them to finish before From 617b75559ec74545e300130fe7097678870d4cfb Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 12 Jun 2024 11:59:24 -0600 Subject: [PATCH 082/249] =?UTF-8?q?Ch.=2017:=20an=20editing=20pass=20on=20?= =?UTF-8?q?=C2=A700=20and=20the=20start=20of=20=C2=A701?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-00-async-await.md | 31 +++++++------ src/ch17-01-futures-and-syntax.md | 75 ++++++++++++++++++------------- 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 7f97432f95..92928f87a4 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -68,8 +68,8 @@ function calls which interact with files, network sockets, or other resources on the computer, because those are the places where an individual program would benefit from the operation being *non*-blocking. -When doing file downloads, we could work around the fact that the call to write to -a network socket is blocking using threads. If we move the data over to a +When doing file downloads, we could use threads to work around the fact that the +call to write to a network socket is blocking. If we move the data over to a dedicated thread which handles the write operation, it will *not* block the rest of the program. But in many ways, it would be nicer if the call were not blocking in the first place. @@ -87,13 +87,14 @@ network_socket.read_non_blocking(|result| { Or we could register callbacks to run when events happen: ```rust,ignore -network_socket.add_listener(Event::ReadFinished, |data| { +network_socket.add_listener(Event::ReadFinished, |event| { // ... }); ``` Or we could have our functions return a type with `and_then` method, which in -turn accepts a callback which can do more work of the same sort: +turn accepts a callback which can do more work of the same sort (Historically, +this was the way that Rust did async): ```rust,ignore network_socket.read_non_blocking().and_then(|result| { @@ -101,21 +102,23 @@ network_socket.read_non_blocking().and_then(|result| { }); ``` -Historically, this last choice was the way that Rust did async! Each of these -can make the control flow for the program more complicated, though. You can end -up with many nested callbacks, or long chains of callbacks, and understanding -the flow of data through the program can become more difficult as a result. +Each of these can make the control flow for the program more complicated, +though. You can end up with event handler callbacks scattered across the code +base, or groups of deeply nested callbacks, or long chains of `and_then` calls. +Understanding the flow of data through the program can become more difficult as +a result, and dealing with callbacks can also complicate ownership. +There are also no particularly good ways to get data out of those callbacks. With other common types in Rust, we often use pattern-matching in scenarios like this. When we are using callbacks we do not yet have the data at the time we call `read_non_blocking`—and we will not have it until the callback gets called. That means that there is no way to match on the data it will return: it is not here yet! -There are also no particularly good ways to get data out of those callbacks. We -might try something like this, imagining a `read_non_blocking` which has exactly -the kind of `and_then` method described above. If we were to try to use that, -with code something like this, it would not compile: +As an alternative, we might try something like this, imagining a +`read_non_blocking` which has exactly the kind of `and_then` method described +above. If we were to try to do that, though, with code kind of like this, it +would not even compile: ```rust,ignore,does_not_compile let mut data = None; @@ -134,8 +137,8 @@ exit, but if the read *happened* to go fast enough, it is possible it could sometimes print some string data instead. That is *definitely* not what we want! -We also cannot cancel `read_non_blocking`: once it has started, it will run till -it finishes unless the whole program stops. +We also could not cancel `read_non_blocking`: once it has started, it will run +till it finishes unless the whole program stops. What we really want to be able to write is something much more direct, like we would write in blocking code, but with the benefits of getting the data when it diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index a7ea2e2814..c9956bd956 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -49,19 +49,17 @@ questions: ### Async functions -In Rust, `async fn` is equivalent to writing a function which returns a future -of the return type, using the `impl Trait` syntax we discussed back in the -[“Traits as Parameters”][impl-trait] section in Chapter 10. An `async` block -compiles to an anonymous struct which implements the `Future` trait. - -That means these two are roughly equivalent: +In Rust, `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 this: ```rust -async fn hello_async() { +async fn hello_async() { println!("Hello, async!"); } ``` +It is basically equivalent to a function defined like this instead: + ```rust fn hello_async() -> impl Future { async { @@ -70,29 +68,45 @@ fn hello_async() -> impl Future { } ``` -That explains why we got the `unused_must_use` warning: writing `async fn` meant -we were actually returning an anonymous `Future`. The compiler will warn us that -“futures do nothing unless you `.await` or poll them”. That is, futures are -*lazy*: they don’t do anything until you ask them to. - -The compiler is telling us that ignoring a `Future` makes it completely useless! -This is different from the behavior we saw when using `thread::spawn` in the -previous chapter, and it is different from how many other languages approach -async. This allows Rust to avoid running async code unless it is actually -needed. We will see why that is later on. For now, let’s start by awaiting the -future returned by `hello_async` to actually have it run. - -> Note: Rust’s `await` keyword goes *after* the expression you are awaiting—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 async and non-async methods much nicer to work -> with. As of now, `await` is the only postfix keyword in the language. +Let’s break that down and see what each part means: + +* It uses the `impl Trait` syntax we discussed back in the [“Traits as + Parameters”][impl-trait] section in Chapter 10 to return a `Future` with an + associated type of `Output`. That tells us that `Future` is a trait, and the + `Output` associated type of `()` matches the original return type from the + async version of the function. + +* It wraps the whole body of the `async fn` in an `async` block. Given that + blocks like this are expressions, and that this is expression is the one which + is returned from the function, we can infer that an `async` block like this + produces some anonymous data type which implements the `Future` trait. + +Combined, those explain that when we called `hello_async` in `main`, it 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. This should remind you of our discussion of iterators [back in Chapter +13][iterators-lazy]. With iterators, you have to call `next` to get them to do +anything—whether by using a `for` loop or by using iterator methods like `.iter()` and `.map()` which ultimately call `next()` under the hood. + +With futures, the same basic idea applies, although for different reasons, and +with different syntax and methods. This is different from the behavior we saw +when using `thread::spawn` in the previous chapter, and it is different from how +many other languages approach async. This allows Rust to avoid running async +code unless it is actually needed. We will see why that is later on. For now, +let’s start by awaiting the future returned by `hello_async` to actually have it +run. + +> Note: 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 async and non-async methods much +> nicer to work with. As of now, `await` is Rust’s only postfix keyword. -```rust +```rust,ignore, does_not_compile fn main() { hello_async().await; } @@ -303,11 +317,11 @@ up to the root of our original problem with running async functions. When we follow that chain far enough, eventually we end up back in some non-async function. At that point, something needs to “translate” between the -async and sync worlds. That “something” is also the runtime! Whatever runtime you use -is what handles the top-level `poll()` call, scheduling and handing off between -the different async operations which may be in flight as they hand back control -at await points, and often also providing async versions of functionality like -file I/O. +async and sync worlds. That “something” is also the runtime! Whatever runtime +you use is what handles the top-level `poll()` call, scheduling and handing off +between the different async operations which may be in flight as they hand back +control at await points, and often also providing async versions of +functionality like file I/O. Now we can understand why the compiler was stopping us in Listing 17-2 (before we added the `trpl::block_on` function). The `main` function is not `async`—and @@ -339,6 +353,7 @@ foundations for working with async in Rust! Now that you know the basics of how futures and runtimes work, we can see some of 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/ From 2360484f63f9f44c88dd53b991430a34257d0d27 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 12 Jun 2024 13:58:46 -0600 Subject: [PATCH 083/249] Ch. 17: reduce dependency list for `trpl` crate This makes compiled output in listings much more reasonable. It may be worth seeing if we can trim it down even further. (Switching to `smol` would do that, I think, but would have other effects.) --- packages/trpl/Cargo.lock | 260 ------------------------ packages/trpl/Cargo.toml | 6 +- packages/trpl/tests/integration/main.rs | 5 +- 3 files changed, 6 insertions(+), 265 deletions(-) diff --git a/packages/trpl/Cargo.lock b/packages/trpl/Cargo.lock index 20893eeaaa..e6e27ec0a4 100644 --- a/packages/trpl/Cargo.lock +++ b/packages/trpl/Cargo.lock @@ -38,18 +38,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.98" @@ -169,16 +157,6 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[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" @@ -194,17 +172,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" @@ -224,29 +191,6 @@ dependencies = [ "memchr", ] -[[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.5", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -277,36 +221,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" @@ -316,22 +236,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.66" @@ -350,27 +254,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -386,148 +271,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/packages/trpl/Cargo.toml b/packages/trpl/Cargo.toml index 046f95da5b..626318db3d 100644 --- a/packages/trpl/Cargo.toml +++ b/packages/trpl/Cargo.toml @@ -7,4 +7,8 @@ edition = "2021" [dependencies] futures = "0.3.30" -tokio = { version = "1", features = ["full"] } +tokio = { version = "1", default-features = false, features = [ + "rt-multi-thread", + "sync", + "time", +] } diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index 9105a5aef0..28421ba5ee 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -9,10 +9,7 @@ //! //! [post]: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html -use std::{ - pin::{pin, Pin}, - time::Duration, -}; +use std::{pin::Pin, time::Duration}; use futures::Future; use trpl::{Either, Receiver, Sender}; From 5458a6a4d4557249b9b7d6240d4f142ad961b554 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 12 Jun 2024 13:58:46 -0600 Subject: [PATCH 084/249] =?UTF-8?q?Ch.=2017:=20correct=20listing=20numbers?= =?UTF-8?q?=20for=20=C2=A701?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch17-async-await/listing-17-01/Cargo.lock | 533 ----------------- .../ch17-async-await/listing-17-01/Cargo.toml | 3 - .../ch17-async-await/listing-17-01/output.txt | 14 + .../listing-17-01/src/main.rs | 26 +- .../ch17-async-await/listing-17-02/Cargo.lock | 533 ----------------- .../ch17-async-await/listing-17-02/Cargo.toml | 3 - .../ch17-async-await/listing-17-02/output.txt | 12 + .../listing-17-02/src/main.rs | 24 +- .../ch17-async-await/listing-17-03/Cargo.lock | 300 +--------- .../ch17-async-await/listing-17-03/Cargo.toml | 6 +- .../ch17-async-await/listing-17-03/output.txt | 27 + .../listing-17-03/src/main.rs | 26 +- .../listing-S02-17-01/Cargo.lock | 540 ++++++++++++++++++ .../listing-S02-17-01/Cargo.toml | 9 + .../listing-S02-17-01/src/main.rs | 25 + .../listing-S02-17-02/Cargo.lock | 540 ++++++++++++++++++ .../listing-S02-17-02/Cargo.toml | 9 + .../listing-S02-17-02/src/main.rs | 21 + .../listing-S02-17-03/Cargo.lock | 540 ++++++++++++++++++ .../listing-S02-17-03/Cargo.toml | 9 + .../listing-S02-17-03/src/main.rs | 23 + src/ch17-01-futures-and-syntax.md | 58 +- src/ch17-02-concurrency-with-async.md | 8 +- 23 files changed, 1823 insertions(+), 1466 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-01/output.txt create mode 100644 listings/ch17-async-await/listing-17-02/output.txt create mode 100644 listings/ch17-async-await/listing-17-03/output.txt create mode 100644 listings/ch17-async-await/listing-S02-17-01/Cargo.lock create mode 100644 listings/ch17-async-await/listing-S02-17-01/Cargo.toml create mode 100644 listings/ch17-async-await/listing-S02-17-01/src/main.rs create mode 100644 listings/ch17-async-await/listing-S02-17-02/Cargo.lock create mode 100644 listings/ch17-async-await/listing-S02-17-02/Cargo.toml create mode 100644 listings/ch17-async-await/listing-S02-17-02/src/main.rs create mode 100644 listings/ch17-async-await/listing-S02-17-03/Cargo.lock create mode 100644 listings/ch17-async-await/listing-S02-17-03/Cargo.toml create mode 100644 listings/ch17-async-await/listing-S02-17-03/src/main.rs diff --git a/listings/ch17-async-await/listing-17-01/Cargo.lock b/listings/ch17-async-await/listing-17-01/Cargo.lock index 3be4eaaa53..d30b928a6c 100644 --- a/listings/ch17-async-await/listing-17-01/Cargo.lock +++ b/listings/ch17-async-await/listing-17-01/Cargo.lock @@ -2,539 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-01/Cargo.toml b/listings/ch17-async-await/listing-17-01/Cargo.toml index 349041d3eb..67729afc80 100644 --- a/listings/ch17-async-await/listing-17-01/Cargo.toml +++ b/listings/ch17-async-await/listing-17-01/Cargo.toml @@ -4,6 +4,3 @@ 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 new file mode 100644 index 0000000000..9fc69b9ac1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-01/output.txt @@ -0,0 +1,14 @@ +$ 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: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.11s + 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 62b08cf5e9..70ce867bf2 100644 --- a/listings/ch17-async-await/listing-17-01/src/main.rs +++ b/listings/ch17-async-await/listing-17-01/src/main.rs @@ -1,25 +1,11 @@ // ANCHOR: all -use std::time::Duration; - fn main() { - // ANCHOR: block_on - trpl::block_on(async { - // ANCHOR_END: block_on - // ANCHOR: task - trpl::spawn_task(async { - for i in 1..10 { - println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - }); + hello_async(); +} - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - // ANCHOR_END: task - // ANCHOR: block_on - }); - // ANCHOR_END: block_on +// ANCHOR: async-fn +async fn hello_async() { + println!("Hello, async!"); } +// ANCHOR_END: async-fn // 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 3be4eaaa53..d30b928a6c 100644 --- a/listings/ch17-async-await/listing-17-02/Cargo.lock +++ b/listings/ch17-async-await/listing-17-02/Cargo.lock @@ -2,539 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-02/Cargo.toml b/listings/ch17-async-await/listing-17-02/Cargo.toml index 349041d3eb..67729afc80 100644 --- a/listings/ch17-async-await/listing-17-02/Cargo.toml +++ b/listings/ch17-async-await/listing-17-02/Cargo.toml @@ -4,6 +4,3 @@ 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 new file mode 100644 index 0000000000..0910145234 --- /dev/null +++ b/listings/ch17-async-await/listing-17-02/output.txt @@ -0,0 +1,12 @@ +$ cargo run + Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-02) +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> src/main.rs:3:19 + | +2 | fn main() { + | ---- this is not `async` +3 | 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 079cbe06a9..4ce7800db7 100644 --- a/listings/ch17-async-await/listing-17-02/src/main.rs +++ b/listings/ch17-async-await/listing-17-02/src/main.rs @@ -1,21 +1,9 @@ -use std::time::Duration; - +// ANCHOR: main fn main() { - trpl::block_on(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(1)).await; - } - }); - - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(1)).await; - } + hello_async().await; +} +// ANCHOR_END: main - handle.await; - // ANCHOR_END: handle - }); +async fn hello_async() { + println!("Hello, async!"); } diff --git a/listings/ch17-async-await/listing-17-03/Cargo.lock b/listings/ch17-async-await/listing-17-03/Cargo.lock index 3be4eaaa53..89df255f72 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.lock +++ b/listings/ch17-async-await/listing-17-03/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -32,9 +32,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -45,23 +45,11 @@ 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" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -160,9 +148,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "hermit-abi" @@ -172,19 +160,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" 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", -] +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "memchr" @@ -194,24 +172,13 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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 = "num_cpus" version = "1.16.0" @@ -224,36 +191,13 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" 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" @@ -268,9 +212,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -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,27 +243,11 @@ 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" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -352,32 +256,13 @@ dependencies = [ [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-03/Cargo.toml b/listings/ch17-async-await/listing-17-03/Cargo.toml index 349041d3eb..5f2e9ac2d0 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.toml +++ b/listings/ch17-async-await/listing-17-03/Cargo.toml @@ -3,7 +3,7 @@ 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" } +trpl = { version = "0.1.0", path = "../../../packages/trpl" } + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/listings/ch17-async-await/listing-17-03/output.txt b/listings/ch17-async-await/listing-17-03/output.txt new file mode 100644 index 0000000000..d0d2eb5d91 --- /dev/null +++ b/listings/ch17-async-await/listing-17-03/output.txt @@ -0,0 +1,27 @@ +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-03/src/main.rs b/listings/ch17-async-await/listing-17-03/src/main.rs index 60889f3aed..111f734666 100644 --- a/listings/ch17-async-await/listing-17-03/src/main.rs +++ b/listings/ch17-async-await/listing-17-03/src/main.rs @@ -1,23 +1,9 @@ -use std::time::Duration; - +// ANCHOR: main fn main() { - trpl::block_on(async { - // ANCHOR: join - let fut1 = async { - for i in 1..10 { - println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - }; - - let fut2 = async { - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - }; + trpl::block_on(hello_async()); +} +// ANCHOR_END: main - trpl::join(fut1, fut2).await; - // ANCHOR_END: join - }); +async fn hello_async() { + println!("Hello, async!"); } diff --git a/listings/ch17-async-await/listing-S02-17-01/Cargo.lock b/listings/ch17-async-await/listing-S02-17-01/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-01/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-S02-17-01/Cargo.toml b/listings/ch17-async-await/listing-S02-17-01/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-01/Cargo.toml @@ -0,0 +1,9 @@ +[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-S02-17-01/src/main.rs b/listings/ch17-async-await/listing-S02-17-01/src/main.rs new file mode 100644 index 0000000000..62b08cf5e9 --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-01/src/main.rs @@ -0,0 +1,25 @@ +// ANCHOR: all +use std::time::Duration; + +fn main() { + // ANCHOR: block_on + trpl::block_on(async { + // ANCHOR_END: block_on + // ANCHOR: task + trpl::spawn_task(async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }); + + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + // ANCHOR_END: task + // ANCHOR: block_on + }); + // ANCHOR_END: block_on +} +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-S02-17-02/Cargo.lock b/listings/ch17-async-await/listing-S02-17-02/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-02/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-S02-17-02/Cargo.toml b/listings/ch17-async-await/listing-S02-17-02/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-02/Cargo.toml @@ -0,0 +1,9 @@ +[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-S02-17-02/src/main.rs b/listings/ch17-async-await/listing-S02-17-02/src/main.rs new file mode 100644 index 0000000000..079cbe06a9 --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-02/src/main.rs @@ -0,0 +1,21 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(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(1)).await; + } + }); + + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + + handle.await; + // ANCHOR_END: handle + }); +} diff --git a/listings/ch17-async-await/listing-S02-17-03/Cargo.lock b/listings/ch17-async-await/listing-S02-17-03/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-03/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-S02-17-03/Cargo.toml b/listings/ch17-async-await/listing-S02-17-03/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-03/Cargo.toml @@ -0,0 +1,9 @@ +[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-S02-17-03/src/main.rs b/listings/ch17-async-await/listing-S02-17-03/src/main.rs new file mode 100644 index 0000000000..60889f3aed --- /dev/null +++ b/listings/ch17-async-await/listing-S02-17-03/src/main.rs @@ -0,0 +1,23 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + // ANCHOR: join + let fut1 = async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }; + + let fut2 = async { + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }; + + trpl::join(fut1, fut2).await; + // ANCHOR_END: join + }); +} diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index c9956bd956..6e0696efeb 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -11,13 +11,7 @@ Let’s write our first async function, and call it: ```rust -fn main() { - hello_async(); -} - -async fn hello_async() { - println!("Hello, async!"); -} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:all}} ``` @@ -25,19 +19,7 @@ async fn hello_async() { If we compile and run this… nothing happens, and we get a compiler warning: ```console -$ cargo run -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: `hello-async` (bin "hello-async") generated 1 warning - Finished dev [unoptimized + debuginfo] target(s) in 1.50s - Running `target/debug/hello-async` +{{#include ../listings/ch17-async-await/listing-17-01/output.txt}} ``` The warning tells us that just calling `hello_async()` was not enough: we also @@ -53,9 +35,7 @@ In Rust, `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 this: ```rust -async fn hello_async() { - println!("Hello, async!"); -} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:async-fn}} ``` It is basically equivalent to a function defined like this instead: @@ -106,24 +86,16 @@ run. -```rust,ignore, does_not_compile -fn main() { - hello_async().await; -} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-02/src/main.rs:main}} ``` Oh no! We have gone from a compiler warning to an actual error: -```text -error[E0728]: `await` is only allowed inside `async` functions and blocks - --> src/main.rs:2:19 - | -1 | fn main() { - | ---- this is not `async` -2 | hello_async().await; - | ^^^^^ only allowed inside `async` functions and blocks +```console +{{#include ../listings/ch17-async-await/listing-17-02/output.txt}} ``` This time, the compiler is informing us we cannot use `.await` in `main`, @@ -177,27 +149,15 @@ completes. ```rust -fn main() { - trpl::block_on(hello_async()); -} - -async fn hello_async() { - println!("Hello, async!"); -} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-03/src/main.rs:main}} ``` When we run this, we get the behavior we might have expected initially: - - ```console -$ cargo run - Compiling hello-async v0.1.0 (/Users/chris/dev/chriskrycho/async-trpl-fun/hello-async) - Finished dev [unoptimized + debuginfo] target(s) in 4.89s - Running `target/debug/hello-async` -Hello, async! +{{#include ../listings/ch17-async-await/listing-17-03/output.txt}} ``` Phew: we finally have some working async code! Now we can answer that second diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index d6189a565d..1f6ba11dcf 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -21,7 +21,7 @@ to implement the same counting example as with threads. To start, we will set up our `main` function with `trpl::block_on`: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:block_on}} +{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-01/src/main.rs:block_on}} ``` > Note: From this point forward in the chapter, every example will include this @@ -35,7 +35,7 @@ top-level `for` loop. Notice that we also need to add a `.await` after the `sleep` calls. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:task}} +{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-01/src/main.rs:task}} ``` This does something very similar to what the thread-based implementation did, as @@ -64,7 +64,7 @@ thread was done running. Here, we can use `await` to do the same thing: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-02/src/main.rs:handle}} +{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-02/src/main.rs:handle}} ``` @@ -103,7 +103,7 @@ ask the runtime to run them both to completion using `trpl::join`: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-03/src/main.rs:join}} +{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-03/src/main.rs:join}} ``` From 217645eb3540dbf63fa23d1ecdc1b16a5e62c964 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 12 Jun 2024 15:28:14 -0600 Subject: [PATCH 085/249] =?UTF-8?q?Ch.=2017=20=C2=A701:=20flag=20a=20TODO?= =?UTF-8?q?=20item=20for=20later?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-01-futures-and-syntax.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 6e0696efeb..5c2c74ba4e 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -273,7 +273,9 @@ us, and has good error messages. We will work through a few of those later in the chapter! This is enough information to let us keep following the chain back up to the root of our original problem with running async functions. - + When we follow that chain far enough, eventually we end up back in some non-async function. At that point, something needs to “translate” between the From c310f54aab8a94ca1d36c01aedb830a2a14988d5 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 12 Jun 2024 15:29:16 -0600 Subject: [PATCH 086/249] Ch. 17: Finish (first pass) documentation for `trpl::race` Explain how it relates to `futures::future::select` and why `trpl` uses `race` semantics instead. --- packages/trpl/src/lib.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index e7ef277c09..2a98c3ac40 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -72,7 +72,16 @@ where time::timeout(duration, future).await.map_err(|_| duration) } -///Run two futures +/// Run two futures, taking whichever finishes first and canceling the other. +/// +/// Notice that this is built on [`futures::future::select`], which has the +/// same overall semantics but does *not* drop the slower future. The idea there +/// is that you can work with the first result and then later *also* continue +/// waiting for the second future. +/// +/// We use the `race` semantics, where the slower future is simply dropped, for +/// the sake of simplicity in the examples: no need to deal with the tuple and +/// intentionally ignore the second future this way! pub async fn race(f1: F1, f2: F2) -> Either where F1: Future, From 69323d90da59cac43ef7bcbd0ea19f1ceeccc3e9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 08:14:22 -0600 Subject: [PATCH 087/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listing=2017-04?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-04-orig/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-04-orig/Cargo.toml | 9 + .../listing-17-04-orig/src/main.rs | 17 + .../ch17-async-await/listing-17-04/Cargo.lock | 260 --------- .../listing-17-04/src/main.rs | 16 +- src/ch17-02-concurrency-with-async.md | 13 +- 6 files changed, 576 insertions(+), 279 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-04-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-04-orig/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-04-orig/src/main.rs diff --git a/listings/ch17-async-await/listing-17-04-orig/Cargo.lock b/listings/ch17-async-await/listing-17-04-orig/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-04-orig/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-04-orig/Cargo.toml b/listings/ch17-async-await/listing-17-04-orig/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-04-orig/Cargo.toml @@ -0,0 +1,9 @@ +[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-04-orig/src/main.rs b/listings/ch17-async-await/listing-17-04-orig/src/main.rs new file mode 100644 index 0000000000..a6033e5994 --- /dev/null +++ b/listings/ch17-async-await/listing-17-04-orig/src/main.rs @@ -0,0 +1,17 @@ +// ANCHOR: all +fn main() { + trpl::block_on(async { + // ANCHOR: add-channel + let (tx, mut rx) = trpl::channel(); + // ANCHOR_END: add-channel + + // ANCHOR: send-and-receive + let val = String::from("hi"); + tx.send(val).unwrap(); + + let received = rx.recv().await.unwrap(); + println!("Got: {received}"); + // ANCHOR_END: send-and-receive + }); +} +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-04/Cargo.lock b/listings/ch17-async-await/listing-17-04/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.lock +++ b/listings/ch17-async-await/listing-17-04/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-04/src/main.rs b/listings/ch17-async-await/listing-17-04/src/main.rs index a6033e5994..ab559c800f 100644 --- a/listings/ch17-async-await/listing-17-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -1,17 +1,7 @@ -// ANCHOR: all fn main() { + // ANCHOR: block_on trpl::block_on(async { - // ANCHOR: add-channel - let (tx, mut rx) = trpl::channel(); - // ANCHOR_END: add-channel - - // ANCHOR: send-and-receive - let val = String::from("hi"); - tx.send(val).unwrap(); - - let received = rx.recv().await.unwrap(); - println!("Got: {received}"); - // ANCHOR_END: send-and-receive + // our implementation will go here }); + // ANCHOR_END: block_on } -// ANCHOR_END: all diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 1f6ba11dcf..8ac7a59ee7 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -18,15 +18,16 @@ 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. -To start, we will set up our `main` function with `trpl::block_on`: +Listing 17-4 shows our starting point. We set up our `main` function with `trpl::block_on`, so that our top-level function can be async. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-01/src/main.rs:block_on}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:block_on}} ``` > Note: From this point forward in the chapter, every example will include this -> exact same code, so we will often skip it just like we do with `main`. Don’t -> forget to include it in your own code! +> 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! Then we can write two loops within that block, each with a `trpl::sleep` call in them. Similar to the threading example, we put one loop in the body of a @@ -169,7 +170,7 @@ single-consumer channel channel API we used with threads back in Chapter 16: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:add-channel}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04-orig/src/main.rs:add-channel}} ``` @@ -182,7 +183,7 @@ using `.await` on the `rx.recv()` call. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:send-and-receive}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04-orig/src/main.rs:send-and-receive}} ``` From ccd68087cd2c5b9f97da43785443ae66bac4037a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 08:35:15 -0600 Subject: [PATCH 088/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listing=2017-05?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-05-orig/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-05-orig/Cargo.toml | 9 + .../listing-17-05-orig/src/main.rs | 31 + .../ch17-async-await/listing-17-05/Cargo.lock | 260 --------- .../listing-17-05/src/main.rs | 34 +- src/ch17-02-concurrency-with-async.md | 10 +- 6 files changed, 600 insertions(+), 284 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-05-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-05-orig/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-05-orig/src/main.rs diff --git a/listings/ch17-async-await/listing-17-05-orig/Cargo.lock b/listings/ch17-async-await/listing-17-05-orig/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-05-orig/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-05-orig/Cargo.toml b/listings/ch17-async-await/listing-17-05-orig/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-05-orig/Cargo.toml @@ -0,0 +1,9 @@ +[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-05-orig/src/main.rs b/listings/ch17-async-await/listing-17-05-orig/src/main.rs new file mode 100644 index 0000000000..c1b62d8e66 --- /dev/null +++ b/listings/ch17-async-await/listing-17-05-orig/src/main.rs @@ -0,0 +1,31 @@ +// ANCHOR: all +// ANCHOR: many-messages +use std::time::Duration; +// ANCHOR_END: many-messages + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + // ANCHOR: many-messages + 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_secs(1)).await; + } + // ANCHOR_END: many-messages + + // ANCHOR: loop + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + // ANCHOR_END: loop + }); +} +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-05/Cargo.lock b/listings/ch17-async-await/listing-17-05/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-05/Cargo.lock +++ b/listings/ch17-async-await/listing-17-05/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-05/src/main.rs b/listings/ch17-async-await/listing-17-05/src/main.rs index c1b62d8e66..36ddedca26 100644 --- a/listings/ch17-async-await/listing-17-05/src/main.rs +++ b/listings/ch17-async-await/listing-17-05/src/main.rs @@ -1,31 +1,19 @@ -// ANCHOR: all -// ANCHOR: many-messages use std::time::Duration; -// ANCHOR_END: many-messages fn main() { trpl::block_on(async { - let (tx, mut rx) = trpl::channel(); + // ANCHOR: task + trpl::spawn_task(async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; + } + }); - // ANCHOR: many-messages - 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_secs(1)).await; - } - // ANCHOR_END: many-messages - - // ANCHOR: loop - while let Some(value) = rx.recv().await { - println!("received '{value}'"); + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; } - // ANCHOR_END: loop + // ANCHOR_END: task }); } -// ANCHOR_END: all diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 8ac7a59ee7..c0b82f2c5e 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -35,14 +35,22 @@ them. Similar to the threading example, we put one loop in the body of a top-level `for` loop. Notice that we also need to add a `.await` after the `sleep` calls. ++ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-01/src/main.rs:task}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:task}} ``` + + This does something very similar to what the thread-based implementation did, as we can see from the output when we run it. (As with the threading example, you may see a different order in your own terminal output when you run this.) + + ```text hi number 1 from the second task! hi number 1 from the first task! From 4c4ebb7bb549e66103ae3496cb0b2e9f02bf6cef Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 08:35:15 -0600 Subject: [PATCH 089/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listing=2017-06?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-06-orig/src/main.rs | 33 +++ .../ch17-async-await/listing-17-06/Cargo.lock | 260 ------------------ .../listing-17-06/src/main.rs | 36 +-- .../listing-S02-17-02/src/main.rs | 21 -- src/ch17-02-concurrency-with-async.md | 22 +- 7 files changed, 59 insertions(+), 313 deletions(-) rename listings/ch17-async-await/{listing-S02-17-02 => listing-17-06-orig}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-S02-17-02 => listing-17-06-orig}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-06-orig/src/main.rs delete mode 100644 listings/ch17-async-await/listing-S02-17-02/src/main.rs diff --git a/listings/ch17-async-await/listing-S02-17-02/Cargo.lock b/listings/ch17-async-await/listing-17-06-orig/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-S02-17-02/Cargo.lock rename to listings/ch17-async-await/listing-17-06-orig/Cargo.lock diff --git a/listings/ch17-async-await/listing-S02-17-02/Cargo.toml b/listings/ch17-async-await/listing-17-06-orig/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-S02-17-02/Cargo.toml rename to listings/ch17-async-await/listing-17-06-orig/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-06-orig/src/main.rs b/listings/ch17-async-await/listing-17-06-orig/src/main.rs new file mode 100644 index 0000000000..aeeacc5462 --- /dev/null +++ b/listings/ch17-async-await/listing-17-06-orig/src/main.rs @@ -0,0 +1,33 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + 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"), + ]; + + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_secs(1)).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 + }); +} diff --git a/listings/ch17-async-await/listing-17-06/Cargo.lock b/listings/ch17-async-await/listing-17-06/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-06/Cargo.lock +++ b/listings/ch17-async-await/listing-17-06/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-06/src/main.rs b/listings/ch17-async-await/listing-17-06/src/main.rs index aeeacc5462..dbc2241b96 100644 --- a/listings/ch17-async-await/listing-17-06/src/main.rs +++ b/listings/ch17-async-await/listing-17-06/src/main.rs @@ -2,32 +2,20 @@ use std::time::Duration; fn main() { trpl::block_on(async { - 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"), - ]; - - for val in vals { - tx.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).await; + // 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(1)).await; } - }; + }); - let rx_fut = async { - // ANCHOR: loop - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - // ANCHOR_END: loop - }; + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; + } - trpl::join(tx_fut, rx_fut).await; - // ANCHOR_END: futures + handle.await.unwrap(); + // ANCHOR_END: handle }); } diff --git a/listings/ch17-async-await/listing-S02-17-02/src/main.rs b/listings/ch17-async-await/listing-S02-17-02/src/main.rs deleted file mode 100644 index 079cbe06a9..0000000000 --- a/listings/ch17-async-await/listing-S02-17-02/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(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(1)).await; - } - }); - - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - - handle.await; - // ANCHOR_END: handle - }); -} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index c0b82f2c5e..570471424d 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -68,17 +68,23 @@ because the task spawned by `spawn_task` is shut down when the main function ends—just like threads are. Thus, 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. Here, we can use `await` to do the same thing: +thread was done running. Here, we can use `await` to do the same thing, and +since the handle’s output is actually a `Result`, we will also unwrap it. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-02/src/main.rs:handle}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-06/src/main.rs:handle}} ``` -Now the output again looks like what we saw in the threading example. +Now the output again looks like what we saw in the threading example. (Again, +the exact output may look different for you.) + + ```text hi number 1 from the second task! @@ -217,7 +223,7 @@ as shown in Listing 17-TODO: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:many-messages}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05-orig/src/main.rs:many-messages}} ``` @@ -232,7 +238,7 @@ Listing 17-TODO, and the loop will end when `rx.recv().await` produces a `None`. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:loop}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05-orig/src/main.rs:loop}} ``` @@ -258,7 +264,7 @@ at the whole thing all together. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05-orig/src/main.rs:all}} ``` @@ -279,7 +285,7 @@ above. Listing 17-TODO shows how that looks. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-06/src/main.rs:futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-06-orig/src/main.rs:futures}} ``` From 4c41d8f015a4b9dd3d63b910b616db2695404c3c Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 09:12:01 -0600 Subject: [PATCH 090/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20remove=20listing?= =?UTF-8?q?=20that=20I=20split=20into=20multiple=20parts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 6fd549dc22fcb1fca1d9d9983f1e6127b2ab3604 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 09:12:01 -0600 Subject: [PATCH 091/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listing=2017-07?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-07-orig/src/main.rs | 45 ++ .../listing-17-07/src/main.rs | 44 +- .../listing-S02-17-01/src/main.rs | 25 - .../listing-S02-17-03/Cargo.lock | 540 ------------------ .../listing-S02-17-03/Cargo.toml | 9 - .../listing-S02-17-03/src/main.rs | 23 - src/ch17-02-concurrency-with-async.md | 6 +- 9 files changed, 59 insertions(+), 633 deletions(-) rename listings/ch17-async-await/{listing-S02-17-01 => listing-17-07-orig}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-S02-17-01 => listing-17-07-orig}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-07-orig/src/main.rs delete mode 100644 listings/ch17-async-await/listing-S02-17-01/src/main.rs delete mode 100644 listings/ch17-async-await/listing-S02-17-03/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-S02-17-03/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-S02-17-03/src/main.rs diff --git a/listings/ch17-async-await/listing-S02-17-01/Cargo.lock b/listings/ch17-async-await/listing-17-07-orig/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-S02-17-01/Cargo.lock rename to listings/ch17-async-await/listing-17-07-orig/Cargo.lock diff --git a/listings/ch17-async-await/listing-S02-17-01/Cargo.toml b/listings/ch17-async-await/listing-17-07-orig/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-S02-17-01/Cargo.toml rename to listings/ch17-async-await/listing-17-07-orig/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-07-orig/src/main.rs b/listings/ch17-async-await/listing-17-07-orig/src/main.rs new file mode 100644 index 0000000000..e5d8f86066 --- /dev/null +++ b/listings/ch17-async-await/listing-17-07-orig/src/main.rs @@ -0,0 +1,45 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx_fut = async { + 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_secs(1)).await; + } + }; + + let rx_fut = async { + while let Some(received) = rx.recv().await { + println!("Got: {received}"); + } + }; + + // ANCHOR: updated + let tx_fut2 = async { + 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; + } + }; + + trpl::join3(tx_fut, tx_fut2, rx_fut).await; + // ANCHOR_END: updated + }); +} 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 e5d8f86066..60889f3aed 100644 --- a/listings/ch17-async-await/listing-17-07/src/main.rs +++ b/listings/ch17-async-await/listing-17-07/src/main.rs @@ -2,44 +2,22 @@ use std::time::Duration; fn main() { trpl::block_on(async { - let (tx, mut rx) = trpl::channel(); - - let tx_fut = async { - 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_secs(1)).await; - } - }; - - let rx_fut = async { - while let Some(received) = rx.recv().await { - println!("Got: {received}"); + // ANCHOR: join + let fut1 = async { + for i in 1..10 { + println!("hi number {i} from the first task!"); + trpl::sleep(Duration::from_millis(1)).await; } }; - // ANCHOR: updated - let tx_fut2 = async { - 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; + let fut2 = async { + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(1)).await; } }; - trpl::join3(tx_fut, tx_fut2, rx_fut).await; - // ANCHOR_END: updated + trpl::join(fut1, fut2).await; + // ANCHOR_END: join }); } diff --git a/listings/ch17-async-await/listing-S02-17-01/src/main.rs b/listings/ch17-async-await/listing-S02-17-01/src/main.rs deleted file mode 100644 index 62b08cf5e9..0000000000 --- a/listings/ch17-async-await/listing-S02-17-01/src/main.rs +++ /dev/null @@ -1,25 +0,0 @@ -// ANCHOR: all -use std::time::Duration; - -fn main() { - // ANCHOR: block_on - trpl::block_on(async { - // ANCHOR_END: block_on - // ANCHOR: task - trpl::spawn_task(async { - for i in 1..10 { - println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - }); - - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - // ANCHOR_END: task - // ANCHOR: block_on - }); - // ANCHOR_END: block_on -} -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-S02-17-03/Cargo.lock b/listings/ch17-async-await/listing-S02-17-03/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-S02-17-03/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-S02-17-03/Cargo.toml b/listings/ch17-async-await/listing-S02-17-03/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-S02-17-03/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-S02-17-03/src/main.rs b/listings/ch17-async-await/listing-S02-17-03/src/main.rs deleted file mode 100644 index 60889f3aed..0000000000 --- a/listings/ch17-async-await/listing-S02-17-03/src/main.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - // ANCHOR: join - let fut1 = async { - for i in 1..10 { - println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - }; - - let fut2 = async { - for i in 1..5 { - println!("hi number {i} from the second task!"); - trpl::sleep(Duration::from_millis(1)).await; - } - }; - - trpl::join(fut1, fut2).await; - // ANCHOR_END: join - }); -} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 570471424d..680e350609 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -115,10 +115,10 @@ concurrency here. Remember that each async block compiles to an anonymous future. That means we can put each of these two loops in an async block and then ask the runtime to run them both to completion using `trpl::join`: -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-S02-17-03/src/main.rs:join}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-07/src/main.rs:join}} ``` @@ -327,7 +327,7 @@ three futures to complete: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-07/src/main.rs:updated}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-07-orig/src/main.rs:updated}} ``` From bd26083b6df2706acc1aa0960bcb0067db9b829b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 09:17:12 -0600 Subject: [PATCH 092/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20leave=20a=20TODO?= =?UTF-8?q?=20about=20one=20bucket=20of=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This one may or may not make sense: the output *order* should be the same regardless, but there will be a *lot* of extra noise in it because of the `cargo build` output before the actual program output, and we do not appear to have a good way to focus on particular subsets of output the way we do for code? --- src/ch17-02-concurrency-with-async.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 680e350609..e12142bf74 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -125,6 +125,8 @@ ask the runtime to run them both to completion using `trpl::join`: When we run this, we see both futures run to completion: + + ```text hi number 1 from the first task! hi number 1 from the second task! From 6d802a08fc7b07d280f9f1656c1178b0a123d6da Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 09:23:20 -0600 Subject: [PATCH 093/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listings=2017-08=20and=2017-09?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-04-orig/src/main.rs | 17 - .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-08-orig/src/main.rs | 34 ++ .../ch17-async-await/listing-17-08/Cargo.lock | 260 --------- .../listing-17-08/src/main.rs | 33 +- .../listing-17-09-orig/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-09-orig/Cargo.toml | 9 + .../listing-17-09-orig/src/main.rs | 46 ++ .../ch17-async-await/listing-17-09/Cargo.lock | 260 --------- .../listing-17-09/src/main.rs | 45 +- src/ch17-02-concurrency-with-async.md | 39 +- 12 files changed, 662 insertions(+), 621 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-04-orig/src/main.rs rename listings/ch17-async-await/{listing-17-04-orig => listing-17-08-orig}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-04-orig => listing-17-08-orig}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-08-orig/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-09-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-09-orig/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-09-orig/src/main.rs diff --git a/listings/ch17-async-await/listing-17-04-orig/src/main.rs b/listings/ch17-async-await/listing-17-04-orig/src/main.rs deleted file mode 100644 index a6033e5994..0000000000 --- a/listings/ch17-async-await/listing-17-04-orig/src/main.rs +++ /dev/null @@ -1,17 +0,0 @@ -// ANCHOR: all -fn main() { - trpl::block_on(async { - // ANCHOR: add-channel - let (tx, mut rx) = trpl::channel(); - // ANCHOR_END: add-channel - - // ANCHOR: send-and-receive - let val = String::from("hi"); - tx.send(val).unwrap(); - - let received = rx.recv().await.unwrap(); - println!("Got: {received}"); - // ANCHOR_END: send-and-receive - }); -} -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-04-orig/Cargo.lock b/listings/ch17-async-await/listing-17-08-orig/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-04-orig/Cargo.lock rename to listings/ch17-async-await/listing-17-08-orig/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-04-orig/Cargo.toml b/listings/ch17-async-await/listing-17-08-orig/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-04-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-08-orig/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-08-orig/src/main.rs b/listings/ch17-async-await/listing-17-08-orig/src/main.rs new file mode 100644 index 0000000000..fa02e21a87 --- /dev/null +++ b/listings/ch17-async-await/listing-17-08-orig/src/main.rs @@ -0,0 +1,34 @@ +// ANCHOR: all +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + // ANCHOR: move + let tx_fut = async move { + // ANCHOR_END: move + + 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_secs(1)).await; + } + }; + + let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; + }); +} +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-08/Cargo.lock b/listings/ch17-async-await/listing-17-08/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-08/Cargo.lock +++ b/listings/ch17-async-await/listing-17-08/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-08/src/main.rs b/listings/ch17-async-await/listing-17-08/src/main.rs index fa02e21a87..b7b3eb8b16 100644 --- a/listings/ch17-async-await/listing-17-08/src/main.rs +++ b/listings/ch17-async-await/listing-17-08/src/main.rs @@ -1,34 +1,13 @@ -// ANCHOR: all -use std::time::Duration; - fn main() { trpl::block_on(async { + // ANCHOR: add-channel let (tx, mut rx) = trpl::channel(); + // ANCHOR_END: add-channel - // ANCHOR: move - let tx_fut = async move { - // ANCHOR_END: move - - 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_secs(1)).await; - } - }; - - let rx_fut = async { - while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); - } - }; + let val = String::from("hi"); + tx.send(val).unwrap(); - trpl::join(tx_fut, rx_fut).await; + let received = rx.recv().await.unwrap(); + println!("Got: {received}"); }); } -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-09-orig/Cargo.lock b/listings/ch17-async-await/listing-17-09-orig/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-09-orig/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-09-orig/Cargo.toml b/listings/ch17-async-await/listing-17-09-orig/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-09-orig/Cargo.toml @@ -0,0 +1,9 @@ +[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-09-orig/src/main.rs b/listings/ch17-async-await/listing-17-09-orig/src/main.rs new file mode 100644 index 0000000000..4c5e65da9b --- /dev/null +++ b/listings/ch17-async-await/listing-17-09-orig/src/main.rs @@ -0,0 +1,46 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + // ANCHOR: here + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + trpl::join3(tx1_fut, tx_fut, rx_fut).await; + // ANCHOR_END: here + }); +} diff --git a/listings/ch17-async-await/listing-17-09/Cargo.lock b/listings/ch17-async-await/listing-17-09/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-09/Cargo.lock +++ b/listings/ch17-async-await/listing-17-09/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-09/src/main.rs b/listings/ch17-async-await/listing-17-09/src/main.rs index 4c5e65da9b..4d98d199b6 100644 --- a/listings/ch17-async-await/listing-17-09/src/main.rs +++ b/listings/ch17-async-await/listing-17-09/src/main.rs @@ -1,46 +1,13 @@ -use std::time::Duration; - fn main() { trpl::block_on(async { - // ANCHOR: here let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - let tx1_fut = async move { - 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; - } - }; - - 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_secs(1)).await; - } - }; + // ANCHOR: send-and-receive + let val = String::from("hi"); + tx.send(val).unwrap(); - trpl::join3(tx1_fut, tx_fut, rx_fut).await; - // ANCHOR_END: here + let received = rx.recv().await.unwrap(); + println!("Got: {received}"); + // ANCHOR_END: send-and-receive }); } diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index e12142bf74..c5113a6fa4 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -181,37 +181,40 @@ implementation is that it returns an `Option` of the type sent over the channel instead of a `Result`. We can start by introducing an async version of the multiple-producer, -single-consumer channel channel API we used with threads back in Chapter 16: +single-consumer channel channel API we used with threads back in Chapter 16. The +API is just a little different here in Listing 17-8: we have a mutable receiver +`rx`. Otherwise, this looks pretty much the same as the thread-based approach. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04-orig/src/main.rs:add-channel}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:add-channel}} ``` -Now we can send messages from the sender to the receiver. Unlike in Chapter 16, -where we needed to spawn a separate thread to allow the message passing to -happen asynchronously, here we opt into async behavior on the receiver side by -using `.await` on the `rx.recv()` call. +Now we can send messages from the sender to the receiver. Again, the API is just +a little different from the threaded version in Chapter 16, where we needed to +spawn a separate thread to allow the message passing to happen asynchronously. +In the version in Listing 17-9, we opt into async behavior on the receiver side +by using `.await` on the `rx.recv()` call. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04-orig/src/main.rs:send-and-receive}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:send-and-receive}} ``` The `send` call does not block, since the channel we are sending it into is unbounded. That was true with our threading example back in Chapter 16, too, -though. The difference here is that the `rx.recv()` call here does not block the -rest of the program, whereas the one in Chapter 16 *did* block the main thread. -Instead, once the program hits the `.await` on the `rx.recv()` call, it hands -control back to the runtime, which can go on scheduling other operations until a -message arrives. It might be hard to see that from this code, though, since the -message will arrive right away! +though. However, there is a big difference with the `rx.recv()` calls. The one +back in Chapter 16 blocked the thread it ran on—in that case, the main thread. +This one does not block at all! Instead, once the program hits the `.await` on +the `rx.recv()` call, it hands control back to the runtime, which can go on +scheduling other operations until a message arrives. It might be hard to see +that from this code, though, since the message will arrive right away! > 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`, @@ -377,7 +380,7 @@ move` block, as in Listing 17-TODO: ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-08-orig/src/main.rs:move}} ``` The result is Listing 17-TODO, and when we run *this* version of the code, it @@ -386,7 +389,7 @@ shuts down gracefully after the last message is sent. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-08-orig/src/main.rs:all}} ``` @@ -400,7 +403,7 @@ block, and switching back to `join3`. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-09-orig/src/main.rs:here}} ``` From 38ddc49c60528888a8e59f739f6cc0b436a22a37 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 09:45:39 -0600 Subject: [PATCH 094/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listings=2017-10=20and=2017-11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-05-orig/src/main.rs | 31 - .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-10-orig/src/main.rs | 47 ++ .../ch17-async-await/listing-17-10/Cargo.lock | 260 --------- .../listing-17-10/src/main.rs | 51 +- .../listing-17-11-orig/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-11-orig/Cargo.toml | 9 + .../listing-17-11-orig/src/main.rs | 49 ++ .../ch17-async-await/listing-17-11/Cargo.lock | 260 --------- .../listing-17-11/src/main.rs | 58 +- src/ch17-02-concurrency-with-async.md | 36 +- src/ch17-03-more-futures.md | 4 +- 13 files changed, 699 insertions(+), 646 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-05-orig/src/main.rs rename listings/ch17-async-await/{listing-17-05-orig => listing-17-10-orig}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-05-orig => listing-17-10-orig}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-10-orig/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-11-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-11-orig/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-11-orig/src/main.rs diff --git a/listings/ch17-async-await/listing-17-05-orig/src/main.rs b/listings/ch17-async-await/listing-17-05-orig/src/main.rs deleted file mode 100644 index c1b62d8e66..0000000000 --- a/listings/ch17-async-await/listing-17-05-orig/src/main.rs +++ /dev/null @@ -1,31 +0,0 @@ -// ANCHOR: all -// ANCHOR: many-messages -use std::time::Duration; -// ANCHOR_END: many-messages - -fn main() { - trpl::block_on(async { - let (tx, mut rx) = trpl::channel(); - - // ANCHOR: many-messages - 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_secs(1)).await; - } - // ANCHOR_END: many-messages - - // ANCHOR: loop - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - // ANCHOR_END: loop - }); -} -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-05-orig/Cargo.lock b/listings/ch17-async-await/listing-17-10-orig/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-05-orig/Cargo.lock rename to listings/ch17-async-await/listing-17-10-orig/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-05-orig/Cargo.toml b/listings/ch17-async-await/listing-17-10-orig/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-05-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-10-orig/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-10-orig/src/main.rs b/listings/ch17-async-await/listing-17-10-orig/src/main.rs new file mode 100644 index 0000000000..78e17a3846 --- /dev/null +++ b/listings/ch17-async-await/listing-17-10-orig/src/main.rs @@ -0,0 +1,47 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + // ANCHOR: here + 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-10/Cargo.lock b/listings/ch17-async-await/listing-17-10/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-10/Cargo.lock +++ b/listings/ch17-async-await/listing-17-10/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-10/src/main.rs b/listings/ch17-async-await/listing-17-10/src/main.rs index 78e17a3846..a9cba44de3 100644 --- a/listings/ch17-async-await/listing-17-10/src/main.rs +++ b/listings/ch17-async-await/listing-17-10/src/main.rs @@ -1,47 +1,26 @@ +// ANCHOR: many-messages use std::time::Duration; +// ANCHOR_END: many-messages fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - let tx1_fut = async move { - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; + // ANCHOR: many-messages - for val in vals { - tx1.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).await; - } - }; + // snip... - let rx_fut = async { - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - }; + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("future"), + ]; - 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_secs(1)).await; - } - }; - - // ANCHOR: here - let futures = vec![tx1_fut, rx_fut, tx_fut]; - trpl::join_all(futures).await; - // ANCHOR_END: here + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_secs(1)).await; + } + // ANCHOR_END: many-messages }); } diff --git a/listings/ch17-async-await/listing-17-11-orig/Cargo.lock b/listings/ch17-async-await/listing-17-11-orig/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-11-orig/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-11-orig/Cargo.toml b/listings/ch17-async-await/listing-17-11-orig/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-11-orig/Cargo.toml @@ -0,0 +1,9 @@ +[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-11-orig/src/main.rs b/listings/ch17-async-await/listing-17-11-orig/src/main.rs new file mode 100644 index 0000000000..beff676dbe --- /dev/null +++ b/listings/ch17-async-await/listing-17-11-orig/src/main.rs @@ -0,0 +1,49 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + // ANCHOR: here + let futures = + vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; + + trpl::join_all(futures).await; + // ANCHOR_END: here + }); +} diff --git a/listings/ch17-async-await/listing-17-11/Cargo.lock b/listings/ch17-async-await/listing-17-11/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-11/Cargo.lock +++ b/listings/ch17-async-await/listing-17-11/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-11/src/main.rs b/listings/ch17-async-await/listing-17-11/src/main.rs index beff676dbe..529a605276 100644 --- a/listings/ch17-async-await/listing-17-11/src/main.rs +++ b/listings/ch17-async-await/listing-17-11/src/main.rs @@ -4,46 +4,22 @@ fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - let tx1_fut = async move { - 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; - } - }; - - 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_secs(1)).await; - } - }; - - // ANCHOR: here - let futures = - vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; - - trpl::join_all(futures).await; - // ANCHOR_END: here + 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_secs(1)).await; + } + + // ANCHOR: loop + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + // ANCHOR_END: loop }); } diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index c5113a6fa4..9c3022b8aa 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -223,36 +223,40 @@ that from this code, though, since the message will arrive right away! > `.await` does not block further operations—as we will see! Let’s go ahead and send a whole series of messages, and sleep in between them, -as shown in Listing 17-TODO: +as shown in Listing 17-10: -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05-orig/src/main.rs:many-messages}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:many-messages}} ``` -Then we can wait on each of those messages in a loop. Here, we need to use a -`while let` loop rather than a `for` loop, because Rust does not yet have an -async version of `Iterator`, which is what the `for` loop does. In TODO: SECTION -TITLE, we will see more about two related traits the community has been working -on, `AsyncIterator` and `Stream`. For now, we can stick with `while let`, as in -Listing 17-TODO, and the loop will end when `rx.recv().await` produces a `None`. +This handles sending the messages, but so far we don’t do anything with them, +and the code just silently runs forever. Listing 17-11 shows how we can receive +those messages by waiting for them in a loop. -+Here, we need to use a `while let` loop rather than a `for` loop, because Rust +does not yet have an async version of `Iterator`, which is what the `for` loop +does. In TODO: SECTION TITLE, we will see more about two related traits the +community has been working on, `AsyncIterator` and `Stream`. For now, we can +stick with `while let`, as in Listing 17-11, and the loop will end when +`rx.recv().await` produces a `None`. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05-orig/src/main.rs:loop}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:loop}} ``` -This code does not do what we want. It does successfully send and receive the -messages, but instead of seeing the messages received at one-second intervals, -we see them arrive all at once, four seconds after we start the program. It -also never stops! You will need to shut it down using -ctrl-c. +This code still does not do exactly what we want. It does successfully send and +receive the messages, but instead of seeing the messages received at one-second +intervals, we see them arrive all at once, four seconds after we start the +program. It also never stops! 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. This highlights an diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 14b0435e57..04b716a41c 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -32,7 +32,7 @@ ticket. Let’s try putting our futures in a vector, and replace `join3` with ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-10-orig/src/main.rs:here}} ``` @@ -132,7 +132,7 @@ still does not compile. ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11-orig/src/main.rs:here}} ``` From 60cde0097bd9ff911a5e134e26e9459caa162fb2 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 09:53:46 -0600 Subject: [PATCH 095/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listing=2017-12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-12-orig/Cargo.lock | 540 ++++++++++++++++++ .../listing-17-12-orig/Cargo.toml | 9 + .../listing-17-12-orig/src/main.rs | 49 ++ .../ch17-async-await/listing-17-12/Cargo.lock | 260 --------- .../listing-17-12/src/main.rs | 60 +- src/ch17-02-concurrency-with-async.md | 6 +- src/ch17-03-more-futures.md | 2 +- 7 files changed, 620 insertions(+), 306 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-12-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-12-orig/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-12-orig/src/main.rs diff --git a/listings/ch17-async-await/listing-17-12-orig/Cargo.lock b/listings/ch17-async-await/listing-17-12-orig/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-12-orig/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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-12-orig/Cargo.toml b/listings/ch17-async-await/listing-17-12-orig/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-12-orig/Cargo.toml @@ -0,0 +1,9 @@ +[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-12-orig/src/main.rs b/listings/ch17-async-await/listing-17-12-orig/src/main.rs new file mode 100644 index 0000000000..b712d344c0 --- /dev/null +++ b/listings/ch17-async-await/listing-17-12-orig/src/main.rs @@ -0,0 +1,49 @@ +use std::{future::Future, time::Duration}; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + // ANCHOR: here + 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-12/Cargo.lock b/listings/ch17-async-await/listing-17-12/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-12/Cargo.lock +++ b/listings/ch17-async-await/listing-17-12/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-12/src/main.rs b/listings/ch17-async-await/listing-17-12/src/main.rs index b712d344c0..cdb982e86c 100644 --- a/listings/ch17-async-await/listing-17-12/src/main.rs +++ b/listings/ch17-async-await/listing-17-12/src/main.rs @@ -1,49 +1,25 @@ -use std::{future::Future, time::Duration}; +// ANCHOR: all +use std::time::Duration; fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - let tx1_fut = async move { - 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; - } - }; - - 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_secs(1)).await; - } - }; - - // ANCHOR: here - let futures: Vec>> = - vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; - // ANCHOR_END: here - - trpl::join_all(futures).await; + 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_secs(1)).await; + } + + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } }); } +// ANCHOR_END: all diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 9c3022b8aa..91c27046f0 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -268,12 +268,12 @@ much easier to follow, because having the order that `.await` keywords appear in the *code* is also the order they happen when running the *program*. With that in mind, we can see why this code behaves the way it does by looking -at the whole thing all together. +at the whole thing all together, in Listing 17-12. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05-orig/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:all}} ``` diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 04b716a41c..1c32bec203 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -156,7 +156,7 @@ little involved, so let’s walk through each part of it. ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12-orig/src/main.rs:here}} ``` From 7e5b6f2c7db2cadc21afeff3d58586dc2495ee92 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 09:56:43 -0600 Subject: [PATCH 096/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listings=2017-13=20and=2017-14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-06-orig/src/main.rs | 33 ---------- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 34 ++++++---- .../listing-17-13/src/main.rs | 42 ++++-------- .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-14-orig/src/main.rs | 66 +++++++++++++++++++ .../listing-17-14/src/main.rs | 47 ++++--------- src/ch17-02-concurrency-with-async.md | 19 +++--- src/ch17-03-more-futures.md | 4 +- 11 files changed, 123 insertions(+), 122 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-06-orig/src/main.rs rename listings/ch17-async-await/{listing-17-06-orig => listing-17-13-orig}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-06-orig => listing-17-13-orig}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-07-orig => listing-17-13-orig}/src/main.rs (54%) rename listings/ch17-async-await/{listing-17-07-orig => listing-17-14-orig}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-07-orig => listing-17-14-orig}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-14-orig/src/main.rs diff --git a/listings/ch17-async-await/listing-17-06-orig/src/main.rs b/listings/ch17-async-await/listing-17-06-orig/src/main.rs deleted file mode 100644 index aeeacc5462..0000000000 --- a/listings/ch17-async-await/listing-17-06-orig/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - 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"), - ]; - - for val in vals { - tx.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).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 - }); -} diff --git a/listings/ch17-async-await/listing-17-06-orig/Cargo.lock b/listings/ch17-async-await/listing-17-13-orig/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-06-orig/Cargo.lock rename to listings/ch17-async-await/listing-17-13-orig/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-06-orig/Cargo.toml b/listings/ch17-async-await/listing-17-13-orig/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-06-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-13-orig/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-07-orig/src/main.rs b/listings/ch17-async-await/listing-17-13-orig/src/main.rs similarity index 54% rename from listings/ch17-async-await/listing-17-07-orig/src/main.rs rename to listings/ch17-async-await/listing-17-13-orig/src/main.rs index e5d8f86066..5520a58ca5 100644 --- a/listings/ch17-async-await/listing-17-07-orig/src/main.rs +++ b/listings/ch17-async-await/listing-17-13-orig/src/main.rs @@ -1,10 +1,15 @@ -use std::time::Duration; +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - let tx_fut = async { + let tx1 = tx.clone(); + let tx1_fut = pin!(async move { let vals = vec![ String::from("hi"), String::from("from"), @@ -13,19 +18,18 @@ fn main() { ]; for val in vals { - tx.send(val).unwrap(); + tx1.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - }; + }); - let rx_fut = async { - while let Some(received) = rx.recv().await { - println!("Got: {received}"); + let rx_fut = pin!(async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); } - }; + }); - // ANCHOR: updated - let tx_fut2 = async { + let tx_fut = pin!(async move { let vals = vec![ String::from("more"), String::from("messages"), @@ -37,9 +41,13 @@ 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)]; + // ANCHOR_END: here - trpl::join3(tx_fut, tx_fut2, rx_fut).await; - // ANCHOR_END: updated + trpl::join_all(futures).await; }); } 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 5520a58ca5..aeeacc5462 100644 --- a/listings/ch17-async-await/listing-17-13/src/main.rs +++ b/listings/ch17-async-await/listing-17-13/src/main.rs @@ -1,15 +1,11 @@ -use std::{ - future::Future, - pin::{pin, Pin}, - time::Duration, -}; +use std::time::Duration; fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - let tx1_fut = pin!(async move { + // ANCHOR: futures + let tx_fut = async { let vals = vec![ String::from("hi"), String::from("from"), @@ -18,36 +14,20 @@ fn main() { ]; for val in vals { - tx1.send(val).unwrap(); + tx.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - }); + }; - let rx_fut = pin!(async { + let rx_fut = async { + // ANCHOR: loop while let Some(value) = rx.recv().await { println!("received '{value}'"); } - }); - - let tx_fut = pin!(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_secs(1)).await; - } - }); - - // ANCHOR: here - let futures: Vec>>> = - vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; - // ANCHOR_END: here + // ANCHOR_END: loop + }; - trpl::join_all(futures).await; + trpl::join(tx_fut, rx_fut).await; + // ANCHOR_END: futures }); } diff --git a/listings/ch17-async-await/listing-17-07-orig/Cargo.lock b/listings/ch17-async-await/listing-17-14-orig/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-07-orig/Cargo.lock rename to listings/ch17-async-await/listing-17-14-orig/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-07-orig/Cargo.toml b/listings/ch17-async-await/listing-17-14-orig/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-07-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-14-orig/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-14-orig/src/main.rs b/listings/ch17-async-await/listing-17-14-orig/src/main.rs new file mode 100644 index 0000000000..a22c9570f7 --- /dev/null +++ b/listings/ch17-async-await/listing-17-14-orig/src/main.rs @@ -0,0 +1,66 @@ +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; + +fn main() { + trpl::block_on(async { + 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"), + String::from("the"), + String::from("future"), + ]; + + for val in vals { + 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 + }); + // ANCHOR_END: here + + // 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-14/src/main.rs b/listings/ch17-async-await/listing-17-14/src/main.rs index a22c9570f7..e5d8f86066 100644 --- a/listings/ch17-async-await/listing-17-14/src/main.rs +++ b/listings/ch17-async-await/listing-17-14/src/main.rs @@ -1,18 +1,10 @@ -use std::{ - future::Future, - pin::{pin, Pin}, - time::Duration, -}; +use std::time::Duration; fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - // ANCHOR: here - let tx1_fut = pin!(async move { - // snip... - // ANCHOR_END: here + let tx_fut = async { let vals = vec![ String::from("hi"), String::from("from"), @@ -21,28 +13,19 @@ fn main() { ]; for val in vals { - tx1.send(val).unwrap(); + tx.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}'"); + let rx_fut = async { + while let Some(received) = rx.recv().await { + println!("Got: {received}"); } - // ANCHOR: here - }); - // ANCHOR_END: here + }; - // ANCHOR: here - let tx_fut = pin!(async move { - // snip... - // ANCHOR_END: here + // ANCHOR: updated + let tx_fut2 = async { let vals = vec![ String::from("more"), String::from("messages"), @@ -54,13 +37,9 @@ 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_END: here + }; - trpl::join_all(futures).await; + trpl::join3(tx_fut, tx_fut2, rx_fut).await; + // ANCHOR_END: updated }); } diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 91c27046f0..c9c0703585 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -289,12 +289,12 @@ receiving each message, rather than before receiving any message, we need to give put the `tx` and `rx` operations in their own async blocks, so the runtime can execute each of them separately. We also need to tell the runtime to actually run them using `trpl::join`, just like we did for the counting example -above. Listing 17-TODO shows how that looks. +above. Listing 17-13 shows how that looks. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-06-orig/src/main.rs:futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:futures}} ``` @@ -333,10 +333,10 @@ Right now, the async block only borrows `tx`. We can confirm this by adding another async block which uses `tx`, and using `trpl::join3` to wait for all three futures to complete: -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-07-orig/src/main.rs:updated}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:updated}} ``` @@ -346,6 +346,8 @@ which `rx` can then receive. When we run that code, we see the extra output from the new `async` block, and the message it sends being received by the `rx.recv()`. + + ```text Got: hi Got: more @@ -358,10 +360,9 @@ Got: you ``` As before, we also see that the program does not shut down on its own and -requires a ctrl-c, though. This little -exploration helps us understand why: it is ultimately about *ownership*. We need -to move `tx` into the async block so that once that block ends, `tx` will be -dropped. +requires a ctrl-c. This little exploration helps +us understand why: it is ultimately about *ownership*. We need to move `tx` into +the async block so that once that block ends, `tx` will be dropped. Since we have seen how `async` blocks borrow the items they reference from their outer scope, we can go ahead and remove the extra block we just added for now, diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 1c32bec203..1b44191516 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -369,7 +369,7 @@ for exactly this. Putting that together, we end up with the code in Listing ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-13-orig/src/main.rs:here}} ``` @@ -410,7 +410,7 @@ dynamic `Future` type. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-14-orig/src/main.rs:here}} ``` From 766ad04fb28f327fa3cb9ade8a2d7570cbf3fe28 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 10:12:25 -0600 Subject: [PATCH 097/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listings=2017-15=20and=2017-16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-08-orig/src/main.rs | 34 -- .../listing-17-09-orig/Cargo.lock | 540 ------------------ .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-15-orig/src/main.rs | 12 + .../ch17-async-await/listing-17-15/Cargo.lock | 260 --------- .../listing-17-15/src/main.rs | 36 +- .../ch17-async-await/listing-17-16/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../src/main.rs | 0 src/ch17-02-concurrency-with-async.md | 20 +- src/ch17-03-more-futures.md | 2 +- 12 files changed, 328 insertions(+), 856 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-08-orig/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-09-orig/Cargo.lock rename listings/ch17-async-await/{listing-17-08-orig => listing-17-15-orig}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-08-orig => listing-17-15-orig}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-15-orig/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-16/Cargo.lock rename listings/ch17-async-await/{listing-17-09-orig => listing-17-16}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-09-orig => listing-17-16}/src/main.rs (100%) diff --git a/listings/ch17-async-await/listing-17-08-orig/src/main.rs b/listings/ch17-async-await/listing-17-08-orig/src/main.rs deleted file mode 100644 index fa02e21a87..0000000000 --- a/listings/ch17-async-await/listing-17-08-orig/src/main.rs +++ /dev/null @@ -1,34 +0,0 @@ -// ANCHOR: all -use std::time::Duration; - -fn main() { - trpl::block_on(async { - let (tx, mut rx) = trpl::channel(); - - // ANCHOR: move - let tx_fut = async move { - // ANCHOR_END: move - - 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_secs(1)).await; - } - }; - - let rx_fut = async { - while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); - } - }; - - trpl::join(tx_fut, rx_fut).await; - }); -} -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-09-orig/Cargo.lock b/listings/ch17-async-await/listing-17-09-orig/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-09-orig/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-08-orig/Cargo.lock b/listings/ch17-async-await/listing-17-15-orig/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-08-orig/Cargo.lock rename to listings/ch17-async-await/listing-17-15-orig/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-08-orig/Cargo.toml b/listings/ch17-async-await/listing-17-15-orig/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-08-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-15-orig/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-15-orig/src/main.rs b/listings/ch17-async-await/listing-17-15-orig/src/main.rs new file mode 100644 index 0000000000..24845f0887 --- /dev/null +++ b/listings/ch17-async-await/listing-17-15-orig/src/main.rs @@ -0,0 +1,12 @@ +fn main() { + trpl::block_on(async { + // ANCHOR: here + let a = async { 1u32 }; + let b = async { "Hello!" }; + let c = async { true }; + // ANCHOR_END: here + + let (a_result, b_result, c_result) = trpl::join!(a, b, c); + println!("{a_result}, {b_result}, {c_result}"); + }); +} diff --git a/listings/ch17-async-await/listing-17-15/Cargo.lock b/listings/ch17-async-await/listing-17-15/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-15/Cargo.lock +++ b/listings/ch17-async-await/listing-17-15/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-15/src/main.rs b/listings/ch17-async-await/listing-17-15/src/main.rs index 24845f0887..652545f09f 100644 --- a/listings/ch17-async-await/listing-17-15/src/main.rs +++ b/listings/ch17-async-await/listing-17-15/src/main.rs @@ -1,12 +1,32 @@ +use std::time::Duration; + fn main() { trpl::block_on(async { - // ANCHOR: here - let a = async { 1u32 }; - let b = async { "Hello!" }; - let c = async { true }; - // ANCHOR_END: here - - let (a_result, b_result, c_result) = trpl::join!(a, b, c); - println!("{a_result}, {b_result}, {c_result}"); + // ANCHOR: with-move + let (tx, mut rx) = trpl::channel(); + + let tx_fut = async move { + 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_secs(1)).await; + } + }; + + let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; + // ANCHOR_END: with-move }); } +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-16/Cargo.lock b/listings/ch17-async-await/listing-17-16/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-16/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-09-orig/Cargo.toml b/listings/ch17-async-await/listing-17-16/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-09-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-16/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-09-orig/src/main.rs b/listings/ch17-async-await/listing-17-16/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-09-orig/src/main.rs rename to listings/ch17-async-await/listing-17-16/src/main.rs diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index c9c0703585..58ecfcbdc3 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -380,35 +380,29 @@ references this way, it needs to move that data into the future—so the `move` keyword works with async blocks just like it does with closures. Thus, we can change the first async block from an `async` block to an `async -move` block, as in Listing 17-TODO: +move` block, like this: -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-08-orig/src/main.rs:move}} -``` - -The result is Listing 17-TODO, and when we run *this* version of the code, it +The result is Listing 17-15, and when we run *this* version of the code, it shuts down gracefully after the last message is sent. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-08-orig/src/main.rs:all}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:with-move}} ``` 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. For example, we can -make the code from Listing 17-TODO work by cloning the `tx` before moving it +make the code from Listing 17-16 work by cloning the `tx` before moving it into the first async block, moving the original `tx` into the second async block, and switching back to `join3`. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-09-orig/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-16/src/main.rs:here}} ``` diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 1b44191516..ccc306e2cb 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -425,7 +425,7 @@ type for `a` implements `Future` and the anonymous future type for ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-15-orig/src/main.rs:here}} ``` From c308400251c7ee16b4c72fd972fb689fdf974ef9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 10:22:27 -0600 Subject: [PATCH 098/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listings=2017-17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-09b/Cargo.lock | 540 ------------------ .../ch17-async-await/listing-17-17/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../src/main.rs | 0 src/ch17-03-more-futures.md | 8 +- 5 files changed, 284 insertions(+), 544 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-09b/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-17/Cargo.lock rename listings/ch17-async-await/{listing-17-09b => listing-17-17}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-09b => listing-17-17}/src/main.rs (100%) diff --git a/listings/ch17-async-await/listing-17-09b/Cargo.lock b/listings/ch17-async-await/listing-17-09b/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-09b/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-17/Cargo.lock b/listings/ch17-async-await/listing-17-17/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-17/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-09b/Cargo.toml b/listings/ch17-async-await/listing-17-17/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-09b/Cargo.toml rename to listings/ch17-async-await/listing-17-17/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-09b/src/main.rs b/listings/ch17-async-await/listing-17-17/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-09b/src/main.rs rename to listings/ch17-async-await/listing-17-17/src/main.rs diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index ccc306e2cb..860b2d27cb 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -4,13 +4,13 @@ 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-TODO to use -`join!` instead of `join3`, as in Listing 17-TODO: +the futures itself. Thus, we could rewrite the code from Listing 17-16 to use +`join!` instead of `join3`, as in Listing 17-17: -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-09b/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-17/src/main.rs:here}} ``` From 6035ba4315c203efee9b6c8383dcfa1fcf12991f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 10:26:17 -0600 Subject: [PATCH 099/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listing=2017-18?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-10-orig/Cargo.lock | 540 ------------------ .../ch17-async-await/listing-17-18/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../ch17-async-await/listing-17-18/output.txt | 53 ++ .../src/main.rs | 0 src/ch17-03-more-futures.md | 33 +- 6 files changed, 336 insertions(+), 570 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-10-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-18/Cargo.lock rename listings/ch17-async-await/{listing-17-10-orig => listing-17-18}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-18/output.txt rename listings/ch17-async-await/{listing-17-10-orig => listing-17-18}/src/main.rs (100%) diff --git a/listings/ch17-async-await/listing-17-10-orig/Cargo.lock b/listings/ch17-async-await/listing-17-10-orig/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-10-orig/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-18/Cargo.lock b/listings/ch17-async-await/listing-17-18/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-18/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-10-orig/Cargo.toml b/listings/ch17-async-await/listing-17-18/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-10-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-18/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-18/output.txt b/listings/ch17-async-await/listing-17-18/output.txt new file mode 100644 index 0000000000..4ad945623f --- /dev/null +++ b/listings/ch17-async-await/listing-17-18/output.txt @@ -0,0 +1,53 @@ +$ 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 libc v0.2.154 + Compiling futures-sink v0.3.30 + Compiling pin-project-lite v0.2.14 + Compiling pin-utils v0.1.0 + Compiling futures-io v0.3.30 + Compiling futures-task v0.3.30 + 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 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-18) +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}` + +For more information about this error, try `rustc --explain E0308`. +error: could not compile `async_await` (bin "async_await") due to 1 previous error diff --git a/listings/ch17-async-await/listing-17-10-orig/src/main.rs b/listings/ch17-async-await/listing-17-18/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-10-orig/src/main.rs rename to listings/ch17-async-await/listing-17-18/src/main.rs diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 860b2d27cb..5845967f1d 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -29,45 +29,18 @@ 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 `join3` with `join_all`. -+ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-10-orig/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-18/src/main.rs:here}} ``` Unfortunately, this does not compile. Instead, we get this error: - - ```text -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}` +{{#include ../listings/ch17-async-await/listing-17-18/output.txt}} ``` This error message is admittedly not the most helpful! It only tells us that it From a1eb8ae8e7a732f88dd5b1ba76accda5fea1d3d0 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 10:29:15 -0600 Subject: [PATCH 100/249] Ch. 17: Fix internal links - Align them with the existing format for links. - Add one missing link. --- src/ch17-03-more-futures.md | 14 ++++++++------ src/ch17-04-more-ways-of-combining-futures.md | 10 ++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 5845967f1d..de1e019b49 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -70,8 +70,8 @@ error[E0308]: mismatched types ``` Saying “expected *something*, found *something else*” is Rust’s standard format -for telling us about a type mismatch. As we saw with vectors in [Using an Enum -to Store Multiple Types][collections] back in Chapter 8, we need the type of +for telling us about a type mismatch. As we saw with vectors in [“Using an Enum +to Store Multiple Types”][collections] back in Chapter 8, we need the type of each item in a collection to be the same—and `tx1_fut`, `rx_fut`, and `tx_fut` do not have the same type. @@ -92,8 +92,8 @@ with a dynamic collection of futures where we do not know what they will all be until runtime. To make this work, we need to use *trait objects*, just as we did for returning -different kinds of errors from the same function in [Returning Errors from the -run function][dyn] back in Chapter 12. Again, we will cover trait objects in +different kinds of errors from the same function in [“Returning Errors from the +run function”][dyn] back in Chapter 12. Again, we will cover trait objects in detail in Chapter 17. Here, it lets us treat each of the anonymous futures produced by these types as interchangeable, since all of them by definition implement the `Future` trait. @@ -208,7 +208,7 @@ type to call `poll`? --> -In [Futures and Syntax: What Are Futures][what-are-futures], we described how +In [“Futures and Syntax: 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. Consider code like this: @@ -421,4 +421,6 @@ handy for building frameworks, or especially 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! -[what-are-futures]: /ch17-01-futures-and-syntax.html#what-are-futures +[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 diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index c5d5fd9c30..f39e7da7e5 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -31,9 +31,9 @@ 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. -To see why, recall from our discussion in [What Are Futures?][futures] that Rust -compiles async blocks in a way that hands control back to the async runtime at -each await point. That has an important corollary: async runtimes can only +To see why, recall from our discussion in [“What Are Futures?”][futures] that +Rust compiles async blocks in a way that hands control back to the async runtime +at each await point. That has an important corollary: async runtimes can only switch which future they are executing at await points. Everything in between await points is just normal synchronous Rust code. That means if you do a bunch of really expensive work in an async function without an `.await`, that future @@ -286,6 +286,4 @@ example, you can use this same approach to combine timeouts with retries, and in turn use those with things like network calls—the exact example we started out with at the beginning of the chapter! -[collections]: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#using-an-enum-to-store-multiple-types -[dyn]: https://doc.rust-lang.org/stable/book/ch12-03-improving-error-handling-and-modularity.html -[futures]: /ch17-01-futures-and-syntax.html#what-are-futures +[futures]: ch17-01-futures-and-syntax.html#what-are-futures From 911167d473fdf8fbce70ea1fff8a9a83ac6777b9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 10:29:15 -0600 Subject: [PATCH 101/249] =?UTF-8?q?Ch.=2017:=20Remove=20completed=20`TODO`?= =?UTF-8?q?=20for=20`Pin`=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-03-more-futures.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index de1e019b49..cc7f60da74 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -198,16 +198,6 @@ above—but that was in terms of `Unpin`, not `Pin`. So what exactly are `Pin` a `Unpin`, how do they relate, and why does `Future` need `self` to be in a `Pin` type to call `poll`? - - - - In [“Futures and Syntax: 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 From b8ecdb5c863b947f7c21903d4b75d5d48b96e7f0 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 10:29:15 -0600 Subject: [PATCH 102/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20extract=20a=20no?= =?UTF-8?q?-listing=20for=20type=20mismatches?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../no-listing-type-mismatch/Cargo.lock | 7 +++++++ .../no-listing-type-mismatch/Cargo.toml | 6 ++++++ .../no-listing-type-mismatch/output.txt | 10 ++++++++++ .../no-listing-type-mismatch/src/main.rs | 7 +++++++ src/ch17-03-more-futures.md | 14 +++----------- 5 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock create mode 100644 listings/ch17-async-await/no-listing-type-mismatch/Cargo.toml create mode 100644 listings/ch17-async-await/no-listing-type-mismatch/output.txt create mode 100644 listings/ch17-async-await/no-listing-type-mismatch/src/main.rs diff --git a/listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock b/listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock new file mode 100644 index 0000000000..d30b928a6c --- /dev/null +++ b/listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "async_await" +version = "0.1.0" diff --git a/listings/ch17-async-await/no-listing-type-mismatch/Cargo.toml b/listings/ch17-async-await/no-listing-type-mismatch/Cargo.toml new file mode 100644 index 0000000000..67729afc80 --- /dev/null +++ b/listings/ch17-async-await/no-listing-type-mismatch/Cargo.toml @@ -0,0 +1,6 @@ +[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 diff --git a/listings/ch17-async-await/no-listing-type-mismatch/output.txt b/listings/ch17-async-await/no-listing-type-mismatch/output.txt new file mode 100644 index 0000000000..5b7dc951b7 --- /dev/null +++ b/listings/ch17-async-await/no-listing-type-mismatch/output.txt @@ -0,0 +1,10 @@ +$ cargo build + Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/no-listing-type-mismatch) +error[E0308]: mismatched types + --> src/main.rs:5:24 + | +5 | let vals = vec![a, b]; + | ^ expected integer, found `&str` + +For more information about this error, try `rustc --explain E0308`. +error: could not compile `async_await` (bin "async_await") due to 1 previous error diff --git a/listings/ch17-async-await/no-listing-type-mismatch/src/main.rs b/listings/ch17-async-await/no-listing-type-mismatch/src/main.rs new file mode 100644 index 0000000000..0c282f4f87 --- /dev/null +++ b/listings/ch17-async-await/no-listing-type-mismatch/src/main.rs @@ -0,0 +1,7 @@ +fn main() { + // ANCHOR: here + let a = 1; + let b = "Hello"; + let vals = vec![a, b]; + // ANCHOR_END: here +} diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index cc7f60da74..343d558e19 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -51,22 +51,14 @@ appear in the code? One clue is the format of this message. Notice that it is exactly the same as if we had tried to create a `Vec` with a a number and a string in it: - - -```rust -let a = 1; -let b = "Hello"; -let vals = vec![a, b]; +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/no-listing-type-mismatch/src/main.rs:here}} ``` The output there would be: ```text -error[E0308]: mismatched types - --> src/main.rs:4:24 - | -4 | let vals = vec![a, b]; - | ^ expected integer, found `&str` +{{#include ../listings/ch17-async-await/no-listing-type-mismatch/output.txt}} ``` Saying “expected *something*, found *something else*” is Rust’s standard format From 2b65e53466338426ad28c57a070fc117b72c5d29 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 12:42:08 -0600 Subject: [PATCH 103/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20correct=20number?= =?UTF-8?q?ing=20and=20content=20for=20Listings=2017-19=20and=2017-20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-11-orig/Cargo.lock | 540 ------------------ .../listing-17-12-orig/Cargo.lock | 540 ------------------ .../ch17-async-await/listing-17-19/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-20/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../ch17-async-await/listing-17-20/output.txt | 82 +++ .../src/main.rs | 0 src/ch17-03-more-futures.md | 35 +- 10 files changed, 651 insertions(+), 1106 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-11-orig/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-12-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-19/Cargo.lock rename listings/ch17-async-await/{listing-17-11-orig => listing-17-19}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-11-orig => listing-17-19}/src/main.rs (100%) create mode 100644 listings/ch17-async-await/listing-17-20/Cargo.lock rename listings/ch17-async-await/{listing-17-12-orig => listing-17-20}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-20/output.txt rename listings/ch17-async-await/{listing-17-12-orig => listing-17-20}/src/main.rs (100%) diff --git a/listings/ch17-async-await/listing-17-11-orig/Cargo.lock b/listings/ch17-async-await/listing-17-11-orig/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-11-orig/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-12-orig/Cargo.lock b/listings/ch17-async-await/listing-17-12-orig/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-12-orig/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-19/Cargo.lock b/listings/ch17-async-await/listing-17-19/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-19/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-11-orig/Cargo.toml b/listings/ch17-async-await/listing-17-19/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-11-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-19/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-11-orig/src/main.rs b/listings/ch17-async-await/listing-17-19/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-11-orig/src/main.rs rename to listings/ch17-async-await/listing-17-19/src/main.rs diff --git a/listings/ch17-async-await/listing-17-20/Cargo.lock b/listings/ch17-async-await/listing-17-20/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-20/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-12-orig/Cargo.toml b/listings/ch17-async-await/listing-17-20/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-12-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-20/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-20/output.txt b/listings/ch17-async-await/listing-17-20/output.txt new file mode 100644 index 0000000000..1fcc787041 --- /dev/null +++ b/listings/ch17-async-await/listing-17-20/output.txt @@ -0,0 +1,82 @@ +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-12-orig/src/main.rs b/listings/ch17-async-await/listing-17-20/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-12-orig/src/main.rs rename to listings/ch17-async-await/listing-17-20/src/main.rs diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 343d558e19..4acce85bd5 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -91,13 +91,13 @@ produced by these types as interchangeable, since all of them by definition implement the `Future` trait. We can start by wrapping each of the futures in the `vec!` in a `Box::new()`. -Unfortunately, the initial way we might try this, as shown in Listing 17-TODO, +Unfortunately, the initial way we might try this, as shown in Listing 17-19, still does not compile. -+ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-11-orig/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} ``` @@ -118,37 +118,20 @@ little involved, so let’s walk through each part of it. - The entire trait is wrapped in a `Box`. - Finally, we state explicitly that `futures` is a `Vec` containing these items. -+ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-12-orig/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} ``` That already made a big difference. Now when we run the compiler, we only have -the errors mentioning `Unpin`, each of which is a variation on this same output: +the errors mentioning `Unpin`. Although there are three of them, notice that +each is very similar in its contets - - -```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}>: 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 `Future` -note: required by a bound in `futures_util::future::join_all::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` +```console +{{#include ../listings/ch17-async-await/listing-17-20/output.txt}} ``` That is a *lot* to digest, so let’s pull it apart. The first part of the message From 67bd0a08bcdf23adbbe114066947154888ceeb83 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 13:23:51 -0600 Subject: [PATCH 104/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20support=20code?= =?UTF-8?q?=20for=20motivating=20`Pin`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rexport `tokio::fs::read_to_string` as `trpl::read_to_string`. - Add a no-listing example for the mutable borrow example. This will keep us honest that the code there itself compiles just fine! --- .../no-listing-borrow-mutable-vec/Cargo.lock | 280 ++++++++++++++++++ .../no-listing-borrow-mutable-vec/Cargo.toml | 9 + .../no-listing-borrow-mutable-vec/src/main.rs | 18 ++ .../test-data/hello.txt | 1 + .../test-data/punct.txt | 1 + .../test-data/world.txt | 1 + packages/trpl/Cargo.toml | 1 + packages/trpl/src/lib.rs | 1 + packages/trpl/tests/integration/main.rs | 11 + packages/trpl/tests/integration/to-read.txt | 1 + src/ch17-03-more-futures.md | 34 +-- 11 files changed, 338 insertions(+), 20 deletions(-) create mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.lock create mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.toml create mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs create mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/hello.txt create mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/punct.txt create mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/world.txt create mode 100644 packages/trpl/tests/integration/to-read.txt diff --git a/listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.lock b/listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.lock new file mode 100644 index 0000000000..9eeeffaff4 --- /dev/null +++ b/listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.lock @@ -0,0 +1,280 @@ +# 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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0d8b92cd8358e8d229c11df9358decae64d137c5be540952c5ca7b25aea768" + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +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 = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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/no-listing-borrow-mutable-vec/Cargo.toml b/listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.toml @@ -0,0 +1,9 @@ +[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/no-listing-borrow-mutable-vec/src/main.rs b/listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs new file mode 100644 index 0000000000..fbba735c3f --- /dev/null +++ b/listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs @@ -0,0 +1,18 @@ +fn main() { + trpl::block_on({ + // ANCHOR: here + async { + let mut strings = vec![]; + + let a = trpl::read_to_string("test-data/hello.txt").await.unwrap(); + strings.push(a.trim()); + + let b = trpl::read_to_string("test-data/world.txt").await.unwrap(); + strings.push(b.trim()); + + let combined = strings.join(" "); + println!("{combined}"); + } + // ANCHOR_END: here + }); +} diff --git a/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/hello.txt b/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/hello.txt new file mode 100644 index 0000000000..e965047ad7 --- /dev/null +++ b/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/hello.txt @@ -0,0 +1 @@ +Hello diff --git a/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/punct.txt b/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/punct.txt new file mode 100644 index 0000000000..cdf4cb4feb --- /dev/null +++ b/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/punct.txt @@ -0,0 +1 @@ +! diff --git a/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/world.txt b/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/world.txt new file mode 100644 index 0000000000..216e97ce08 --- /dev/null +++ b/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/world.txt @@ -0,0 +1 @@ +World diff --git a/packages/trpl/Cargo.toml b/packages/trpl/Cargo.toml index 626318db3d..898dae43f9 100644 --- a/packages/trpl/Cargo.toml +++ b/packages/trpl/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] futures = "0.3.30" tokio = { version = "1", default-features = false, features = [ + "fs", "rt-multi-thread", "sync", "time", diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 2a98c3ac40..4d748d4783 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -20,6 +20,7 @@ pub use futures::{ join, }; pub use tokio::{ + fs::read_to_string, runtime::Runtime, // We use the `unbounded` variants because they most closely match the APIs // from `std::sync::mpsc::channel`. Tokio's API choices are interesting: diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index 28421ba5ee..ecff695515 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -188,3 +188,14 @@ fn yield_now() { assert_eq!(result, "done"); } + +#[test] +fn read_to_string() { + let result = trpl::block_on(async { + trpl::read_to_string("tests/integration/to-read.txt") + .await + .unwrap() + }); + + assert_eq!(result, String::from("This is some text!\n")); +} diff --git a/packages/trpl/tests/integration/to-read.txt b/packages/trpl/tests/integration/to-read.txt new file mode 100644 index 0000000000..2af04f5bdf --- /dev/null +++ b/packages/trpl/tests/integration/to-read.txt @@ -0,0 +1 @@ +This is some text! diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 4acce85bd5..985c9d7384 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -178,21 +178,8 @@ a series of await points in a future get compiled into a state machine—and not how the compiler helps make sure that state machine follows all of Rust’s normal rules around safety, including borrowing and ownership. Consider code like this: - - ```rust -async { - let mut strings = vec![]; - - let a = trpl::read_to_string("test-data/hello.txt").await.unwrap(); - strings.push(a.trim()); - - let b = trpl::read_to_string("test-data/world.txt").await.unwrap(); - strings.push(b.trim()); - - let combined = strings.join(" "); - println!("{combined}"); -} +{{#rustdoc_include ../listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs:here}} ``` If we think about the state machine that would get compiled to, it might be @@ -200,15 +187,22 @@ something kind of like this: ```rust,ignore enum AsyncStateMachine<'a> { - FirstAwait(&'a mut Vec), - SecondAwait(&'a mut Vec), + AfterFirstAwait(&'a mut Vec), + AfterSecondAwait(&'a mut Vec), } ``` -This could actually be fine, on its own—Rust would keep track of those mutable -references, and if we got something wrong, the borrow checker would tell us. It -gets a bit tricky, though, if we want to move around the future that corresponds -to that block. Remember, we could always do something like this: +That is, at each `.await` in the source code, Rust would look at what state is +needed between that await point and the point another `.await` appears or the +async block ends, and create a corresponding variant in the `AsyncStateMachine`. +Each variant has the appropriate kind of reference to the data that will be +referenced in that section. The real implementation is not *exactly* like this, +but it is close enough to give the right mental model. + +And this could actually be fine, on its own—Rust would keep track of those +mutable references, and if we got something wrong, the borrow checker would tell +us. It gets a bit tricky, though, if we want to move around the future that +corresponds to that block. Remember, we could always do something like this: ```rust,ignore let file_reads_future = async { From 686b3e4f6876ac61c0e611f77ccc8e8c068a5a1c Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 13:38:41 -0600 Subject: [PATCH 105/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20add=20a=20TODO?= =?UTF-8?q?=20for=20checking=20Pin=20description=20correctness?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-03-more-futures.md | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 985c9d7384..13dad71be8 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -216,19 +216,24 @@ let some_other_future = async { trpl::join(file_reads_future, some_other_future).await; ``` + + If we pass those futures into `join`, or return them from a function, or put -them in a data structure to keep track of for some reason, we move the state -machine as well, and that means the `Vec` for the values we read in with -`trpl::read_to_string` moves. But the state machine Rust generated for us has -references to it. Since references point to the actual memory address of the -`Vec`, Rust needs some way to either update them so they are still valid after -the `Vec` moves, or it needs some way to keep `Vec` from getting moved around so -that the references do not need to be updated. Updating all the references to an -object every time it moves could be quite a lot of work for the compiler to add, -especially since there can be a whole web of references that need updating. On -the other hand, making sure the underlying item *does not move in memory* can be -“free” at runtime in exchange for keeping some promises at compile time. That is -where `Pin` and `Unpin` come in. +them in a data structure to keep track of for some reason, that moves the state +machine as well. That means the reference to `Vec` for the values we +read in with `trpl::read_to_string` moves along with it. Since references point +to the actual memory address of the `Vec`, Rust needs some way to either update +them so they are still valid after the `Vec` moves, or it needs some way to keep +`Vec` from getting moved around so that the references do not need to be +updated. Updating all the references to an object every time it moves could be +quite a lot of work for the compiler to add, especially since there can be a +whole web of references that need updating. On the other hand, making sure the +underlying item *does not move in memory* can be “free” at runtime in exchange +for keeping some promises at compile time. That is where `Pin` and `Unpin` come +in. > Note: 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 From 91565da622d3edb8242352586281f11d469d57cf Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 13:45:20 -0600 Subject: [PATCH 106/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20correct=20listin?= =?UTF-8?q?gs=20and=20wording=20for=20`Pin`=20materials?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-13-orig/Cargo.lock | 540 ------------------ .../listing-17-14-orig/Cargo.lock | 540 ------------------ .../listing-17-15-orig/Cargo.lock | 540 ------------------ .../ch17-async-await/listing-17-21/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-22/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../src/main.rs | 4 - .../ch17-async-await/listing-17-23/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../src/main.rs | 2 +- src/ch17-03-more-futures.md | 57 +- 13 files changed, 873 insertions(+), 1650 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-13-orig/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-14-orig/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-15-orig/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-21/Cargo.lock rename listings/ch17-async-await/{listing-17-13-orig => listing-17-21}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-13-orig => listing-17-21}/src/main.rs (100%) create mode 100644 listings/ch17-async-await/listing-17-22/Cargo.lock rename listings/ch17-async-await/{listing-17-14-orig => listing-17-22}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-14-orig => listing-17-22}/src/main.rs (93%) create mode 100644 listings/ch17-async-await/listing-17-23/Cargo.lock rename listings/ch17-async-await/{listing-17-15-orig => listing-17-23}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-15-orig => listing-17-23}/src/main.rs (100%) diff --git a/listings/ch17-async-await/listing-17-13-orig/Cargo.lock b/listings/ch17-async-await/listing-17-13-orig/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-13-orig/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-14-orig/Cargo.lock b/listings/ch17-async-await/listing-17-14-orig/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-14-orig/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-15-orig/Cargo.lock b/listings/ch17-async-await/listing-17-15-orig/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-15-orig/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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/Cargo.lock b/listings/ch17-async-await/listing-17-21/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-21/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-13-orig/Cargo.toml b/listings/ch17-async-await/listing-17-21/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-13-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-21/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-13-orig/src/main.rs b/listings/ch17-async-await/listing-17-21/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-13-orig/src/main.rs rename to listings/ch17-async-await/listing-17-21/src/main.rs diff --git a/listings/ch17-async-await/listing-17-22/Cargo.lock b/listings/ch17-async-await/listing-17-22/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-22/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-14-orig/Cargo.toml b/listings/ch17-async-await/listing-17-22/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-14-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-22/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-14-orig/src/main.rs b/listings/ch17-async-await/listing-17-22/src/main.rs similarity index 93% rename from listings/ch17-async-await/listing-17-14-orig/src/main.rs rename to listings/ch17-async-await/listing-17-22/src/main.rs index a22c9570f7..7e33ab3cc8 100644 --- a/listings/ch17-async-await/listing-17-14-orig/src/main.rs +++ b/listings/ch17-async-await/listing-17-22/src/main.rs @@ -26,9 +26,7 @@ fn main() { } // ANCHOR: here }); - // ANCHOR_END: here - // ANCHOR: here let rx_fut = pin!(async { // snip... // ANCHOR_END: here @@ -37,9 +35,7 @@ fn main() { } // ANCHOR: here }); - // ANCHOR_END: here - // ANCHOR: here let tx_fut = pin!(async move { // snip... // ANCHOR_END: here diff --git a/listings/ch17-async-await/listing-17-23/Cargo.lock b/listings/ch17-async-await/listing-17-23/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-23/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-15-orig/Cargo.toml b/listings/ch17-async-await/listing-17-23/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-15-orig/Cargo.toml rename to listings/ch17-async-await/listing-17-23/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-15-orig/src/main.rs b/listings/ch17-async-await/listing-17-23/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-15-orig/src/main.rs rename to listings/ch17-async-await/listing-17-23/src/main.rs index 24845f0887..6603223a5b 100644 --- a/listings/ch17-async-await/listing-17-15-orig/src/main.rs +++ b/listings/ch17-async-await/listing-17-23/src/main.rs @@ -4,9 +4,9 @@ fn main() { let a = async { 1u32 }; let b = async { "Hello!" }; let c = async { true }; - // ANCHOR_END: here 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/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 13dad71be8..f76a4a8c7b 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -301,19 +301,21 @@ get our `join_all` call to compile! First, we need to explicitly annotate `futures` as referring to a pinned `Box` of futures. Second, we actually need to pin the futures, which we can do using the handy `Box::pin` API, which exists for exactly this. Putting that together, we end up with the code in Listing -17-TODO. +17-21. -+ -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-13-orig/src/main.rs:here}} +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:here}} ``` If we compile and run this, we finally get the output we hoped for: - + ```text received 'hi' @@ -342,40 +344,45 @@ 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. +dynamic `Future` type, as in Listing 17-22. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-14-orig/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:here}} ``` -This keeps everything on the stack, and that is a nice little performance win, -but it is still a lot of explicit types, which is quite unusual for Rust! There -is another problem, too. We got this far by ignoring the fact that we might have -different `Output` types. For example, in Listing 17-TODO, the anonymous future -type for `a` implements `Future` and the anonymous future type for -`b` implements `Future`. +This keeps everything on the stack, which is a nice little performance win, but +it is still a lot of explicit types, which is quite unusual for Rust! -+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-23, +the anonymous future type for `a` implements `Future`, the +anonymous future type for `b` implements `Future`, and the +anonymous future type for `c` implements `Future`. We can use +`trpl::join!` to await them together, since it accepts futures of different +types. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-15-orig/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:here}} ``` -We can use `trpl::join!` to await them together, since it accepts two different -future types, but we cannot use `trpl::join_all` with these futures, because we -will never be able to make them have the same type. We have a basic tradeoff -here: 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 with a set number of futures -with the `join` functions or the `join!` macro, even if they have different -types. This is the same as working with any other type in Rust, though: futures -are not special, even though we have some nice syntax for working with them, and -that is a good thing! +We cannot use `trpl::join_all` with these futures, though, because +we will never be able to make them have the same type. (Remember, that error is +what got us started on this adventure with `Pin`!) + +We have a basic tradeoff here: 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 +with a set number of futures with the `join` functions or the `join!` macro, +even if they have different types. This is the same as working with any other +type 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 only as a secondary tool reach for the functions like `join` or `join_all`, or their From fb683c9965b4a0b810c32fd5a470babb3683ab79 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 13 Jun 2024 13:58:56 -0600 Subject: [PATCH 107/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20correct=20listin?= =?UTF-8?q?gs=20and=20wording=20for=20first=20half=20of=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-25/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../listing-17-25/src/main.rs | 14 + .../ch17-async-await/listing-17-26/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../ch17-async-await/listing-17-26/output.txt | 38 ++ .../src/main.rs | 2 - .../ch17-async-await/listing-17-27/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../ch17-async-await/listing-17-29/Cargo.toml | 9 + .../src/main.rs | 0 .../listing-17-yield-b-yield/Cargo.lock | 540 ------------------ .../listing-17-yield-c-performance/Cargo.lock | 540 ------------------ src/ch17-04-more-ways-of-combining-futures.md | 86 +-- 22 files changed, 948 insertions(+), 1121 deletions(-) rename listings/ch17-async-await/{listing-17-race => listing-17-24}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-race => listing-17-24}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-race => listing-17-24}/src/main.rs (100%) create mode 100644 listings/ch17-async-await/listing-17-25/Cargo.lock rename listings/ch17-async-await/{listing-17-yield-0-blocked => listing-17-25}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-25/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-26/Cargo.lock rename listings/ch17-async-await/{listing-17-yield-a-sleep => listing-17-26}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-26/output.txt rename listings/ch17-async-await/{listing-17-yield-0-blocked => listing-17-26}/src/main.rs (96%) create mode 100644 listings/ch17-async-await/listing-17-27/Cargo.lock rename listings/ch17-async-await/{listing-17-yield-b-yield => listing-17-27}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-yield-a-sleep => listing-17-27}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-yield-0-blocked => listing-17-28}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-yield-c-performance => listing-17-28}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-yield-b-yield => listing-17-28}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-yield-a-sleep => listing-17-29}/Cargo.lock (100%) create mode 100644 listings/ch17-async-await/listing-17-29/Cargo.toml rename listings/ch17-async-await/{listing-17-yield-c-performance => listing-17-29}/src/main.rs (100%) delete mode 100644 listings/ch17-async-await/listing-17-yield-b-yield/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-yield-c-performance/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-race/Cargo.lock b/listings/ch17-async-await/listing-17-24/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-race/Cargo.lock rename to listings/ch17-async-await/listing-17-24/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-race/Cargo.toml b/listings/ch17-async-await/listing-17-24/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-race/Cargo.toml rename to listings/ch17-async-await/listing-17-24/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-race/src/main.rs b/listings/ch17-async-await/listing-17-24/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-race/src/main.rs rename to listings/ch17-async-await/listing-17-24/src/main.rs diff --git a/listings/ch17-async-await/listing-17-25/Cargo.lock b/listings/ch17-async-await/listing-17-25/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-25/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-yield-0-blocked/Cargo.toml b/listings/ch17-async-await/listing-17-25/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-yield-0-blocked/Cargo.toml rename to listings/ch17-async-await/listing-17-25/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-25/src/main.rs b/listings/ch17-async-await/listing-17-25/src/main.rs new file mode 100644 index 0000000000..9d8dedfb3b --- /dev/null +++ b/listings/ch17-async-await/listing-17-25/src/main.rs @@ -0,0 +1,14 @@ +use std::{thread, time::Duration}; + +fn main() { + trpl::block_on(async { + // 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-26/Cargo.lock b/listings/ch17-async-await/listing-17-26/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-26/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-yield-a-sleep/Cargo.toml b/listings/ch17-async-await/listing-17-26/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-yield-a-sleep/Cargo.toml rename to listings/ch17-async-await/listing-17-26/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-26/output.txt b/listings/ch17-async-await/listing-17-26/output.txt new file mode 100644 index 0000000000..22cbc4fad4 --- /dev/null +++ b/listings/ch17-async-await/listing-17-26/output.txt @@ -0,0 +1,38 @@ +$ cargo run + Compiling proc-macro2 v1.0.82 + Compiling unicode-ident v1.0.12 + Compiling autocfg v1.3.0 + Compiling futures-sink v0.3.30 + Compiling futures-core v0.3.30 + Compiling libc v0.2.154 + Compiling pin-project-lite v0.2.14 + Compiling futures-io v0.3.30 + Compiling memchr v2.7.2 + Compiling futures-task 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-26) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.32s + Running `target/debug/async_await` +'a' started. +'a' ran for 300ms +'a' ran for 100ms +'a' ran for 200ms +'a' ran for 900ms +'b' started. +'b' ran for 750ms +'b' ran for 100ms +'b' ran for 150ms +'b' ran for 350ms +'b' ran for 150ms +'a' finished. diff --git a/listings/ch17-async-await/listing-17-yield-0-blocked/src/main.rs b/listings/ch17-async-await/listing-17-26/src/main.rs similarity index 96% rename from listings/ch17-async-await/listing-17-yield-0-blocked/src/main.rs rename to listings/ch17-async-await/listing-17-26/src/main.rs index aac0f70fa3..9948c79e57 100644 --- a/listings/ch17-async-await/listing-17-yield-0-blocked/src/main.rs +++ b/listings/ch17-async-await/listing-17-26/src/main.rs @@ -29,9 +29,7 @@ fn main() { }); } -// 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-27/Cargo.lock b/listings/ch17-async-await/listing-17-27/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-27/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-yield-b-yield/Cargo.toml b/listings/ch17-async-await/listing-17-27/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-yield-b-yield/Cargo.toml rename to listings/ch17-async-await/listing-17-27/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs b/listings/ch17-async-await/listing-17-27/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs rename to listings/ch17-async-await/listing-17-27/src/main.rs diff --git a/listings/ch17-async-await/listing-17-yield-0-blocked/Cargo.lock b/listings/ch17-async-await/listing-17-28/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-yield-0-blocked/Cargo.lock rename to listings/ch17-async-await/listing-17-28/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.toml b/listings/ch17-async-await/listing-17-28/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-yield-c-performance/Cargo.toml rename to listings/ch17-async-await/listing-17-28/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-yield-b-yield/src/main.rs b/listings/ch17-async-await/listing-17-28/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-yield-b-yield/src/main.rs rename to listings/ch17-async-await/listing-17-28/src/main.rs diff --git a/listings/ch17-async-await/listing-17-yield-a-sleep/Cargo.lock b/listings/ch17-async-await/listing-17-29/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-yield-a-sleep/Cargo.lock rename to listings/ch17-async-await/listing-17-29/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-29/Cargo.toml b/listings/ch17-async-await/listing-17-29/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-29/Cargo.toml @@ -0,0 +1,9 @@ +[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-yield-c-performance/src/main.rs b/listings/ch17-async-await/listing-17-29/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-yield-c-performance/src/main.rs rename to listings/ch17-async-await/listing-17-29/src/main.rs diff --git a/listings/ch17-async-await/listing-17-yield-b-yield/Cargo.lock b/listings/ch17-async-await/listing-17-yield-b-yield/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-yield-b-yield/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-yield-c-performance/Cargo.lock b/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-yield-c-performance/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index f39e7da7e5..647a8b5ecc 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -6,16 +6,16 @@ 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-TODO, we use `race` to run two futures, `slow` and `fast`, against +In Listing 17-24, 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-race/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:here}} ``` @@ -59,43 +59,30 @@ function “slow” will just take a number of milliseconds to run, and sleep t thread for that long. This is intentionally not an async function, because the idea is to represent work that is *not* async. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-0-blocked/src/main.rs:slow}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:slow}} ``` -In Listing 17-TODO we have this kind of slow work in a pair of futures which -only hand control back to the runtime *after* carrying out a bunch of slow -operations, represented by calls to `slow`: +In Listing 17-26, 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-yield-0-blocked/src/main.rs:slow-futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:slow-futures}} ``` If you run this, you will see this output: - - -```text -'a' started. -'a' ran for 300ms -'a' ran for 100ms -'a' ran for 200ms -'a' ran for 900ms -'b' started. -'b' ran for 750ms -'b' ran for 100ms -'b' ran for 150ms -'b' ran for 350ms -'b' ran for 150ms -'a' finished. +```console +{{#include ../listings/ch17-async-await/listing-17-26/output.txt}} ``` As with our earlier example, `race` still finishes when `a` finishes. There is @@ -110,21 +97,42 @@ something we can await! However, we can also see the handoff happening in this very example: if we removed the `trpl::sleep` at the end of the `a` future, it would complete without the `b` future running *at all*. Given that, maybe we could use the -`sleep` function as a starting point, as in Listing 17-TODO. +`sleep` function as a starting point, as in Listing 17-27. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-a-sleep/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:here}} ``` -Now the two futures’ work is interleaved. The `a` future still runs for a bit -before handing off control to `b`, because it has some expensive work to do up -front, but after that they just swap back and forth every time one of them hits -an await point. In this case, we have done that after ever call to `slow`, but -we could break up the work however makes the most sense to us. +Now the two futures’ work is interleaved, as we can see if we run it. + + + +```text +'a' started. +'a' ran for 300ms +'b' started. +'b' ran for 750ms +'a' ran for 100ms +'b' ran for 100ms +'a' ran for 200ms +'b' ran for 150ms +'a' ran for 900ms +'b' ran for 350ms +'a' finished. +``` + + +The `a` future still runs for a bit before handing off control to `b`, because +it has some expensive work to do up front, but after that they just swap back +and forth every 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. However, we do not actually need to sleep to accomplish this. We just need to hand back control to the runtime. We can actually *yield* control back to the @@ -132,10 +140,10 @@ runtime, using a function named `yield_now`. It does just what it says: hands control back to the runtime, so that the runtime can check whether any other tasks are ready to make progress. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-b-yield/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:here}} ``` @@ -148,18 +156,18 @@ 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-TODO. (This is not an especially rigorous way to do performance +Listing 17-29. (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-TODO and 17-TODO. Then we run for 1,000 iterations and see how long +Listings 17-27 and 17-28. Then we run for 1,000 iterations and see how long `sleep` takes vs. `yield_now`. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-yield-c-performance/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:here}} ``` From 9d8f2c5fa7b7add21222d13973f936d86edf29c6 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 14 Jun 2024 09:22:51 -0600 Subject: [PATCH 108/249] Ch. 17: renumber listings to eliminate `no-listing` listings --- .../ch17-async-await/listing-17-19/Cargo.lock | 273 --------- .../ch17-async-await/listing-17-19/Cargo.toml | 3 - .../output.txt | 0 .../listing-17-19/src/main.rs | 52 +- .../listing-17-20/src/main.rs | 6 +- .../output.txt | 0 .../listing-17-21/src/main.rs | 22 +- .../ch17-async-await/listing-17-22/Cargo.lock | 44 +- .../listing-17-22/src/main.rs | 64 +-- .../test-data/hello.txt | 0 .../test-data/punct.txt | 0 .../test-data/world.txt | 0 .../listing-17-23/src/main.rs | 53 +- .../ch17-async-await/listing-17-24/Cargo.lock | 260 --------- .../listing-17-24/src/main.rs | 69 ++- .../listing-17-25/src/main.rs | 18 +- .../ch17-async-await/listing-17-26/Cargo.lock | 260 +++++++++ .../listing-17-26/src/main.rs | 36 +- .../listing-17-27/src/main.rs | 36 +- .../ch17-async-await/listing-17-28/Cargo.lock | 260 --------- .../output.txt | 0 .../listing-17-28/src/main.rs | 15 +- .../ch17-async-await/listing-17-29/Cargo.lock | 260 --------- .../listing-17-29/src/main.rs | 62 +- .../ch17-async-await/listing-17-30/Cargo.lock | 540 ++++++++++++++++++ .../Cargo.toml | 0 .../listing-17-30/src/main.rs | 42 ++ .../ch17-async-await/listing-17-31/Cargo.lock | 540 ++++++++++++++++++ .../Cargo.toml | 3 + .../listing-17-31/src/main.rs | 34 ++ .../no-listing-borrow-mutable-vec/Cargo.lock | 280 --------- .../no-listing-borrow-mutable-vec/src/main.rs | 18 - .../no-listing-type-mismatch/Cargo.lock | 7 - .../no-listing-type-mismatch/src/main.rs | 7 - src/ch17-03-more-futures.md | 52 +- src/ch17-04-more-ways-of-combining-futures.md | 36 +- 36 files changed, 1681 insertions(+), 1671 deletions(-) rename listings/ch17-async-await/{no-listing-type-mismatch => listing-17-19}/output.txt (100%) rename listings/ch17-async-await/{listing-17-20 => listing-17-21}/output.txt (100%) rename listings/ch17-async-await/{no-listing-borrow-mutable-vec => listing-17-22}/test-data/hello.txt (100%) rename listings/ch17-async-await/{no-listing-borrow-mutable-vec => listing-17-22}/test-data/punct.txt (100%) rename listings/ch17-async-await/{no-listing-borrow-mutable-vec => listing-17-22}/test-data/world.txt (100%) rename listings/ch17-async-await/{listing-17-26 => listing-17-28}/output.txt (100%) create mode 100644 listings/ch17-async-await/listing-17-30/Cargo.lock rename listings/ch17-async-await/{no-listing-borrow-mutable-vec => listing-17-30}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-30/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-31/Cargo.lock rename listings/ch17-async-await/{no-listing-type-mismatch => listing-17-31}/Cargo.toml (73%) create mode 100644 listings/ch17-async-await/listing-17-31/src/main.rs delete mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.lock delete mode 100644 listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs delete mode 100644 listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock delete mode 100644 listings/ch17-async-await/no-listing-type-mismatch/src/main.rs diff --git a/listings/ch17-async-await/listing-17-19/Cargo.lock b/listings/ch17-async-await/listing-17-19/Cargo.lock index c0e8bb2b3f..d30b928a6c 100644 --- a/listings/ch17-async-await/listing-17-19/Cargo.lock +++ b/listings/ch17-async-await/listing-17-19/Cargo.lock @@ -2,279 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "cc" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.154" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -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.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -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.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 = "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.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tokio" -version = "1.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[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-19/Cargo.toml b/listings/ch17-async-await/listing-17-19/Cargo.toml index 349041d3eb..67729afc80 100644 --- a/listings/ch17-async-await/listing-17-19/Cargo.toml +++ b/listings/ch17-async-await/listing-17-19/Cargo.toml @@ -4,6 +4,3 @@ 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/no-listing-type-mismatch/output.txt b/listings/ch17-async-await/listing-17-19/output.txt similarity index 100% rename from listings/ch17-async-await/no-listing-type-mismatch/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 beff676dbe..0c282f4f87 100644 --- a/listings/ch17-async-await/listing-17-19/src/main.rs +++ b/listings/ch17-async-await/listing-17-19/src/main.rs @@ -1,49 +1,7 @@ -use std::time::Duration; - fn main() { - trpl::block_on(async { - let (tx, mut rx) = trpl::channel(); - - let tx1 = tx.clone(); - let tx1_fut = async move { - 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; - } - }; - - 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_secs(1)).await; - } - }; - - // ANCHOR: here - let futures = - vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; - - trpl::join_all(futures).await; - // ANCHOR_END: here - }); + // ANCHOR: here + let a = 1; + let b = "Hello"; + let vals = vec![a, b]; + // ANCHOR_END: here } 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 b712d344c0..beff676dbe 100644 --- a/listings/ch17-async-await/listing-17-20/src/main.rs +++ b/listings/ch17-async-await/listing-17-20/src/main.rs @@ -1,4 +1,4 @@ -use std::{future::Future, time::Duration}; +use std::time::Duration; fn main() { trpl::block_on(async { @@ -40,10 +40,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-20/output.txt b/listings/ch17-async-await/listing-17-21/output.txt similarity index 100% rename from listings/ch17-async-await/listing-17-20/output.txt rename to listings/ch17-async-await/listing-17-21/output.txt 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 5520a58ca5..b712d344c0 100644 --- a/listings/ch17-async-await/listing-17-21/src/main.rs +++ b/listings/ch17-async-await/listing-17-21/src/main.rs @@ -1,15 +1,11 @@ -use std::{ - future::Future, - pin::{pin, Pin}, - time::Duration, -}; +use std::{future::Future, time::Duration}; fn main() { trpl::block_on(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"), @@ -21,15 +17,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"), @@ -41,11 +37,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-22/Cargo.lock b/listings/ch17-async-await/listing-17-22/Cargo.lock index c0e8bb2b3f..9eeeffaff4 100644 --- a/listings/ch17-async-await/listing-17-22/Cargo.lock +++ b/listings/ch17-async-await/listing-17-22/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -32,9 +32,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -148,9 +148,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "hermit-abi" @@ -160,21 +160,21 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "6d0d8b92cd8358e8d229c11df9358decae64d137c5be540952c5ca7b25aea768" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -212,9 +212,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -245,9 +245,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.63" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "num_cpus", 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 7e33ab3cc8..fbba735c3f 100644 --- a/listings/ch17-async-await/listing-17-22/src/main.rs +++ b/listings/ch17-async-await/listing-17-22/src/main.rs @@ -1,62 +1,18 @@ -use std::{ - future::Future, - pin::{pin, Pin}, - time::Duration, -}; - fn main() { - trpl::block_on(async { - let (tx, mut rx) = trpl::channel(); - - let tx1 = tx.clone(); + trpl::block_on({ // ANCHOR: here - 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 - }); + async { + let mut strings = vec![]; - let rx_fut = pin!(async { - // snip... - // ANCHOR_END: here - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - // ANCHOR: here - }); + let a = trpl::read_to_string("test-data/hello.txt").await.unwrap(); + strings.push(a.trim()); - 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"), - ]; + let b = trpl::read_to_string("test-data/world.txt").await.unwrap(); + strings.push(b.trim()); - 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]; + let combined = strings.join(" "); + println!("{combined}"); + } // ANCHOR_END: here - - trpl::join_all(futures).await; }); } diff --git a/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/hello.txt b/listings/ch17-async-await/listing-17-22/test-data/hello.txt similarity index 100% rename from listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/hello.txt rename to listings/ch17-async-await/listing-17-22/test-data/hello.txt diff --git a/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/punct.txt b/listings/ch17-async-await/listing-17-22/test-data/punct.txt similarity index 100% rename from listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/punct.txt rename to listings/ch17-async-await/listing-17-22/test-data/punct.txt diff --git a/listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/world.txt b/listings/ch17-async-await/listing-17-22/test-data/world.txt similarity index 100% rename from listings/ch17-async-await/no-listing-borrow-mutable-vec/test-data/world.txt rename to listings/ch17-async-await/listing-17-22/test-data/world.txt 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 6603223a5b..5520a58ca5 100644 --- a/listings/ch17-async-await/listing-17-23/src/main.rs +++ b/listings/ch17-async-await/listing-17-23/src/main.rs @@ -1,12 +1,53 @@ +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; + fn main() { trpl::block_on(async { - // ANCHOR: here - let a = async { 1u32 }; - let b = async { "Hello!" }; - let c = async { true }; + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = pin!(async move { + 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; + } + }); + + let rx_fut = pin!(async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + }); - let (a_result, b_result, c_result) = trpl::join!(a, b, c); - println!("{a_result}, {b_result}, {c_result}"); + let tx_fut = pin!(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_secs(1)).await; + } + }); + + // 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-24/Cargo.lock b/listings/ch17-async-await/listing-17-24/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-24/Cargo.lock +++ b/listings/ch17-async-await/listing-17-24/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-24/src/main.rs b/listings/ch17-async-await/listing-17-24/src/main.rs index eb86c1a486..7e33ab3cc8 100644 --- a/listings/ch17-async-await/listing-17-24/src/main.rs +++ b/listings/ch17-async-await/listing-17-24/src/main.rs @@ -1,21 +1,62 @@ -use std::time::Duration; +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; fn main() { trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); // 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."); - }; - - trpl::race(slow, fast).await; + 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 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-25/src/main.rs b/listings/ch17-async-await/listing-17-25/src/main.rs index 9d8dedfb3b..6603223a5b 100644 --- a/listings/ch17-async-await/listing-17-25/src/main.rs +++ b/listings/ch17-async-await/listing-17-25/src/main.rs @@ -1,14 +1,12 @@ -use std::{thread, time::Duration}; - fn main() { trpl::block_on(async { - // We will call `slow` here later - }); -} + // ANCHOR: here + let a = async { 1u32 }; + let b = async { "Hello!" }; + let c = async { true }; -// ANCHOR: slow -fn slow(name: &str, ms: u64) { - thread::sleep(Duration::from_millis(ms)); - println!("'{name}' ran for {ms}ms"); + let (a_result, b_result, c_result) = trpl::join!(a, b, c); + println!("{a_result}, {b_result}, {c_result}"); + // ANCHOR_END: here + }); } -// ANCHOR_END: slow diff --git a/listings/ch17-async-await/listing-17-26/Cargo.lock b/listings/ch17-async-await/listing-17-26/Cargo.lock index c0e8bb2b3f..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,8 +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-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -278,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 9948c79e57..eb86c1a486 100644 --- a/listings/ch17-async-await/listing-17-26/src/main.rs +++ b/listings/ch17-async-await/listing-17-26/src/main.rs @@ -1,35 +1,21 @@ -use std::{thread, time::Duration}; +use std::time::Duration; fn main() { trpl::block_on(async { - // ANCHOR: slow-futures - let a = async { - println!("'a' started."); - slow("a", 300); - slow("a", 100); - slow("a", 200); - slow("a", 900); - trpl::sleep(Duration::from_millis(50)).await; - println!("'a' finished."); + // ANCHOR: here + let slow = async { + println!("'slow' started."); + trpl::sleep(Duration::from_millis(100)).await; + println!("'slow' finished."); }; - let b = async { - println!("'b' started."); - slow("b", 750); - slow("b", 100); - slow("b", 150); - slow("b", 350); - slow("b", 150); + let fast = async { + println!("'fast' started."); trpl::sleep(Duration::from_millis(50)).await; - println!("'b' finished."); + println!("'fast' finished."); }; - trpl::race(a, b).await; - // ANCHOR_END: slow-futures + trpl::race(slow, fast).await; + // ANCHOR_END: here }); } - -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-27/src/main.rs b/listings/ch17-async-await/listing-17-27/src/main.rs index d5c90e0226..9d8dedfb3b 100644 --- a/listings/ch17-async-await/listing-17-27/src/main.rs +++ b/listings/ch17-async-await/listing-17-27/src/main.rs @@ -2,43 +2,13 @@ use std::{thread, time::Duration}; fn main() { trpl::block_on(async { - // ANCHOR: here - let one_ms = Duration::from_millis(1); - - let a = async { - println!("'a' started."); - slow("a", 300); - trpl::sleep(one_ms).await; - slow("a", 100); - trpl::sleep(one_ms).await; - slow("a", 200); - trpl::sleep(one_ms).await; - slow("a", 900); - trpl::sleep(one_ms).await; - println!("'a' finished."); - }; - - let b = async { - println!("'b' started."); - slow("b", 750); - trpl::sleep(one_ms).await; - slow("b", 100); - trpl::sleep(one_ms).await; - slow("b", 150); - trpl::sleep(one_ms).await; - slow("b", 350); - trpl::sleep(one_ms).await; - slow("b", 150); - trpl::sleep(one_ms).await; - println!("'b' finished."); - }; - // ANCHOR_END: here - - trpl::race(a, b).await; + // 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-28/Cargo.lock b/listings/ch17-async-await/listing-17-28/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-28/Cargo.lock +++ b/listings/ch17-async-await/listing-17-28/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-26/output.txt b/listings/ch17-async-await/listing-17-28/output.txt similarity index 100% rename from listings/ch17-async-await/listing-17-26/output.txt rename to listings/ch17-async-await/listing-17-28/output.txt 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 d4552dace7..9948c79e57 100644 --- a/listings/ch17-async-await/listing-17-28/src/main.rs +++ b/listings/ch17-async-await/listing-17-28/src/main.rs @@ -2,37 +2,30 @@ use std::{thread, time::Duration}; fn main() { trpl::block_on(async { - // ANCHOR: here + // ANCHOR: slow-futures let a = async { println!("'a' started."); slow("a", 300); - trpl::yield_now().await; slow("a", 100); - trpl::yield_now().await; slow("a", 200); - trpl::yield_now().await; slow("a", 900); - trpl::yield_now().await; + trpl::sleep(Duration::from_millis(50)).await; println!("'a' finished."); }; let b = async { println!("'b' started."); slow("b", 750); - trpl::yield_now().await; slow("b", 100); - trpl::yield_now().await; slow("b", 150); - trpl::yield_now().await; slow("b", 350); - trpl::yield_now().await; slow("b", 150); - trpl::yield_now().await; + 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-29/Cargo.lock b/listings/ch17-async-await/listing-17-29/Cargo.lock index 3be4eaaa53..c0e8bb2b3f 100644 --- a/listings/ch17-async-await/listing-17-29/Cargo.lock +++ b/listings/ch17-async-await/listing-17-29/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,8 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -393,148 +278,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-29/src/main.rs b/listings/ch17-async-await/listing-17-29/src/main.rs index ef99235640..d5c90e0226 100644 --- a/listings/ch17-async-await/listing-17-29/src/main.rs +++ b/listings/ch17-async-await/listing-17-29/src/main.rs @@ -1,34 +1,44 @@ -use std::time::{Duration, Instant}; +use std::{thread, time::Duration}; fn main() { trpl::block_on(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() - ); + let one_ms = Duration::from_millis(1); - 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() - ); + let a = async { + println!("'a' started."); + slow("a", 300); + trpl::sleep(one_ms).await; + slow("a", 100); + trpl::sleep(one_ms).await; + slow("a", 200); + trpl::sleep(one_ms).await; + slow("a", 900); + trpl::sleep(one_ms).await; + println!("'a' finished."); + }; + + let b = async { + println!("'b' started."); + slow("b", 750); + trpl::sleep(one_ms).await; + slow("b", 100); + trpl::sleep(one_ms).await; + slow("b", 150); + trpl::sleep(one_ms).await; + slow("b", 350); + trpl::sleep(one_ms).await; + slow("b", 150); + trpl::sleep(one_ms).await; + println!("'b' finished."); + }; // ANCHOR_END: here + + 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-30/Cargo.lock b/listings/ch17-async-await/listing-17-30/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-30/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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/no-listing-borrow-mutable-vec/Cargo.toml b/listings/ch17-async-await/listing-17-30/Cargo.toml similarity index 100% rename from listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.toml rename to listings/ch17-async-await/listing-17-30/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-30/src/main.rs b/listings/ch17-async-await/listing-17-30/src/main.rs new file mode 100644 index 0000000000..d4552dace7 --- /dev/null +++ b/listings/ch17-async-await/listing-17-30/src/main.rs @@ -0,0 +1,42 @@ +use std::{thread, time::Duration}; + +fn main() { + trpl::block_on(async { + // ANCHOR: here + let a = async { + println!("'a' started."); + slow("a", 300); + trpl::yield_now().await; + slow("a", 100); + trpl::yield_now().await; + slow("a", 200); + trpl::yield_now().await; + slow("a", 900); + trpl::yield_now().await; + println!("'a' finished."); + }; + + let b = async { + println!("'b' started."); + slow("b", 750); + trpl::yield_now().await; + slow("b", 100); + trpl::yield_now().await; + slow("b", 150); + trpl::yield_now().await; + slow("b", 350); + trpl::yield_now().await; + slow("b", 150); + trpl::yield_now().await; + println!("'b' finished."); + }; + // ANCHOR_end: here + + 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-31/Cargo.lock b/listings/ch17-async-await/listing-17-31/Cargo.lock new file mode 100644 index 0000000000..3be4eaaa53 --- /dev/null +++ b/listings/ch17-async-await/listing-17-31/Cargo.lock @@ -0,0 +1,540 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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 = "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 = "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" +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.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 = "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" +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 = "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 = "tokio" +version = "1.37.0" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[package]] +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/no-listing-type-mismatch/Cargo.toml b/listings/ch17-async-await/listing-17-31/Cargo.toml similarity index 73% rename from listings/ch17-async-await/no-listing-type-mismatch/Cargo.toml rename to listings/ch17-async-await/listing-17-31/Cargo.toml index 67729afc80..349041d3eb 100644 --- a/listings/ch17-async-await/no-listing-type-mismatch/Cargo.toml +++ b/listings/ch17-async-await/listing-17-31/Cargo.toml @@ -4,3 +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-31/src/main.rs b/listings/ch17-async-await/listing-17-31/src/main.rs new file mode 100644 index 0000000000..ef99235640 --- /dev/null +++ b/listings/ch17-async-await/listing-17-31/src/main.rs @@ -0,0 +1,34 @@ +use std::time::{Duration, Instant}; + +fn main() { + trpl::block_on(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() + ); + + 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/no-listing-borrow-mutable-vec/Cargo.lock b/listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.lock deleted file mode 100644 index 9eeeffaff4..0000000000 --- a/listings/ch17-async-await/no-listing-borrow-mutable-vec/Cargo.lock +++ /dev/null @@ -1,280 +0,0 @@ -# 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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d8b92cd8358e8d229c11df9358decae64d137c5be540952c5ca7b25aea768" - -[[package]] -name = "miniz_oxide" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" -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 = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[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/no-listing-borrow-mutable-vec/src/main.rs b/listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs deleted file mode 100644 index fbba735c3f..0000000000 --- a/listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -fn main() { - trpl::block_on({ - // ANCHOR: here - async { - let mut strings = vec![]; - - let a = trpl::read_to_string("test-data/hello.txt").await.unwrap(); - strings.push(a.trim()); - - let b = trpl::read_to_string("test-data/world.txt").await.unwrap(); - strings.push(b.trim()); - - let combined = strings.join(" "); - println!("{combined}"); - } - // ANCHOR_END: here - }); -} diff --git a/listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock b/listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock deleted file mode 100644 index d30b928a6c..0000000000 --- a/listings/ch17-async-await/no-listing-type-mismatch/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "async_await" -version = "0.1.0" diff --git a/listings/ch17-async-await/no-listing-type-mismatch/src/main.rs b/listings/ch17-async-await/no-listing-type-mismatch/src/main.rs deleted file mode 100644 index 0c282f4f87..0000000000 --- a/listings/ch17-async-await/no-listing-type-mismatch/src/main.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - // ANCHOR: here - let a = 1; - let b = "Hello"; - let vals = vec![a, b]; - // ANCHOR_END: here -} diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index f76a4a8c7b..08144b647c 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -51,14 +51,18 @@ appear in the code? One clue is the format of this message. Notice that it is exactly the same as if we had tried to create a `Vec` with a a number and a string in it: ++ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/no-listing-type-mismatch/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} ``` + + The output there would be: ```text -{{#include ../listings/ch17-async-await/no-listing-type-mismatch/output.txt}} +{{#include ../listings/ch17-async-await/listing-17-19/output.txt}} ``` Saying “expected *something*, found *something else*” is Rust’s standard format @@ -91,13 +95,13 @@ produced by these types as interchangeable, since all of them by definition implement the `Future` trait. We can start by wrapping each of the futures in the `vec!` in a `Box::new()`. -Unfortunately, the initial way we might try this, as shown in Listing 17-19, +Unfortunately, the initial way we might try this, as shown in Listing 17-20, still does not compile. -+ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} ``` @@ -109,7 +113,7 @@ second and third `Box::new` calls, and we also get new errors referring to the We can start by fixing the type error around the `Box::new` calls, by telling the compiler explicitly that we want to use these types as trait objects. The clearest way to do that here is by adding a type annotation to the declaration -of `futures`, as we see in Listing 17-TODO. The type we have to write here is a +of `futures`, as we see in Listing 17-21. The type we have to write here is a little involved, so let’s walk through each part of it. - The innermost type is the future itself. We note explicitly that it the output @@ -118,20 +122,20 @@ little involved, so let’s walk through each part of it. - The entire trait is wrapped in a `Box`. - Finally, we state explicitly that `futures` is a `Vec` containing these items. -+ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:here}} ``` That already made a big difference. Now when we run the compiler, we only have the errors mentioning `Unpin`. Although there are three of them, notice that -each is very similar in its contets +each is very similar in its contents. ```console -{{#include ../listings/ch17-async-await/listing-17-20/output.txt}} +{{#include ../listings/ch17-async-await/listing-17-21/output.txt}} ``` That is a *lot* to digest, so let’s pull it apart. The first part of the message @@ -176,12 +180,18 @@ type to call `poll`? In [“Futures and Syntax: 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. Consider code like this: +rules around safety, including borrowing and ownership. Consider code which has +a mutable `Vec` of strings, which asynchronously reads strings from files and +pushes those strings into the `Vec`: + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/no-listing-borrow-mutable-vec/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:here}} ``` + + If we think about the state machine that would get compiled to, it might be something kind of like this: @@ -301,12 +311,12 @@ get our `join_all` call to compile! First, we need to explicitly annotate `futures` as referring to a pinned `Box` of futures. Second, we actually need to pin the futures, which we can do using the handy `Box::pin` API, which exists for exactly this. Putting that together, we end up with the code in Listing -17-21. +17-23. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:here}} ``` @@ -344,12 +354,12 @@ 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-22. +dynamic `Future` type, as in Listing 17-24. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:here}} ``` @@ -358,17 +368,17 @@ This keeps everything on the stack, which is a nice little performance win, but it is still a lot of explicit types, which is quite unusual for Rust! 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-23, +fact that we might have different `Output` types. For example, in Listing 17-25, the anonymous future type for `a` implements `Future`, the anonymous future type for `b` implements `Future`, and the anonymous future type for `c` implements `Future`. We can use `trpl::join!` to await them together, since it accepts futures of different types. -+ ```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}} ``` diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index 647a8b5ecc..b5a96fa7a1 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -6,16 +6,16 @@ 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-24, we use `race` to run two futures, `slow` and `fast`, against +In Listing 17-26, 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-24/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:here}} ``` @@ -59,22 +59,22 @@ function “slow” will just take a number of milliseconds to run, and sleep t thread for that long. This is intentionally not an async function, because the idea is to represent work that is *not* async. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:slow}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:slow}} ``` -In Listing 17-26, we use `slow` to emulate doing this kind of CPU-bound work in +In Listing 17-28, 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-26/src/main.rs:slow-futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:slow-futures}} ``` @@ -82,7 +82,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: ```console -{{#include ../listings/ch17-async-await/listing-17-26/output.txt}} +{{#include ../listings/ch17-async-await/listing-17-28/output.txt}} ``` As with our earlier example, `race` still finishes when `a` finishes. There is @@ -97,12 +97,12 @@ something we can await! However, we can also see the handoff happening in this very example: if we removed the `trpl::sleep` at the end of the `a` future, it would complete without the `b` future running *at all*. Given that, maybe we could use the -`sleep` function as a starting point, as in Listing 17-27. +`sleep` function as a starting point, as in Listing 17-29. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:here}} ``` @@ -140,10 +140,10 @@ runtime, using a function named `yield_now`. It does just what it says: hands control back to the runtime, so that the runtime can check whether any other tasks are ready to make progress. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-30/src/main.rs:here}} ``` @@ -156,18 +156,18 @@ 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-29. (This is not an especially rigorous way to do performance +Listing 17-31. (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-27 and 17-28. Then we run for 1,000 iterations and see how long +Listings 17-29 and 17-30. Then we run for 1,000 iterations and see how long `sleep` takes vs. `yield_now`. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs:here}} ``` From 4f93e8b19fafb6ea00b7cc135f9496f07c088542 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 14 Jun 2024 09:41:02 -0600 Subject: [PATCH 109/249] =?UTF-8?q?Ch.=2017:=20finish=20listing=20numbers?= =?UTF-8?q?=20for=20=C2=A704?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-33/Cargo.lock | 280 +++++++++ .../Cargo.toml | 0 .../listing-17-33/src/main.rs | 21 + .../ch17-async-await/listing-17-34/Cargo.lock | 280 +++++++++ .../ch17-async-await/listing-17-34/Cargo.toml | 9 + .../listing-17-34/src/main.rs | 31 + .../ch17-async-await/listing-17-35/Cargo.lock | 280 +++++++++ .../ch17-async-await/listing-17-35/Cargo.toml | 9 + .../src/main.rs | 5 - .../listing-17-timeout-final/Cargo.lock | 540 ------------------ src/ch17-04-more-ways-of-combining-futures.md | 22 +- 14 files changed, 921 insertions(+), 556 deletions(-) rename listings/ch17-async-await/{listing-17-timeout-a => listing-17-32}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-timeout-a => listing-17-32}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-timeout-a => listing-17-32}/src/main.rs (100%) create mode 100644 listings/ch17-async-await/listing-17-33/Cargo.lock rename listings/ch17-async-await/{listing-17-timeout-final => listing-17-33}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-33/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-34/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-34/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-34/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-35/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-35/Cargo.toml rename listings/ch17-async-await/{listing-17-timeout-final => listing-17-35}/src/main.rs (89%) delete mode 100644 listings/ch17-async-await/listing-17-timeout-final/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-timeout-a/Cargo.lock b/listings/ch17-async-await/listing-17-32/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-timeout-a/Cargo.lock rename to listings/ch17-async-await/listing-17-32/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-timeout-a/Cargo.toml b/listings/ch17-async-await/listing-17-32/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-timeout-a/Cargo.toml rename to listings/ch17-async-await/listing-17-32/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-timeout-a/src/main.rs b/listings/ch17-async-await/listing-17-32/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-timeout-a/src/main.rs rename to listings/ch17-async-await/listing-17-32/src/main.rs diff --git a/listings/ch17-async-await/listing-17-33/Cargo.lock b/listings/ch17-async-await/listing-17-33/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-33/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-timeout-final/Cargo.toml b/listings/ch17-async-await/listing-17-33/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-timeout-final/Cargo.toml rename to listings/ch17-async-await/listing-17-33/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-33/src/main.rs b/listings/ch17-async-await/listing-17-33/src/main.rs new file mode 100644 index 0000000000..17d2f985f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-33/src/main.rs @@ -0,0 +1,21 @@ +use std::{future::Future, time::Duration}; + +fn main() { + trpl::block_on(async { + let slow = async { + trpl::sleep(Duration::from_secs(5)).await; + "Finally finished" + }; + + // Here we will actually use the new `timeout` with `slow`. + }); +} + +// ANCHOR: declaration +async fn timeout( + max_time: Duration, + future: F, +) -> Result { + // ANCHOR_END: declaration + unimplemented!() +} diff --git a/listings/ch17-async-await/listing-17-34/Cargo.lock b/listings/ch17-async-await/listing-17-34/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-34/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-34/Cargo.toml b/listings/ch17-async-await/listing-17-34/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-34/Cargo.toml @@ -0,0 +1,9 @@ +[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-34/src/main.rs b/listings/ch17-async-await/listing-17-34/src/main.rs new file mode 100644 index 0000000000..7ff4a59390 --- /dev/null +++ b/listings/ch17-async-await/listing-17-34/src/main.rs @@ -0,0 +1,31 @@ +use std::{future::Future, time::Duration}; + +// ANCHOR: timeout +use trpl::Either; +// ANCHOR_END: timeout + +fn main() { + trpl::block_on(async { + let slow = async { + trpl::sleep(Duration::from_secs(5)).await; + "Finally finished" + }; + + // Here we will actually use the new `timeout` with `slow`. + }); +} + +// Note for maintainers: the extra space after the `ANCHOR` is intentional: it +// makes this render more nicely! +// ANCHOR: timeout + +async fn timeout( + max_time: Duration, + future: F, +) -> Result { + match trpl::race(future, trpl::sleep(max_time)).await { + Either::Left(output) => Ok(output), + Either::Right(_) => Err(max_time), + } +} +// ANCHOR_END: timeout diff --git a/listings/ch17-async-await/listing-17-35/Cargo.lock b/listings/ch17-async-await/listing-17-35/Cargo.lock new file mode 100644 index 0000000000..c0e8bb2b3f --- /dev/null +++ b/listings/ch17-async-await/listing-17-35/Cargo.lock @@ -0,0 +1,280 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-35/Cargo.toml b/listings/ch17-async-await/listing-17-35/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-35/Cargo.toml @@ -0,0 +1,9 @@ +[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-timeout-final/src/main.rs b/listings/ch17-async-await/listing-17-35/src/main.rs similarity index 89% rename from listings/ch17-async-await/listing-17-timeout-final/src/main.rs rename to listings/ch17-async-await/listing-17-35/src/main.rs index eaee49d51b..2e389a6509 100644 --- a/listings/ch17-async-await/listing-17-timeout-final/src/main.rs +++ b/listings/ch17-async-await/listing-17-35/src/main.rs @@ -20,17 +20,12 @@ fn main() { }); } -// ANCHOR: timeout - -// ANCHOR: declaration async fn timeout( max_time: Duration, future: F, ) -> Result { - // ANCHOR_END: declaration match trpl::race(future, trpl::sleep(max_time)).await { Either::Left(output) => Ok(output), Either::Right(_) => Err(max_time), } } -// ANCHOR_END: timeout diff --git a/listings/ch17-async-await/listing-17-timeout-final/Cargo.lock b/listings/ch17-async-await/listing-17-timeout-final/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-timeout-final/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index b5a96fa7a1..e488341314 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -191,15 +191,15 @@ important one to keep in mind, though! Many of these patterns are common enough to warrant abstracting over. For example, the `trpl::timeout` function takes a `Duration` for the maximum time to run, but also takes a future to run, and produces a new future you can await, -whose `Output` type is a `Result`. Listing 17-TODO shows how we can use it. If +whose `Output` type is a `Result`. Listing 17-32 shows how we can use it. If the passed-in future finishes first, the output result will be `Ok`, with the result of that passed-in future. If the duration elapses before the passed-in future finishes, the result will be `Err` with the duration that elapsed. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-a/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs:here}} ``` @@ -215,12 +215,12 @@ the API of `timeout`: be `Ok` with the value produced by the future. If the timeout happens, the `Result` will be `Err` with the duration that the timeout waited for. -We can write the same signature ourselves, as in Listing 17-TODO. +We can write the same signature ourselves, as in Listing 17-33. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-final/src/main.rs:declaration}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-33/src/main.rs:declaration}} ``` @@ -228,7 +228,7 @@ We can write the same signature ourselves, as in Listing 17-TODO. Then, in the body of the function, we can `race` whatever future the caller passes with a `sleep` future. -When we saw `race` earlier in Listing 17-TODO, we ignored its return type, +When we saw `race` earlier in Listing 17-26, 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 @@ -259,10 +259,10 @@ match trpl::race(future_a, future_b).await { That gives us enough to be able to implement `timeout` ourselves using `race` and `sleep`. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-final/src/main.rs:timeout}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-34/src/main.rs:timeout}} ``` @@ -280,10 +280,10 @@ duration the user passed in instead. And that’s it! Back in `main`, we can call this new `timeout` function exactly like we called `trpl::timeout` before, but without the `trpl::` namespace: -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-timeout-final/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-35/src/main.rs:main}} ``` From 4598e2cb4fddb75e4cc9893e06d56d99ee417f98 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 14 Jun 2024 10:28:34 -0600 Subject: [PATCH 110/249] =?UTF-8?q?Ch.=2017=20=C2=A701:=20make=20the=20con?= =?UTF-8?q?clusion=20section=20coherent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-01-futures-and-syntax.md | 34 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 5c2c74ba4e..dc63fd0c4a 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -84,8 +84,6 @@ run. - - ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch17-async-await/listing-17-02/src/main.rs:main}} ``` @@ -124,8 +122,8 @@ helper functions we supply are doing. > ### The `futures` and `tokio` Crates > > Whenever you see code from the `trpl` crate throughout the rest of the -> chapter, it will be re-exporting code from the `futures` and [`tokio`][tokio] -> crates. +> chapter, it will be re-exporting code 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. @@ -179,6 +177,12 @@ pub trait Future { } ``` +Notice that this is a normal trait. While we often interact with futures via +async blocks, you can also implement this yourself on your own data types when +you need to. Many of the functions we will see throughout this chapter return +types which have their own implementations of `Future`. Those implementations +can compose together nicely + `Future` has an associated type, `Output`, which says what the result of the future will be when it resolves. (This is analogous to the `Item` associated type for the `Iterator` trait, which we saw back in Chapter 13.) Beyond that, @@ -270,20 +274,12 @@ really is an `enum` like this, just an anonymous one you don’t have to name. A a result, the normal rules around data structures all apply, including for borrowing and ownership. Happily, the compiler also handles checking that for us, and has good error messages. We will work through a few of those later in -the chapter! This is enough information to let us keep following the chain back -up to the root of our original problem with running async functions. - - +the chapter! -When we follow that chain far enough, eventually we end up back in some -non-async function. At that point, something needs to “translate” between the -async and sync worlds. That “something” is also the runtime! Whatever runtime -you use is what handles the top-level `poll()` call, scheduling and handing off -between the different async operations which may be in flight as they hand back -control at await points, and often also providing async versions of -functionality like file I/O. +Once all of that compilation work is done, though, we need a runtime to actually +poll the futures, coordinate between different futures as they hand off control +at await points, and even provide async versions of common functionality like +file or network I/O. Now we can understand why the compiler was stopping us in Listing 17-2 (before we added the `trpl::block_on` function). The `main` function is not `async`—and @@ -319,7 +315,9 @@ futures and runtimes work, we can see some of the things we can *do* with async. [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 [tokio]: https://tokio.rs - + From c0c24e2c868566709ce0830c59acae1ac6ebc61c Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 17 Jun 2024 11:25:37 -0600 Subject: [PATCH 111/249] =?UTF-8?q?Ch.=2017=20=C2=A702:=20transition=20for?= =?UTF-8?q?=20=C2=A703=20and=20TODO=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-02-concurrency-with-async.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 58ecfcbdc3..e69bc4526d 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -125,7 +125,9 @@ ask the runtime to run them both to completion using `trpl::join`: When we run this, we see both futures run to completion: - + ```text hi number 1 from the first task! @@ -346,7 +348,9 @@ which `rx` can then receive. When we run that code, we see the extra output from the new `async` block, and the message it sends being received by the `rx.recv()`. - + ```text Got: hi @@ -407,7 +411,12 @@ block, and switching back to `join3`. -Both of these blocks need to be `async move` blocks, or else we will end up back -in the same infinite loop we started out in. +*Both* of these blocks need to be `async move` blocks, or else we will end up +back in the same infinite loop we started out in. With that done, though, we get +all the messages we expected, with little delays between them. Notice that since +each of the sending futures do a one-second delay after sending, the messages +come in right after each other at one-second intervals. The delays are +concurrent, not sequential, just as we would expect. - +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. From 74df84eaedd6d05e5be4bb4ae7d11a1877242541 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 17 Jun 2024 11:36:40 -0600 Subject: [PATCH 112/249] =?UTF-8?q?Ch.=2017:=20Add=20a=20new=20=C2=A705=20?= =?UTF-8?q?on=20Stream=20and=20AsyncIterator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pushes back the Tasks, Futures, and Threads discussion one more spot, to become §06. --- src/SUMMARY.md | 3 +- src/ch17-04-more-ways-of-combining-futures.md | 2 + src/ch17-05-futures-tasks-threads.md | 102 ------------------ src/ch17-05-streams-async-iterators.md | 13 +++ src/ch17-06-futures-tasks-threads.md | 1 + 5 files changed, 18 insertions(+), 103 deletions(-) delete mode 100644 src/ch17-05-futures-tasks-threads.md create mode 100644 src/ch17-05-streams-async-iterators.md create mode 100644 src/ch17-06-futures-tasks-threads.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index f161db9097..4a9779468a 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -106,7 +106,8 @@ - [Concurrency With Async](ch17-02-concurrency-with-async.md) - [Working With More Futures](ch17-03-more-futures.md) - [More Ways of Combining Futures](ch17-04-more-ways-of-combining-futures.md) - - [Futures, Tasks, and Threads](ch17-05-futures-tasks-threads.md) + - [Streams and Async Iterators](ch17-05-streams-async-iterators.md) + - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.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-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index e488341314..aa623af9d7 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -294,4 +294,6 @@ example, you can use this same approach to combine timeouts with retries, and in turn use those with things like network calls—the exact example we started out with at the beginning of the chapter! +Up next, let’s look at how we can work with *sequences* of futures. + [futures]: ch17-01-futures-and-syntax.html#what-are-futures diff --git a/src/ch17-05-futures-tasks-threads.md b/src/ch17-05-futures-tasks-threads.md deleted file mode 100644 index 230289d086..0000000000 --- a/src/ch17-05-futures-tasks-threads.md +++ /dev/null @@ -1,102 +0,0 @@ -## Futures, Tasks, and Threads - - - -As we saw in the previous chapter, threads provide one approach to concurrency, -and they let us solve some of these issues. However, they also have some -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! While mainstream desktop and mobile operating systems have all had -threading for many years, many embedded operating systems, like those used on -some microcontrollers, do not. - -The async model provides a different—and ultimately complementary—set of -tradeoffs. In the async model, concurrent operations do not require their own -threads. Instead, they can run on *tasks*. A task is a bit like a thread, but -instead of being managed by the operating system, it is managed by code that -lives at the level of libraries. - - - -### Parallelism and Concurrency - -First, though, we need to dig a little deeper into the differences between -parallelism and concurrency. In the previous chapter we treated them as mostly -interchangeable. Now we need to distinguish between the two a little more, -because the differences will show up as we start working: - -* *Parallelism* is when operations can happen simultaneously. - -* *Concurrency* is when operations can make progress without having to wait for - all other operations to complete. - -One common analogy for thinking about the difference between concurrency and -parallelism is cooking in a kitchen. Parallelism is like having two cooks: one -working on cooking eggs, and the other working on preparing fruit bowls. Those -can happen at the same time, without either affecting the other. Concurrency is -like having a single cook who can start cooking some eggs, start dicing up some -vegetables to use in the omelette, adding seasoning and whatever vegetables are -ready to the eggs at certain points, and switching back and forth between those -tasks. - -(This analogy breaks down if you think about it too hard. The eggs keep cooking -while the cook is chopping up the vegetables, after all. That is parallelism, -not just concurrency! The focus of the analogy is the *cook*, not the food, -though, and as long as you keep that in mind, it mostly works.) - -On a machine with multiple CPU cores, we can actually do work in parallel. One -core can be doing one thing while another core does something completely -unrelated, and those actually happen at the same time. On a machine with a -single CPU core, the CPU can only do one operation at a time, but we can still -have concurrency. Using tools like threads, processes, and async, the computer -can pause one activity and switch to others before eventually cycling back to -that first activity again. So all parallel operations are also concurrent, but -not all concurrent operations happen in parallel! - -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, that concurrency may use some degree of parallelism under the hood, or it -may not. (More about async runtimes later!) - -A big difference between the cooking analogy and Rust’s async model for -concurrency is that in the cooking example, the cook makes the decision about -when to switch tasks. In Rust’s async model, the tasks are in control of that. -To see how, let’s look at how Rust actually uses async. - -## Misc. other stuff - - -The `async` keyword does not yet work with closures directly. That is, there is -no direct equivalent to `async fn` for anonymous functions. As a result, you -cannot write code like these function calls: - -```rust,ignore -example_1(async || { ... }); -example_2(async move || { ... }); -``` - -However, since async blocks themselves can be marked with `move`, this ends up -not being a problem. Because `async` blocks compile to anonymous futures, you -can write calls like this instead: - -```rust,ignore -example_1(|| async { ... }); -example_2(|| async move { ... }); -``` - -These closures now return anonymous futures, meaning they work basically the -same way that an async function does. - - - -> Note: This is how closures work, too, but we did not have to talk about it -> back in Chapter 13, because the details did not bubble up to the surface the -> way they do here! - - diff --git a/src/ch17-05-streams-async-iterators.md b/src/ch17-05-streams-async-iterators.md new file mode 100644 index 0000000000..2372dfd1a4 --- /dev/null +++ b/src/ch17-05-streams-async-iterators.md @@ -0,0 +1,13 @@ +## Streams and Async Iterators + + diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md new file mode 100644 index 0000000000..53b122978f --- /dev/null +++ b/src/ch17-06-futures-tasks-threads.md @@ -0,0 +1 @@ +# Futures, Tasks, and Threads From f0825ad05c20122bbcaa4a655f5eb15b33b422ae Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 17 Jun 2024 13:29:44 -0600 Subject: [PATCH 113/249] =?UTF-8?q?Ch.=2017=20S=C2=A702:=20introduce=20and?= =?UTF-8?q?=20explain=20`while=20let`=20syntax.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is actually the first time it appears in the book, to my great surprise! We will also need to update Chapter 19 to account for having introduced this form already, following the example for how it handles Chapter 6’s introduction of `if let`. --- src/ch17-02-concurrency-with-async.md | 60 ++++++++++++++++++--------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index e69bc4526d..4373036419 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -175,12 +175,12 @@ Sharing data between futures will look familiar. We can again use async versions of Rust’s types for message-passing. Instead of `std::sync:mpsc::channel`, we will use a `tprl::channel`, for example. -The `Receiver::recv()` method in the `std` channel blocks until it receives a -message. The `trpl::Receiver::recv()` method, by contrast, is an `async` -function. Instead of blocking, it sleeps until a message is received or the send -side of the channel closes. One other difference with this particular `recv()` -implementation is that it returns an `Option` of the type sent over the channel -instead of a `Result`. +The synchronous `Receiver::recv()` method in `std::mpsc::channel` blocks until +it receives a message. The `trpl::Receiver::recv()` method, by contrast, is an +`async` function. Instead of blocking, it waits until a message is received or +the send side of the channel closes. One other difference with this particular +`recv()` implementation is that it returns an `Option` of the type sent over the +channel instead of a `Result`. We can start by introducing an async version of the multiple-producer, single-consumer channel channel API we used with threads back in Chapter 16. The @@ -236,15 +236,22 @@ as shown in Listing 17-10: This handles sending the messages, but so far we don’t do anything with them, -and the code just silently runs forever. Listing 17-11 shows how we can receive -those messages by waiting for them in a loop. - -Here, we need to use a `while let` loop rather than a `for` loop, because Rust -does not yet have an async version of `Iterator`, which is what the `for` loop -does. In TODO: SECTION TITLE, we will see more about two related traits the -community has been working on, `AsyncIterator` and `Stream`. For now, we can -stick with `while let`, as in Listing 17-11, and the loop will end when -`rx.recv().await` produces a `None`. +and the code just silently runs forever. We need to actually *receive* the +messages. In this case, we could do that manually, because we 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. + +That sounds like a good job for a loop! In synchronous code, we might use a +`for` loop to process a sequence of items, 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. It continues as +long as the condition it relies on is true. Listing 17-11 shows how we can use +this with `rx.recv` to print all the messages send by the `tx` transmitter. + + @@ -254,10 +261,23 @@ stick with `while let`, as in Listing 17-11, and the loop will end when -This code still does not do exactly what we want. It does successfully send and -receive the messages, but instead of seeing the messages received at one-second -intervals, we see them arrive all at once, four seconds after we start the -program. It also never stops! 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 @@ -420,3 +440,5 @@ concurrent, not sequential, just as we would expect. 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 From a05c34eaa91d44cb88a7339cd3c192b654ccf21e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 17 Jun 2024 13:29:44 -0600 Subject: [PATCH 114/249] =?UTF-8?q?Ch.=2017=20=C2=A705:=20Introduce=20`Str?= =?UTF-8?q?eam`=20and=20drop=20`AsyncIterator`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SUMMARY.md | 2 +- src/ch17-04-more-ways-of-combining-futures.md | 4 +- src/ch17-05-streams-async-iterators.md | 13 --- src/ch17-05-streams.md | 105 ++++++++++++++++++ 4 files changed, 109 insertions(+), 15 deletions(-) delete mode 100644 src/ch17-05-streams-async-iterators.md create mode 100644 src/ch17-05-streams.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 4a9779468a..5a6dbfc377 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -106,7 +106,7 @@ - [Concurrency With Async](ch17-02-concurrency-with-async.md) - [Working With More Futures](ch17-03-more-futures.md) - [More Ways of Combining Futures](ch17-04-more-ways-of-combining-futures.md) - - [Streams and Async Iterators](ch17-05-streams-async-iterators.md) + - [Streams](ch17-05-streams.md) - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.md) - [Object Oriented Programming Features of Rust](ch18-00-oop.md) diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index aa623af9d7..fb0cb56c3c 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -294,6 +294,8 @@ example, you can use this same approach to combine timeouts with retries, and in turn use those with things like network calls—the exact example we started out with at the beginning of the chapter! -Up next, let’s look at how we can work with *sequences* of futures. +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-async-iterators.md b/src/ch17-05-streams-async-iterators.md deleted file mode 100644 index 2372dfd1a4..0000000000 --- a/src/ch17-05-streams-async-iterators.md +++ /dev/null @@ -1,13 +0,0 @@ -## Streams and Async Iterators - - diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md new file mode 100644 index 0000000000..3628191d6b --- /dev/null +++ b/src/ch17-05-streams.md @@ -0,0 +1,105 @@ +## Streams + +In Chapter 13, we looked at the `Iterator` trait, and we saw how we could work +with a sequence of items in turn. 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: + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:loop}} +``` + +This is because the `rx` receiver actually represents a *stream* of messages: a +sequence over time. + +Unlike `Iterator` and `Future`, there is no definition of a `Stream` type in the +standard library yet but there *is* a +very common definition used throughout the ecosystem. If we start with the +definition of the `Iterator` and `Trait` types, we can figure out what a trait +that merges them together might look like. + +The `Iterator` trait defines an associated type `Item` and a function `next`, +which produces `Some(Item)` until the underlying iterator is empty, and then +produces `None`. + + + +```rust +trait Iterator { + type Item; + + fn next(&mut self) -> Option; +} +``` + +As we saw earlier in this chapter, the `Future` trait defines an associated item +`Output` and a function `poll`, which produces `Poll::Pending` while waiting and +then `Poll::Ready(Output)` once the future is ready. + +```rust +trait Future { + type Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; +} +``` + +From `Iterator`, we have the idea of a sequence; its `next` method provides an +`Option`. From `Future`, we have the idea of readiness; its `poll` +method provides a `Poll`. To get a stream, a sequence of items +which become ready over time, we can define a `Stream` as a trait which has all +of those features put together: + +* An associated type `Item` for the type of the items, just like in `Iterator`. + Unlike in `Future`, where there was a single `Output`, we use `Item` here to + indicate that it is more like `Iterator`: there may be zero to many of these. + +* A method to get those items. We can call it `poll_next`, to make it clear that + it is polling like a future and producing a sequence of items one after another + like an iterator. + +* A return type from `poll_next` which uses both `Poll` and `Option`. The outer + type is `Poll`, since it has to be checked for readiness as a kind of future. + The inner type is `Option`, since it needs to signal whether there are more + messages, just like an iterator. + +When we put those all together, we end up with the same definition for a +`Stream` trait as the one used by the Rust ecosystem: + +```rust +trait Stream { + type Item; + + fn poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_> + ) -> Poll>; +} +``` + +Something very similar to this will likely end up standardized as part of Rust’s +standard library, just the way `Future` was. + +### Working With Streams + +Now that we have seen the API, we can see that `rx.recv` is a good model for how +we will use streams. + +> Note: As mentioned in the [“Message Passing”][17-02-messages] section, there +> is not yet an async version of `for` loops. There may well be in the future, +> though, and if so it will be built on something a lot like `Stream`. + + + +[17-02-messages]: /ch17-02-concurrency-with-async.md#message-passing From ad360d7fe4632d1771f1abb7d7be3715538e7556 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 18 Jun 2024 08:16:11 -0600 Subject: [PATCH 115/249] =?UTF-8?q?Ch=2017.=20=C2=A701:=20leave=20a=20TODO?= =?UTF-8?q?=20about=20`IntoFuture`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-01-futures-and-syntax.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index dc63fd0c4a..681727d387 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -214,7 +214,8 @@ available. > documentation. Under the hood, when you call `.await`, Rust compiles that to code which calls -`poll`, kind of like this: +`poll`, kind of (although not exactly ) +like this: ```rust,ignore match hello_async().poll() { From 52c516c59369b5e0a7b2ea49bed731dd3d742d60 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 18 Jun 2024 08:16:11 -0600 Subject: [PATCH 116/249] =?UTF-8?q?Ch.=2017=20=C2=A705:=20start=20explaini?= =?UTF-8?q?ng=20how=20we=20work=20with=20streams?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-05-streams.md | 53 ++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index 3628191d6b..a56ed79ae0 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -56,8 +56,8 @@ of those features put together: indicate that it is more like `Iterator`: there may be zero to many of these. * A method to get those items. We can call it `poll_next`, to make it clear that - it is polling like a future and producing a sequence of items one after another - like an iterator. + it is polling like a future and producing a sequence of items one after + another, just like an iterator. * A return type from `poll_next` which uses both `Poll` and `Option`. The outer type is `Poll`, since it has to be checked for readiness as a kind of future. @@ -79,27 +79,50 @@ trait Stream { ``` Something very similar to this will likely end up standardized as part of Rust’s -standard library, just the way `Future` was. +standard library, just the way `Future` was. 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! ### Working With Streams -Now that we have seen the API, we can see that `rx.recv` is a good model for how -we will use streams. +We *could* work directly in terms of the `poll_next` API by hand-writing our own +`Stream` state machines. However, just as we do not generally work with futures +directly via their `poll` method, we generally also do not work directly with +the `poll_next` method for streams. Instead, we usually use a `next` method, +which is defined roughly like this: -> Note: As mentioned in the [“Message Passing”][17-02-messages] section, there -> is not yet an async version of `for` loops. There may well be in the future, -> though, and if so it will be built on something a lot like `Stream`. +```rust +trait Stream { + async fn next(&mut self) -> Option; +} +``` -- Motivation: you can do a lot with `while let` but it would be nice to be able - to use `for` loops, even `async for`. (But we don’t get those from the - ecosystem traits… so maybe only call them out in a `Note: …` context?) - -- The basic API, with `poll_next()`, plus the “surface” syntax, `.next().await`. - -- How to use it, with a worked example from . +> 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 +> fn next(&mut self) -> Next<'_, Self> where Self: Unpin; +> ``` +> +> That `Next` type is just a simple `struct` which implements `Future`, so that +> `.await` can work with this! + +Working with this API will be kind of like working with iterators without the +convenience of a `for` loop. In fact, it will look a lot like the way we used +`rx.recv` back in the [“Message Passing”][17-02-messages] section, using `while +let` loops. + [17-02-messages]: /ch17-02-concurrency-with-async.md#message-passing From e3ab302d2787f9cd38a49adc55d83662f191e7d8 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 19 Jun 2024 10:47:13 -0600 Subject: [PATCH 117/249] Ch. 17: Remove a now-properly-numbered listing I moved this into dedicated listings appropriately but forgot to remove the original. --- .../listing-17-timeout-b/Cargo.lock | 540 ------------------ .../listing-17-timeout-b/Cargo.toml | 9 - .../listing-17-timeout-b/src/main.rs | 19 - 3 files changed, 568 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-timeout-b/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-timeout-b/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-timeout-b/src/main.rs diff --git a/listings/ch17-async-await/listing-17-timeout-b/Cargo.lock b/listings/ch17-async-await/listing-17-timeout-b/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-timeout-b/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-timeout-b/Cargo.toml b/listings/ch17-async-await/listing-17-timeout-b/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-timeout-b/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-timeout-b/src/main.rs b/listings/ch17-async-await/listing-17-timeout-b/src/main.rs deleted file mode 100644 index 5d10b86764..0000000000 --- a/listings/ch17-async-await/listing-17-timeout-b/src/main.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - // ANCHOR: fast - let fast = async { - trpl::sleep(Duration::from_secs(1)).await; - "I finished!" - }; - // ANCHOR_END: fast - - match trpl::timeout(Duration::from_secs(2), fast).await { - Ok(message) => println!("Succeeded with '{message}'"), - Err(duration) => { - println!("Failed after {} seconds", duration.as_secs()) - } - } - }); -} From bf5e4aa687033d39d8e59295500e568ac38b3d3e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 19 Jun 2024 10:47:13 -0600 Subject: [PATCH 118/249] Ch. 17 (infra): add a base listing to use when generating new ones --- .../listing-17-base/Cargo.lock | 280 ++++++++++++++++++ .../listing-17-base/Cargo.toml | 8 + .../listing-17-base/src/main.rs | 5 + 3 files changed, 293 insertions(+) create mode 100644 listings/ch17-async-await/listing-17-base/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-base/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-base/src/main.rs diff --git a/listings/ch17-async-await/listing-17-base/Cargo.lock b/listings/ch17-async-await/listing-17-base/Cargo.lock new file mode 100644 index 0000000000..53a9a9dde6 --- /dev/null +++ b/listings/ch17-async-await/listing-17-base/Cargo.lock @@ -0,0 +1,280 @@ +# 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 = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + +[[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-base/Cargo.toml b/listings/ch17-async-await/listing-17-base/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-base/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-base/src/main.rs b/listings/ch17-async-await/listing-17-base/src/main.rs new file mode 100644 index 0000000000..3c247f888f --- /dev/null +++ b/listings/ch17-async-await/listing-17-base/src/main.rs @@ -0,0 +1,5 @@ +fn main() { + trpl::block_on(async { + // TODO: use this! + }) +} From e790c2cc9008b2135c63db7382f1ac71fac8e261 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 19 Jun 2024 10:47:13 -0600 Subject: [PATCH 119/249] Ch. 17: re-export `Stream`, `StreamExt`, and `stream_iter` in `trpl` --- packages/trpl/Cargo.lock | 12 ++++++++++++ packages/trpl/Cargo.toml | 1 + packages/trpl/src/lib.rs | 2 ++ packages/trpl/tests/integration/main.rs | 20 ++++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/packages/trpl/Cargo.lock b/packages/trpl/Cargo.lock index e6e27ec0a4..03bebc8dd8 100644 --- a/packages/trpl/Cargo.lock +++ b/packages/trpl/Cargo.lock @@ -258,12 +258,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/packages/trpl/Cargo.toml b/packages/trpl/Cargo.toml index 898dae43f9..c842170443 100644 --- a/packages/trpl/Cargo.toml +++ b/packages/trpl/Cargo.toml @@ -13,3 +13,4 @@ tokio = { version = "1", default-features = false, features = [ "sync", "time", ] } +tokio-stream = "0.1.15" diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 4d748d4783..b572b0a17b 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -41,6 +41,8 @@ pub use tokio::{ time::sleep, }; +pub use tokio_stream::{iter as stream_from_iter, Stream, StreamExt}; + /// Run a single future to completion on a bespoke Tokio `Runtime`. /// /// Every time you call this, a new instance of `tokio::runtime::Runtime` will diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index ecff695515..e067732500 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -199,3 +199,23 @@ fn read_to_string() { assert_eq!(result, String::from("This is some text!\n")); } + +#[test] +fn stream_iter() { + use trpl::StreamExt; + + let result = trpl::block_on(async { + let ns = vec![1, 2, 3]; + let mut stream = trpl::stream_from_iter(ns); + let mut result = vec![]; + while let Some(n) = stream.next().await { + result.push(format!("{n}")); + } + result + }); + + assert_eq!( + result, + vec![String::from("1"), String::from("2"), String::from("3")] + ) +} From ce9b286b8fc404ec2815b89bf003c3ea4839a97b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 20 Jun 2024 13:45:50 -0600 Subject: [PATCH 120/249] =?UTF-8?q?Ch.=2017=20=C2=A705:=20describe=20how?= =?UTF-8?q?=20to=20use=20`Stream`s=20with=20`Iterator`s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also start laying the foundation for (a) showing how that interacts with previous material, e.g. around slow operations; and (b) showing how it composes nicely with other async operations, e.g. timeouts, throttling, and (maybe!) even merging streams. --- .../ch17-async-await/listing-17-36/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-36/Cargo.toml | 8 + .../listing-17-36/src/main.rs | 8 + .../ch17-async-await/listing-17-37/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-37/Cargo.toml | 8 + .../listing-17-37/src/main.rs | 9 + .../ch17-async-await/listing-17-38/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-38/Cargo.toml | 8 + .../ch17-async-await/listing-17-38/output.txt | 51 +++ .../listing-17-38/src/main.rs | 13 + .../ch17-async-await/listing-17-39/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-39/Cargo.toml | 8 + .../listing-17-39/src/main.rs | 15 + .../ch17-async-await/listing-17-40/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-40/Cargo.toml | 8 + .../listing-17-40/src/main.rs | 19 ++ src/ch17-05-streams.md | 96 +++++- 17 files changed, 1707 insertions(+), 4 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-36/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-36/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-36/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-37/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-37/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-37/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-38/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-38/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-38/output.txt create mode 100644 listings/ch17-async-await/listing-17-38/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-39/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-39/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-39/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-40/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-40/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-40/src/main.rs diff --git a/listings/ch17-async-await/listing-17-36/Cargo.lock b/listings/ch17-async-await/listing-17-36/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-36/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-36/Cargo.toml b/listings/ch17-async-await/listing-17-36/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-36/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-36/src/main.rs b/listings/ch17-async-await/listing-17-36/src/main.rs new file mode 100644 index 0000000000..afe325e6d6 --- /dev/null +++ b/listings/ch17-async-await/listing-17-36/src/main.rs @@ -0,0 +1,8 @@ +fn main() { + trpl::block_on(async { + // ANCHOR: range + let values = 1..101; + let iter = values.map(|n| n * 2); + // ANCHOR_END: range + }); +} diff --git a/listings/ch17-async-await/listing-17-37/Cargo.lock b/listings/ch17-async-await/listing-17-37/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-37/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-37/Cargo.toml b/listings/ch17-async-await/listing-17-37/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-37/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-37/src/main.rs b/listings/ch17-async-await/listing-17-37/src/main.rs new file mode 100644 index 0000000000..5bc9e01ac5 --- /dev/null +++ b/listings/ch17-async-await/listing-17-37/src/main.rs @@ -0,0 +1,9 @@ +fn main() { + trpl::block_on(async { + let values = 1..101; + let iter = values.map(|n| n * 2); + // ANCHOR: stream + let mut stream = trpl::stream_from_iter(iter); + // ANCHOR_END: stream + }); +} diff --git a/listings/ch17-async-await/listing-17-38/Cargo.lock b/listings/ch17-async-await/listing-17-38/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-38/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-38/Cargo.toml b/listings/ch17-async-await/listing-17-38/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-38/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-38/output.txt b/listings/ch17-async-await/listing-17-38/output.txt new file mode 100644 index 0000000000..6e6886fb5c --- /dev/null +++ b/listings/ch17-async-await/listing-17-38/output.txt @@ -0,0 +1,51 @@ +$ cargo run + Compiling proc-macro2 v1.0.85 + Compiling unicode-ident v1.0.12 + Compiling autocfg v1.3.0 + Compiling pin-project-lite v0.2.14 + Compiling futures-core v0.3.30 + Compiling libc v0.2.155 + Compiling futures-sink v0.3.30 + Compiling futures-task v0.3.30 + Compiling pin-utils v0.1.0 + Compiling futures-io v0.3.30 + Compiling memchr v2.7.4 + 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.38.0 + Compiling syn v2.0.66 + 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-38) +error[E0599]: no method named `next` found for struct `Iter` in the current scope + --> src/main.rs:8:40 + | +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-38/target/debug/deps/async_await-bbd5bb8f6851cb5f.long-type-17453505919820464996.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 + | +1 + use futures_util::stream::stream::StreamExt; + | +1 + use std::iter::Iterator; + | +1 + use std::str::pattern::Searcher; + | +1 + use trpl::StreamExt; + | +help: there is a method `try_next` with a similar name + | +8 | while let Some(value) = stream.try_next().await { + | ~~~~~~~~ + +For more information about this error, try `rustc --explain E0599`. +error: could not compile `async_await` (bin "async_await") due to 1 previous error diff --git a/listings/ch17-async-await/listing-17-38/src/main.rs b/listings/ch17-async-await/listing-17-38/src/main.rs new file mode 100644 index 0000000000..08bd4b0b72 --- /dev/null +++ b/listings/ch17-async-await/listing-17-38/src/main.rs @@ -0,0 +1,13 @@ +fn main() { + trpl::block_on(async { + let values = 1..101; + let iter = values.map(|n| n * 2); + let mut stream = trpl::stream_from_iter(iter); + + // ANCHOR: next + while let Some(value) = stream.next().await { + println!("The value was: {value}"); + } + // ANCHOR_END: next + }); +} diff --git a/listings/ch17-async-await/listing-17-39/Cargo.lock b/listings/ch17-async-await/listing-17-39/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-39/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-39/Cargo.toml b/listings/ch17-async-await/listing-17-39/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-39/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-39/src/main.rs b/listings/ch17-async-await/listing-17-39/src/main.rs new file mode 100644 index 0000000000..317677eba1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-39/src/main.rs @@ -0,0 +1,15 @@ +// ANCHOR: all +use trpl::StreamExt; + +fn main() { + trpl::block_on(async { + let values = 1..101; + let iter = values.map(|n| n * 2); + let mut stream = trpl::stream_from_iter(iter); + + while let Some(value) = stream.next().await { + println!("The value was: {value}"); + } + }); +} +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-40/Cargo.lock b/listings/ch17-async-await/listing-17-40/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-40/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-40/Cargo.toml b/listings/ch17-async-await/listing-17-40/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-40/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-40/src/main.rs b/listings/ch17-async-await/listing-17-40/src/main.rs new file mode 100644 index 0000000000..8c98a66dfe --- /dev/null +++ b/listings/ch17-async-await/listing-17-40/src/main.rs @@ -0,0 +1,19 @@ +use trpl::StreamExt; + +fn main() { + trpl::block_on(async { + let values = 1..101; + let iter = values.map(|n| n * 2); + let stream = trpl::stream_from_iter(iter); + + // ANCHOR: filter + let mut filtered = + stream.filter(|value| value % 3 == 0 || value % 5 == 0); + + while let Some(value) = filtered.next().await { + println!("The value was: {value}"); + } + // ANCHOR_END: filter + }); +} +// ANCHOR_END: all diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index a56ed79ae0..ace132f8f5 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -118,11 +118,99 @@ convenience of a `for` loop. In fact, it will look a lot like the way we used `rx.recv` back in the [“Message Passing”][17-02-messages] section, using `while let` loops. +Let’s start with a very simple example: using an iterator *as* a stream. Let’s +start by creating a range of numbers, including every integer from 1 to 100, +using the `..` range operator. Then we can double all of those values with the +`map` method, as Listing 17-36 shows: + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-36/src/main.rs:range}} +``` + + + +We can convert this iterator to a stream using the `trpl::stream_from_iter` +function. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:stream}} +``` + + + +This gives us the stream. Now, to work with it, we want to use the `next` method +with a `while let` loop as described above, as in Listing 17-38: + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-38/src/main.rs:next}} +``` + + + +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. + +```console +{{#include ../listings/ch17-async-await/listing-17-38/output.txt}} +``` + +As the output suggests, the problem is that we need the right trait in scope to +be able to use it. In this case, that trait is `StreamExt`. (The `Ext` there is +for “extension”: this is a common pattern in the Rust community for extending +one trait with another.) `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. All we +need to do, then, is add a `use` statement for `trpl::StreamExt`, as in Listing +17-39. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-39/src/main.rs:all}} +``` + + + + With all those pieces put together, things work the way we want! There is a lot + of output, though, since we told it to print all of the 100 numbers in the + iterator. We can filter that down, to, say, multiples of three and five by using + the `filter` method, which conveniently also comes from `StreamExt`. + + + + ```rust,ignore,does_not_compile + {{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:filter}} + ``` + + + +Of course, in the real world, the only time we would be directly converting an +iterator to a stream like this is to help break up longer chunks of work, like +we discussed in the previous section. There are more interesting things we can +do with streams, though! + +For one thing, lots of things are naturally represented as streams—items +becoming available in a queue over time, for example, 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. For another +thing, since streams are futures, we can use them with any other kind of +future, and we can combine them in interesting ways. + +This is the kind of thing we might actually do to help break up longer chunks of +work, like we discussed in the previous section—though of course, presumably +with more interesting iterators than this one! + [17-02-messages]: /ch17-02-concurrency-with-async.md#message-passing From b4f5763368f441fb9c6f1c838c1db7cb67b68311 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 24 Jun 2024 14:00:08 -0600 Subject: [PATCH 121/249] =?UTF-8?q?Ch.=2017:=20final=20example=20for=20?= =?UTF-8?q?=C2=A705,=20with=20more=20re-exported=20streams?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use `IntervalStream` and `ReceiverStream` to show the composition of multiple streams, along with throttling and timeouts. This will also provide a useful foundation for discussing the relationships between futures, tasks, and threads in the final sections of the book, since you can accomplish the same basic API by simply substituting threads for tasks—but with different tradeoffs! --- .../listing-17-s05-final/Cargo.lock | 292 ++++++++++++++++++ .../listing-17-s05-final/Cargo.toml | 8 + .../listing-17-s05-final/src/main.rs | 80 +++++ packages/trpl/src/lib.rs | 8 +- packages/trpl/tests/integration/main.rs | 33 ++ src/ch17-06-futures-tasks-threads.md | 86 ++++++ 6 files changed, 505 insertions(+), 2 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-s05-final/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-s05-final/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-s05-final/src/main.rs diff --git a/listings/ch17-async-await/listing-17-s05-final/Cargo.lock b/listings/ch17-async-await/listing-17-s05-final/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-s05-final/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-s05-final/Cargo.toml b/listings/ch17-async-await/listing-17-s05-final/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-s05-final/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-s05-final/src/main.rs b/listings/ch17-async-await/listing-17-s05-final/src/main.rs new file mode 100644 index 0000000000..e8ee79e4a4 --- /dev/null +++ b/listings/ch17-async-await/listing-17-s05-final/src/main.rs @@ -0,0 +1,80 @@ +use std::{pin::pin, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(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 mut merged = pin!(messages.merge(intervals).take(20)); + + while let Some(result) = merged.next().await { + match result { + Ok(item) => println!("{item}"), + Err(reason) => eprintln!("Problem: {reason:?}"), + } + } + }) +} + +// ANCHOR: errors +fn get_messages() -> impl Stream { + // --snip-- + + // ANCHOR_END: errors + 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; + + // ANCHOR: errors + if let Err(send_error) = + tx.send(format!("Message: '{message}' after {time_to_sleep}ms")) + { + eprintln!("Cannot send message '{message}': {send_error}"); + break; + } + // ANCHOR_END: errors + } + }); + + ReceiverStream::new(rx) + // ANCHOR: errors + + // --snip-- +} + +fn get_intervals() -> impl Stream { + // --snip-- + + // ANCHOR_END: errors + let (tx, rx) = trpl::channel(); + + trpl::spawn_task(async move { + let mut count = 0; + loop { + trpl::sleep(Duration::from_millis(1)).await; + count += 1; + // ANCHOR: errors + if let Err(send_error) = tx.send(count) { + eprintln!("Could not send interval {count}: {send_error}"); + break; + }; + // ANCHOR_END: errors + } + }); + + ReceiverStream::new(rx) + // ANCHOR: errors + + // --snip-- +} +// ANCHOR_END: errors diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index b572b0a17b..4ffdbc365b 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -38,10 +38,14 @@ pub use tokio::{ UnboundedSender as Sender, }, task::{spawn as spawn_task, yield_now}, - time::sleep, + time::{interval, sleep}, }; -pub use tokio_stream::{iter as stream_from_iter, Stream, StreamExt}; +pub use tokio_stream::{ + iter as stream_from_iter, + wrappers::{IntervalStream, UnboundedReceiverStream as ReceiverStream}, + Stream, StreamExt, +}; /// Run a single future to completion on a bespoke Tokio `Runtime`. /// diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index e067732500..a46533534a 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -219,3 +219,36 @@ fn stream_iter() { vec![String::from("1"), String::from("2"), String::from("3")] ) } + +#[test] +fn receiver_stream() { + use trpl::ReceiverStream; + use trpl::StreamExt; + + let result: Vec = trpl::block_on(async { + println!("startup"); + let (tx, rx) = trpl::channel(); + let rx_stream = ReceiverStream::new(rx); + println!("sending 123"); + tx.send(123).unwrap(); + drop(tx); // So the receiver channel closes! + + rx_stream.collect().await + }); + + assert_eq!(result, vec![123]); +} + +#[test] +fn re_exported_interval_stream_works() { + use trpl::{IntervalStream, StreamExt}; + + trpl::block_on(async { + let mut interval_stream = + IntervalStream::new(trpl::interval(Duration::from_millis(1))) + .take(1); + + assert!(interval_stream.next().await.is_some()); + assert!(interval_stream.next().await.is_none()); + }); +} diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 53b122978f..70baf0ce67 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -1 +1,87 @@ # Futures, Tasks, and Threads + +Working code from end of previous section: + +```rust +use std::{pin::pin, time::Duration}; + +use trpl::{interval, IntervalStream, ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + let messages = pin!(get_messages()); + + let deciseconds = + pin!(IntervalStream::new(interval(Duration::from_millis(1))) + .throttle(Duration::from_millis(100)) + .map(|interval| { + let duration = interval.elapsed(); + format!("milliseconds elapsed: {}", duration.as_millis()) + })); + + let mut merged = messages.merge(deciseconds).take(10); + while let Some(alternative) = merged.next().await { + println!("Got: {alternative:?}"); + } + }) +} + +fn get_messages() -> impl Stream { + let (tx, rx) = trpl::channel(); + + trpl::spawn_task(async move { + for message in [String::from("Hello"), String::from("Goodbye")] { + tx.send(message).unwrap(); + trpl::sleep(Duration::from_millis(500)).await; + } + }); + + ReceiverStream::new(rx) +} +``` + +We can also do this using `std::thread`: + +```rust +use std::{pin::pin, thread, time::Duration}; + +use trpl::{interval, IntervalStream, ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + let messages = pin!(get_messages()); + + let deciseconds = + pin!(IntervalStream::new(interval(Duration::from_millis(1))) + .throttle(Duration::from_millis(100)) + .map(|interval| { + let duration = interval.elapsed(); + format!("milliseconds elapsed: {}", duration.as_millis()) + })); + + let mut merged = messages.merge(deciseconds).take(10); + while let Some(alternative) = merged.next().await { + println!("Got: {alternative:?}"); + } + }) +} + +fn get_messages() -> impl Stream { + let (tx, rx) = trpl::channel(); + + // ANCHOR: thread + thread::spawn(move || { + for message in [String::from("Hello"), String::from("Goodbye")] { + tx.send(message).unwrap(); + thread::sleep(Duration::from_millis(500)); + } + }); + // ANCHOR_END: thread + + ReceiverStream::new(rx) +} +``` + +Notice that very little changes here from the perspective of the calling code! +That is as we might expect, given that async tasks are kind of like lightweight, +runtime-managed threads. From e71b6678065602c91a582747f46e9b4784fd65ee Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 20 Jun 2024 13:45:50 -0600 Subject: [PATCH 122/249] =?UTF-8?q?Ch.=2017=20=C2=A705:=20First=20part=20o?= =?UTF-8?q?f=20final=20example,=20with=20`ReceiverStream`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch17-async-await/listing-17-41/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-41/Cargo.toml | 8 + .../listing-17-41/src/main.rs | 17 + .../ch17-async-await/listing-17-42/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-42/Cargo.toml | 8 + .../listing-17-42/src/main.rs | 24 ++ .../ch17-async-await/listing-17-43/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-43/Cargo.toml | 8 + .../listing-17-43/src/main.rs | 32 ++ .../ch17-async-await/listing-17-44/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-44/Cargo.toml | 8 + .../listing-17-44/src/main.rs | 33 ++ .../ch17-async-await/listing-17-45/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-45/Cargo.toml | 8 + .../listing-17-45/src/main.rs | 35 +++ src/ch17-05-streams.md | 179 ++++++++++- 16 files changed, 1810 insertions(+), 10 deletions(-) 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 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 create mode 100644 listings/ch17-async-await/listing-17-43/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-43/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-43/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-44/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-44/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-44/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-45/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-45/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-45/src/main.rs 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..4ca575988a --- /dev/null +++ b/listings/ch17-async-await/listing-17-41/src/main.rs @@ -0,0 +1,17 @@ +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + let mut messages = get_messages(); + + while let Some(message) = messages.next().await { + println!("{message}"); + } + }) +} + +fn get_messages() -> impl Stream { + let (tx, rx) = trpl::channel(); + + ReceiverStream::new(rx) +} 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..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-42/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-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..d503a4c77d --- /dev/null +++ b/listings/ch17-async-await/listing-17-42/src/main.rs @@ -0,0 +1,24 @@ +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + let mut messages = get_messages(); + + while let Some(message) = messages.next().await { + println!("{message}"); + } + }) +} + +fn get_messages() -> impl Stream { + let (tx, rx) = trpl::channel(); + + // ANCHOR: send + let messages = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; + for message in messages { + tx.send(format!("Message: '{message}'")).unwrap(); + } + // ANCHOR_END: send + + ReceiverStream::new(rx) +} diff --git a/listings/ch17-async-await/listing-17-43/Cargo.lock b/listings/ch17-async-await/listing-17-43/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-43/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-43/Cargo.toml b/listings/ch17-async-await/listing-17-43/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-43/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-43/src/main.rs b/listings/ch17-async-await/listing-17-43/src/main.rs new file mode 100644 index 0000000000..2ec150b9ac --- /dev/null +++ b/listings/ch17-async-await/listing-17-43/src/main.rs @@ -0,0 +1,32 @@ +// ANCHOR: timeout +use std::time::Duration; +// --snip-- +// ANCHOR_END: timeout +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + // ANCHOR: timeout + + let mut messages = get_messages().timeout(Duration::from_millis(200)); + + while let Some(result) = messages.next().await { + match result { + Ok(message) => println!("{message}"), + Err(reason) => eprintln!("Problem: {reason:?}"), + } + } + // ANCHOR_END: timeout + }) +} + +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) +} diff --git a/listings/ch17-async-await/listing-17-44/Cargo.lock b/listings/ch17-async-await/listing-17-44/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-44/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-44/Cargo.toml b/listings/ch17-async-await/listing-17-44/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-44/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-44/src/main.rs b/listings/ch17-async-await/listing-17-44/src/main.rs new file mode 100644 index 0000000000..986d0419e9 --- /dev/null +++ b/listings/ch17-async-await/listing-17-44/src/main.rs @@ -0,0 +1,33 @@ +// ANCHOR: pin +use std::{pin::pin, time::Duration}; +// --snip-- + +// ANCHOR_END: pin +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + // ANCHOR: pin + let mut messages = + pin!(get_messages().timeout(Duration::from_millis(200))); + // ANCHOR_END: pin + + while let Some(result) = messages.next().await { + match result { + Ok(message) => println!("{message}"), + Err(reason) => eprintln!("Problem: {reason:?}"), + } + } + }) +} + +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) +} diff --git a/listings/ch17-async-await/listing-17-45/Cargo.lock b/listings/ch17-async-await/listing-17-45/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-45/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-45/Cargo.toml b/listings/ch17-async-await/listing-17-45/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-45/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-45/src/main.rs b/listings/ch17-async-await/listing-17-45/src/main.rs new file mode 100644 index 0000000000..f044684113 --- /dev/null +++ b/listings/ch17-async-await/listing-17-45/src/main.rs @@ -0,0 +1,35 @@ +use std::{pin::pin, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + let mut messages = + pin!(get_messages().timeout(Duration::from_millis(200))); + + while let Some(result) = messages.next().await { + match result { + Ok(message) => println!("{message}"), + Err(reason) => eprintln!("Problem: {reason:?}"), + } + } + }) +} + +fn get_messages() -> impl Stream { + let (tx, rx) = trpl::channel(); + + // ANCHOR: messages + 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(); + } + }); + // ANCHOR_END: messages + + ReceiverStream::new(rx) +} diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index ace132f8f5..7b1527a5e0 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -183,7 +183,7 @@ need to do, then, is add a `use` statement for `trpl::StreamExt`, as in Listing iterator. We can filter that down, to, say, multiples of three and five by using the `filter` method, which conveniently also comes from `StreamExt`. - + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:filter}} @@ -192,10 +192,12 @@ need to do, then, is add a `use` statement for `trpl::StreamExt`, as in Listing Of course, in the real world, the only time we would be directly converting an -iterator to a stream like this is to help break up longer chunks of work, like +iterator to a stream like this is to help break up longer chunks of work, like we discussed in the previous section. There are more interesting things we can do with streams, though! +### Composing Streams + For one thing, lots of things are naturally represented as streams—items becoming available in a queue over time, for example, or working with more data than can fit in a computer’s memory by only pulling chunks of it from the file @@ -203,14 +205,171 @@ system at a time, or data arriving over the network over time. For another thing, since streams are futures, we can use them with any other kind of future, and we can combine them in interesting ways. -This is the kind of thing we might actually do to help break up longer chunks of -work, like we discussed in the previous section—though of course, presumably -with more interesting iterators than this one! +In the real world, we can use this to do things like 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. This is similar to what we +might see from a WebSocket or some other real-time communication protocol. To +begin, we will create a function, `get_messages()`, which returns `impl +Stream`, and use a `while let` loop to print all the messages +from the stream. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-41/src/main.rs}} +``` + + + +In Listing 17-41, we also use a new type: `ReceiverStream`. This converts the +`rx` receiver from the `trpl::channel` into a stream. This is pretty easy, since +the API for a receiver like this already has the same basic shape as a `Stream`. + +So far this will compile just fine, but we are not sending any messages, so +nothing will happen when we run the program. We can change that by looping over +the first ten letters of the English alphabet, and sending those across the +channel. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-42/src/main.rs:send}} +``` + + + +When we run the code in Listing 17-42, we get exactly the results we would +expect: + + + +```text +Message: 'a' +Message: 'b' +Message: 'c' +Message: 'd' +Message: 'e' +Message: 'f' +Message: 'g' +Message: 'h' +Message: 'i' +Message: 'j' +``` + +Thus far, we have not seen anything we could not do with the regular `recv` API. +Since this is a stream, though, we can do things like add a timeout which +applies to every item in the stream, as in Listing 17-43. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-43/src/main.rs:timeout}} +``` + + + +First, we add a timeout to the stream itself, using the the `timeout` method, +which is available on the stream because we already have `StreamExt` in scope. +Second, we update the the `while let` loop because the stream now returns a +`Result`, where the `Ok` variant indicates a message arrived in time and the +`Err` variant indicates that the timeout elapsed before any message arrived. We +can use a `match` to either print the message when we receive it successfully, +or to notify about a problem if the timeout happened. + +Unfortunately, this does not compile. It is our old friend `Unpin` again! Both +the `next()` method and the `await` tell us that that type `PhantomPin` cannot +be unpinned. (This `PhantomPin` is just a special type that the runtime is using +to keep track of what needs to be pinned in a way that *only* shows up at +compile time, but has no cost when actually running the program.) The solution +is exactly the same as what we saw earlier in the chapter: to pin the `messages` +with the `pin` macro. Once we add that, as in Listing 17-44, the program +compiles again. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-44/src/main.rs:pin}} +``` + + + +However, since there are no delays between messages, this timeout does not +change the behavior of the program yet. To see the timeout actually have an +effect, we will add a delay to the messages we send. We will use the `enumerate` +iterator method to get the index of the items we are sending, and apply a 100 +millisecond delay to even-index items 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. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-45/src/main.rs:messages}} +``` + + + +To do that without blocking the `get_messages` function, we need to use async. +However, we cannot just turn `get_messages` itself into an async function, +because then we would return a `Future>` instead +of just a `Stream>`. In practical terms, we would end up sending +all the messages and sleeping repeatedly before finally returning the receiver +stream. The caller would end up getting all the messages immediately, *without* +the sleep in between them, because the caller would not even be able to *start* +processing the stream until all of the await points in `get_messages` had been +hit. + +Instead, we leave `get_messages` as a regular function which returns a stream, +and spawn a task to handle the async `sleep` calls. + +> Note: calling `spawn_task` like this works because we already set up our +> runtime. Calling this particular implementation of `spawn_task` *without* +> first setting up a runtime will cause a panic. Other implementations choose +> different tradeoffs: they might spawn a new runtime and so avoid the panic but +> end up with a bit of extra overhead, or simply not provide a standalone way to +> spawn tasks without reference to a runtime. You should make sure you know what +> tradeoff your runtime has chosen and write your code accordingly! + +Now our code has a much more interesting result! Between the messages, we see an +error reported: `Problem: Elapsed(())`. Notice that it does not prevent the +messages from arriving in the end—we still get all of the original messages. +This is because our channel is unbounded: it can hold as many messages as we can +fit in memory. If the message does not arrive before the timeout, our stream +handler will account for that, but when it polls the stream again, the message +may now have arrived. + + + +```text +Message: 'a' +Problem: Elapsed(()) +Message: 'b' +Message: 'c' +Problem: Elapsed(()) +Message: 'd' +Message: 'e' +Problem: Elapsed(()) +Message: 'f' +Message: 'g' +Problem: Elapsed(()) +Message: 'h' +Message: 'i' +Problem: Elapsed(()) +Message: 'j' +``` + +You can get different behavior if needed by using other kinds of channels, or +other kinds of streams more generally. Let’s see one of those in practice in our +final example for this section, by combining a stream of time intervals with +this stream of messages. + +### Merging Streams + - [17-02-messages]: /ch17-02-concurrency-with-async.md#message-passing From 3c6c32cbe30ced543e08012dcf5aacfe2993018b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 25 Jun 2024 10:58:54 -0600 Subject: [PATCH 123/249] =?UTF-8?q?Ch.=2017=20=C2=A705:=20complete=20examp?= =?UTF-8?q?le=20with=20`throttle`=20and=20`take`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../listing-17-46/src/main.rs | 50 +++ .../ch17-async-await/listing-17-47/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-47/Cargo.toml | 8 + .../listing-17-47/src/main.rs | 52 ++++ .../ch17-async-await/listing-17-48/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-48/Cargo.toml | 8 + .../listing-17-48/src/main.rs | 54 ++++ .../ch17-async-await/listing-17-49/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-49/Cargo.toml | 8 + .../listing-17-49/src/main.rs | 55 ++++ .../ch17-async-await/listing-17-50/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-50/Cargo.toml | 8 + .../src/main.rs | 0 src/ch17-05-streams.md | 139 +++++++++ 16 files changed, 1550 insertions(+) rename listings/ch17-async-await/{listing-17-s05-final => listing-17-46}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-s05-final => listing-17-46}/Cargo.toml (100%) create mode 100644 listings/ch17-async-await/listing-17-46/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-47/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-47/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-47/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-48/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-48/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-48/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-49/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-49/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-49/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-50/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-50/Cargo.toml rename listings/ch17-async-await/{listing-17-s05-final => listing-17-50}/src/main.rs (100%) diff --git a/listings/ch17-async-await/listing-17-s05-final/Cargo.lock b/listings/ch17-async-await/listing-17-46/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-s05-final/Cargo.lock rename to listings/ch17-async-await/listing-17-46/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-s05-final/Cargo.toml b/listings/ch17-async-await/listing-17-46/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-s05-final/Cargo.toml rename to listings/ch17-async-await/listing-17-46/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-46/src/main.rs b/listings/ch17-async-await/listing-17-46/src/main.rs new file mode 100644 index 0000000000..5dbcb1d96e --- /dev/null +++ b/listings/ch17-async-await/listing-17-46/src/main.rs @@ -0,0 +1,50 @@ +use std::{pin::pin, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + let mut messages = + pin!(get_messages().timeout(Duration::from_millis(200))); + + while let Some(result) = messages.next().await { + match result { + Ok(message) => println!("{message}"), + 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; + + tx.send(format!("Message: '{message}'")).unwrap(); + } + }); + + 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 diff --git a/listings/ch17-async-await/listing-17-47/Cargo.lock b/listings/ch17-async-await/listing-17-47/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-47/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-47/Cargo.toml b/listings/ch17-async-await/listing-17-47/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-47/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-47/src/main.rs b/listings/ch17-async-await/listing-17-47/src/main.rs new file mode 100644 index 0000000000..62a93fc0f6 --- /dev/null +++ b/listings/ch17-async-await/listing-17-47/src/main.rs @@ -0,0 +1,52 @@ +use std::{pin::pin, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + // ANCHOR: main + let messages = get_messages().timeout(Duration::from_millis(200)); + let intervals = get_intervals(); + + let merged = messages.merge(intervals); + // ANCHOR_END: main + + while let Some(result) = merged.next().await { + match result { + Ok(message) => println!("{message}"), + 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; + + tx.send(format!("Message: '{message}'")).unwrap(); + } + }); + + ReceiverStream::new(rx) +} + +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) +} diff --git a/listings/ch17-async-await/listing-17-48/Cargo.lock b/listings/ch17-async-await/listing-17-48/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-48/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-48/Cargo.toml b/listings/ch17-async-await/listing-17-48/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-48/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-48/src/main.rs b/listings/ch17-async-await/listing-17-48/src/main.rs new file mode 100644 index 0000000000..30d0928ea9 --- /dev/null +++ b/listings/ch17-async-await/listing-17-48/src/main.rs @@ -0,0 +1,54 @@ +use std::{pin::pin, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(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 mut merged = pin!(messages.merge(intervals)); + // ANCHOR_END: main + + while let Some(result) = merged.next().await { + match result { + Ok(message) => println!("{message}"), + 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; + + tx.send(format!("Message: '{message}'")).unwrap(); + } + }); + + ReceiverStream::new(rx) +} + +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) +} diff --git a/listings/ch17-async-await/listing-17-49/Cargo.lock b/listings/ch17-async-await/listing-17-49/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-49/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-49/Cargo.toml b/listings/ch17-async-await/listing-17-49/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-49/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-49/src/main.rs b/listings/ch17-async-await/listing-17-49/src/main.rs new file mode 100644 index 0000000000..48e4ceea43 --- /dev/null +++ b/listings/ch17-async-await/listing-17-49/src/main.rs @@ -0,0 +1,55 @@ +use std::{pin::pin, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(async { + let messages = get_messages().timeout(Duration::from_millis(200)); + // ANCHOR: throttle + let intervals = get_intervals() + .map(|count| format!("Interval #{count}")) + .throttle(Duration::from_millis(100)) + .timeout(Duration::from_secs(10)); + + let mut merged = pin!(messages.merge(intervals).take(20)); + // ANCHOR_END: throttle + + while let Some(result) = merged.next().await { + match result { + Ok(message) => println!("{message}"), + 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; + + tx.send(format!("Message: '{message}'")).unwrap(); + } + }); + + ReceiverStream::new(rx) +} + +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) +} diff --git a/listings/ch17-async-await/listing-17-50/Cargo.lock b/listings/ch17-async-await/listing-17-50/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-50/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-50/Cargo.toml b/listings/ch17-async-await/listing-17-50/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-50/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-s05-final/src/main.rs b/listings/ch17-async-await/listing-17-50/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-s05-final/src/main.rs rename to listings/ch17-async-await/listing-17-50/src/main.rs diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index 7b1527a5e0..d52334ce02 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -370,6 +370,145 @@ 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 that delay, and combine it with the same +approach of creating a stream from a channel that we used for `get_messages`. +(There are, of course, many other ways to build streams, including some +dedicated to working with intervals!) The difference is that this time, we are +going to send back the count of intervals, rather than a string, so the +resulting stream will have the type `Stream`. + +In Listing 17-46, 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 +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. + + +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-46/src/main.rs:intervals}} +``` + + + +This kind of infinite loop, which only ends when the whole runtime gets torn +down, is a fairly common pattern when dealing with many different kinds of async +operations in Rust. That is because there are many kinds of programs which need +to keep running until something actually ends the program. + +Now we need to use these intervals! Back in our main function’s async block, we +start by getting the intervals. Then we can try to create a merged stream using +`messages` and `intervals`, and loop over that combined stream instead of over +`messages` (Listing 17-47). 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 let` loop, but we will come back to that +after fixing this first.) + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-47/src/main.rs:main}} +``` + + + +The problem is that our two streams have different types. The `messages` stream +has the type `Timeout>`. The `Timeout` is the type +which implements `Stream` for a `timeout` call! Meanwhile, the `intervals` stream has +the type `impl Stream`. To merge these two streams, we need to transform one of +them to match the other. Let’s work with the `intervals`, since `messages` is +already in the basic format we want and has to handle timeout errors. + +Listing 17-48 shows the transformations we need. 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 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. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-48/src/main.rs:main}} +``` + + + +That gets us *almost* to where we need to be. Everything type checks! If you run +this, though, the messages from the English alphabet will be buried in the midst +of all the interval counter messages: + + + +```text +--snip-- +Interval #38 +Interval #39 +Interval #40 +Message: 'a' +Interval #41 +Interval #42 +Interval #43 +--snip-- +``` + +This is no good; we need to only take *some* of those intervals—say, once every +hundred milliseconds. For that, we can use the `throttle` method. 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. We also don’t want to keep going +indefinitely! We can use the `take` method to limit how many items we pull from +a stream. In Listing 17-49, we apply `throttle` to the `intervals` stream, +because we want to avoid overwhelming the stream of messages, but we apply the +`take` method to the *merged* messages, because we want to limit the final +output, not just one stream or the other. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-49/src/main.rs:throttle}} +``` + + + +There is one last thing we need to handle: errors! With both of these +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-50 shows +a simple error strategy: print the issue and then `break` from the loops. As +usual, the correct behavior on a message send error will vary—just make sure you +do in fact have a strategy. + ++ +```rust +{{#rustdoc_include ../listings/ch17-async-await/listing-17-50/src/main.rs:errors}} +``` + + + +Notice that we do not get `Interval #100` or `Interval #200` or so on, but +instead simply get `Interval #1`, `Interval #2`, and so on—even though we have a +source stream which *can* produce an event every millisecond. That is because +the `throttle` call produces a new stream, wrapping the original stream, so that +the original stream only gets polled at the throttle rate, not its own “native” +rate. We do not have a bunch of unhandled interval messages we are simply +choosing to ignore. Instead, we never produce those interval messages in the +first place! This is the inherent “laziness” of Rust’s futures at work again, +allowing us to choose our performance characteristics. + +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 From bea85577081fefda53271593a793e59cd224f96a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 25 Jun 2024 15:10:22 -0600 Subject: [PATCH 124/249] =?UTF-8?q?Ch.=2017=20=C2=A706:=20Start=20discussi?= =?UTF-8?q?ng=20future/task/thread=20tradeoffs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reintroduce accidentally-dropped content. I meant to simply carry this over in 74df84ea, but failed to, perhaps because I had `mdbook serve` running and it tries to be helpful about generating files which are referenced in `SUMMARY.md` but do not exist on disk. Either way, this is back now and we can use it to explain these concepts. - Start on an example showing how `thread::spawn` and `spawn_task` are basically interchangeable from an API POV, so that we can then see how they differ in terms of runtime consequences. --- .../ch17-async-await/listing-17-51/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-51/Cargo.toml | 8 + .../listing-17-51/src/main.rs | 64 ++++ src/ch17-06-futures-tasks-threads.md | 155 +++++----- 4 files changed, 441 insertions(+), 78 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-51/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-51/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-51/src/main.rs diff --git a/listings/ch17-async-await/listing-17-51/Cargo.lock b/listings/ch17-async-await/listing-17-51/Cargo.lock new file mode 100644 index 0000000000..36905af42a --- /dev/null +++ b/listings/ch17-async-await/listing-17-51/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-51/Cargo.toml b/listings/ch17-async-await/listing-17-51/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/listing-17-51/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-51/src/main.rs b/listings/ch17-async-await/listing-17-51/src/main.rs new file mode 100644 index 0000000000..7298362527 --- /dev/null +++ b/listings/ch17-async-await/listing-17-51/src/main.rs @@ -0,0 +1,64 @@ +use std::{pin::pin, thread, time::Duration}; + +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::block_on(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 mut merged = pin!(messages.merge(intervals).take(20)); + + while let Some(result) = merged.next().await { + match result { + Ok(item) => println!("{item}"), + Err(reason) => eprintln!("Problem: {reason:?}"), + } + } + }) +} + +// ANCHOR: thread +fn get_messages() -> impl Stream { + let (tx, rx) = trpl::channel(); + + thread::spawn(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 }; + thread::sleep(Duration::from_millis(time_to_sleep)); + + if let Err(send_error) = + tx.send(format!("Message: '{message}' after {time_to_sleep}ms")) + { + eprintln!("Cannot send message '{message}': {send_error}"); + break; + } + } + }); + + ReceiverStream::new(rx) +} + +fn get_intervals() -> impl Stream { + let (tx, rx) = trpl::channel(); + + thread::spawn(move || { + let mut count = 0; + loop { + 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: thread diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 70baf0ce67..dbfbc2a461 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -1,87 +1,86 @@ # Futures, Tasks, and Threads -Working code from end of previous section: +As we saw in the previous chapter, threads provide one approach to concurrency, +and they let us solve some of these issues. However, they also have some +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! While mainstream desktop and mobile operating systems have all had +threading for many years, many embedded operating systems, like those used on +some microcontrollers, do not. + +The async model provides a different—and ultimately complementary—set of +tradeoffs. In the async model, concurrent operations do not require their own +threads. Instead, they can run on *tasks*. A task is a bit like a thread, but +instead of being managed by the operating system, it is managed by code that +lives at the level of libraries. + +In the previous section, we saw that we could build a `Stream` by using a +channel and spawning an async task which we could call from synchronous code. +We could do the exact same thing with a thread! We’ll use a simpler version of +the streams example so we can focus on the differences. Back in Listing 17-45, we used +`trpl::spawn_task` and `trpl::sleep`. In Listing 17-51, we replace those with +the `thread::spawn` and `thread::sleep` APIs from the standard library. + + + + ```rust -use std::{pin::pin, time::Duration}; - -use trpl::{interval, IntervalStream, ReceiverStream, Stream, StreamExt}; - -fn main() { - trpl::block_on(async { - let messages = pin!(get_messages()); - - let deciseconds = - pin!(IntervalStream::new(interval(Duration::from_millis(1))) - .throttle(Duration::from_millis(100)) - .map(|interval| { - let duration = interval.elapsed(); - format!("milliseconds elapsed: {}", duration.as_millis()) - })); - - let mut merged = messages.merge(deciseconds).take(10); - while let Some(alternative) = merged.next().await { - println!("Got: {alternative:?}"); - } - }) -} - -fn get_messages() -> impl Stream { - let (tx, rx) = trpl::channel(); - - trpl::spawn_task(async move { - for message in [String::from("Hello"), String::from("Goodbye")] { - tx.send(message).unwrap(); - trpl::sleep(Duration::from_millis(500)).await; - } - }); - - ReceiverStream::new(rx) -} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-51/src/main.rs:thread}} ``` -We can also do this using `std::thread`: - -```rust -use std::{pin::pin, thread, time::Duration}; - -use trpl::{interval, IntervalStream, ReceiverStream, Stream, StreamExt}; - -fn main() { - trpl::block_on(async { - let messages = pin!(get_messages()); - - let deciseconds = - pin!(IntervalStream::new(interval(Duration::from_millis(1))) - .throttle(Duration::from_millis(100)) - .map(|interval| { - let duration = interval.elapsed(); - format!("milliseconds elapsed: {}", duration.as_millis()) - })); - - let mut merged = messages.merge(deciseconds).take(10); - while let Some(alternative) = merged.next().await { - println!("Got: {alternative:?}"); - } - }) -} - -fn get_messages() -> impl Stream { - let (tx, rx) = trpl::channel(); - - // ANCHOR: thread - thread::spawn(move || { - for message in [String::from("Hello"), String::from("Goodbye")] { - tx.send(message).unwrap(); - thread::sleep(Duration::from_millis(500)); - } - }); - // ANCHOR_END: thread - - ReceiverStream::new(rx) -} -``` + Notice that very little changes here from the perspective of the calling code! That is as we might expect, given that async tasks are kind of like lightweight, -runtime-managed threads. +runtime-managed threads. However, there is a meaningful difference in the way +this system behaves, though we might have a hard time measuring it in this very +simple example. A run + +### Parallelism and Concurrency + + + +First, though, we need to dig a little deeper into the differences between +parallelism and concurrency. In the previous chapter we treated them as mostly +interchangeable. Now we need to distinguish between the two a little more, +because the differences will show up as we start working: + +* *Parallelism* is when operations can happen simultaneously. + +* *Concurrency* is when operations can make progress without having to wait for + all other operations to complete. + +One common analogy for thinking about the difference between concurrency and +parallelism is cooking in a kitchen. Parallelism is like having two cooks: one +working on cooking eggs, and the other working on preparing fruit bowls. Those +can happen at the same time, without either affecting the other. Concurrency is +like having a single cook who can start cooking some eggs, start dicing up some +vegetables to use in the omelette, adding seasoning and whatever vegetables are +ready to the eggs at certain points, and switching back and forth between those +tasks. + +(This analogy breaks down if you think about it too hard. The eggs keep cooking +while the cook is chopping up the vegetables, after all. That is parallelism, +not just concurrency! The focus of the analogy is the *cook*, not the food, +though, and as long as you keep that in mind, it mostly works.) + +On a machine with multiple CPU cores, we can actually do work in parallel. One +core can be doing one thing while another core does something completely +unrelated, and those actually happen at the same time. On a machine with a +single CPU core, the CPU can only do one operation at a time, but we can still +have concurrency. Using tools like threads, processes, and async, the computer +can pause one activity and switch to others before eventually cycling back to +that first activity again. So all parallel operations are also concurrent, but +not all concurrent operations happen in parallel! + +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, that concurrency may use some degree of parallelism under the hood, or it +may not. (More about async runtimes later!) + +A big difference between the cooking analogy and Rust’s async model for +concurrency is that in the cooking example, the cook makes the decision about +when to switch tasks. In Rust’s async model, the tasks are in control of that. +To see how, let’s look at how Rust actually uses async. From bdd8f3e62fa767a7324d53e783be9097f84642fe Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 26 Jun 2024 11:54:31 -0600 Subject: [PATCH 125/249] =?UTF-8?q?Ch.=2017=20=C2=A706:=20more=20on=20task?= =?UTF-8?q?s=20and=20threads,=20better=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-51/src/main.rs | 14 ++-- src/ch17-06-futures-tasks-threads.md | 70 +++++++++++++------ 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/listings/ch17-async-await/listing-17-51/src/main.rs b/listings/ch17-async-await/listing-17-51/src/main.rs index 7298362527..4b44ab723e 100644 --- a/listings/ch17-async-await/listing-17-51/src/main.rs +++ b/listings/ch17-async-await/listing-17-51/src/main.rs @@ -1,4 +1,4 @@ -use std::{pin::pin, thread, time::Duration}; +use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; @@ -21,16 +21,15 @@ fn main() { }) } -// ANCHOR: thread fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); - thread::spawn(move || { + 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 }; - thread::sleep(Duration::from_millis(time_to_sleep)); + trpl::sleep(Duration::from_millis(time_to_sleep)).await; if let Err(send_error) = tx.send(format!("Message: '{message}' after {time_to_sleep}ms")) @@ -44,13 +43,14 @@ fn get_messages() -> impl Stream { ReceiverStream::new(rx) } +// ANCHOR: threads fn get_intervals() -> impl Stream { let (tx, rx) = trpl::channel(); - thread::spawn(move || { + trpl::spawn_task(async move { let mut count = 0; loop { - thread::sleep(Duration::from_millis(1)); + 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}"); @@ -61,4 +61,4 @@ fn get_intervals() -> impl Stream { ReceiverStream::new(rx) } -// ANCHOR_END: thread +// ANCHOR_END: threads diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index dbfbc2a461..dd8eab2173 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -1,42 +1,66 @@ # Futures, Tasks, and Threads -As we saw in the previous chapter, threads provide one approach to concurrency, -and they let us solve some of these issues. However, they also have some -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! While mainstream desktop and mobile operating systems have all had -threading for many years, many embedded operating systems, like those used on -some microcontrollers, do not. +As we saw in the previous chapter, threads provide one approach to concurrency. +We have seen another approach to concurrency in this chapter, using async with +futures and streams. You might be wondering why you would choose one or the +other. The answer is: it depends! And in many cases, it is not threads *vs.* +async but rather threads *and* async. + +Threads are an older and more common tool for concurrency. Many operating +systems have supplied threading-based concurrency models for decades now, and +many programming languages have support for them as a result. 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. The async model provides a different—and ultimately complementary—set of tradeoffs. In the async model, concurrent operations do not require their own -threads. Instead, they can run on *tasks*. A task is a bit like a thread, but -instead of being managed by the operating system, it is managed by code that -lives at the level of libraries. +threads. Instead, they can run on tasks, as when we used `trpl::spawn_task` to +kick off work from a synchronous function throughout the streams section. A task +is a lot like a thread—but instead of being managed by the operating system, it +is managed by library-level code: the runtime. In the previous section, we saw that we could build a `Stream` by using a -channel and spawning an async task which we could call from synchronous code. -We could do the exact same thing with a thread! We’ll use a simpler version of -the streams example so we can focus on the differences. Back in Listing 17-45, we used +channel and spawning an async task which we could call from synchronous code. We +could do the exact same thing with a thread! We’ll use a simpler version of the +streams example so we can focus on the differences. In Listing 17-50, we used `trpl::spawn_task` and `trpl::sleep`. In Listing 17-51, we replace those with -the `thread::spawn` and `thread::sleep` APIs from the standard library. - - +the `thread::spawn` and `thread::sleep` APIs from the standard library, in just +the `get_intervals` function. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-51/src/main.rs:thread}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-51/src/main.rs:threads}} ``` -Notice that very little changes here from the perspective of the calling code! -That is as we might expect, given that async tasks are kind of like lightweight, -runtime-managed threads. However, there is a meaningful difference in the way -this system behaves, though we might have a hard time measuring it in this very -simple example. A run +If you run this, the output is identical. And notice how little changes here +from the perspective of the calling code! What is more, even though one of our +functions spawned an async task on the runtime and the other spawned an +operating system thread, they worked exactly the same way as far as processing +the stream was concerned. + +This highlights that async tasks are kind of like lightweight, runtime-managed +threads. However, there is a meaningful difference in the way this system +behaves, although we might have a hard time measuring it in this very simple +example. We could spawn hundreds of thousands or even millions of async tasks on +any modern personal computer. If we tried to do that with threads, we would +literally run out of memory! + +However, this does not mean that async tasks are always better than threads. In +fact, they often work very well *together*. 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. + + ### Parallelism and Concurrency From ffb2d1ba29bf66ffc9820e10d63aef16b25bb508 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 26 Jun 2024 12:22:48 -0600 Subject: [PATCH 126/249] =?UTF-8?q?Ch.=2017:=20Most=20of=20=C2=A706=20draf?= =?UTF-8?q?ted,=20needs=20a=20conclusion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added a discussion of the relationship between futures, tasks, and threads—I am not in love with it, but it is a starting point. - Moved the still-to-be-rewritten 'Parallelism and Concurrency' back to §01, where it can be rewritten after getting some feedback. --- src/ch17-00-async-await.md | 45 ++++++++++++ src/ch17-06-futures-tasks-threads.md | 100 +++++++++++---------------- 2 files changed, 87 insertions(+), 58 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 92928f87a4..c974eb32f9 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -153,3 +153,48 @@ println!("{data}"); That is exactly what Rust’s async abstraction gives us. It is designed to help us solve all of these issues. In the next section, we will see how this works in practice. + +### Parallelism and Concurrency + +First, though, we need to dig a little deeper into the differences between +parallelism and concurrency. In the previous chapter we treated them as mostly +interchangeable. Now we need to distinguish between the two a little more, +because the differences will show up as we start working: + +* *Parallelism* is when operations can happen simultaneously. + +* *Concurrency* is when operations can make progress without having to wait for + all other operations to complete. + +One common analogy for thinking about the difference between concurrency and +parallelism is cooking in a kitchen. Parallelism is like having two cooks: one +working on cooking eggs, and the other working on preparing fruit bowls. Those +can happen at the same time, without either affecting the other. Concurrency is +like having a single cook who can start cooking some eggs, start dicing up some +vegetables to use in the omelette, adding seasoning and whatever vegetables are +ready to the eggs at certain points, and switching back and forth between those +tasks. + +(This analogy breaks down if you think about it too hard. The eggs keep cooking +while the cook is chopping up the vegetables, after all. That is parallelism, +not just concurrency! The focus of the analogy is the *cook*, not the food, +though, and as long as you keep that in mind, it mostly works.) + +On a machine with multiple CPU cores, we can actually do work in parallel. One +core can be doing one thing while another core does something completely +unrelated, and those actually happen at the same time. On a machine with a +single CPU core, the CPU can only do one operation at a time, but we can still +have concurrency. Using tools like threads, processes, and async, the computer +can pause one activity and switch to others before eventually cycling back to +that first activity again. So all parallel operations are also concurrent, but +not all concurrent operations happen in parallel! + +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, that concurrency may use some degree of parallelism under the hood, or it +may not. (More about async runtimes later!) + +A big difference between the cooking analogy and Rust’s async model for +concurrency is that in the cooking example, the cook makes the decision about +when to switch tasks. In Rust’s async model, the tasks are in control of that. +To see how, let’s look at how async programming in Rust actually works. diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index dd8eab2173..74a032df99 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -45,66 +45,50 @@ functions spawned an async task on the runtime and the other spawned an operating system thread, they worked exactly the same way as far as processing the stream was concerned. -This highlights that async tasks are kind of like lightweight, runtime-managed -threads. However, there is a meaningful difference in the way this system +However, there is a meaningful difference in the way this system behaves, although we might have a hard time measuring it in this very simple example. We could spawn hundreds of thousands or even millions of async tasks on any modern personal computer. If we tried to do that with threads, we would literally run out of memory! -However, this does not mean that async tasks are always better than threads. In -fact, they often work very well *together*. 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. - - - -### Parallelism and Concurrency - - - -First, though, we need to dig a little deeper into the differences between -parallelism and concurrency. In the previous chapter we treated them as mostly -interchangeable. Now we need to distinguish between the two a little more, -because the differences will show up as we start working: - -* *Parallelism* is when operations can happen simultaneously. - -* *Concurrency* is when operations can make progress without having to wait for - all other operations to complete. - -One common analogy for thinking about the difference between concurrency and -parallelism is cooking in a kitchen. Parallelism is like having two cooks: one -working on cooking eggs, and the other working on preparing fruit bowls. Those -can happen at the same time, without either affecting the other. Concurrency is -like having a single cook who can start cooking some eggs, start dicing up some -vegetables to use in the omelette, adding seasoning and whatever vegetables are -ready to the eggs at certain points, and switching back and forth between those -tasks. - -(This analogy breaks down if you think about it too hard. The eggs keep cooking -while the cook is chopping up the vegetables, after all. That is parallelism, -not just concurrency! The focus of the analogy is the *cook*, not the food, -though, and as long as you keep that in mind, it mostly works.) - -On a machine with multiple CPU cores, we can actually do work in parallel. One -core can be doing one thing while another core does something completely -unrelated, and those actually happen at the same time. On a machine with a -single CPU core, the CPU can only do one operation at a time, but we can still -have concurrency. Using tools like threads, processes, and async, the computer -can pause one activity and switch to others before eventually cycling back to -that first activity again. So all parallel operations are also concurrent, but -not all concurrent operations happen in parallel! - -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, that concurrency may use some degree of parallelism under the hood, or it -may not. (More about async runtimes later!) - -A big difference between the cooking analogy and Rust’s async model for -concurrency is that in the cooking example, the cook makes the decision about -when to switch tasks. In Rust’s async model, the tasks are in control of that. -To see how, let’s look at how Rust actually uses async. +However, there is a reason these APIs are so similar. Threads act as a boundary +for sets of synchronous operations; concurrency is possible *between* threads. +Tasks act as a boundary for sets of *asynchronous* operations; concurrency is +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. + +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. + +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 [“Building Our Own Async Abstractions”][combining-futures], or the +`throttle` method we used with streams in [“Working With Streams”][streams]. The fact +that futures are richer data structures means they *can* be composed together +more naturally, as we have seen. + +Tasks then give *additional* control over futures, allowing you to choose where +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. + + + +[combining-futures]: /ch17-04-more-ways-of-combining-futures.md#building-our-own-async-abstractions +[streams]: /ch17-05-streams.md#working-with-streams From 63214c3fb2b9c67f8757446e4046be469f1f17e9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 26 Jun 2024 15:40:06 -0600 Subject: [PATCH 127/249] =?UTF-8?q?Ch.=2017=20=C2=A700:=20rewrite=20the=20?= =?UTF-8?q?parallelism=20and=20concurrency=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-00-async-await.md | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index c974eb32f9..182edf2ac1 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -166,19 +166,31 @@ because the differences will show up as we start working: * *Concurrency* is when operations can make progress without having to wait for all other operations to complete. -One common analogy for thinking about the difference between concurrency and -parallelism is cooking in a kitchen. Parallelism is like having two cooks: one -working on cooking eggs, and the other working on preparing fruit bowls. Those -can happen at the same time, without either affecting the other. Concurrency is -like having a single cook who can start cooking some eggs, start dicing up some -vegetables to use in the omelette, adding seasoning and whatever vegetables are -ready to the eggs at certain points, and switching back and forth between those -tasks. - -(This analogy breaks down if you think about it too hard. The eggs keep cooking -while the cook is chopping up the vegetables, after all. That is parallelism, -not just concurrency! The focus of the analogy is the *cook*, not the food, -though, and as long as you keep that in mind, it mostly works.) +One way to think about the difference between parallelism and concurrency is to +think about working on a software project as a team. When you agree to split up +a group of tasks between a group of people, with each person working on one task +and delivering them separately, this is *parallelism*. Each person on the team +can be making progress at the exact same time. + +On the other hand, 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 tasks at the exact same time. + +With both of these situations, you might have to coordinate between different +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, maybe with the two projects you were +switching between yourself, you realize that one of them needs the result from +the other, so 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, then +you might need to focus on that project and not give any time to the other one +until it is done, so your own work stops being concurrent. On a machine with multiple CPU cores, we can actually do work in parallel. One core can be doing one thing while another core does something completely From 6914bc41a4be98e01d1198729ba8b9d838c036f5 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 26 Jun 2024 16:35:45 -0600 Subject: [PATCH 128/249] =?UTF-8?q?Ch.=2017=20=C2=A700:=20no=20more=20cook?= =?UTF-8?q?s!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-00-async-await.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 182edf2ac1..17541b4d85 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -204,9 +204,4 @@ not all concurrent operations happen in parallel! 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, that concurrency may use some degree of parallelism under the hood, or it -may not. (More about async runtimes later!) - -A big difference between the cooking analogy and Rust’s async model for -concurrency is that in the cooking example, the cook makes the decision about -when to switch tasks. In Rust’s async model, the tasks are in control of that. -To see how, let’s look at how async programming in Rust actually works. +may not. Let’s dive into how async programming in Rust actually works! From e774613c8e4308013aa4860c0cb64d9b35089ea6 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 1 Jul 2024 12:30:18 -0600 Subject: [PATCH 129/249] Ch. 17: remove 'base' listing --- .../listing-17-base/Cargo.lock | 280 ------------------ .../listing-17-base/Cargo.toml | 8 - .../listing-17-base/src/main.rs | 5 - 3 files changed, 293 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-base/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-base/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-base/src/main.rs diff --git a/listings/ch17-async-await/listing-17-base/Cargo.lock b/listings/ch17-async-await/listing-17-base/Cargo.lock deleted file mode 100644 index 53a9a9dde6..0000000000 --- a/listings/ch17-async-await/listing-17-base/Cargo.lock +++ /dev/null @@ -1,280 +0,0 @@ -# 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 = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[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-base/Cargo.toml b/listings/ch17-async-await/listing-17-base/Cargo.toml deleted file mode 100644 index e094f067f1..0000000000 --- a/listings/ch17-async-await/listing-17-base/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[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-base/src/main.rs b/listings/ch17-async-await/listing-17-base/src/main.rs deleted file mode 100644 index 3c247f888f..0000000000 --- a/listings/ch17-async-await/listing-17-base/src/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - trpl::block_on(async { - // TODO: use this! - }) -} From f039ca3c7da6295501c2d10ab987658c67566086 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 27 Jun 2024 13:22:53 -0600 Subject: [PATCH 130/249] Ch. 17: Transition materials from Ch. 16 and into Ch. 18 - Rewrite the end of Ch. 16 to account for the fact that it no longer transitions to the OOP/etc. chapter. - Add a summary to the end of Ch. 17, pulling over a bunch of the text that was previously in the end of Ch. 16. - Rewrite the introduction to Ch. 17, for a more seamless shift from Ch. 16 and contextualizing async in the broader software ecosystem. --- ...16-04-extensible-concurrency-sync-and-send.md | 9 ++------- src/ch17-00-async-await.md | 14 +++++++++++--- src/ch17-06-futures-tasks-threads.md | 16 +++++++++++++++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/ch16-04-extensible-concurrency-sync-and-send.md b/src/ch16-04-extensible-concurrency-sync-and-send.md index 4586b8d2c4..1b74554341 100644 --- a/src/ch16-04-extensible-concurrency-sync-and-send.md +++ b/src/ch16-04-extensible-concurrency-sync-and-send.md @@ -62,10 +62,6 @@ uphold them. ## Summary -This isn’t the last you’ll see of concurrency in this book: the project in -Chapter 20 will use the concepts in this chapter in a more realistic situation -than the smaller examples discussed here. - As mentioned earlier, because very little of how Rust handles concurrency is part of the language, many concurrency solutions are implemented as crates. These evolve more quickly than the standard library, so be sure to search @@ -81,9 +77,8 @@ run on multiple threads without the kinds of hard-to-track-down bugs common in other languages. Concurrent programming is no longer a concept to be afraid of: go forth and make your programs concurrent, fearlessly! -Next, we’ll talk about idiomatic ways to model problems and structure solutions -as your Rust programs get bigger. In addition, we’ll discuss how Rust’s idioms -relate to those you might be familiar with from object-oriented programming. +This is just your first step into Rust’s concurrency story. In the next chapter, +we will explore a complementary approach, asynchronous programming. [sharing-a-mutext-between-multiple-threads]: ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 17541b4d85..049dddc384 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -1,8 +1,16 @@ ## Async and Await -In Chapter 16, we saw one of Rust’s approaches to concurrency: using threads. -Since Rust 1.39, there has been another option for concurrency: asynchronous -programming, or *async*. +The threading-based concurrency model is one of the oldest concurrency models in +computing, and it was present and well-supported in Rust since 1.0. In the past +few decades, though, many programming languages have been experimenting with +other approaches to concurrency, especially asynchronous programming, or +*async*. + +It took a few years to work out the right design for async in Rust. After a +bunch of experimentation and design work in the library ecosystem, Rust added +language-level support for async in Rust 1.39, in 2019, and there is a thriving +ecosystem of crates supporting all sorts of interesting capabilities offered by +those language primitives. In the rest of this chapter, we will: diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 74a032df99..a723a022e9 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -88,7 +88,21 @@ 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. - +## Summary + +This isn’t the last you’ll see of concurrency in this book: the project in +Chapter 21 will use the concepts in this chapter in a more realistic situation +than the smaller examples discussed here—and compare more directly what it looks +like to solve these kinds of problems with threading vs. with tasks and futures. + +Whether with threads or with futures and tasks, or combining them for greatest +performance, Rust gives you the tools you need to write safe, fast, concurrent +code—whether for a high-throughput web server or an embedded operating system. + +Next, we’ll talk about idiomatic ways to model problems and structure solutions +as your Rust programs get bigger. In addition, we’ll discuss how Rust’s idioms +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#working-with-streams From 5fdd92ceea95a1d2527593011045dd94cfd98993 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 1 Jul 2024 14:11:27 -0600 Subject: [PATCH 131/249] =?UTF-8?q?Ch.=2017=C2=A700=20initial=20edits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-00-async-await.md | 171 ++++++++++++++++++------------------- 1 file changed, 85 insertions(+), 86 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 049dddc384..bc1a301a6c 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -26,61 +26,60 @@ First, though, let’s explore what async gives us. Many operations we ask the computer to do can take a while to finish. For example, if you used a video editor to create a video of a family celebration, -exporting it could take anywhere from minutes to hours. Similarly, when you -download a video shared by someone in your family, that download process might -take a long time. It would be nice if we could do something else while we are -waiting for those long-running processes to complete. +exporting it could take anywhere from minutes to hours. Similarly, downloading a +video shared by someone in your family might take a long time. It would be nice +if we could do something else while we are waiting for those long-running +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, so instead your computer +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 -small amounts of work done along the way. - -The file download is different. It does not take up very much CPU time. Instead, -you are mostly waiting on data to transfer across the network. You can start -reading from a network socket, but it might take a while for all the data to -arrive and be fed into the socket by the network controller. Moreover, 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 socket. Even if “some time” here is just a second -or two, that is a very long time for a modern processor, which can do billions -of operations every second. You could choose to wait for all of that to finish, -but you might be waiting for a while… with your CPU doing not much! Thus, even -if your specific program cannot do anything until it finishes reading data from -a network socket, your computer will once again invisibly interrupt your -program so other things can happen at the same time as the network operation. +work done along the way. + +The file download is different. It does not take up very much CPU time. You are +mostly waiting on data to transfer across the network. You can start reading +from a network socket, but it might take a while for all the data to arrive and +be fed into the socket by the network controller. 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 socket. 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 happen while the network +operation is still ongoing. > Note: The video export is the kind of operation which is often described as -> “CPU-bound”. It is limited by the speed of the computer’s CPU (and GPU), and -> how much of that power it can use. The video download is the kind of operation +> “CPU-bound”. It is limited by the speed of the computer’s *CPU and GPU*, and +> how much of that speed it can use. The video download is the kind of operation > which is often described as “IO-bound,” because it is limited by the speed of > the computer’s *input and output*. It can only go as fast as the data can be > sent across the network, which means that it can only go as fast as the data > can be written to the socket by the network controller. -In both of these examples, the concurrency happens at the level of the whole -program. The operating system decides to interrupt the program to let other +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 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 lots of -opportunities for concurrency that the operating system cannot see. For example, -if we are building a tool to manage file downloads, it is important that the -user interface stay responsive while a download is happening. In fact, we should -even be able to start multiple downloads at the same time. - -However, many operating system APIs for interacting with network sockets are -*blocking*. That is, the function calls block further progress in the program -when they are called until they return. This is how *most* function calls work, -if you think about it! However, we normally reserve the term “blocking” for -function calls which interact with files, network sockets, or other resources on -the computer, because those are the places where an individual program would -benefit from the operation being *non*-blocking. - -When doing file downloads, we could use threads to work around the fact that the -call to write to a network socket is blocking. If we move the data over to a -dedicated thread which handles the write operation, it will *not* block the rest -of the program. But in many ways, it would be nicer if the call were not -blocking in the first place. +much more granular level than the operating system does, we can spot lots of +opportunities for concurrency that the operating system cannot see. + +For example, if we are building a tool to manage file downloads, we should be +able to write our program in such a way that starting one download does not lock +up the UI, and users should be able to start multiple downloads at the same +time. Many operating system APIs for interacting with network sockets are +*blocking*, though. That is, the function calls block further progress in the +program when they are called until they return. + +> Note: This is how *most* function calls work, if you think about it! However, +we normally reserve the term “blocking” for function calls which interact with +files, network sockets, or other resources on the computer, because those are +the places where an individual program would benefit from the operation being +*non*-blocking. + +We could use threads to avoid blocking while downloading files, by using a +dedicated thread. But it would be nicer if the call were not blocking in the +first place. One way to accomplish that would be to use an API built around callbacks. For each blocking operation, we could pass in a function to call once the operation @@ -110,11 +109,10 @@ network_socket.read_non_blocking().and_then(|result| { }); ``` -Each of these can make the control flow for the program more complicated, -though. You can end up with event handler callbacks scattered across the code -base, or groups of deeply nested callbacks, or long chains of `and_then` calls. -Understanding the flow of data through the program can become more difficult as -a result, and dealing with callbacks can also complicate ownership. +Each of these makes it harder to understand both the control flow and the flow +of data through the program. You can end up with event handler callbacks +scattered across the code base, or groups of deeply nested callbacks, or long +chains of `and_then` calls. There are also no particularly good ways to get data out of those callbacks. With other common types in Rust, we often use pattern-matching in scenarios like @@ -136,17 +134,18 @@ network_socket.read_non_blocking().and_then(|result| { println!("{data:?}"); ``` -The callback passed to `and_then` needs a mutable reference to `data`, but the -`load` function tries to return `data` to the caller. Rust would helpfully tell -us that we cannot borrow `data` immutably to print it because it is still -borrowed mutably for the `and_then` callback. This is not just Rust being fussy, -either: the result of this would normally always just print the `None` value and -exit, but if the read *happened* to go fast enough, it is possible it could -sometimes print some string data instead. That is *definitely* not what we -want! +In this very broken code, the callback passed to `and_then` needs a mutable +reference to `data`, but the `println` macro needs to borrow a reference to +`data` to be able to print it. Rust would helpfully tell us that we cannot +borrow `data` immutably to print it because it is still borrowed mutably for the +`and_then` callback. This is not just Rust being fussy, either: the result of +this would normally always just print the `None` value, but if the read +*happened* to go fast enough, it is possible it could sometimes print some +string data instead. That is *definitely* not what we want! We also could not cancel `read_non_blocking`: once it has started, it will run -till it finishes unless the whole program stops. +till it finishes unless the whole program stops. What we really want to be able to write is something much more direct, like we would write in blocking code, but with the benefits of getting the data when it @@ -159,57 +158,57 @@ println!("{data}"); ``` That is exactly what Rust’s async abstraction gives us. It is designed to help -us solve all of these issues. In the next section, we will see how this works in -practice. +us solve all of these issues. Before we will see how this works in practice, +though, we need to dig a little deeper into the differences between parallelism +and concurrency. ### Parallelism and Concurrency -First, though, we need to dig a little deeper into the differences between -parallelism and concurrency. In the previous chapter we treated them as mostly -interchangeable. Now we need to distinguish between the two a little more, -because the differences will show up as we start working: +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: * *Parallelism* is when operations can happen simultaneously. * *Concurrency* is when operations can make progress without having to wait for all other operations to complete. -One way to think about the difference between parallelism and concurrency is to -think about working on a software project as a team. When you agree to split up +Think about working on a software project as a team. When you agree to split up a group of tasks between a group of people, with each person working on one task and delivering them separately, this is *parallelism*. Each person on the team -can be making progress at the exact same time. - -On the other hand, 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 tasks at the exact same time. +can be making progress at the exact same time. On the other hand, 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 tasks at +the exact same time—but you can multi-task, making progress on multiple tasks by +switching between them. Work on one does not necessarily *block* working on the +other. With both of these situations, you might have to coordinate between different 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 +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, maybe with the two projects you were -switching between yourself, you realize that one of them needs the result from -the other, so now your concurrent work has also become *serial*. +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. 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, then -you might need to focus on that project and not give any time to the other one +you might need to focus on that project and not give any time to your other task until it is done, so your own work stops being concurrent. -On a machine with multiple CPU cores, we can actually do work in parallel. One -core can be doing one thing while another core does something completely -unrelated, and those actually happen at the same time. On a machine with a -single CPU core, the CPU can only do one operation at a time, but we can still -have concurrency. Using tools like threads, processes, and async, the computer -can pause one activity and switch to others before eventually cycling back to -that first activity again. So all parallel operations are also concurrent, but -not all concurrent operations happen in parallel! +On a machine with a single CPU core, the CPU can only do one operation at a +time, but we can still have concurrency. Using tools like threads, processes, +and async, the computer can pause one activity and switch to others before +eventually cycling back to that first activity again. On a machine with multiple +CPU cores, we can actually do work in parallel. One core can be doing one thing +while another core does something completely unrelated, and those actually +happen at the same 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, that concurrency may use some degree of parallelism under the hood, or it -may not. Let’s dive into how async programming in Rust actually works! +using—more on async runtimes shortly!—that concurrency may or may not also use +parallelism under the hood. Now, let’s dive into how async programming in Rust +actually works! From f023032403e5ace5ea0bfa78059cea20e6ffd024 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 1 Jul 2024 15:33:45 -0600 Subject: [PATCH 132/249] Ch. 17: add some more explanatory comments to `trpl` --- packages/trpl/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 4ffdbc365b..c661ffd459 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -12,9 +12,11 @@ //! never be broken by upstream changes, e.g. if Tokio does a breaking 2.0 //! release at some point. +// For direct use within the `trpl` crate, *not* re-exported. use std::{future::Future, pin::pin, time::Duration}; use tokio::time; +// Re-exports, to be used like `trpl::join`. pub use futures::{ future::{self, join, join3, join_all, Either}, join, From eec174540a6c87d7fc2f89c00c93cf80e1f19545 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 1 Jul 2024 15:33:45 -0600 Subject: [PATCH 133/249] =?UTF-8?q?Ch.=2017=C2=A701=20initial=20edits=20fo?= =?UTF-8?q?r=20the=20first=20subsection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch17-async-await/listing-17-01/output.txt | 8 +- .../listing-17-01/src/main.rs | 9 +- .../ch17-async-await/listing-17-02/output.txt | 6 +- .../listing-17-02/src/main.rs | 7 +- .../listing-17-03-fix/Cargo.lock | 7 + .../listing-17-03-fix/Cargo.toml | 6 + .../listing-17-03-fix/output.txt | 10 + .../listing-17-03-fix/src/main.rs | 10 + .../ch17-async-await/listing-17-03/Cargo.lock | 12 + .../listing-17-03/src/main.rs | 9 +- .../ch17-async-await/listing-17-04/Cargo.lock | 12 + src/ch17-01-futures-and-syntax.md | 206 ++++++++++-------- 12 files changed, 193 insertions(+), 109 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-03-fix/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-03-fix/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-03-fix/output.txt create mode 100644 listings/ch17-async-await/listing-17-03-fix/src/main.rs diff --git a/listings/ch17-async-await/listing-17-01/output.txt b/listings/ch17-async-await/listing-17-01/output.txt index 9fc69b9ac1..46e6cd3111 100644 --- a/listings/ch17-async-await/listing-17-01/output.txt +++ b/listings/ch17-async-await/listing-17-01/output.txt @@ -1,14 +1,14 @@ $ 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:2:5 + --> src/main.rs:3:5 | -2 | hello_async(); - | ^^^^^^^^^^^^^ +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.11s + 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 70ce867bf2..68c82536aa 100644 --- a/listings/ch17-async-await/listing-17-01/src/main.rs +++ b/listings/ch17-async-await/listing-17-01/src/main.rs @@ -1,11 +1,10 @@ // ANCHOR: all fn main() { - hello_async(); + hello("async"); } -// ANCHOR: async-fn -async fn hello_async() { - println!("Hello, async!"); +async fn hello(name: &str) { + let greeting = format!("Hello, {name}!"); + println!("{greeting}"); } -// ANCHOR_END: async-fn // ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-02/output.txt b/listings/ch17-async-await/listing-17-02/output.txt index 0910145234..5400d6f5e1 100644 --- a/listings/ch17-async-await/listing-17-02/output.txt +++ b/listings/ch17-async-await/listing-17-02/output.txt @@ -1,12 +1,12 @@ $ cargo run Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-02) error[E0728]: `await` is only allowed inside `async` functions and blocks - --> src/main.rs:3:19 + --> src/main.rs:3:20 | 2 | fn main() { | ---- this is not `async` -3 | hello_async().await; - | ^^^^^ only allowed inside `async` functions and blocks +3 | 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 4ce7800db7..153458bc0a 100644 --- a/listings/ch17-async-await/listing-17-02/src/main.rs +++ b/listings/ch17-async-await/listing-17-02/src/main.rs @@ -1,9 +1,10 @@ // ANCHOR: main fn main() { - hello_async().await; + hello("async").await; } // ANCHOR_END: main -async fn hello_async() { - println!("Hello, async!"); +async fn hello(name: &str) { + let greeting = format!("Hello, {name}!"); + println!("{greeting}"); } diff --git a/listings/ch17-async-await/listing-17-03-fix/Cargo.lock b/listings/ch17-async-await/listing-17-03-fix/Cargo.lock new file mode 100644 index 0000000000..d30b928a6c --- /dev/null +++ b/listings/ch17-async-await/listing-17-03-fix/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "async_await" +version = "0.1.0" diff --git a/listings/ch17-async-await/listing-17-03-fix/Cargo.toml b/listings/ch17-async-await/listing-17-03-fix/Cargo.toml new file mode 100644 index 0000000000..67729afc80 --- /dev/null +++ b/listings/ch17-async-await/listing-17-03-fix/Cargo.toml @@ -0,0 +1,6 @@ +[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 diff --git a/listings/ch17-async-await/listing-17-03-fix/output.txt b/listings/ch17-async-await/listing-17-03-fix/output.txt new file mode 100644 index 0000000000..17922a261c --- /dev/null +++ b/listings/ch17-async-await/listing-17-03-fix/output.txt @@ -0,0 +1,10 @@ +$ cargo run + Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-03-fix) +error[E0752]: `main` function is not allowed to be `async` + --> src/main.rs:2:1 + | +2 | 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-fix/src/main.rs b/listings/ch17-async-await/listing-17-03-fix/src/main.rs new file mode 100644 index 0000000000..443cadcc0e --- /dev/null +++ b/listings/ch17-async-await/listing-17-03-fix/src/main.rs @@ -0,0 +1,10 @@ +// ANCHOR: main +async fn main() { + hello("async").await; +} +// ANCHOR_END: main + +async fn hello(name: &str) { + let greeting = format!("Hello, {name}!"); + println!("{greeting}"); +} diff --git a/listings/ch17-async-await/listing-17-03/Cargo.lock b/listings/ch17-async-await/listing-17-03/Cargo.lock index 89df255f72..b6971aa2e9 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.lock +++ b/listings/ch17-async-await/listing-17-03/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-03/src/main.rs b/listings/ch17-async-await/listing-17-03/src/main.rs index 111f734666..6974137d66 100644 --- a/listings/ch17-async-await/listing-17-03/src/main.rs +++ b/listings/ch17-async-await/listing-17-03/src/main.rs @@ -1,9 +1,12 @@ // ANCHOR: main fn main() { - trpl::block_on(hello_async()); + trpl::block_on(async { + hello("async").await; + }); } // ANCHOR_END: main -async fn hello_async() { - println!("Hello, async!"); +async fn hello(name: &str) { + let greeting = format!("Hello, {name}!"); + println!("{greeting}"); } diff --git a/listings/ch17-async-await/listing-17-04/Cargo.lock b/listings/ch17-async-await/listing-17-04/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.lock +++ b/listings/ch17-async-await/listing-17-04/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/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 681727d387..1eae9e69e8 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -1,10 +1,10 @@ ## Futures and the Async Syntax -Like other languages with async, Rust uses the `async` and `await` -keywords—though with some important differences from how other languages do -things, as we will see. 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. +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. Let’s write our first async function, and call it: @@ -22,65 +22,75 @@ If we compile and run this… nothing happens, and we get a compiler warning: {{#include ../listings/ch17-async-await/listing-17-01/output.txt}} ``` -The warning tells us that just calling `hello_async()` was not enough: we also -need to `.await` or poll the future it returns. This raises two important -questions: +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: - Given there is no return type on the function, how is it returning a future? -- What is 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? -### Async functions - -In Rust, `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 this: +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. -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-01/src/main.rs:async-fn}} -``` +### Async functions -It is basically equivalent to a function defined like this instead: +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: ```rust -fn hello_async() -> impl Future { +fn hello(name: &str) -> impl Future { async { - println!("Hello, async!"); + let greeting = format!("Hello, {name}!"); + println!("{greeting}"); } } ``` -Let’s break that down and see what each part means: +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 to return a `Future` with an - associated type of `Output`. That tells us that `Future` is a trait, and the - `Output` associated type of `()` matches the original return type from the - async version of the function. - -* It wraps the whole body of the `async fn` in an `async` block. Given that - blocks like this are expressions, and that this is expression is the one which - is returned from the function, we can infer that an `async` block like this - produces some anonymous data type which implements the `Future` trait. - -Combined, those explain that when we called `hello_async` in `main`, it 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. This should remind you of our discussion of iterators [back in Chapter -13][iterators-lazy]. With iterators, you have to call `next` to get them to do -anything—whether by using a `for` loop or by using iterator methods like `.iter()` and `.map()` which ultimately call `next()` under the hood. - -With futures, the same basic idea applies, although for different reasons, and -with different syntax and methods. This is different from the behavior we saw -when using `thread::spawn` in the previous chapter, and it is different from how -many other languages approach async. This allows Rust to avoid running async -code unless it is actually needed. We will see why that is later on. For now, -let’s start by awaiting the future returned by `hello_async` to actually have it -run. - -> Note: 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 async and non-async methods much -> nicer to work with. As of now, `await` is Rust’s only postfix keyword. + 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`. +* The whole body of the function is wrapped in an `async` block. Remember that + blocks are expressions. This whole block is the expression returned from the + function. +* 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`. + +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. 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. + + +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`. @@ -97,52 +107,67 @@ Oh no! We have gone from a compiler warning to an actual error: ``` This time, the compiler is informing us we cannot use `.await` in `main`, -because `main` is not an `async` function. That is because async code needs a -*runtime*: a Rust crate which manages the details of executing asynchronous -code. - -Most languages which support async, including C#, JavaScript, Go, Kotlin, -Erlang, and Swift, bundle a runtime with the language. At least for now, 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 dozens of CPU cores and terabytes of -RAM has very different different needs than a microcontroller with a single -core, one gigabyte of RAM, and no ability to do heap allocations. - -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, and in a couple cases wires up a few things for you which are less -relevant to the subject of the book. There is no magic involved, though! 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 handful of -helper functions we supply are doing. - -> ### The `futures` and `tokio` Crates +because `main` is not an `async` function. Your first thought might be to make +`main` an async function then, as in Listing 17-TODO-3. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-03-fix/src/main.rs:main}} +``` + + + +However, we get another compiler error here: + +```console +{{#include ../listings/ch17-async-await/listing-17-03-fix/output.txt}} +``` + +The problem is that async code needs a *runtime*: a Rust crate which manages the +details of executing asynchronous code. + +Most languages which support async bundle a runtime with the language. At least +for now, 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 dozens of CPU cores and +terabytes of RAM has very different different needs than a microcontroller with +a single core, one gigabyte of RAM, and no ability to do heap allocations. + +> ### The `trpl` Crate > -> Whenever you see code from the `trpl` crate throughout the rest of the -> chapter, it will be re-exporting code from the [`futures`][futures-crate] and -> [`tokio`][tokio] crates. +> 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 options out there, -> too, and they may be more suitable for your purposes. We are using Tokio -> because it is the most widely-used runtime—not as a judgment call on whether -> it is the *best* runtime! +> 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 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. -For now, go ahead and add the `trpl` crate to your `hello-async` project: +Go ahead and add the `trpl` crate to your `hello-async` project: ```console $ cargo add trpl ``` -Then, in our `main` function, let’s wrap the call to `hello_async` with the +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. +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 +doing more than just one async function call, so instead we will pass an `async` +block and explicitly await the result of calling `hello`. @@ -158,9 +183,8 @@ When we run this, we get the behavior we might have expected initially: {{#include ../listings/ch17-async-await/listing-17-03/output.txt}} ``` -Phew: we finally have some working async code! Now we can answer that second -question: what is a future anyway? That will also help us understand why we need -that `trpl::block_on` call to make this work. +Phew: we finally have some working async code! Now we can turn our attention to +how the `Future` trait works. ### What Are Futures? @@ -218,7 +242,7 @@ Under the hood, when you call `.await`, Rust compiles that to code which calls like this: ```rust,ignore -match hello_async().poll() { +match hello("async").poll() { Ready(_) => { // We’re done! } @@ -233,9 +257,9 @@ the `Future` is still `Pending`? We need some way to try again. We would need to have something like this instead: ```rust,ignore -let hello_async_fut = hello_async(); +let hello_fut = hello("async"); loop { - match hello_async_fut.poll() { + match hello_fut.poll() { Ready(_) => { break; } @@ -286,7 +310,7 @@ Now we can understand why the compiler was stopping us in Listing 17-2 (before we added the `trpl::block_on` function). The `main` function is not `async`—and it really cannot be: if it were, something would need to call `poll()` on whatever `main` returned! Instead, we use the `trpl::block_on` function, which -polls the `Future` returned by `hello_async` until it returns `Ready`. Every +polls the `Future` returned by `hello` until it returns `Ready`. Every async program in Rust has at least one place where it sets up an executor and executes code. @@ -295,7 +319,7 @@ executes code. > you never have to think about it when writing Rust. > > The loop as written also wouldn’t compile, because it doesn’t actually satisfy -> the contract for a `Future`. In particular, `hello_async_fut` is not *pinned* +> the contract for a `Future`. In particular, `hello_fut` is not *pinned* > with the `Pin` type and we did not pass along a `Context` argument. We will > see a little more about `Pin` later in the chapter, but we will not dig into > `Context` because you will not normally need them for working with futures in From e23834292e72416478c5c8c34cf7fc270d42921b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 2 Jul 2024 09:12:39 -0600 Subject: [PATCH 134/249] =?UTF-8?q?Ch.=2017=C2=A701=20initial=20edits=20fo?= =?UTF-8?q?r=20the=20second=20subsection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ch17-01-futures-and-syntax.md | 127 +++++++++++++----------------- 1 file changed, 55 insertions(+), 72 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 1eae9e69e8..eed28f8c20 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -188,10 +188,10 @@ how the `Future` trait works. ### What Are Futures? -A *future* is a data structure which represents the state of some async -operation. More precisely, a Rust `Future` is a trait; it allows many different -data structures to represent different async operations in different ways, but -with a common interface. Here is the definition of the trait: +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 pub trait Future { @@ -201,20 +201,18 @@ pub trait Future { } ``` -Notice that this is a normal trait. While we often interact with futures via -async blocks, you can also implement this yourself on your own data types when -you need to. Many of the functions we will see throughout this chapter return -types which have their own implementations of `Future`. Those implementations -can compose together nicely - -`Future` has an associated type, `Output`, which says what the result of the -future will be when it resolves. (This is analogous to the `Item` associated -type for the `Iterator` trait, which we saw back in Chapter 13.) Beyond that, -`Future` has only one method: `poll`, which takes a special `Pin` reference for -its `self` parameter and a mutable reference to some `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: +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 { @@ -223,19 +221,17 @@ enum Poll { } ``` -You may notice that this `Poll` type is a lot like an `Option`: it has one -variant which has a value (`Ready(T)` and `Some(T)`), and one which does not -(`Pending` and `None`). Having a dedicated type lets Rust treat `Poll` -differently from `Option`, though, which is important since they have very -different meanings! The `Pending` variant indicates that the future still has +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 after becoming -> ready! Futures which are safe to poll again will say so explicitly in their -> documentation. +> 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 ) @@ -252,9 +248,9 @@ match hello("async").poll() { } ``` -As you can see from this sample, though, there is a question: what happens when -the `Future` is still `Pending`? We need some way to try again. We would need to -have something like this instead: +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"); @@ -270,16 +266,15 @@ loop { } ``` -When we use `.await`, Rust compiles it to something fairly similar to that loop. -If Rust compiled it to *exactly* that code, though, every `.await` would block -the computer from doing anything else—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. +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. -Every *await point*—that is, every place where the code explicitly calls -`.await`—represents one of those places where control gets handed back to the +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 @@ -293,37 +288,26 @@ enum MyAsyncStateMachine { } ``` -Writing that out by hand would be tedious and error-prone—especially when making -changes to code later. Async Rust creates that state machine for us, and it -really is an `enum` like this, just an anonymous one you don’t have to name. As -a result, the normal rules around data structures all apply, including for -borrowing and ownership. Happily, the compiler also handles checking that for -us, and has good error messages. We will work through a few of those later in -the chapter! - -Once all of that compilation work is done, though, we need a runtime to actually -poll the futures, coordinate between different futures as they hand off control -at await points, and even provide async versions of common functionality like -file or network I/O. - -Now we can understand why the compiler was stopping us in Listing 17-2 (before -we added the `trpl::block_on` function). The `main` function is not `async`—and -it really cannot be: if it were, something would need to call `poll()` on -whatever `main` returned! Instead, we use the `trpl::block_on` function, which -polls the `Future` returned by `hello` until it returns `Ready`. Every -async program in Rust has at least one place where it sets up an executor and -executes code. - -> Note: Under the hood, Rust uses *generators* so that it can hand off control -> between different functions. These are an implementation detail, though, and -> you never have to think about it when writing Rust. -> -> The loop as written also wouldn’t compile, because it doesn’t actually satisfy -> the contract for a `Future`. In particular, `hello_fut` is not *pinned* -> with the `Pin` type and we did not pass along a `Context` argument. We will -> see a little more about `Pin` later in the chapter, but we will not dig into -> `Context` because you will not normally need them for working with futures in -> day-to-day Rust code. +Writing that out by hand would be tedious and error-prone, especially when +making changes to code later. Instead, async Rust creates and manages the state +machine data structures for us. (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!) + +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`. + +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. > > If you want to understand how things work “under the hood,” though, the > official [_Asynchronous Programming in Rust_][async-book] book covers them: @@ -331,9 +315,8 @@ executes code. > - [Chapter 2: Under the Hood: Executing Futures and Tasks][under-the-hood] > - [Chapter 4: Pinning][pinning]. -Now, that’s a lot of work to just print a string, but we have laid some key -foundations for working with async in Rust! 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 how futures and runtimes work, we can see some +of the things we can *do* with async. [impl-trait]: ch10-02-traits.html#traits-as-parameters [iterators-lazy]: ch13-02-iterators.html From 09b80f9934b604aa355b2ec654ae84d128ae8aa3 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 2 Jul 2024 14:24:10 -0600 Subject: [PATCH 135/249] =?UTF-8?q?Ch.=2017=C2=A702=20initial=20edits=20on?= =?UTF-8?q?=20'Counting'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revise the text itself, of course; but also fold together Listings 04 and 05, which also lets us expand Listing 03 into two listings (which I did not do previously because I knew this kind of thing would come up later!). --- .../listing-17-03-fix/Cargo.lock | 7 - .../listing-17-03-fix/Cargo.toml | 6 - .../listing-17-03-fix/output.txt | 10 - .../listing-17-03-fix/src/main.rs | 10 - .../ch17-async-await/listing-17-03/Cargo.lock | 285 ------------------ .../ch17-async-await/listing-17-03/Cargo.toml | 3 - .../ch17-async-await/listing-17-03/output.txt | 37 +-- .../listing-17-03/src/main.rs | 6 +- .../ch17-async-await/listing-17-04/Cargo.lock | 40 +-- .../ch17-async-await/listing-17-04/Cargo.toml | 6 +- .../ch17-async-await/listing-17-04/output.txt | 27 ++ .../listing-17-04/src/main.rs | 11 +- .../listing-17-05/src/main.rs | 2 - src/ch17-01-futures-and-syntax.md | 14 +- src/ch17-02-concurrency-with-async.md | 92 +++--- 15 files changed, 120 insertions(+), 436 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-03-fix/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-03-fix/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-03-fix/output.txt delete mode 100644 listings/ch17-async-await/listing-17-03-fix/src/main.rs create mode 100644 listings/ch17-async-await/listing-17-04/output.txt diff --git a/listings/ch17-async-await/listing-17-03-fix/Cargo.lock b/listings/ch17-async-await/listing-17-03-fix/Cargo.lock deleted file mode 100644 index d30b928a6c..0000000000 --- a/listings/ch17-async-await/listing-17-03-fix/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "async_await" -version = "0.1.0" diff --git a/listings/ch17-async-await/listing-17-03-fix/Cargo.toml b/listings/ch17-async-await/listing-17-03-fix/Cargo.toml deleted file mode 100644 index 67729afc80..0000000000 --- a/listings/ch17-async-await/listing-17-03-fix/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[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 diff --git a/listings/ch17-async-await/listing-17-03-fix/output.txt b/listings/ch17-async-await/listing-17-03-fix/output.txt deleted file mode 100644 index 17922a261c..0000000000 --- a/listings/ch17-async-await/listing-17-03-fix/output.txt +++ /dev/null @@ -1,10 +0,0 @@ -$ cargo run - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-03-fix) -error[E0752]: `main` function is not allowed to be `async` - --> src/main.rs:2:1 - | -2 | 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-fix/src/main.rs b/listings/ch17-async-await/listing-17-03-fix/src/main.rs deleted file mode 100644 index 443cadcc0e..0000000000 --- a/listings/ch17-async-await/listing-17-03-fix/src/main.rs +++ /dev/null @@ -1,10 +0,0 @@ -// ANCHOR: main -async fn main() { - hello("async").await; -} -// ANCHOR_END: main - -async fn hello(name: &str) { - let greeting = format!("Hello, {name}!"); - println!("{greeting}"); -} diff --git a/listings/ch17-async-await/listing-17-03/Cargo.lock b/listings/ch17-async-await/listing-17-03/Cargo.lock index b6971aa2e9..d30b928a6c 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.lock +++ b/listings/ch17-async-await/listing-17-03/Cargo.lock @@ -2,291 +2,6 @@ # 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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "miniz_oxide" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" -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-03/Cargo.toml b/listings/ch17-async-await/listing-17-03/Cargo.toml index 5f2e9ac2d0..67729afc80 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.toml +++ b/listings/ch17-async-await/listing-17-03/Cargo.toml @@ -3,7 +3,4 @@ name = "async_await" 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 diff --git a/listings/ch17-async-await/listing-17-03/output.txt b/listings/ch17-async-await/listing-17-03/output.txt index d0d2eb5d91..17922a261c 100644 --- a/listings/ch17-async-await/listing-17-03/output.txt +++ b/listings/ch17-async-await/listing-17-03/output.txt @@ -1,27 +1,10 @@ -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 +$ cargo run + Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/listing-17-03-fix) +error[E0752]: `main` function is not allowed to be `async` + --> src/main.rs:2:1 + | +2 | 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 6974137d66..443cadcc0e 100644 --- a/listings/ch17-async-await/listing-17-03/src/main.rs +++ b/listings/ch17-async-await/listing-17-03/src/main.rs @@ -1,8 +1,6 @@ // ANCHOR: main -fn main() { - trpl::block_on(async { - hello("async").await; - }); +async fn main() { + hello("async").await; } // ANCHOR_END: main diff --git a/listings/ch17-async-await/listing-17-04/Cargo.lock b/listings/ch17-async-await/listing-17-04/Cargo.lock index 2e0f3ebedb..b6971aa2e9 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.lock +++ b/listings/ch17-async-await/listing-17-04/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -32,9 +32,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -148,9 +148,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "hermit-abi" @@ -160,9 +160,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "memchr" @@ -172,9 +172,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -212,9 +212,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -245,9 +245,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.63" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "num_cpus", diff --git a/listings/ch17-async-await/listing-17-04/Cargo.toml b/listings/ch17-async-await/listing-17-04/Cargo.toml index 349041d3eb..5f2e9ac2d0 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.toml +++ b/listings/ch17-async-await/listing-17-04/Cargo.toml @@ -3,7 +3,7 @@ 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" } +trpl = { version = "0.1.0", path = "../../../packages/trpl" } + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/listings/ch17-async-await/listing-17-04/output.txt b/listings/ch17-async-await/listing-17-04/output.txt new file mode 100644 index 0000000000..d0d2eb5d91 --- /dev/null +++ b/listings/ch17-async-await/listing-17-04/output.txt @@ -0,0 +1,27 @@ +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-04/src/main.rs b/listings/ch17-async-await/listing-17-04/src/main.rs index ab559c800f..6974137d66 100644 --- a/listings/ch17-async-await/listing-17-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -1,7 +1,12 @@ +// ANCHOR: main fn main() { - // ANCHOR: block_on trpl::block_on(async { - // our implementation will go here + hello("async").await; }); - // ANCHOR_END: block_on +} +// ANCHOR_END: main + +async fn hello(name: &str) { + let greeting = format!("Hello, {name}!"); + println!("{greeting}"); } 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 36ddedca26..4af024741e 100644 --- a/listings/ch17-async-await/listing-17-05/src/main.rs +++ b/listings/ch17-async-await/listing-17-05/src/main.rs @@ -2,7 +2,6 @@ use std::time::Duration; fn main() { trpl::block_on(async { - // ANCHOR: task trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); @@ -14,6 +13,5 @@ fn main() { println!("hi number {i} from the second task!"); trpl::sleep(Duration::from_millis(1)).await; } - // ANCHOR_END: task }); } diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index eed28f8c20..d3e08bc01b 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -108,12 +108,12 @@ Oh no! We have gone from a compiler warning to an actual error: 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-TODO-3. +`main` an async function then, as in Listing 17-3. -+ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-03-fix/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-03/src/main.rs:main}} ``` @@ -121,7 +121,7 @@ because `main` is not an `async` function. Your first thought might be to make However, we get another compiler error here: ```console -{{#include ../listings/ch17-async-await/listing-17-03-fix/output.txt}} +{{#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 @@ -169,10 +169,10 @@ completes. Since `hello` returns a `Future`, we could simply wrap it directly in 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-03/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:main}} ``` @@ -180,7 +180,7 @@ block and explicitly await the result of calling `hello`. When we run this, we get the behavior we might have expected initially: ```console -{{#include ../listings/ch17-async-await/listing-17-03/output.txt}} +{{#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 diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 4373036419..9470eac86c 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -16,36 +16,30 @@ 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. +to implement the same counting example as with threads, in Listing 17-5. -Listing 17-4 shows our starting point. We set up our `main` function with `trpl::block_on`, so that our top-level function can be async. + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-04/src/main.rs:block_on}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs}} ``` + + +As our starting point, we set up our `main` function with `trpl::block_on`, 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! -Then we can write two loops within that block, each with a `trpl::sleep` call in -them. Similar to the threading example, we put one loop in the body of a -`trpl::spawn_task`, the same way we did with `thread::spawn`, and the other in a -top-level `for` loop. Notice that we also need to add a `.await` after the -`sleep` calls. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:task}} -``` - - +Then we write two loops within that block, each with a `trpl::sleep` call in it. +We put one loop in the body of a `trpl::spawn_task` and the other in a top-level +`for` loop. We also add an `.await` after the `sleep` calls. -This does something very similar to what the thread-based implementation did, as -we can see from the output when we run it. (As with the threading example, you -may see a different order in your own terminal output when you run this.) +This does something similar to the thread-based implementation—including the +fact that you may see the messages appear in a different order in your own +terminal when you run it. @@ -147,16 +142,15 @@ hi number 9 from the first task! Here, you will see the exact same order every time, which is very different from what we saw with threads. That is because the `trpl::join` function is *fair*, -meaning it checks both futures equally, rather than letting one race ahead. With -threads, the operating system decides which thread to check, and that is -ultimately out of our control. With an async runtime, the runtime itself decides -which future to check, so it has the final say. 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, but a runtime can still choose -to guarantee fairness even so. However, runtimes do not have to guarantee -fairness for any given operation, and even within a given runtime, different -APIs sometimes exist to let you choose whether fairness is something you care -about as a caller. +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 +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 +fairness for any given operation, and runtimes often offer different APIs to let +you choose whether you want fairness or not. Try some of these different variations on awaiting the futures and see what they do: From e5c9afd8916c81e1c1796df06f06e029c2ba765d Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 2 Jul 2024 16:15:20 -0600 Subject: [PATCH 136/249] =?UTF-8?q?Ch.=2017=C2=A702=20initial=20edits=20on?= =?UTF-8?q?=20'Message=20Passing'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The usual kinds of clarifications, cleaning up redundancies, etc. - Fold together listings: - 8 and 9 → 8 - 10, 11, 12 → 9 - 13 → 10 - 15 → 11 - 16 → 12 - Tweak the durations used for the listings throughout this section, including making the durations *differ* between the two sending blocks in the final example. --- .../ch17-async-await/listing-17-05/Cargo.lock | 12 + .../listing-17-05/src/main.rs | 4 +- .../ch17-async-await/listing-17-06/Cargo.lock | 12 + .../listing-17-06/src/main.rs | 4 +- .../ch17-async-await/listing-17-07/Cargo.lock | 262 +-------- .../listing-17-07/src/main.rs | 4 +- .../ch17-async-await/listing-17-08/Cargo.lock | 12 + .../listing-17-08/src/main.rs | 4 +- .../ch17-async-await/listing-17-09/Cargo.lock | 12 + .../listing-17-09/src/main.rs | 24 +- .../ch17-async-await/listing-17-10/Cargo.lock | 12 + .../listing-17-10/src/main.rs | 37 +- .../ch17-async-await/listing-17-11/Cargo.lock | 12 + .../listing-17-11/src/main.rs | 37 +- .../ch17-async-await/listing-17-12/Cargo.lock | 12 + .../listing-17-12/src/main.rs | 51 +- .../ch17-async-await/listing-17-13/Cargo.lock | 540 ------------------ .../ch17-async-await/listing-17-13/Cargo.toml | 9 - .../listing-17-13/src/main.rs | 33 -- .../ch17-async-await/listing-17-14/Cargo.lock | 540 ------------------ .../ch17-async-await/listing-17-14/Cargo.toml | 9 - .../listing-17-14/src/main.rs | 45 -- .../ch17-async-await/listing-17-15/Cargo.lock | 280 --------- .../ch17-async-await/listing-17-15/Cargo.toml | 9 - .../listing-17-15/src/main.rs | 32 -- .../ch17-async-await/listing-17-16/Cargo.lock | 280 --------- .../ch17-async-await/listing-17-16/Cargo.toml | 9 - .../listing-17-16/src/main.rs | 46 -- src/ch17-02-concurrency-with-async.md | 305 ++++------ 29 files changed, 310 insertions(+), 2338 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-13/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-13/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-13/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-14/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-14/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-14/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-15/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-15/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-15/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-16/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-16/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-16/src/main.rs diff --git a/listings/ch17-async-await/listing-17-05/Cargo.lock b/listings/ch17-async-await/listing-17-05/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-05/Cargo.lock +++ b/listings/ch17-async-await/listing-17-05/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-05/src/main.rs b/listings/ch17-async-await/listing-17-05/src/main.rs index 4af024741e..1a727a9a09 100644 --- a/listings/ch17-async-await/listing-17-05/src/main.rs +++ b/listings/ch17-async-await/listing-17-05/src/main.rs @@ -5,13 +5,13 @@ fn main() { trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; + 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(1)).await; + trpl::sleep(Duration::from_millis(500)).await; } }); } diff --git a/listings/ch17-async-await/listing-17-06/Cargo.lock b/listings/ch17-async-await/listing-17-06/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-06/Cargo.lock +++ b/listings/ch17-async-await/listing-17-06/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-06/src/main.rs b/listings/ch17-async-await/listing-17-06/src/main.rs index dbc2241b96..c7e74c8233 100644 --- a/listings/ch17-async-await/listing-17-06/src/main.rs +++ b/listings/ch17-async-await/listing-17-06/src/main.rs @@ -6,13 +6,13 @@ fn main() { let handle = trpl::spawn_task(async { for i in 1..10 { println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; + 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(1)).await; + trpl::sleep(Duration::from_millis(500)).await; } handle.await.unwrap(); diff --git a/listings/ch17-async-await/listing-17-07/Cargo.lock b/listings/ch17-async-await/listing-17-07/Cargo.lock index 3be4eaaa53..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-07/Cargo.lock +++ b/listings/ch17-async-await/listing-17-07/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-07/src/main.rs b/listings/ch17-async-await/listing-17-07/src/main.rs index 60889f3aed..7f38d5ebdf 100644 --- a/listings/ch17-async-await/listing-17-07/src/main.rs +++ b/listings/ch17-async-await/listing-17-07/src/main.rs @@ -6,14 +6,14 @@ fn main() { let fut1 = async { for i in 1..10 { println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(1)).await; + 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(1)).await; + trpl::sleep(Duration::from_millis(500)).await; } }; diff --git a/listings/ch17-async-await/listing-17-08/Cargo.lock b/listings/ch17-async-await/listing-17-08/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-08/Cargo.lock +++ b/listings/ch17-async-await/listing-17-08/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-08/src/main.rs b/listings/ch17-async-await/listing-17-08/src/main.rs index b7b3eb8b16..bd19c58886 100644 --- a/listings/ch17-async-await/listing-17-08/src/main.rs +++ b/listings/ch17-async-await/listing-17-08/src/main.rs @@ -1,13 +1,13 @@ fn main() { trpl::block_on(async { - // ANCHOR: add-channel + // ANCHOR: channel let (tx, mut rx) = trpl::channel(); - // ANCHOR_END: add-channel let val = String::from("hi"); tx.send(val).unwrap(); let received = rx.recv().await.unwrap(); println!("Got: {received}"); + // ANCHOR_END: channel }); } diff --git a/listings/ch17-async-await/listing-17-09/Cargo.lock b/listings/ch17-async-await/listing-17-09/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-09/Cargo.lock +++ b/listings/ch17-async-await/listing-17-09/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-09/src/main.rs b/listings/ch17-async-await/listing-17-09/src/main.rs index 4d98d199b6..7a96259e29 100644 --- a/listings/ch17-async-await/listing-17-09/src/main.rs +++ b/listings/ch17-async-await/listing-17-09/src/main.rs @@ -1,13 +1,25 @@ +use std::time::Duration; + fn main() { trpl::block_on(async { + // ANCHOR: many-messages let (tx, mut rx) = trpl::channel(); - // ANCHOR: send-and-receive - let val = String::from("hi"); - tx.send(val).unwrap(); + 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 received = rx.recv().await.unwrap(); - println!("Got: {received}"); - // ANCHOR_END: send-and-receive + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + // ANCHOR_END: many-messages }); } diff --git a/listings/ch17-async-await/listing-17-10/Cargo.lock b/listings/ch17-async-await/listing-17-10/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-10/Cargo.lock +++ b/listings/ch17-async-await/listing-17-10/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-10/src/main.rs b/listings/ch17-async-await/listing-17-10/src/main.rs index a9cba44de3..cbcd9ee60b 100644 --- a/listings/ch17-async-await/listing-17-10/src/main.rs +++ b/listings/ch17-async-await/listing-17-10/src/main.rs @@ -1,26 +1,33 @@ -// ANCHOR: many-messages use std::time::Duration; -// ANCHOR_END: many-messages fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); - // ANCHOR: many-messages + // ANCHOR: futures + let tx_fut = async { + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("future"), + ]; - // snip... + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_millis(500)).await; + } + }; - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; + let rx_fut = async { + // ANCHOR: loop + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + // ANCHOR_END: loop + }; - for val in vals { - tx.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).await; - } - // ANCHOR_END: many-messages + trpl::join(tx_fut, rx_fut).await; + // ANCHOR_END: futures }); } diff --git a/listings/ch17-async-await/listing-17-11/Cargo.lock b/listings/ch17-async-await/listing-17-11/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-11/Cargo.lock +++ b/listings/ch17-async-await/listing-17-11/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-11/src/main.rs b/listings/ch17-async-await/listing-17-11/src/main.rs index 529a605276..626999e4f8 100644 --- a/listings/ch17-async-await/listing-17-11/src/main.rs +++ b/listings/ch17-async-await/listing-17-11/src/main.rs @@ -2,24 +2,31 @@ use std::time::Duration; fn main() { trpl::block_on(async { + // ANCHOR: with-move let (tx, mut rx) = trpl::channel(); - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; + let tx_fut = async move { + 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_secs(1)).await; - } + for val in vals { + tx.send(val).unwrap(); + trpl::sleep(Duration::from_millis(500)).await; + } + }; - // ANCHOR: loop - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - // ANCHOR_END: loop + let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; + // ANCHOR_END: with-move }); } +// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-12/Cargo.lock b/listings/ch17-async-await/listing-17-12/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-12/Cargo.lock +++ b/listings/ch17-async-await/listing-17-12/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-12/src/main.rs b/listings/ch17-async-await/listing-17-12/src/main.rs index cdb982e86c..e51b82ac8a 100644 --- a/listings/ch17-async-await/listing-17-12/src/main.rs +++ b/listings/ch17-async-await/listing-17-12/src/main.rs @@ -1,25 +1,46 @@ -// ANCHOR: all use std::time::Duration; fn main() { trpl::block_on(async { + // ANCHOR: here let (tx, mut rx) = trpl::channel(); - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; + let tx1 = tx.clone(); + let tx1_fut = async move { + 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_secs(1)).await; - } + for val in vals { + tx1.send(val).unwrap(); + trpl::sleep(Duration::from_millis(500)).await; + } + }; - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } + 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; + } + }; + + trpl::join3(tx1_fut, tx_fut, rx_fut).await; + // ANCHOR_END: here }); } -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-13/Cargo.lock b/listings/ch17-async-await/listing-17-13/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-13/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-13/Cargo.toml b/listings/ch17-async-await/listing-17-13/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-13/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-13/src/main.rs b/listings/ch17-async-await/listing-17-13/src/main.rs deleted file mode 100644 index aeeacc5462..0000000000 --- a/listings/ch17-async-await/listing-17-13/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - 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"), - ]; - - for val in vals { - tx.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).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 - }); -} diff --git a/listings/ch17-async-await/listing-17-14/Cargo.lock b/listings/ch17-async-await/listing-17-14/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-14/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-14/Cargo.toml b/listings/ch17-async-await/listing-17-14/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-14/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-14/src/main.rs b/listings/ch17-async-await/listing-17-14/src/main.rs deleted file mode 100644 index e5d8f86066..0000000000 --- a/listings/ch17-async-await/listing-17-14/src/main.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - let (tx, mut rx) = trpl::channel(); - - let tx_fut = async { - 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_secs(1)).await; - } - }; - - let rx_fut = async { - while let Some(received) = rx.recv().await { - println!("Got: {received}"); - } - }; - - // ANCHOR: updated - let tx_fut2 = async { - 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; - } - }; - - trpl::join3(tx_fut, tx_fut2, rx_fut).await; - // ANCHOR_END: updated - }); -} diff --git a/listings/ch17-async-await/listing-17-15/Cargo.lock b/listings/ch17-async-await/listing-17-15/Cargo.lock deleted file mode 100644 index c0e8bb2b3f..0000000000 --- a/listings/ch17-async-await/listing-17-15/Cargo.lock +++ /dev/null @@ -1,280 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "cc" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.154" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -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.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -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.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 = "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.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tokio" -version = "1.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[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-15/Cargo.toml b/listings/ch17-async-await/listing-17-15/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-15/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-15/src/main.rs b/listings/ch17-async-await/listing-17-15/src/main.rs deleted file mode 100644 index 652545f09f..0000000000 --- a/listings/ch17-async-await/listing-17-15/src/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - // ANCHOR: with-move - let (tx, mut rx) = trpl::channel(); - - let tx_fut = async move { - 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_secs(1)).await; - } - }; - - let rx_fut = async { - while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); - } - }; - - trpl::join(tx_fut, rx_fut).await; - // ANCHOR_END: with-move - }); -} -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-16/Cargo.lock b/listings/ch17-async-await/listing-17-16/Cargo.lock deleted file mode 100644 index c0e8bb2b3f..0000000000 --- a/listings/ch17-async-await/listing-17-16/Cargo.lock +++ /dev/null @@ -1,280 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "cc" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.154" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -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.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -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.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 = "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.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tokio" -version = "1.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[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-16/Cargo.toml b/listings/ch17-async-await/listing-17-16/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-16/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-16/src/main.rs b/listings/ch17-async-await/listing-17-16/src/main.rs deleted file mode 100644 index 4c5e65da9b..0000000000 --- a/listings/ch17-async-await/listing-17-16/src/main.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::time::Duration; - -fn main() { - trpl::block_on(async { - // ANCHOR: here - let (tx, mut rx) = trpl::channel(); - - let tx1 = tx.clone(); - let tx1_fut = async move { - 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; - } - }; - - 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_secs(1)).await; - } - }; - - trpl::join3(tx1_fut, tx_fut, rx_fut).await; - // ANCHOR_END: here - }); -} diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 9470eac86c..40b2927e42 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -26,16 +26,18 @@ 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 that our top-level function can be async. +As our starting point, we set up our `main` function with `trpl::block_on`, 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! -Then we write two loops within that block, each with a `trpl::sleep` call in it. -We put one loop in the body of a `trpl::spawn_task` and the other in a top-level -`for` loop. We also add an `.await` after the `sleep` calls. +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 +message. We put one loop in the body of a `trpl::spawn_task` and the other in a +top-level `for` loop. We also add an `.await` after the `sleep` calls. This does something similar to the thread-based implementation—including the fact that you may see the messages appear in a different order in your own @@ -165,52 +167,30 @@ each case *before* running the code! ### Message Passing -Sharing data between futures will look familiar. We can again use async versions -of Rust’s types for message-passing. Instead of `std::sync:mpsc::channel`, we -will use a `tprl::channel`, for example. - -The synchronous `Receiver::recv()` method in `std::mpsc::channel` blocks until -it receives a message. The `trpl::Receiver::recv()` method, by contrast, is an -`async` function. Instead of blocking, it waits until a message is received or -the send side of the channel closes. One other difference with this particular -`recv()` implementation is that it returns an `Option` of the type sent over the -channel instead of a `Result`. - -We can start by introducing an async version of the multiple-producer, -single-consumer channel channel API we used with threads back in Chapter 16. The -API is just a little different here in Listing 17-8: we have a mutable receiver -`rx`. Otherwise, this looks pretty much the same as the thread-based approach. +Sharing data between futures will also be familiar: we will use message passing, +again, but this with async versions of the types and functions. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:add-channel}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-08/src/main.rs:channel}} ``` -Now we can send messages from the sender to the receiver. Again, the API is just -a little different from the threaded version in Chapter 16, where we needed to -spawn a separate thread to allow the message passing to happen asynchronously. -In the version in Listing 17-9, we opt into async behavior on the receiver side -by using `.await` on the `rx.recv()` call. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:send-and-receive}} -``` - - +We start by using `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: we have a mutable receiver `rx`. +With the channel in place, we can send messages from the sender to the receiver. +Again, the API is just a little different from the threaded version. Instead of +spawning a separate thread, we await the `rx.recv()` call. -The `send` call does not block, since the channel we are sending it into is -unbounded. That was true with our threading example back in Chapter 16, too, -though. However, there is a big difference with the `rx.recv()` calls. The one -back in Chapter 16 blocked the thread it ran on—in that case, the main thread. -This one does not block at all! Instead, once the program hits the `.await` on -the `rx.recv()` call, it hands control back to the runtime, which can go on -scheduling other operations until a message arrives. It might be hard to see -that from this code, though, since the message will arrive right away! +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 will return `Poll::Pending` until 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, 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`, @@ -218,23 +198,23 @@ that from this code, though, since the message will arrive right away! > transition between sync and async code. However, *within* this block, the > `.await` does not block further operations—as we will see! -Let’s go ahead and send a whole series of messages, and sleep in between them, -as shown in Listing 17-10: +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: -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:many-messages}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:many-messages}} ``` -This handles sending the messages, but so far we don’t do anything with them, -and the code just silently runs forever. We need to actually *receive* the -messages. In this case, we could do that manually, because we 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 addition to sending the messages, we need to receive them. In this case, we +could do that manually, by just doing `rx.recv().await` four times, because we +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. That sounds like a good job for a loop! In synchronous code, we might use a `for` loop to process a sequence of items, regardless of how many items are in @@ -242,88 +222,60 @@ 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. It continues as -long as the condition it relies on is true. Listing 17-11 shows how we can use -this with `rx.recv` to print all the messages send by the `tx` transmitter. +long as the condition it relies on is true. -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:loop}} -``` - - - -The `rx.recv()` call produces a `Future`. The `Output` of the future is an -`Option` of the message type. While waiting on messages, it will respond with -`Poll::Pending`, so the runtime will pause it until it is time to check it -again. Once a message arrives, it will respond with -`Poll::Ready(Some(message))`. When the channel closes, it will instead respond -with `Poll::Ready(None)`, which we can use to know that it is done. The `while -let` 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 use it in the loop -body, just like we could with `if let`. If the result is `None`, the loop ends. -Every time the loop completes, it hits the await point again, so the runtime -pauses it again until another message arrives. - -With the `while let` loop in place, the code now successfully sends and receives -the messages. Unfortunately, there are still a couple problems. For one thing, -the messages do not arrive at one-second intervals, we see them arrive all at -once, four seconds after we start the program. For another, this program also -never stops! You will need to shut it down using ctrl-c. +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 `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 +use it in the loop body, just like we could with `if let`. If the result is +`None`, the loop ends. Every time the loop completes, it hits the await point +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. 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. This highlights an -important point about the way that async works in Rust. Within any given async -block, the await points are sequential: each one happens one after another. That -is, after all, one of the big motivations for using this syntax instead of -callbacks, event handlers, or chains of methods: the flow through the program is -much easier to follow, because having the order that `.await` keywords appear in -the *code* is also the order they happen when running the *program*. - -With that in mind, we can see why this code behaves the way it does by looking -at the whole thing all together, in Listing 17-12. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:all}} -``` - - +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 just one async block here, so everything here will proceed linearly. -Every one of the `.await` points for the `trpl::sleep` calls appears before the -`.await` points on the `rx.recv()`, so all the `tx.send` calls happen, -interspersed with all of the `trpl::sleep` calls. Only then does the `while let` -loop get to go through all of the `.await` points on the `recv` calls. +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. -To get the behavior we actually want, where the delay happens in between -receiving each message, rather than before receiving any message, we need to -give put the `tx` and `rx` operations in their own async blocks, so the runtime -can execute each of them separately. We also need to tell the runtime to -actually run them using `trpl::join`, just like we did for the counting example -above. Listing 17-13 shows how that looks. +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. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:futures}} ``` -With these changes made, the messages get printed at one-second intervals, -rather than all in a rush after four seconds. +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 running, though. That’s because of the combination -of the `while let` loop and the `trpl::join` call. Let’s consider the way this -loop works: +The program still never stops, because of the way `while let` loop interacts +with `trpl::join`: -* The `trpl::join` future only completes once *both* futures passed to it - have completed. +* 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. @@ -337,101 +289,70 @@ loop works: * The block cannot end because it is blocked on `trpl::join` completing, which takes us back to the top of this list! -We need to make sure the channel gets closed so that `trpl::join` will complete. -We could manually close `rx` somewhere by calling `rx.close()`, but that does -not make much sense in this case. The idea is that `rx` should keep listening -until `tx` is done sending. Stopping after handling some arbitrary number of -messages would make the program shut down, but it would mean we could miss -messages if the sending side changed. Given that we cannot use `rx.close()`, we -need 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 only borrows `tx`. We can confirm this by adding -another async block which uses `tx`, and using `trpl::join3` to wait for all -three futures to complete: +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 +ends. In Chapter 13, we learned how to use the `move` keyword with closures, and +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. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-14/src/main.rs:updated}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:with-move}} ``` -Now both blocks borrow `tx`, so they are both able to use it to send messages, -which `rx` can then receive. When we run that code, we see the extra output from -the new `async` block, and the message it sends being received by the -`rx.recv()`. - - - -```text -Got: hi -Got: more -Got: from -Got: messages -Got: the -Got: for -Got: future -Got: you -``` - -As before, we also see that the program does not shut down on its own and -requires a ctrl-c. This little exploration helps -us understand why: it is ultimately about *ownership*. We need to move `tx` into -the async block so that once that block ends, `tx` will be dropped. - -Since we have seen how `async` blocks borrow the items they reference from their -outer scope, we can go ahead and remove the extra block we just added for now, -and switch back from `join3` to `join`. - -The last step here is to figure out how to get ownership of the data instead of -just borrowing it. In Chapter 13, we learned how to use the `move` keyword with -closures, and in Chapter 16, we saw that we often need to use closures marked -with `move` when working with threads. As we have discovered, the same dynamics -apply to async blocks! Hopefully this will make sense if you remember that any -time you write a future, a runtime is ultimately responsible for executing it. -That means that an async block might outlive the function where you write it, -the same way a closure can. When a future takes ownership of the data it -references this way, it needs to move that data into the future—so the `move` -keyword works with async blocks just like it does with closures. - -Thus, we can change the first async block from an `async` block to an `async -move` block, like this: +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.) -The result is Listing 17-15, and when we run *this* version of the code, it -shuts down gracefully after the last message is sent. +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 +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. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:with-move}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-12/src/main.rs:here}} ``` -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. For example, we can -make the code from Listing 17-16 work by cloning the `tx` before moving it -into the first async block, moving the original `tx` into the second async -block, and switching back to `join3`. +Now we see all the messages from both sending futures. Because the sending +futures use slightly different delays after sending, the messages are also +received at those different intervals. -+ -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-16/src/main.rs:here}} +```text +received 'hi' +received 'more' +received 'from' +received 'the' +received 'messages' +received 'future' +received 'for' +received 'you' ``` - - -*Both* of these blocks need to be `async move` blocks, or else we will end up -back in the same infinite loop we started out in. With that done, though, we get -all the messages we expected, with little delays between them. Notice that since -each of the sending futures do a one-second delay after sending, the messages -come in right after each other at one-second intervals. The delays are -concurrent, not sequential, just as we would expect. - 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. From 89920d5a52072baab0a576b7a5e687ae42ac2988 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 3 Jul 2024 11:14:16 -0600 Subject: [PATCH 137/249] =?UTF-8?q?Ch.=2017=C2=A703=20Initial=20edits=20on?= =?UTF-8?q?=20opening=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the listings, eliminating them where possible and adding notes about manual regeneration as necessary. Also clean up a *lot* of issues with wording, phrasing, etc.! --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 12 + .../Cargo.toml | 0 .../output.txt | 17 +- .../src/main.rs | 0 .../Cargo.lock | 12 + .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../output.txt | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-19/Cargo.lock | 7 - .../ch17-async-await/listing-17-19/Cargo.toml | 6 - .../ch17-async-await/listing-17-19/output.txt | 10 - .../listing-17-19/src/main.rs | 7 - src/ch17-03-more-futures.md | 261 ++++++++++++------ 19 files changed, 206 insertions(+), 126 deletions(-) rename listings/ch17-async-await/{listing-17-17 => listing-17-13}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-17 => listing-17-13}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-17 => listing-17-13}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-20 => listing-17-14}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-18 => listing-17-14}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-18 => listing-17-14}/output.txt (87%) rename listings/ch17-async-await/{listing-17-18 => listing-17-14}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-21 => listing-17-15}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-20 => listing-17-15}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-20 => listing-17-15}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-18 => listing-17-16}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-21 => listing-17-16}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-21 => listing-17-16}/output.txt (100%) rename listings/ch17-async-await/{listing-17-21 => listing-17-16}/src/main.rs (100%) delete mode 100644 listings/ch17-async-await/listing-17-19/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-19/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-19/output.txt delete mode 100644 listings/ch17-async-await/listing-17-19/src/main.rs diff --git a/listings/ch17-async-await/listing-17-17/Cargo.lock b/listings/ch17-async-await/listing-17-13/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-17/Cargo.lock rename to listings/ch17-async-await/listing-17-13/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-17/Cargo.toml b/listings/ch17-async-await/listing-17-13/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-17/Cargo.toml rename to listings/ch17-async-await/listing-17-13/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-17/src/main.rs b/listings/ch17-async-await/listing-17-13/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-17/src/main.rs rename to listings/ch17-async-await/listing-17-13/src/main.rs diff --git a/listings/ch17-async-await/listing-17-20/Cargo.lock b/listings/ch17-async-await/listing-17-14/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-20/Cargo.lock rename to listings/ch17-async-await/listing-17-14/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-20/Cargo.lock +++ b/listings/ch17-async-await/listing-17-14/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-18/Cargo.toml b/listings/ch17-async-await/listing-17-14/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-18/Cargo.toml rename to listings/ch17-async-await/listing-17-14/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-18/output.txt b/listings/ch17-async-await/listing-17-14/output.txt similarity index 87% rename from listings/ch17-async-await/listing-17-18/output.txt rename to listings/ch17-async-await/listing-17-14/output.txt index 4ad945623f..365d1f0145 100644 --- a/listings/ch17-async-await/listing-17-18/output.txt +++ b/listings/ch17-async-await/listing-17-14/output.txt @@ -1,14 +1,15 @@ $ cargo run + Updating crates.io index 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-core v0.3.30 Compiling futures-sink v0.3.30 - Compiling pin-project-lite v0.2.14 - Compiling pin-utils v0.1.0 - Compiling futures-io 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 @@ -16,12 +17,13 @@ $ cargo run 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-18) + 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 | @@ -48,6 +50,5 @@ error[E0308]: mismatched types | = 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}` - -For more information about this error, try `rustc --explain E0308`. -error: could not compile `async_await` (bin "async_await") due to 1 previous error + = 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 diff --git a/listings/ch17-async-await/listing-17-18/src/main.rs b/listings/ch17-async-await/listing-17-14/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-18/src/main.rs rename to listings/ch17-async-await/listing-17-14/src/main.rs diff --git a/listings/ch17-async-await/listing-17-21/Cargo.lock b/listings/ch17-async-await/listing-17-15/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-21/Cargo.lock rename to listings/ch17-async-await/listing-17-15/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-21/Cargo.lock +++ b/listings/ch17-async-await/listing-17-15/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-20/Cargo.toml b/listings/ch17-async-await/listing-17-15/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-20/Cargo.toml rename to listings/ch17-async-await/listing-17-15/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-20/src/main.rs b/listings/ch17-async-await/listing-17-15/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-20/src/main.rs rename to listings/ch17-async-await/listing-17-15/src/main.rs diff --git a/listings/ch17-async-await/listing-17-18/Cargo.lock b/listings/ch17-async-await/listing-17-16/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-18/Cargo.lock rename to listings/ch17-async-await/listing-17-16/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-21/Cargo.toml b/listings/ch17-async-await/listing-17-16/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-21/Cargo.toml rename to listings/ch17-async-await/listing-17-16/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-21/output.txt b/listings/ch17-async-await/listing-17-16/output.txt similarity index 100% rename from listings/ch17-async-await/listing-17-21/output.txt rename to listings/ch17-async-await/listing-17-16/output.txt diff --git a/listings/ch17-async-await/listing-17-21/src/main.rs b/listings/ch17-async-await/listing-17-16/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-21/src/main.rs rename to listings/ch17-async-await/listing-17-16/src/main.rs diff --git a/listings/ch17-async-await/listing-17-19/Cargo.lock b/listings/ch17-async-await/listing-17-19/Cargo.lock deleted file mode 100644 index d30b928a6c..0000000000 --- a/listings/ch17-async-await/listing-17-19/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "async_await" -version = "0.1.0" diff --git a/listings/ch17-async-await/listing-17-19/Cargo.toml b/listings/ch17-async-await/listing-17-19/Cargo.toml deleted file mode 100644 index 67729afc80..0000000000 --- a/listings/ch17-async-await/listing-17-19/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[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 diff --git a/listings/ch17-async-await/listing-17-19/output.txt b/listings/ch17-async-await/listing-17-19/output.txt deleted file mode 100644 index 5b7dc951b7..0000000000 --- a/listings/ch17-async-await/listing-17-19/output.txt +++ /dev/null @@ -1,10 +0,0 @@ -$ cargo build - Compiling async_await v0.1.0 (/Users/chris/dev/rust-lang/book/listings/ch17-async-await/no-listing-type-mismatch) -error[E0308]: mismatched types - --> src/main.rs:5:24 - | -5 | let vals = vec![a, b]; - | ^ expected integer, found `&str` - -For more information about this error, try `rustc --explain E0308`. -error: could not compile `async_await` (bin "async_await") due to 1 previous error diff --git a/listings/ch17-async-await/listing-17-19/src/main.rs b/listings/ch17-async-await/listing-17-19/src/main.rs deleted file mode 100644 index 0c282f4f87..0000000000 --- a/listings/ch17-async-await/listing-17-19/src/main.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - // ANCHOR: here - let a = 1; - let b = "Hello"; - let vals = vec![a, b]; - // ANCHOR_END: here -} diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 08144b647c..7057e02cb2 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -4,148 +4,233 @@ 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-16 to use -`join!` instead of `join3`, as in Listing 17-17: +the futures itself. Thus, we could rewrite the code from Listing 17-12 to use +`join!` instead of `join3`, as in Listing 17-13: -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-17/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-13/src/main.rs:here}} ``` This is definitely a nice improvement over needing to swap between `join` and -`join3` and `join4` and so on! However, both the function nor macro forms of -`join` only work for cases where we know the number of futures ahead of time. If -instead we have a dynamic number of futures, we need a function which works with -a collection type which can grow and shrink dynamically at runtime, such as a -vector. In real-world Rust, pushing futures into a collection and then waiting -on some or all the futures in that collection to complete is a very common -pattern. +`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. -The `trpl::join_all` function accepts any type which 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 `join3` with -`join_all`. +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 +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 `join3` with `join_all`. -+ ```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-14/src/main.rs:here}} ``` Unfortunately, this does not compile. Instead, we get this error: -```text -{{#include ../listings/ch17-async-await/listing-17-18/output.txt}} -``` + -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} -``` - + -The output there would be: +> 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 -{{#include ../listings/ch17-async-await/listing-17-19/output.txt}} +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 ``` -Saying “expected *something*, found *something else*” is Rust’s standard format -for telling us about a type mismatch. As we saw with vectors in [“Using an Enum -to Store Multiple Types”][collections] back in Chapter 8, we need the type of -each item in a collection to be the same—and `tx1_fut`, `rx_fut`, and `tx_fut` -do not have the same type. - -The underlying issue here is what we learned in the previous section: async -blocks compile to anonymous futures. Under the hood, there is a data structure -corresponding to each of these blocks, and it has its own unique type. This -might be surprising. After all, none of them returns anything, so the `Future` -type in each case is `Future`. However, `Future` is a trait, not a -concrete type. The actual types here are invisible from our point of view as the -person writing the code. - -In Chapter 8, we discussed one way to include multiple types in a single vector: -using an enum to represent each of the different types which can appear in the -vector. We cannot do that here, though. For one thing, we do not even have a way -to name the different types, because they are anonymous. For another, the reason -we reached for a vector and `join_all` in the first place was to be able to work -with a dynamic collection of futures where we do not know what they will all be -until runtime. - -To make this work, we need to use *trait objects*, just as we did for returning -different kinds of errors from the same function in [“Returning Errors from the -run function”][dyn] back in Chapter 12. Again, we will cover trait objects in -detail in Chapter 17. Here, it lets us treat each of the anonymous futures -produced by these types as interchangeable, since all of them by definition +This might be surprising. After all, none of them returns anything, so each +block produces a `Future`. However, `Future` is a trait, not a +concrete type. The concrete types are the individual data structures generated +by the compiler for async blocks. You cannot put two different hand-written +structs in a `Vec`, and the same thing applies to the different structs +generated by the compiler. + +To make this work, we need to use *trait objects*, just as we did in [“Returning +Errors from the run function”][dyn] in Chapter 12. (We will cover trait objects +in detail in Chapter 18.) Using trait objects lets us treat each of the +anonymous futures produced by these types as the same type, since all of them implement the `Future` trait. -We can start by wrapping each of the futures in the `vec!` in a `Box::new()`. -Unfortunately, the initial way we might try this, as shown in Listing 17-20, -still does not compile. +> Note: In Chapter 8, we discussed another way to include multiple types in a +> `Vec`: using an enum to represent each of the different types which can +> appear in the vector. We cannot do that here, though. For one thing, we have +> no way to name the different types, because they are anonymous. For another, +> the reason we reached for a vector and `join_all` in the first place was to be +> 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. + + ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-15/src/main.rs:here}} ``` -In fact, we have the same basic 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 can start by fixing the type error around the `Box::new` calls, by telling -the compiler explicitly that we want to use these types as trait objects. The -clearest way to do that here is by adding a type annotation to the declaration -of `futures`, as we see in Listing 17-21. The type we have to write here is a -little involved, so let’s walk through each part of it. +Unfortunately, this still does not compile. In fact, we have the same basic +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). -- The innermost type is the future itself. We note explicitly that it 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`. -- Finally, we state explicitly that `futures` is a `Vec` containing these items. - -+ ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-16/src/main.rs:here}} ``` +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`. +* Then we annotate the trait with `dyn` to mark it as dynamic. +* The entire trait 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 the errors mentioning `Unpin`. Although there are three of them, notice that each is very similar in its contents. -```console -{{#include ../listings/ch17-async-await/listing-17-21/output.txt}} + + +```text +error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned + --> src/main.rs:46:24 + | +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` + | | + | 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<{async block@src/main.rs:8:23: 20:10}>` 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]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned + --> src/main.rs:46:9 + | +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` + +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`. ``` 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, which is itself a `Future`, is also generic over a `Future`, and -`Future` itself requires 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*. +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 From 451f77bc65952032f1946c80525e9792ef1e2da3 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 3 Jul 2024 13:50:07 -0600 Subject: [PATCH 138/249] =?UTF-8?q?Ch.=2017=C2=A703=20initial=20edits=20on?= =?UTF-8?q?=20pinning=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Made a bunch of structural changes, including removing an entire unhelpful aside with an example that actually just confused things, and I *think* it is much more technically accurate *and* much easier to follow. - Updated the listings referenced within it for their new numberings, including deleting one per the above. --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../output.txt | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-22/Cargo.lock | 280 ---------------- .../listing-17-22/src/main.rs | 18 -- .../listing-17-22/test-data/hello.txt | 1 - .../listing-17-22/test-data/punct.txt | 1 - .../listing-17-22/test-data/world.txt | 1 - .../ch17-async-await/listing-17-25/Cargo.toml | 9 - src/ch17-01-futures-and-syntax.md | 20 +- src/ch17-03-more-futures.md | 306 ++++++++---------- 18 files changed, 143 insertions(+), 493 deletions(-) rename listings/ch17-async-await/{listing-17-23 => listing-17-17}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-14 => listing-17-17}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-23 => listing-17-17}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-14 => listing-17-18}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-22 => listing-17-18}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-14 => listing-17-18}/output.txt (100%) rename listings/ch17-async-await/{listing-17-14 => listing-17-18}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-25 => listing-17-19}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-23 => listing-17-19}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-25 => listing-17-19}/src/main.rs (100%) delete mode 100644 listings/ch17-async-await/listing-17-22/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-22/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-22/test-data/hello.txt delete mode 100644 listings/ch17-async-await/listing-17-22/test-data/punct.txt delete mode 100644 listings/ch17-async-await/listing-17-22/test-data/world.txt delete mode 100644 listings/ch17-async-await/listing-17-25/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-23/Cargo.lock b/listings/ch17-async-await/listing-17-17/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-23/Cargo.lock rename to listings/ch17-async-await/listing-17-17/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-14/Cargo.toml b/listings/ch17-async-await/listing-17-17/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-14/Cargo.toml rename to listings/ch17-async-await/listing-17-17/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-23/src/main.rs b/listings/ch17-async-await/listing-17-17/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-23/src/main.rs rename to listings/ch17-async-await/listing-17-17/src/main.rs diff --git a/listings/ch17-async-await/listing-17-14/Cargo.lock b/listings/ch17-async-await/listing-17-18/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-14/Cargo.lock rename to listings/ch17-async-await/listing-17-18/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-22/Cargo.toml b/listings/ch17-async-await/listing-17-18/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-22/Cargo.toml rename to listings/ch17-async-await/listing-17-18/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-14/output.txt b/listings/ch17-async-await/listing-17-18/output.txt similarity index 100% rename from listings/ch17-async-await/listing-17-14/output.txt rename to listings/ch17-async-await/listing-17-18/output.txt diff --git a/listings/ch17-async-await/listing-17-14/src/main.rs b/listings/ch17-async-await/listing-17-18/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-14/src/main.rs rename to listings/ch17-async-await/listing-17-18/src/main.rs diff --git a/listings/ch17-async-await/listing-17-25/Cargo.lock b/listings/ch17-async-await/listing-17-19/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-25/Cargo.lock rename to listings/ch17-async-await/listing-17-19/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-23/Cargo.toml b/listings/ch17-async-await/listing-17-19/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-23/Cargo.toml rename to listings/ch17-async-await/listing-17-19/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-25/src/main.rs b/listings/ch17-async-await/listing-17-19/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-25/src/main.rs rename to listings/ch17-async-await/listing-17-19/src/main.rs diff --git a/listings/ch17-async-await/listing-17-22/Cargo.lock b/listings/ch17-async-await/listing-17-22/Cargo.lock deleted file mode 100644 index 9eeeffaff4..0000000000 --- a/listings/ch17-async-await/listing-17-22/Cargo.lock +++ /dev/null @@ -1,280 +0,0 @@ -# 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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d8b92cd8358e8d229c11df9358decae64d137c5be540952c5ca7b25aea768" - -[[package]] -name = "miniz_oxide" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" -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 = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[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-22/src/main.rs b/listings/ch17-async-await/listing-17-22/src/main.rs deleted file mode 100644 index fbba735c3f..0000000000 --- a/listings/ch17-async-await/listing-17-22/src/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -fn main() { - trpl::block_on({ - // ANCHOR: here - async { - let mut strings = vec![]; - - let a = trpl::read_to_string("test-data/hello.txt").await.unwrap(); - strings.push(a.trim()); - - let b = trpl::read_to_string("test-data/world.txt").await.unwrap(); - strings.push(b.trim()); - - let combined = strings.join(" "); - println!("{combined}"); - } - // ANCHOR_END: here - }); -} diff --git a/listings/ch17-async-await/listing-17-22/test-data/hello.txt b/listings/ch17-async-await/listing-17-22/test-data/hello.txt deleted file mode 100644 index e965047ad7..0000000000 --- a/listings/ch17-async-await/listing-17-22/test-data/hello.txt +++ /dev/null @@ -1 +0,0 @@ -Hello diff --git a/listings/ch17-async-await/listing-17-22/test-data/punct.txt b/listings/ch17-async-await/listing-17-22/test-data/punct.txt deleted file mode 100644 index cdf4cb4feb..0000000000 --- a/listings/ch17-async-await/listing-17-22/test-data/punct.txt +++ /dev/null @@ -1 +0,0 @@ -! diff --git a/listings/ch17-async-await/listing-17-22/test-data/world.txt b/listings/ch17-async-await/listing-17-22/test-data/world.txt deleted file mode 100644 index 216e97ce08..0000000000 --- a/listings/ch17-async-await/listing-17-22/test-data/world.txt +++ /dev/null @@ -1 +0,0 @@ -World diff --git a/listings/ch17-async-await/listing-17-25/Cargo.toml b/listings/ch17-async-await/listing-17-25/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-25/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index d3e08bc01b..f5e912ba79 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -282,18 +282,24 @@ state machine, as if you wrote something like this: ```rust enum MyAsyncStateMachine { - FirstAwaitPoint(/* the state used after the first await point */), - SecondAwaitPoint(/* the state used after the second await point */), + FirstAwaitPoint { + // the state used up to the first await point... + }, + SecondAwaitPoint { + // the state used up to the second await point... + }, // etc. for each `.await` point... } ``` Writing that out by hand would be tedious and error-prone, especially when -making changes to code later. Instead, async Rust creates and manages the state -machine data structures for us. (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!) +making changes to code later. Instead, the Rust compiler creates and manages the +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! 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 diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 7057e02cb2..4f15c6b861 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -234,9 +234,10 @@ the idea of *pinning*. ### Pinning and the Pin and Unpin Traits -When we introduced the `Future` trait in the previous chapter, we saw that the -definition of its `poll` method has an unusual way of specifying the `self` -parameter. To review, here is the full definition of `Future`: + + +Let’s look again at the definition of `Future`, focusing now on its `poll` +method’s `self` type: ```rust pub trait Future { @@ -247,95 +248,15 @@ pub trait Future { } ``` -We have not seen a method definition like this before, where `self` has a type -annotation rather than simply being named like `self`, `mut self`, `&self`, or -`&mut self`. This syntax means that the method can only be called when the -instance of the type which implements `Future` is behind a `Pin` pointer type. -This syntax is not specific to `Pin`; it also works with `Box` and other smart -pointer types, and we will see it again in Chapter 18. - -Here, the signature tells us that if we want to poll a future to check whether -it is `Pending` or `Ready(Output)`, the type which implements `Future` has to be -behind a `Pin` smart 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 [“Futures and Syntax: 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. Consider code which has -a mutable `Vec` of strings, which asynchronously reads strings from files and -pushes those strings into the `Vec`: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:here}} -``` - - - -If we think about the state machine that would get compiled to, it might be -something kind of like this: - -```rust,ignore -enum AsyncStateMachine<'a> { - AfterFirstAwait(&'a mut Vec), - AfterSecondAwait(&'a mut Vec), -} -``` - -That is, at each `.await` in the source code, Rust would look at what state is -needed between that await point and the point another `.await` appears or the -async block ends, and create a corresponding variant in the `AsyncStateMachine`. -Each variant has the appropriate kind of reference to the data that will be -referenced in that section. The real implementation is not *exactly* like this, -but it is close enough to give the right mental model. - -And this could actually be fine, on its own—Rust would keep track of those -mutable references, and if we got something wrong, the borrow checker would tell -us. It gets a bit tricky, though, if we want to move around the future that -corresponds to that block. Remember, we could always do something like this: - -```rust,ignore -let file_reads_future = async { - // snip... -}; - -let some_other_future = async { - // snip... -}; - -trpl::join(file_reads_future, some_other_future).await; -``` - - - -If we pass those futures into `join`, or return them from a function, or put -them in a data structure to keep track of for some reason, that moves the state -machine as well. That means the reference to `Vec` for the values we -read in with `trpl::read_to_string` moves along with it. Since references point -to the actual memory address of the `Vec`, Rust needs some way to either update -them so they are still valid after the `Vec` moves, or it needs some way to keep -`Vec` from getting moved around so that the references do not need to be -updated. Updating all the references to an object every time it moves could be -quite a lot of work for the compiler to add, especially since there can be a -whole web of references that need updating. On the other hand, making sure the -underlying item *does not move in memory* can be “free” at runtime in exchange -for keeping some promises at compile time. That is where `Pin` and `Unpin` come -in. - -> Note: 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 fundamentally, that is a great place to start. -> Those details are not at all necessary for working with async Rust day to day, -> though. Here, we will stick to the parts you *do* need to understand to work -> with them in everyday Rust! +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* @@ -343,65 +264,103 @@ 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. including references, -other smart pointers, and so on. - -Wrapping a pointer type in `Pin` enforces the exact guarantee we need: the value -*behind* the pointer we wrap in `Pin` cannot move. It is “pinned” in its current -spot by the `Pin` wrapper. 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. +`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. Remember: the problem `Pin` addresses is when data -structures have internal references which need to maintained when the structure -moves around, as happens with internal references in futures. 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. But what happens if -you have a `Pin` or a `Pin>`? - -We need a way to tell the compiler that it is actually just fine to move items -around in cases like these where there is nothing to worry about. 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. +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 -most types, and implementing it manually is unsafe. That is because you have to -make sure that the type for which you are implementing `Unsafe` *never* moves -data out from a reference that *needs* to be stable. +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*. That is, they are data structures where one part -> of the structure refers to another internally. As we have seen, futures can -> match that description, so 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. - -Now we know enough to understand the error message from above. The problem is -that the futures produced by an async block are *not* pinned by default. -Strictly: they implement `!Unpin` to opt out of being copyable by default the -way most types are. We need to pin them explicitly. - -Now that we have an idea what that error message was telling us, we can finally -get our `join_all` call to compile! First, we need to explicitly annotate -`futures` as referring to a pinned `Box` of futures. Second, we actually need to -pin the futures, which we can do using the handy `Box::pin` API, which exists -for exactly this. Putting that together, we end up with the code in Listing -17-23. - -+> 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. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-17/src/main.rs:here}} ``` @@ -432,60 +391,55 @@ 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 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 -instead. +with each future, using the `std::pin::pin` macro. -The `std::pin::pin` macro exists to do just that for values. 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-24. +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. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-18/src/main.rs:here}} ``` -This keeps everything on the stack, which is a nice little performance win, but -it is still a lot of explicit types, which is quite unusual for Rust! - 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-25, -the anonymous future type for `a` implements `Future`, the -anonymous future type for `b` implements `Future`, and the -anonymous future type for `c` implements `Future`. We can use -`trpl::join!` to await them together, since it accepts futures of different -types. +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`. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-19/src/main.rs:here}} ``` -We cannot use `trpl::join_all` with these futures, though, because -we will never be able to make them have the same type. (Remember, that error is -what got us started on this adventure with `Pin`!) +We can use `trpl::join!` to await them, because it allows you to pass in +multiple future types and produces a tuple of those htypes. 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`!) -We have a basic tradeoff here: we can either deal with a dynamic number of +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 with a set number of futures with the `join` functions or the `join!` macro, even if they have different types. This is the same as working with any other -type 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 only -as a secondary tool reach for the functions like `join` or `join_all`, or their -corresponding macro equivalents. Likewise, you will only need to reach for `pin` -now and again to use them *with* those APIs. These kinds of tools are mostly -handy for building frameworks, or especially 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! +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! [collections]: ch08-01-vectors.html#using-an-enum-to-store-multiple-types [dyn]: ch12-03-improving-error-handling-and-modularity.html From 1cc4dbedd9d739afcd900841725d4562b88ff442 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 5 Jul 2024 17:25:22 -0600 Subject: [PATCH 139/249] =?UTF-8?q?Ch.=2017=C2=A703:=20Rename=20the=20sect?= =?UTF-8?q?ion=20for=20clarity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SUMMARY.md | 2 +- src/ch17-03-more-futures.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 5a6dbfc377..2645cfcedf 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 Futures](ch17-03-more-futures.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) - [Futures, Tasks, and Threads](ch17-06-futures-tasks-threads.md) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 4f15c6b861..6475a268fa 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -1,4 +1,4 @@ -## Working With More Futures +## Working With More Than Two 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 From cc0f913a74402ad25e43547116428ceb3755db78 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 5 Jul 2024 17:25:22 -0600 Subject: [PATCH 140/249] Ch. 17: remove now unused Listing 17-24 --- .../ch17-async-await/listing-17-24/Cargo.lock | 280 ------------------ .../ch17-async-await/listing-17-24/Cargo.toml | 9 - .../listing-17-24/src/main.rs | 62 ---- 3 files changed, 351 deletions(-) delete mode 100644 listings/ch17-async-await/listing-17-24/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-24/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-24/src/main.rs diff --git a/listings/ch17-async-await/listing-17-24/Cargo.lock b/listings/ch17-async-await/listing-17-24/Cargo.lock deleted file mode 100644 index c0e8bb2b3f..0000000000 --- a/listings/ch17-async-await/listing-17-24/Cargo.lock +++ /dev/null @@ -1,280 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "cc" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.154" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -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.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -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.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 = "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.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tokio" -version = "1.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[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-24/Cargo.toml b/listings/ch17-async-await/listing-17-24/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-24/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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-24/src/main.rs b/listings/ch17-async-await/listing-17-24/src/main.rs deleted file mode 100644 index 7e33ab3cc8..0000000000 --- a/listings/ch17-async-await/listing-17-24/src/main.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::{ - future::Future, - pin::{pin, Pin}, - time::Duration, -}; - -fn main() { - trpl::block_on(async { - 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"), - String::from("the"), - String::from("future"), - ]; - - for val in vals { - tx1.send(val).unwrap(); - trpl::sleep(Duration::from_secs(1)).await; - } - // 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; - }); -} From 1030015d0b34bc72e304f0b8e0c5cb1503faf895 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 5 Jul 2024 17:25:22 -0600 Subject: [PATCH 141/249] =?UTF-8?q?Ch.=2017=C2=A704=20initial=20edits=20on?= =?UTF-8?q?=20intro=20and=20=E2=80=9CYielding=E2=80=9D=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 12 + .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 12 + .../Cargo.toml | 0 .../src/main.rs | 14 +- .../Cargo.lock | 12 + .../Cargo.toml | 0 .../src/main.rs | 18 +- .../ch17-async-await/listing-17-24/Cargo.lock | 292 ++++++++++ .../Cargo.toml | 0 .../src/main.rs | 22 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../ch17-async-await/listing-17-28/output.txt | 38 -- .../ch17-async-await/listing-17-31/Cargo.lock | 540 ------------------ src/ch17-04-more-ways-of-combining-futures.md | 195 +++---- 21 files changed, 448 insertions(+), 707 deletions(-) rename listings/ch17-async-await/{listing-17-26 => listing-17-20}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-26 => listing-17-20}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-26 => listing-17-20}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-27 => listing-17-21}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-27 => listing-17-21}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-27 => listing-17-21}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-28 => listing-17-22}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-28 => listing-17-22}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-28 => listing-17-22}/src/main.rs (75%) rename listings/ch17-async-await/{listing-17-29 => listing-17-23}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-29 => listing-17-23}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-29 => listing-17-23}/src/main.rs (71%) create mode 100644 listings/ch17-async-await/listing-17-24/Cargo.lock rename listings/ch17-async-await/{listing-17-30 => listing-17-24}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-30 => listing-17-24}/src/main.rs (65%) rename listings/ch17-async-await/{listing-17-30 => listing-17-25}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-31 => listing-17-25}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-31 => listing-17-25}/src/main.rs (100%) delete mode 100644 listings/ch17-async-await/listing-17-28/output.txt delete mode 100644 listings/ch17-async-await/listing-17-31/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-26/Cargo.lock b/listings/ch17-async-await/listing-17-20/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-26/Cargo.lock rename to listings/ch17-async-await/listing-17-20/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-26/Cargo.toml b/listings/ch17-async-await/listing-17-20/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-26/Cargo.toml rename to listings/ch17-async-await/listing-17-20/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-26/src/main.rs b/listings/ch17-async-await/listing-17-20/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-26/src/main.rs rename to listings/ch17-async-await/listing-17-20/src/main.rs diff --git a/listings/ch17-async-await/listing-17-27/Cargo.lock b/listings/ch17-async-await/listing-17-21/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-27/Cargo.lock rename to listings/ch17-async-await/listing-17-21/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-27/Cargo.lock +++ b/listings/ch17-async-await/listing-17-21/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-27/Cargo.toml b/listings/ch17-async-await/listing-17-21/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-27/Cargo.toml rename to listings/ch17-async-await/listing-17-21/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-27/src/main.rs b/listings/ch17-async-await/listing-17-21/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-27/src/main.rs rename to listings/ch17-async-await/listing-17-21/src/main.rs diff --git a/listings/ch17-async-await/listing-17-28/Cargo.lock b/listings/ch17-async-await/listing-17-22/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-28/Cargo.lock rename to listings/ch17-async-await/listing-17-22/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-28/Cargo.lock +++ b/listings/ch17-async-await/listing-17-22/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-28/Cargo.toml b/listings/ch17-async-await/listing-17-22/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-28/Cargo.toml rename to listings/ch17-async-await/listing-17-22/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-28/src/main.rs b/listings/ch17-async-await/listing-17-22/src/main.rs similarity index 75% rename from listings/ch17-async-await/listing-17-28/src/main.rs rename to listings/ch17-async-await/listing-17-22/src/main.rs index 9948c79e57..e9474873c9 100644 --- a/listings/ch17-async-await/listing-17-28/src/main.rs +++ b/listings/ch17-async-await/listing-17-22/src/main.rs @@ -5,21 +5,19 @@ fn main() { // ANCHOR: slow-futures let a = async { println!("'a' started."); - slow("a", 300); - slow("a", 100); - slow("a", 200); - slow("a", 900); + 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", 750); - slow("b", 100); - slow("b", 150); + slow("b", 75); + slow("b", 10); + slow("b", 15); slow("b", 350); - slow("b", 150); trpl::sleep(Duration::from_millis(50)).await; println!("'b' finished."); }; diff --git a/listings/ch17-async-await/listing-17-29/Cargo.lock b/listings/ch17-async-await/listing-17-23/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-29/Cargo.lock rename to listings/ch17-async-await/listing-17-23/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-29/Cargo.lock +++ b/listings/ch17-async-await/listing-17-23/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-29/Cargo.toml b/listings/ch17-async-await/listing-17-23/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-29/Cargo.toml rename to listings/ch17-async-await/listing-17-23/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-29/src/main.rs b/listings/ch17-async-await/listing-17-23/src/main.rs similarity index 71% rename from listings/ch17-async-await/listing-17-29/src/main.rs rename to listings/ch17-async-await/listing-17-23/src/main.rs index d5c90e0226..ae9536c5bd 100644 --- a/listings/ch17-async-await/listing-17-29/src/main.rs +++ b/listings/ch17-async-await/listing-17-23/src/main.rs @@ -7,28 +7,24 @@ fn main() { let a = async { println!("'a' started."); - slow("a", 300); + slow("a", 30); trpl::sleep(one_ms).await; - slow("a", 100); + slow("a", 10); trpl::sleep(one_ms).await; - slow("a", 200); - trpl::sleep(one_ms).await; - slow("a", 900); + slow("a", 20); trpl::sleep(one_ms).await; println!("'a' finished."); }; let b = async { println!("'b' started."); - slow("b", 750); - trpl::sleep(one_ms).await; - slow("b", 100); + slow("b", 75); trpl::sleep(one_ms).await; - slow("b", 150); + slow("b", 10); trpl::sleep(one_ms).await; - slow("b", 350); + slow("b", 15); trpl::sleep(one_ms).await; - slow("b", 150); + slow("b", 35); trpl::sleep(one_ms).await; println!("'b' finished."); }; diff --git a/listings/ch17-async-await/listing-17-24/Cargo.lock b/listings/ch17-async-await/listing-17-24/Cargo.lock new file mode 100644 index 0000000000..2e0f3ebedb --- /dev/null +++ b/listings/ch17-async-await/listing-17-24/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.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +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-30/Cargo.toml b/listings/ch17-async-await/listing-17-24/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-30/Cargo.toml rename to listings/ch17-async-await/listing-17-24/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-30/src/main.rs b/listings/ch17-async-await/listing-17-24/src/main.rs similarity index 65% rename from listings/ch17-async-await/listing-17-30/src/main.rs rename to listings/ch17-async-await/listing-17-24/src/main.rs index d4552dace7..7efd8fff9a 100644 --- a/listings/ch17-async-await/listing-17-30/src/main.rs +++ b/listings/ch17-async-await/listing-17-24/src/main.rs @@ -2,35 +2,31 @@ use std::{thread, time::Duration}; fn main() { trpl::block_on(async { - // ANCHOR: here + // ANCHOR: yields let a = async { println!("'a' started."); - slow("a", 300); + slow("a", 30); trpl::yield_now().await; - slow("a", 100); + slow("a", 10); trpl::yield_now().await; - slow("a", 200); - trpl::yield_now().await; - slow("a", 900); + slow("a", 20); trpl::yield_now().await; println!("'a' finished."); }; let b = async { println!("'b' started."); - slow("b", 750); - trpl::yield_now().await; - slow("b", 100); + slow("b", 75); trpl::yield_now().await; - slow("b", 150); + slow("b", 10); trpl::yield_now().await; - slow("b", 350); + slow("b", 15); trpl::yield_now().await; - slow("b", 150); + slow("b", 35); trpl::yield_now().await; println!("'b' finished."); }; - // ANCHOR_end: here + // ANCHOR_END: yields trpl::race(a, b).await; }); diff --git a/listings/ch17-async-await/listing-17-30/Cargo.lock b/listings/ch17-async-await/listing-17-25/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-30/Cargo.lock rename to listings/ch17-async-await/listing-17-25/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-31/Cargo.toml b/listings/ch17-async-await/listing-17-25/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-31/Cargo.toml rename to listings/ch17-async-await/listing-17-25/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-31/src/main.rs b/listings/ch17-async-await/listing-17-25/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-31/src/main.rs rename to listings/ch17-async-await/listing-17-25/src/main.rs diff --git a/listings/ch17-async-await/listing-17-28/output.txt b/listings/ch17-async-await/listing-17-28/output.txt deleted file mode 100644 index 22cbc4fad4..0000000000 --- a/listings/ch17-async-await/listing-17-28/output.txt +++ /dev/null @@ -1,38 +0,0 @@ -$ cargo run - Compiling proc-macro2 v1.0.82 - Compiling unicode-ident v1.0.12 - Compiling autocfg v1.3.0 - Compiling futures-sink v0.3.30 - Compiling futures-core v0.3.30 - Compiling libc v0.2.154 - Compiling pin-project-lite v0.2.14 - Compiling futures-io v0.3.30 - Compiling memchr v2.7.2 - Compiling futures-task 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-26) - Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.32s - Running `target/debug/async_await` -'a' started. -'a' ran for 300ms -'a' ran for 100ms -'a' ran for 200ms -'a' ran for 900ms -'b' started. -'b' ran for 750ms -'b' ran for 100ms -'b' ran for 150ms -'b' ran for 350ms -'b' ran for 150ms -'a' finished. diff --git a/listings/ch17-async-await/listing-17-31/Cargo.lock b/listings/ch17-async-await/listing-17-31/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-31/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index fb0cb56c3c..49e3190237 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -1,113 +1,118 @@ ## More Ways of Combining Futures -Thus far, we have only used the `join` family of functions and macros. When we -“join” on some collection of futures, 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. +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-26, we use `race` to run two futures, `slow` and `fast`, against +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-26/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-20/src/main.rs:here}} ``` -One other thing to notice: if you flip the order of the arguments to `race`, the -order of the start 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 start 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. - -To see why, recall from our discussion in [“What Are Futures?”][futures] that -Rust compiles async blocks in a way that hands control back to the async runtime -at each await point. That has an important corollary: async runtimes can only -switch which future they are executing at await points. Everything in between -await points is just normal synchronous Rust code. That means if you do a bunch -of really expensive work in an async function without an `.await`, that future -will block any other futures from making progress. - -> Note: You may sometimes hear this referred to as one future *starving* other -> futures. The same thing applies to threads, too! - -That has another important consequence for using `race`, `join`, and other such -helpers. *Some* future is going to run first, and everything up to the first -await point in that future will run before any part of any other future gets a -chance to run. For simple code, 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. +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 consider a long-running operation. Here, we will simulate it using `sleep` -inside the function, but in the real world it could be any of operations which -might take a while, and which, critically, are *blocking*. Our `slow` helper -function “slow” will just take a number of milliseconds to run, and sleep the -thread for that long. This is intentionally not an async function, because the -idea is to represent work that is *not* async. +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. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:slow}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-21/src/main.rs:slow}} ``` -In Listing 17-28, we use `slow` to emulate doing this kind of CPU-bound work in +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-28/src/main.rs:slow-futures}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-22/src/main.rs:slow-futures}} ``` If you run this, you will see this output: -```console -{{#include ../listings/ch17-async-await/listing-17-28/output.txt}} + + +```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 when `a` finishes. 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. It would be better if both futures could make progress between their -slow tasks. We need some way to hand control back to the runtime there—and we -know that await points are the way to do that. However, that means we need +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! -However, we can also see the handoff happening in this very example: if we +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*. Given that, maybe we could use the -`sleep` function as a starting point, as in Listing 17-29. +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-29/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-23/src/main.rs:here}} ``` -Now the two futures’ work is interleaved, as we can see if we run it. +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 300ms +'a' ran for 30ms 'b' started. -'b' ran for 750ms -'a' ran for 100ms -'b' ran for 100ms -'a' ran for 200ms -'b' ran for 150ms -'a' ran for 900ms -'b' ran for 350ms +'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 has some expensive work to do up front, but after that they just swap back -and forth every 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. +it calls `slow` before ever calling `trpl::sleep`, but after that the futures +swap back and forth eaach 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. -However, we do not actually need to sleep to accomplish this. We just need to -hand back control to the runtime. We can actually *yield* control back to the -runtime, using a function named `yield_now`. It does just what it says: hands -control back to the runtime, so that the runtime can check whether any other -tasks are ready to make progress. +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-30/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-24/src/main.rs:yields}} ``` @@ -156,34 +157,34 @@ 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-31. (This is not an especially rigorous way to do performance +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-29 and 17-30. Then we run for 1,000 iterations and see how long +Listings 17-23 and 17-24. Then we run for 1,000 iterations and see how long `sleep` takes vs. `yield_now`. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs:here}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-25/src/main.rs:here}} ``` The version with `yield_now` is *way* faster! -> Note: This also means that async can be a useful tool 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 and -> therefore also the *responsibility* to avoid blocking for too long. This is -> how some Rust-based embedded operating systems work! +> Note: This means that async can be a useful tool 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 and therefore +> also the *responsibility* to avoid blocking for too long. This is how some +> Rust-based embedded operating systems work! -In real-world code, you will not usually be alternative regular function calls -with await points on every single line, of course. The underlying dynamic is an +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 @@ -228,7 +229,7 @@ We can write the same signature ourselves, as in Listing 17-33. Then, in the body of the function, we can `race` whatever future the caller passes with a `sleep` future. -When we saw `race` earlier in Listing 17-26, we ignored its return type, +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 From ef1ed96053cc07759f6573a5b5d189f38232fcc3 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 8 Jul 2024 08:28:46 -0600 Subject: [PATCH 142/249] =?UTF-8?q?Ch.=2017=C2=A704=20initial=20edits=20on?= =?UTF-8?q?=20Building=20Our=20Own=20Async=20Abstractions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate `trpl::timeout` entirely. Instead, just build the `timeout` directly (as the rest of the section already did). Restructure the listings as well, eliminating duplication and extraneous bits. --- .../Cargo.lock | 12 + .../Cargo.toml | 0 .../src/main.rs | 4 +- .../Cargo.lock | 12 + .../Cargo.toml | 0 .../src/main.rs | 13 +- .../Cargo.lock | 12 + .../Cargo.toml | 0 .../src/main.rs | 4 +- .../ch17-async-await/listing-17-32/Cargo.lock | 540 ------------------ .../listing-17-34/src/main.rs | 31 - .../ch17-async-await/listing-17-35/Cargo.toml | 9 - packages/trpl/src/lib.rs | 26 +- packages/trpl/tests/integration/main.rs | 27 +- src/ch17-04-more-ways-of-combining-futures.md | 155 +++-- 15 files changed, 132 insertions(+), 713 deletions(-) rename listings/ch17-async-await/{listing-17-34 => listing-17-26}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-32 => listing-17-26}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-32 => listing-17-26}/src/main.rs (75%) rename listings/ch17-async-await/{listing-17-33 => listing-17-27}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-33 => listing-17-27}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-33 => listing-17-27}/src/main.rs (51%) rename listings/ch17-async-await/{listing-17-35 => listing-17-28}/Cargo.lock (96%) rename listings/ch17-async-await/{listing-17-34 => listing-17-28}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-35 => listing-17-28}/src/main.rs (92%) delete mode 100644 listings/ch17-async-await/listing-17-32/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-34/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-35/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-34/Cargo.lock b/listings/ch17-async-await/listing-17-26/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-34/Cargo.lock rename to listings/ch17-async-await/listing-17-26/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-34/Cargo.lock +++ b/listings/ch17-async-await/listing-17-26/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-32/Cargo.toml b/listings/ch17-async-await/listing-17-26/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-32/Cargo.toml rename to listings/ch17-async-await/listing-17-26/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-32/src/main.rs b/listings/ch17-async-await/listing-17-26/src/main.rs similarity index 75% rename from listings/ch17-async-await/listing-17-32/src/main.rs rename to listings/ch17-async-await/listing-17-26/src/main.rs index 5e702a2edc..4727e58c48 100644 --- a/listings/ch17-async-await/listing-17-32/src/main.rs +++ b/listings/ch17-async-await/listing-17-26/src/main.rs @@ -4,11 +4,11 @@ fn main() { trpl::block_on(async { // ANCHOR: here let slow = async { - trpl::sleep(Duration::from_secs(5)).await; + trpl::sleep(Duration::from_millis(100)).await; "I finished!" }; - match trpl::timeout(Duration::from_secs(2), slow).await { + match timeout(slow, Duration::from_millis(10)).await { Ok(message) => println!("Succeeded with '{message}'"), Err(duration) => { println!("Failed after {} seconds", duration.as_secs()) diff --git a/listings/ch17-async-await/listing-17-33/Cargo.lock b/listings/ch17-async-await/listing-17-27/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-33/Cargo.lock rename to listings/ch17-async-await/listing-17-27/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-33/Cargo.lock +++ b/listings/ch17-async-await/listing-17-27/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-33/Cargo.toml b/listings/ch17-async-await/listing-17-27/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-33/Cargo.toml rename to listings/ch17-async-await/listing-17-27/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-33/src/main.rs b/listings/ch17-async-await/listing-17-27/src/main.rs similarity index 51% rename from listings/ch17-async-await/listing-17-33/src/main.rs rename to listings/ch17-async-await/listing-17-27/src/main.rs index 17d2f985f1..a53169bfb2 100644 --- a/listings/ch17-async-await/listing-17-33/src/main.rs +++ b/listings/ch17-async-await/listing-17-27/src/main.rs @@ -7,15 +7,20 @@ fn main() { "Finally finished" }; - // Here we will actually use the new `timeout` with `slow`. + match timeout(slow, Duration::from_millis(10)).await { + Ok(message) => println!("Succeeded with '{message}'"), + Err(duration) => { + println!("Failed after {} seconds", duration.as_secs()) + } + } }); } // ANCHOR: declaration async fn timeout( - max_time: Duration, future: F, + max_time: Duration, ) -> Result { - // ANCHOR_END: declaration - unimplemented!() + // Here is where our implementation will go! } +// ANCHOR_END: declaration diff --git a/listings/ch17-async-await/listing-17-35/Cargo.lock b/listings/ch17-async-await/listing-17-28/Cargo.lock similarity index 96% rename from listings/ch17-async-await/listing-17-35/Cargo.lock rename to listings/ch17-async-await/listing-17-28/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-35/Cargo.lock +++ b/listings/ch17-async-await/listing-17-28/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-34/Cargo.toml b/listings/ch17-async-await/listing-17-28/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-34/Cargo.toml rename to listings/ch17-async-await/listing-17-28/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-35/src/main.rs b/listings/ch17-async-await/listing-17-28/src/main.rs similarity index 92% rename from listings/ch17-async-await/listing-17-35/src/main.rs rename to listings/ch17-async-await/listing-17-28/src/main.rs index 2e389a6509..639d9c8978 100644 --- a/listings/ch17-async-await/listing-17-35/src/main.rs +++ b/listings/ch17-async-await/listing-17-28/src/main.rs @@ -9,9 +9,7 @@ fn main() { "Finally finished" }; - // ANCHOR: main match timeout(Duration::from_secs(2), slow).await { - // ANCHOR_END: main Ok(message) => println!("Succeeded with '{message}'"), Err(duration) => { println!("Failed after {} seconds", duration.as_secs()) @@ -24,8 +22,10 @@ async fn timeout( max_time: Duration, future: F, ) -> Result { + // ANCHOR: implementation match trpl::race(future, 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-32/Cargo.lock b/listings/ch17-async-await/listing-17-32/Cargo.lock deleted file mode 100644 index 3be4eaaa53..0000000000 --- a/listings/ch17-async-await/listing-17-32/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[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.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[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.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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[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 = "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 = "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" -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.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 = "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" -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 = "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 = "tokio" -version = "1.37.0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "trpl" -version = "0.1.0" -dependencies = [ - "futures", - "tokio", -] - -[[package]] -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-34/src/main.rs b/listings/ch17-async-await/listing-17-34/src/main.rs deleted file mode 100644 index 7ff4a59390..0000000000 --- a/listings/ch17-async-await/listing-17-34/src/main.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::{future::Future, time::Duration}; - -// ANCHOR: timeout -use trpl::Either; -// ANCHOR_END: timeout - -fn main() { - trpl::block_on(async { - let slow = async { - trpl::sleep(Duration::from_secs(5)).await; - "Finally finished" - }; - - // Here we will actually use the new `timeout` with `slow`. - }); -} - -// Note for maintainers: the extra space after the `ANCHOR` is intentional: it -// makes this render more nicely! -// ANCHOR: timeout - -async fn timeout( - max_time: Duration, - future: F, -) -> Result { - match trpl::race(future, trpl::sleep(max_time)).await { - Either::Left(output) => Ok(output), - Either::Right(_) => Err(max_time), - } -} -// ANCHOR_END: timeout diff --git a/listings/ch17-async-await/listing-17-35/Cargo.toml b/listings/ch17-async-await/listing-17-35/Cargo.toml deleted file mode 100644 index 349041d3eb..0000000000 --- a/listings/ch17-async-await/listing-17-35/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[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/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index c661ffd459..e95cce16d1 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -13,8 +13,7 @@ //! release at some point. // For direct use within the `trpl` crate, *not* re-exported. -use std::{future::Future, pin::pin, time::Duration}; -use tokio::time; +use std::{future::Future, pin::pin}; // Re-exports, to be used like `trpl::join`. pub use futures::{ @@ -65,22 +64,6 @@ pub fn block_on(future: F) -> F::Output { rt.block_on(future) } -/// Race a future against a specified timeout duration. -/// -/// Under the hood, this uses `tokio::time::timeout`, but instead of returning -/// Tokio's internal error type in the case of a failure, this simply returns -/// the duration which had elapsed. (It actually provides strictly *more* info -/// than Tokio's error does, though it does not `impl Error`.) -pub async fn timeout( - duration: Duration, - future: F, -) -> Result -where - F: Future, -{ - time::timeout(duration, future).await.map_err(|_| duration) -} - /// Run two futures, taking whichever finishes first and canceling the other. /// /// Notice that this is built on [`futures::future::select`], which has the @@ -91,6 +74,13 @@ where /// We use the `race` semantics, where the slower future is simply dropped, for /// the sake of simplicity in the examples: no need to deal with the tuple and /// intentionally ignore the second future this way! +/// +/// Note that this only works as “simply” as it does because: +/// +/// - It takes ownership of the futures. +/// - It internally *pins* the futures. +/// - It throws away (rather than returning) the unused future (which is why it +/// can get away with pinning them). pub async fn race(f1: F1, f2: F2) -> Either where F1: Future, diff --git a/packages/trpl/tests/integration/main.rs b/packages/trpl/tests/integration/main.rs index a46533534a..639c460eb6 100644 --- a/packages/trpl/tests/integration/main.rs +++ b/packages/trpl/tests/integration/main.rs @@ -94,10 +94,10 @@ mod re_exported_join_apis_work { let result = trpl::block_on(async { let a = async { format!("{}", 1) }; - let b = async { format!("Hello") }; + let b = async { "Hello".to_string() }; let outer = String::from("World"); - let c = async move { format!("{outer}") }; + let c = async move { outer.to_string() }; let futures: Vec>>> = vec![Box::pin(a), Box::pin(b), Box::pin(c)]; @@ -131,29 +131,6 @@ mod re_exported_join_apis_work { } } -#[test] -fn re_exported_timeout_works() { - let val = trpl::block_on(async { - let winner = async { - trpl::sleep(Duration::from_millis(1)).await; - String::from("Hello") - }; - trpl::timeout(Duration::from_millis(2), winner).await - }); - - assert_eq!(val, Ok(String::from("Hello"))); - - let val = trpl::block_on(async { - let loser = async { - trpl::sleep(Duration::from_millis(2)).await; - String::from("Hello") - }; - trpl::timeout(Duration::from_millis(1), loser).await - }); - - assert!(val.is_err()); -} - #[test] fn race() { #[derive(Debug, PartialEq)] diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index 49e3190237..060cd569f5 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -73,9 +73,11 @@ a pair of futures. To begin, each future only hands control back to the runtime If you run this, you will see this output: - + ```text 'a' started. @@ -114,9 +116,11 @@ as a starting point? 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. @@ -175,13 +179,13 @@ Listings 17-23 and 17-24. Then we run for 1,000 iterations and see how long The version with `yield_now` is *way* faster! -> Note: This means that async can be a useful tool 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 and therefore -> also the *responsibility* to avoid blocking for too long. This is how some -> Rust-based embedded operating systems work! +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 @@ -189,55 +193,57 @@ important one to keep in mind, though! ### Building Our Own Async Abstractions -Many of these patterns are common enough to warrant abstracting over. For -example, the `trpl::timeout` function takes a `Duration` for the maximum time to -run, but also takes a future to run, and produces a new future you can await, -whose `Output` type is a `Result`. Listing 17-32 shows how we can use it. If -the passed-in future finishes first, the output result will be `Ok`, with the -result of that passed-in future. If the duration elapses before the passed-in -future finishes, the result will be `Err` with the duration that elapsed. +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 -{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs:here}} ++ +```rust,ignore +{{#rustdoc_include ../listings/ch17-async-await/listing-17-26/src/main.rs:here}} ``` -Here we were using the `timeout` supplied by `trpl`, but we do not have to. We -can implement it ourselves using `race` and `sleep`! To begin, let’s think about -the API of `timeout`: +Let’s implement this! To begin, let’s think about the API for `timeout`: -- Its first parameter is a `std::time::Duration` which specifies the maximum - time to wait. -- Its second parameter is the future to run. -- It returns a `Result`. If the future completes successfully, the `Result` will - be `Ok` with the value produced by the future. If the timeout happens, the - `Result` will be `Err` with the duration that the timeout waited for. +- 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. -We can write the same signature ourselves, as in Listing 17-33. +Listing 17-27 shows this declaration. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-33/src/main.rs:declaration}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:declaration}} ``` -Then, in the body of the function, we can `race` whatever future the caller -passes with a `sleep` future. +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 +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`. Like `Result`, -`Either` can be one of two types, but unlike `Result`, there is no notion of -success or failure baked into the type. Instead, it uses `Left` and `Right` to -indicate “one or the other”. Its implementation looks like this: +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”: ```rust enum Either { @@ -246,54 +252,39 @@ enum Either { } ``` -In the case of `race` specifically, it 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. - -```rust,ignore -match trpl::race(future_a, future_b).await { - Either::Left(output_from_future_a) => /* ... */, - Either::Right(output_from_future_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. 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 gives us enough to be able to implement `timeout` ourselves using `race` -and `sleep`. +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. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-34/src/main.rs:timeout}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-28/src/main.rs:implementation}} ``` -Let’s walk through the details. Since we know from earlier that `race` is not -fair, and will prefer the first argument to the second, we pass it the future -first so it gets a chance to complete even if the caller passes in a very short -value for `max_time`. Then we match on the result of awaiting the `race`. If the -future passed in by the caller finished first, we will have `Left(output)`, -which we can return as a success with `Ok`. If the sleep finished first, we will -have `Right(())` instead, since `timeout` returns the unit type `()` if it -succeeds. We can ignore that `()` by using `_` and return `Err` with the -duration the user passed in instead. And that’s it! +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: -Back in `main`, we can call this new `timeout` function exactly like we called -`trpl::timeout` before, but without the `trpl::` namespace: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-35/src/main.rs:main}} +```text +Failed after 2 seconds ``` - - -This pattern is quite common and useful. Futures compose with other futures, so -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—the exact example we started -out with at the beginning of the chapter! +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 From 074c44267fbf09261e0e0b7d797009830d698424 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 9 Jul 2024 09:03:43 -0600 Subject: [PATCH 143/249] =?UTF-8?q?Ch.=2017=C2=A705=20initial=20edits=20on?= =?UTF-8?q?=20first=20two=20sections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Flip the order, so that the semi-practical introduction comes first. - Merge several of the listings together. - The usual polishing and iterating on the text. --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 8 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 6 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 3 - .../listing-17-36/src/main.rs | 8 - .../listing-17-37/src/main.rs | 9 - .../ch17-async-await/listing-17-38/output.txt | 51 --- .../ch17-async-await/listing-17-39/Cargo.lock | 292 ------------------ .../ch17-async-await/listing-17-39/Cargo.toml | 8 - .../ch17-async-await/listing-17-40/Cargo.lock | 292 ------------------ .../ch17-async-await/listing-17-40/Cargo.toml | 8 - src/ch17-05-streams.md | 268 ++++++++-------- 17 files changed, 146 insertions(+), 807 deletions(-) rename listings/ch17-async-await/{listing-17-36 => listing-17-29}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-36 => listing-17-29}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-38 => listing-17-29}/src/main.rs (57%) rename listings/ch17-async-await/{listing-17-37 => listing-17-30}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-37 => listing-17-30}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-39 => listing-17-30}/src/main.rs (69%) rename listings/ch17-async-await/{listing-17-38 => listing-17-31}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-38 => listing-17-31}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-40 => listing-17-31}/src/main.rs (84%) delete mode 100644 listings/ch17-async-await/listing-17-36/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-37/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-38/output.txt delete mode 100644 listings/ch17-async-await/listing-17-39/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-39/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-40/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-40/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-36/Cargo.lock b/listings/ch17-async-await/listing-17-29/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-36/Cargo.lock rename to listings/ch17-async-await/listing-17-29/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-36/Cargo.toml b/listings/ch17-async-await/listing-17-29/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-36/Cargo.toml rename to listings/ch17-async-await/listing-17-29/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-38/src/main.rs b/listings/ch17-async-await/listing-17-29/src/main.rs similarity index 57% rename from listings/ch17-async-await/listing-17-38/src/main.rs rename to listings/ch17-async-await/listing-17-29/src/main.rs index 08bd4b0b72..db9c724d4f 100644 --- a/listings/ch17-async-await/listing-17-38/src/main.rs +++ b/listings/ch17-async-await/listing-17-29/src/main.rs @@ -1,13 +1,13 @@ fn main() { trpl::block_on(async { - let values = 1..101; - let iter = values.map(|n| n * 2); + // 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); - // ANCHOR: next while let Some(value) = stream.next().await { println!("The value was: {value}"); } - // ANCHOR_END: next + // ANCHOR_END: stream }); } diff --git a/listings/ch17-async-await/listing-17-37/Cargo.lock b/listings/ch17-async-await/listing-17-30/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-37/Cargo.lock rename to listings/ch17-async-await/listing-17-30/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-37/Cargo.toml b/listings/ch17-async-await/listing-17-30/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-37/Cargo.toml rename to listings/ch17-async-await/listing-17-30/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-39/src/main.rs b/listings/ch17-async-await/listing-17-30/src/main.rs similarity index 69% rename from listings/ch17-async-await/listing-17-39/src/main.rs rename to listings/ch17-async-await/listing-17-30/src/main.rs index 317677eba1..ad546a68fc 100644 --- a/listings/ch17-async-await/listing-17-39/src/main.rs +++ b/listings/ch17-async-await/listing-17-30/src/main.rs @@ -1,10 +1,9 @@ -// ANCHOR: all use trpl::StreamExt; fn main() { trpl::block_on(async { - let values = 1..101; - let iter = values.map(|n| n * 2); + 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); while let Some(value) = stream.next().await { @@ -12,4 +11,3 @@ fn main() { } }); } -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-38/Cargo.lock b/listings/ch17-async-await/listing-17-31/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-38/Cargo.lock rename to listings/ch17-async-await/listing-17-31/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-38/Cargo.toml b/listings/ch17-async-await/listing-17-31/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-38/Cargo.toml rename to listings/ch17-async-await/listing-17-31/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-40/src/main.rs b/listings/ch17-async-await/listing-17-31/src/main.rs similarity index 84% rename from listings/ch17-async-await/listing-17-40/src/main.rs rename to listings/ch17-async-await/listing-17-31/src/main.rs index 8c98a66dfe..5cda39eb4c 100644 --- a/listings/ch17-async-await/listing-17-40/src/main.rs +++ b/listings/ch17-async-await/listing-17-31/src/main.rs @@ -6,14 +6,11 @@ fn main() { let iter = values.map(|n| n * 2); let stream = trpl::stream_from_iter(iter); - // ANCHOR: filter let mut filtered = stream.filter(|value| value % 3 == 0 || value % 5 == 0); while let Some(value) = filtered.next().await { println!("The value was: {value}"); } - // ANCHOR_END: filter }); } -// ANCHOR_END: all diff --git a/listings/ch17-async-await/listing-17-36/src/main.rs b/listings/ch17-async-await/listing-17-36/src/main.rs deleted file mode 100644 index afe325e6d6..0000000000 --- a/listings/ch17-async-await/listing-17-36/src/main.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - trpl::block_on(async { - // ANCHOR: range - let values = 1..101; - let iter = values.map(|n| n * 2); - // ANCHOR_END: range - }); -} diff --git a/listings/ch17-async-await/listing-17-37/src/main.rs b/listings/ch17-async-await/listing-17-37/src/main.rs deleted file mode 100644 index 5bc9e01ac5..0000000000 --- a/listings/ch17-async-await/listing-17-37/src/main.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - trpl::block_on(async { - let values = 1..101; - let iter = values.map(|n| n * 2); - // ANCHOR: stream - let mut stream = trpl::stream_from_iter(iter); - // ANCHOR_END: stream - }); -} diff --git a/listings/ch17-async-await/listing-17-38/output.txt b/listings/ch17-async-await/listing-17-38/output.txt deleted file mode 100644 index 6e6886fb5c..0000000000 --- a/listings/ch17-async-await/listing-17-38/output.txt +++ /dev/null @@ -1,51 +0,0 @@ -$ cargo run - Compiling proc-macro2 v1.0.85 - Compiling unicode-ident v1.0.12 - Compiling autocfg v1.3.0 - Compiling pin-project-lite v0.2.14 - Compiling futures-core v0.3.30 - Compiling libc v0.2.155 - Compiling futures-sink v0.3.30 - Compiling futures-task v0.3.30 - Compiling pin-utils v0.1.0 - Compiling futures-io v0.3.30 - Compiling memchr v2.7.4 - 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.38.0 - Compiling syn v2.0.66 - 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-38) -error[E0599]: no method named `next` found for struct `Iter` in the current scope - --> src/main.rs:8:40 - | -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-38/target/debug/deps/async_await-bbd5bb8f6851cb5f.long-type-17453505919820464996.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 - | -1 + use futures_util::stream::stream::StreamExt; - | -1 + use std::iter::Iterator; - | -1 + use std::str::pattern::Searcher; - | -1 + use trpl::StreamExt; - | -help: there is a method `try_next` with a similar name - | -8 | while let Some(value) = stream.try_next().await { - | ~~~~~~~~ - -For more information about this error, try `rustc --explain E0599`. -error: could not compile `async_await` (bin "async_await") due to 1 previous error diff --git a/listings/ch17-async-await/listing-17-39/Cargo.lock b/listings/ch17-async-await/listing-17-39/Cargo.lock deleted file mode 100644 index 36905af42a..0000000000 --- a/listings/ch17-async-await/listing-17-39/Cargo.lock +++ /dev/null @@ -1,292 +0,0 @@ -# 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-39/Cargo.toml b/listings/ch17-async-await/listing-17-39/Cargo.toml deleted file mode 100644 index e094f067f1..0000000000 --- a/listings/ch17-async-await/listing-17-39/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[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-40/Cargo.lock b/listings/ch17-async-await/listing-17-40/Cargo.lock deleted file mode 100644 index 36905af42a..0000000000 --- a/listings/ch17-async-await/listing-17-40/Cargo.lock +++ /dev/null @@ -1,292 +0,0 @@ -# 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-40/Cargo.toml b/listings/ch17-async-await/listing-17-40/Cargo.toml deleted file mode 100644 index e094f067f1..0000000000 --- a/listings/ch17-async-await/listing-17-40/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[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/src/ch17-05-streams.md b/src/ch17-05-streams.md index d52334ce02..988ea383f9 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -1,23 +1,116 @@ ## Streams -In Chapter 13, we looked at the `Iterator` trait, and we saw how we could work -with a sequence of items in turn. 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: +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*. + +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` +method, and then awaiting the output, as in Listing 17-29. + ++ +```rust,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:stream}} +``` + + + +We start with an array of numbers, which we convert to an iterator and then call +`map` on to double all the values. Then we convert the iterator into a stream +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. + + + + +```console +error[E0599]: no method named `next` found for struct `Iter` in the current scope + --> src/main.rs:8:40 + | +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: 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 + | +1 + use futures_util::stream::stream::StreamExt; + | +1 + use std::iter::Iterator; + | +1 + use std::str::pattern::Searcher; + | +1 + use trpl::StreamExt; + | +help: there is a method `try_next` with a similar name + | +8 | while let Some(value) = stream.try_next().await { + | ~~~~~~~~ + +For more information about this error, try `rustc --explain E0599`. +``` + +As the output suggests, the problem is that we need the right trait in scope to +be able to use the `next` method. In this case, that trait is `StreamExt`. The +`Ext` there is for “extension”: this is a common pattern in the Rust community +for extending one trait with another. We will discuss `StreamExt` more shortly! +All we need to do here is add a `use` statement for `trpl::StreamExt`, as in +Listing 17-30. + ++ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch17-async-await/listing-17-30/src/main.rs}} +``` + + + +With all those pieces put together, things work the way we want! From here, we +can do the same kinds of things we can with iterators. For example, we can +filter out everything but multiples of three and five by using the `filter` +method, which conveniently also comes from `StreamExt`, as in Listing 17-31. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-11/src/main.rs:loop}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs}} ``` -This is because the `rx` receiver actually represents a *stream* of messages: a -sequence over time. + -Unlike `Iterator` and `Future`, there is no definition of a `Stream` type in the -standard library yet but there *is* a -very common definition used throughout the ecosystem. If we start with the -definition of the `Iterator` and `Trait` types, we can figure out what a trait -that merges them together might look like. +Of course, these examples are not very interesting. We could do these things +with normal iterators and without any async at all. There are more interesting +things we can do with streams, of course! First, though, let’s take a step back +and dig into the `Stream` and `StreamExt` traits themselves. + +### 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. The `Iterator` trait defines an associated type `Item` and a function `next`, which produces `Some(Item)` until the underlying iterator is empty, and then @@ -33,9 +126,9 @@ trait Iterator { } ``` -As we saw earlier in this chapter, the `Future` trait defines an associated item -`Output` and a function `poll`, which produces `Poll::Pending` while waiting and -then `Poll::Ready(Output)` once the future is ready. +The `Future` trait defines an associated item `Output` and a function `poll`, +which produces `Poll::Pending` while waiting and then `Poll::Ready(Output)` once +the future is ready. ```rust trait Future { @@ -45,27 +138,11 @@ trait Future { } ``` -From `Iterator`, we have the idea of a sequence; its `next` method provides an -`Option`. From `Future`, we have the idea of readiness; its `poll` -method provides a `Poll`. To get a stream, a sequence of items -which become ready over time, we can define a `Stream` as a trait which has all -of those features put together: - -* An associated type `Item` for the type of the items, just like in `Iterator`. - Unlike in `Future`, where there was a single `Output`, we use `Item` here to - indicate that it is more like `Iterator`: there may be zero to many of these. - -* A method to get those items. We can call it `poll_next`, to make it clear that - it is polling like a future and producing a sequence of items one after - another, just like an iterator. - -* A return type from `poll_next` which uses both `Poll` and `Option`. The outer - type is `Poll`, since it has to be checked for readiness as a kind of future. - The inner type is `Option`, since it needs to signal whether there are more - messages, just like an iterator. - -When we put those all together, we end up with the same definition for a -`Stream` trait as the one used by the Rust ecosystem: +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 trait Stream { @@ -78,21 +155,30 @@ trait Stream { } ``` -Something very similar to this will likely end up standardized as part of Rust’s -standard library, just the way `Future` was. 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! +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`. -### Working With Streams +`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! -We *could* work directly in terms of the `poll_next` API by hand-writing our own -`Stream` state machines. However, just as we do not generally work with futures -directly via their `poll` method, we generally also do not work directly with -the `poll_next` method for streams. Instead, we usually use a `next` method, -which is defined roughly like this: +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 -trait Stream { +trait StreamExt { async fn next(&mut self) -> Option; } ``` @@ -113,88 +199,14 @@ since the lack thereof is the reason they do not yet have this. > That `Next` type is just a simple `struct` which implements `Future`, so that > `.await` can work with this! -Working with this API will be kind of like working with iterators without the -convenience of a `for` loop. In fact, it will look a lot like the way we used -`rx.recv` back in the [“Message Passing”][17-02-messages] section, using `while -let` loops. - -Let’s start with a very simple example: using an iterator *as* a stream. Let’s -start by creating a range of numbers, including every integer from 1 to 100, -using the `..` range operator. Then we can double all of those values with the -`map` method, as Listing 17-36 shows: - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-36/src/main.rs:range}} -``` - - - -We can convert this iterator to a stream using the `trpl::stream_from_iter` -function. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:stream}} -``` - - - -This gives us the stream. Now, to work with it, we want to use the `next` method -with a `while let` loop as described above, as in Listing 17-38: - -- -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-38/src/main.rs:next}} -``` - - - -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. - -```console -{{#include ../listings/ch17-async-await/listing-17-38/output.txt}} -``` - -As the output suggests, the problem is that we need the right trait in scope to -be able to use it. In this case, that trait is `StreamExt`. (The `Ext` there is -for “extension”: this is a common pattern in the Rust community for extending -one trait with another.) `StreamExt` is automatically implemented for every type +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. All we -need to do, then, is add a `use` statement for `trpl::StreamExt`, as in Listing -17-39. - -- -```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-async-await/listing-17-39/src/main.rs:all}} -``` - - - - With all those pieces put together, things work the way we want! There is a lot - of output, though, since we told it to print all of the 100 numbers in the - iterator. We can filter that down, to, say, multiples of three and five by using - the `filter` method, which conveniently also comes from `StreamExt`. - - - - ```rust,ignore,does_not_compile - {{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:filter}} - ``` - - +iterate on the foundational trait distinctly from the convenience APIs. -Of course, in the real world, the only time we would be directly converting an -iterator to a stream like this is to help break up longer chunks of work, like -we discussed in the previous section. There are more interesting things we can -do with streams, though! +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. ### Composing Streams From fbcdb24fd74219627d47c61a04303e05b2090b27 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 10 Jul 2024 20:03:05 -0600 Subject: [PATCH 144/249] =?UTF-8?q?Ch.=2017=C2=A705=20initial=20edits=20on?= =?UTF-8?q?=20'Composing=20Streams'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 4 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 8 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 4 +- .../listing-17-41/src/main.rs | 17 - .../listing-17-43/src/main.rs | 32 -- .../ch17-async-await/listing-17-44/Cargo.lock | 292 ------------------ .../ch17-async-await/listing-17-44/Cargo.toml | 8 - .../ch17-async-await/listing-17-45/Cargo.lock | 292 ------------------ .../ch17-async-await/listing-17-45/Cargo.toml | 8 - src/ch17-05-streams.md | 161 ++++------ 16 files changed, 73 insertions(+), 753 deletions(-) rename listings/ch17-async-await/{listing-17-41 => listing-17-32}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-41 => listing-17-32}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-42 => listing-17-32}/src/main.rs (91%) rename listings/ch17-async-await/{listing-17-42 => listing-17-33}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-42 => listing-17-33}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-44 => listing-17-33}/src/main.rs (88%) rename listings/ch17-async-await/{listing-17-43 => listing-17-34}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-43 => listing-17-34}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-45 => listing-17-34}/src/main.rs (94%) delete mode 100644 listings/ch17-async-await/listing-17-41/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-43/src/main.rs delete mode 100644 listings/ch17-async-await/listing-17-44/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-44/Cargo.toml delete mode 100644 listings/ch17-async-await/listing-17-45/Cargo.lock delete mode 100644 listings/ch17-async-await/listing-17-45/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-41/Cargo.lock b/listings/ch17-async-await/listing-17-32/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-41/Cargo.lock rename to listings/ch17-async-await/listing-17-32/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-41/Cargo.toml b/listings/ch17-async-await/listing-17-32/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-41/Cargo.toml rename to listings/ch17-async-await/listing-17-32/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-42/src/main.rs b/listings/ch17-async-await/listing-17-32/src/main.rs similarity index 91% rename from listings/ch17-async-await/listing-17-42/src/main.rs rename to listings/ch17-async-await/listing-17-32/src/main.rs index d503a4c77d..5f818ae9f6 100644 --- a/listings/ch17-async-await/listing-17-42/src/main.rs +++ b/listings/ch17-async-await/listing-17-32/src/main.rs @@ -7,18 +7,16 @@ fn main() { while let Some(message) = messages.next().await { println!("{message}"); } - }) + }); } fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); - // ANCHOR: send let messages = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; for message in messages { tx.send(format!("Message: '{message}'")).unwrap(); } - // ANCHOR_END: send ReceiverStream::new(rx) } diff --git a/listings/ch17-async-await/listing-17-42/Cargo.lock b/listings/ch17-async-await/listing-17-33/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-42/Cargo.lock rename to listings/ch17-async-await/listing-17-33/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-42/Cargo.toml b/listings/ch17-async-await/listing-17-33/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-42/Cargo.toml rename to listings/ch17-async-await/listing-17-33/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-44/src/main.rs b/listings/ch17-async-await/listing-17-33/src/main.rs similarity index 88% rename from listings/ch17-async-await/listing-17-44/src/main.rs rename to listings/ch17-async-await/listing-17-33/src/main.rs index 986d0419e9..c99c1f3636 100644 --- a/listings/ch17-async-await/listing-17-44/src/main.rs +++ b/listings/ch17-async-await/listing-17-33/src/main.rs @@ -1,16 +1,11 @@ -// ANCHOR: pin +// ANCHOR: timeout use std::{pin::pin, time::Duration}; -// --snip-- - -// ANCHOR_END: pin use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { trpl::block_on(async { - // ANCHOR: pin let mut messages = pin!(get_messages().timeout(Duration::from_millis(200))); - // ANCHOR_END: pin while let Some(result) = messages.next().await { match result { @@ -20,6 +15,7 @@ fn main() { } }) } +// ANCHOR_END: timeout fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); diff --git a/listings/ch17-async-await/listing-17-43/Cargo.lock b/listings/ch17-async-await/listing-17-34/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-43/Cargo.lock rename to listings/ch17-async-await/listing-17-34/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-43/Cargo.toml b/listings/ch17-async-await/listing-17-34/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-43/Cargo.toml rename to listings/ch17-async-await/listing-17-34/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-45/src/main.rs b/listings/ch17-async-await/listing-17-34/src/main.rs similarity index 94% rename from listings/ch17-async-await/listing-17-45/src/main.rs rename to listings/ch17-async-await/listing-17-34/src/main.rs index f044684113..4dc6ed1fdb 100644 --- a/listings/ch17-async-await/listing-17-45/src/main.rs +++ b/listings/ch17-async-await/listing-17-34/src/main.rs @@ -16,10 +16,10 @@ fn main() { }) } +// ANCHOR: messages fn get_messages() -> impl Stream { let (tx, rx) = trpl::channel(); - // ANCHOR: messages 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() { @@ -29,7 +29,7 @@ fn get_messages() -> impl Stream { tx.send(format!("Message: '{message}'")).unwrap(); } }); - // ANCHOR_END: messages ReceiverStream::new(rx) } +// ANCHOR_END: messages diff --git a/listings/ch17-async-await/listing-17-41/src/main.rs b/listings/ch17-async-await/listing-17-41/src/main.rs deleted file mode 100644 index 4ca575988a..0000000000 --- a/listings/ch17-async-await/listing-17-41/src/main.rs +++ /dev/null @@ -1,17 +0,0 @@ -use trpl::{ReceiverStream, Stream, StreamExt}; - -fn main() { - trpl::block_on(async { - let mut messages = get_messages(); - - while let Some(message) = messages.next().await { - println!("{message}"); - } - }) -} - -fn get_messages() -> impl Stream { - let (tx, rx) = trpl::channel(); - - ReceiverStream::new(rx) -} diff --git a/listings/ch17-async-await/listing-17-43/src/main.rs b/listings/ch17-async-await/listing-17-43/src/main.rs deleted file mode 100644 index 2ec150b9ac..0000000000 --- a/listings/ch17-async-await/listing-17-43/src/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -// ANCHOR: timeout -use std::time::Duration; -// --snip-- -// ANCHOR_END: timeout -use trpl::{ReceiverStream, Stream, StreamExt}; - -fn main() { - trpl::block_on(async { - // ANCHOR: timeout - - let mut messages = get_messages().timeout(Duration::from_millis(200)); - - while let Some(result) = messages.next().await { - match result { - Ok(message) => println!("{message}"), - Err(reason) => eprintln!("Problem: {reason:?}"), - } - } - // ANCHOR_END: timeout - }) -} - -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) -} diff --git a/listings/ch17-async-await/listing-17-44/Cargo.lock b/listings/ch17-async-await/listing-17-44/Cargo.lock deleted file mode 100644 index 36905af42a..0000000000 --- a/listings/ch17-async-await/listing-17-44/Cargo.lock +++ /dev/null @@ -1,292 +0,0 @@ -# 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-44/Cargo.toml b/listings/ch17-async-await/listing-17-44/Cargo.toml deleted file mode 100644 index e094f067f1..0000000000 --- a/listings/ch17-async-await/listing-17-44/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[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-45/Cargo.lock b/listings/ch17-async-await/listing-17-45/Cargo.lock deleted file mode 100644 index 36905af42a..0000000000 --- a/listings/ch17-async-await/listing-17-45/Cargo.lock +++ /dev/null @@ -1,292 +0,0 @@ -# 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-45/Cargo.toml b/listings/ch17-async-await/listing-17-45/Cargo.toml deleted file mode 100644 index e094f067f1..0000000000 --- a/listings/ch17-async-await/listing-17-45/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[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/src/ch17-05-streams.md b/src/ch17-05-streams.md index 988ea383f9..173ee4f0fe 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -210,49 +210,34 @@ streams in interesting ways. ### Composing Streams -For one thing, lots of things are naturally represented as streams—items -becoming available in a queue over time, for example, 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. For another -thing, since streams are futures, we can use them with any other kind of -future, and we can combine them in interesting ways. - -In the real world, we can use this to do things like 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. This is similar to what we -might see from a WebSocket or some other real-time communication protocol. To -begin, we will create a function, `get_messages()`, which returns `impl -Stream`, and use a `while let` loop to print all the messages -from the stream. - -+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. + +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. + +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. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-41/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs}} ``` -In Listing 17-41, we also use a new type: `ReceiverStream`. This converts the -`rx` receiver from the `trpl::channel` into a stream. This is pretty easy, since -the API for a receiver like this already has the same basic shape as a `Stream`. - -So far this will compile just fine, but we are not sending any messages, so -nothing will happen when we run the program. We can change that by looping over -the first ten letters of the English alphabet, and sending those across the -channel. - -- -```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-42/src/main.rs:send}} -``` - - - -When we run the code in Listing 17-42, we get exactly the results we would -expect: +When we run this code, we get exactly the results we would expect: +To sleep between messages in the `get_messages` function without blocking, we +need to use async. However, we cannot make `get_messages` itself into an async +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. Instead, we leave `get_messages` as a regular function which returns a stream, and spawn a task to handle the async `sleep` calls. @@ -345,17 +317,14 @@ and spawn a task to handle the async `sleep` calls. > spawn tasks without reference to a runtime. You should make sure you know what > tradeoff your runtime has chosen and write your code accordingly! -Now our code has a much more interesting result! Between the messages, we see an -error reported: `Problem: Elapsed(())`. Notice that it does not prevent the -messages from arriving in the end—we still get all of the original messages. -This is because our channel is unbounded: it can hold as many messages as we can -fit in memory. If the message does not arrive before the timeout, our stream -handler will account for that, but when it polls the stream again, the message -may now have arrived. +Now our code has a much more interesting result! Between every other pair of +messages, we see an error reported: `Problem: Elapsed(())`. - + ```text Message: 'a' @@ -375,6 +344,12 @@ Problem: Elapsed(()) Message: 'j' ``` +The timeout does not prevent the messages from arriving in the end—we still get +all of the original messages. This is because our channel is unbounded: it can +hold as many messages as we can fit in memory. If the message does not arrive +before the timeout, our stream handler will account for that, but when it polls +the stream again, the message may now have arrived. + You can get different behavior if needed by using other kinds of channels, or other kinds of streams more generally. Let’s see one of those in practice in our final example for this section, by combining a stream of time intervals with From 2797d950ab36f26c11b473461383df16986471f0 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 11 Jul 2024 17:14:08 -0600 Subject: [PATCH 145/249] =?UTF-8?q?Ch.=2017=C2=A705=20initial=20edits=20on?= =?UTF-8?q?=20'Merging=20Streams'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 1 - .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 8 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 8 +- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 25 +-- src/ch17-05-streams.md | 182 ++++++++++-------- 16 files changed, 120 insertions(+), 104 deletions(-) rename listings/ch17-async-await/{listing-17-46 => listing-17-35}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-46 => listing-17-35}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-46 => listing-17-35}/src/main.rs (100%) rename listings/ch17-async-await/{listing-17-47 => listing-17-36}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-47 => listing-17-36}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-47 => listing-17-36}/src/main.rs (99%) rename listings/ch17-async-await/{listing-17-48 => listing-17-37}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-48 => listing-17-37}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-48 => listing-17-37}/src/main.rs (87%) rename listings/ch17-async-await/{listing-17-49 => listing-17-38}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-49 => listing-17-38}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-49 => listing-17-38}/src/main.rs (90%) rename listings/ch17-async-await/{listing-17-50 => listing-17-39}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-50 => listing-17-39}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-50 => listing-17-39}/src/main.rs (78%) diff --git a/listings/ch17-async-await/listing-17-46/Cargo.lock b/listings/ch17-async-await/listing-17-35/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-46/Cargo.lock rename to listings/ch17-async-await/listing-17-35/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-46/Cargo.toml b/listings/ch17-async-await/listing-17-35/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-46/Cargo.toml rename to listings/ch17-async-await/listing-17-35/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-46/src/main.rs b/listings/ch17-async-await/listing-17-35/src/main.rs similarity index 100% rename from listings/ch17-async-await/listing-17-46/src/main.rs rename to listings/ch17-async-await/listing-17-35/src/main.rs diff --git a/listings/ch17-async-await/listing-17-47/Cargo.lock b/listings/ch17-async-await/listing-17-36/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-47/Cargo.lock rename to listings/ch17-async-await/listing-17-36/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-47/Cargo.toml b/listings/ch17-async-await/listing-17-36/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-47/Cargo.toml rename to listings/ch17-async-await/listing-17-36/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-47/src/main.rs b/listings/ch17-async-await/listing-17-36/src/main.rs similarity index 99% rename from listings/ch17-async-await/listing-17-47/src/main.rs rename to listings/ch17-async-await/listing-17-36/src/main.rs index 62a93fc0f6..dde9b34c6f 100644 --- a/listings/ch17-async-await/listing-17-47/src/main.rs +++ b/listings/ch17-async-await/listing-17-36/src/main.rs @@ -7,7 +7,6 @@ fn main() { // ANCHOR: main let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals(); - let merged = messages.merge(intervals); // ANCHOR_END: main diff --git a/listings/ch17-async-await/listing-17-48/Cargo.lock b/listings/ch17-async-await/listing-17-37/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-48/Cargo.lock rename to listings/ch17-async-await/listing-17-37/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-48/Cargo.toml b/listings/ch17-async-await/listing-17-37/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-48/Cargo.toml rename to listings/ch17-async-await/listing-17-37/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-48/src/main.rs b/listings/ch17-async-await/listing-17-37/src/main.rs similarity index 87% rename from listings/ch17-async-await/listing-17-48/src/main.rs rename to listings/ch17-async-await/listing-17-37/src/main.rs index 30d0928ea9..4d2c747cc7 100644 --- a/listings/ch17-async-await/listing-17-48/src/main.rs +++ b/listings/ch17-async-await/listing-17-37/src/main.rs @@ -7,13 +7,13 @@ fn main() { // ANCHOR: main let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() - .map(|count| format!("Interval #{count}")) + .map(|count| format!("Interval: {count}")) .timeout(Duration::from_secs(10)); - - let mut merged = pin!(messages.merge(intervals)); + let merged = messages.merge(intervals); + let mut stream = pin!(merged); // ANCHOR_END: main - while let Some(result) = merged.next().await { + while let Some(result) = stream.next().await { match result { Ok(message) => println!("{message}"), Err(reason) => eprintln!("Problem: {reason:?}"), diff --git a/listings/ch17-async-await/listing-17-49/Cargo.lock b/listings/ch17-async-await/listing-17-38/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-49/Cargo.lock rename to listings/ch17-async-await/listing-17-38/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-49/Cargo.toml b/listings/ch17-async-await/listing-17-38/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-49/Cargo.toml rename to listings/ch17-async-await/listing-17-38/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-49/src/main.rs b/listings/ch17-async-await/listing-17-38/src/main.rs similarity index 90% rename from listings/ch17-async-await/listing-17-49/src/main.rs rename to listings/ch17-async-await/listing-17-38/src/main.rs index 48e4ceea43..5103787668 100644 --- a/listings/ch17-async-await/listing-17-49/src/main.rs +++ b/listings/ch17-async-await/listing-17-38/src/main.rs @@ -4,17 +4,17 @@ use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { trpl::block_on(async { - let messages = get_messages().timeout(Duration::from_millis(200)); // ANCHOR: throttle + let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() .map(|count| format!("Interval #{count}")) .throttle(Duration::from_millis(100)) .timeout(Duration::from_secs(10)); - - let mut merged = pin!(messages.merge(intervals).take(20)); + let merged = messages.merge(intervals).take(20); + let mut stream = pin!(merged); // ANCHOR_END: throttle - while let Some(result) = merged.next().await { + while let Some(result) = stream.next().await { match result { Ok(message) => println!("{message}"), Err(reason) => eprintln!("Problem: {reason:?}"), diff --git a/listings/ch17-async-await/listing-17-50/Cargo.lock b/listings/ch17-async-await/listing-17-39/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-50/Cargo.lock rename to listings/ch17-async-await/listing-17-39/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-50/Cargo.toml b/listings/ch17-async-await/listing-17-39/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-50/Cargo.toml rename to listings/ch17-async-await/listing-17-39/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-50/src/main.rs b/listings/ch17-async-await/listing-17-39/src/main.rs similarity index 78% rename from listings/ch17-async-await/listing-17-50/src/main.rs rename to listings/ch17-async-await/listing-17-39/src/main.rs index e8ee79e4a4..597e6f0298 100644 --- a/listings/ch17-async-await/listing-17-50/src/main.rs +++ b/listings/ch17-async-await/listing-17-39/src/main.rs @@ -23,9 +23,6 @@ fn main() { // ANCHOR: errors fn get_messages() -> impl Stream { - // --snip-- - - // ANCHOR_END: errors let (tx, rx) = trpl::channel(); trpl::spawn_task(async move { @@ -35,27 +32,18 @@ fn get_messages() -> impl Stream { let time_to_sleep = if index % 2 == 0 { 100 } else { 300 }; trpl::sleep(Duration::from_millis(time_to_sleep)).await; - // ANCHOR: errors - if let Err(send_error) = - tx.send(format!("Message: '{message}' after {time_to_sleep}ms")) - { + let result = tx.send(format!("Message: '{message}'")); + if let Err(send_error) = result { eprintln!("Cannot send message '{message}': {send_error}"); break; } - // ANCHOR_END: errors } }); ReceiverStream::new(rx) - // ANCHOR: errors - - // --snip-- } fn get_intervals() -> impl Stream { - // --snip-- - - // ANCHOR_END: errors let (tx, rx) = trpl::channel(); trpl::spawn_task(async move { @@ -63,18 +51,15 @@ fn get_intervals() -> impl Stream { loop { trpl::sleep(Duration::from_millis(1)).await; count += 1; - // ANCHOR: errors - if let Err(send_error) = tx.send(count) { + + let result = tx.send(count); + if let Err(send_error) = result { eprintln!("Could not send interval {count}: {send_error}"); break; }; - // ANCHOR_END: errors } }); ReceiverStream::new(rx) - // ANCHOR: errors - - // --snip-- } // ANCHOR_END: errors diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index 173ee4f0fe..49b69f6246 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -359,14 +359,12 @@ this stream of messages. 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 that delay, and combine it with the same -approach of creating a stream from a channel that we used for `get_messages`. -(There are, of course, many other ways to build streams, including some -dedicated to working with intervals!) The difference is that this time, we are -going to send back the count of intervals, rather than a string, so the -resulting stream will have the type `Stream`. - -In Listing 17-46, we start by defining a `count` in the task. (We could define +`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`. + +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 variable.) Then we create a an infinite loop. Each iteration of the loop asynchronously sleeps for one millisecond, increments the count, and then sends @@ -374,63 +372,65 @@ 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. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-46/src/main.rs:intervals}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-35/src/main.rs:intervals}} ``` This kind of infinite loop, which only ends when the whole runtime gets torn -down, is a fairly common pattern when dealing with many different kinds of async -operations in Rust. That is because there are many kinds of programs which need -to keep running until something actually ends the program. +down, is fairly common in async Rust: many programs need to keep running +indefinitely. With async, this does not block anything else! -Now we need to use these intervals! Back in our main function’s async block, we -start by getting the intervals. Then we can try to create a merged stream using -`messages` and `intervals`, and loop over that combined stream instead of over -`messages` (Listing 17-47). 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 let` loop, but we will come back to that -after fixing this first.) +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). -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-47/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-36/src/main.rs:main}} ``` -The problem is that our two streams have different types. The `messages` stream -has the type `Timeout>`. The `Timeout` is the type -which implements `Stream` for a `timeout` call! Meanwhile, the `intervals` stream has -the type `impl Stream`. To merge these two streams, we need to transform one of -them to match the other. Let’s work with the `intervals`, since `messages` is -already in the basic format we want and has to handle timeout errors. - -Listing 17-48 shows the transformations we need. 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 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. - -+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 +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` +for a `timeout` call. Meanwhile, the `intervals` stream has the type `impl +Stream`. 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 +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 +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. + + ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-48/src/main.rs:main}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:main}} ``` -That gets us *almost* to where we need to be. Everything type checks! If you run -this, though, the messages from the English alphabet will be buried in the midst -of all the interval counter messages: + +That gets us *almost* to where we need to be. Everything type checks. If you run +this, though, there will be two problems. First, it will never stop! You will +need to stop it with ctrl-c. Second, the +messages from the English alphabet will be buried in the midst of all the +interval counter messages: ```text --snip-- -Interval #38 -Interval #39 -Interval #40 +Interval: 38 +Interval: 39 +Interval: 40 Message: 'a' -Interval #41 -Interval #42 -Interval #43 +Interval: 41 +Interval: 42 +Interval: 43 --snip-- ``` -This is no good; we need to only take *some* of those intervals—say, once every -hundred milliseconds. For that, we can use the `throttle` method. 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. We also don’t want to keep going -indefinitely! We can use the `take` method to limit how many items we pull from -a stream. In Listing 17-49, we apply `throttle` to the `intervals` stream, -because we want to avoid overwhelming the stream of messages, but we apply the -`take` method to the *merged* messages, because we want to limit the final +Listing 17-38 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 +hundred milliseconds should do, since that is in the same ballpark as how often +our messages arrive. + +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. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-49/src/main.rs:throttle}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-38/src/main.rs:throttle}} ``` +Now when we run the program, it stop after pulling twenty items from the stream, +and the intervals do not overwhelm the messages. We also do not get `Interval: +100` or `Interval: 200` or so on, but instead simply get `Interval: 1`, +`Interval: 2`, and so on—even though we have a source stream which *can* produce +an event every millisecond. That is because the `throttle` call produces a new +stream, wrapping the original stream, so that the original stream only gets +polled at the throttle rate, not its own “native” rate. We do not have a bunch +of unhandled interval messages we are simply choosing to ignore. Instead, we +never produce those interval messages in the first place! This is the inherent +“laziness” of Rust’s futures at work again, allowing us to choose our +performance characteristics. + + + +```text +Interval #1 +Message: 'a' +Interval #2 +Interval #3 +Problem: Elapsed(()) +Interval #4 +Message: 'b' +Interval #5 +Message: 'c' +Interval #6 +Interval #7 +Problem: Elapsed(()) +Interval #8 +Message: 'd' +Interval #9 +Message: 'e' +Interval #10 +Interval #11 +Problem: Elapsed(()) +Interval #12 +``` + There is one last thing we need to handle: errors! With both of these 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-50 shows +ending the loop so we do not try to send any more messages! Listing 17-39 shows a simple error strategy: print the issue and then `break` from the loops. As -usual, the correct behavior on a message send error will vary—just make sure you -do in fact have a strategy. +usual, the correct way to handle a message send error will vary—just make sure +you have a strategy. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-50/src/main.rs:errors}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-39/src/main.rs:errors}} ``` -Notice that we do not get `Interval #100` or `Interval #200` or so on, but -instead simply get `Interval #1`, `Interval #2`, and so on—even though we have a -source stream which *can* produce an event every millisecond. That is because -the `throttle` call produces a new stream, wrapping the original stream, so that -the original stream only gets polled at the throttle rate, not its own “native” -rate. We do not have a bunch of unhandled interval messages we are simply -choosing to ignore. Instead, we never produce those interval messages in the -first place! This is the inherent “laziness” of Rust’s futures at work again, -allowing us to choose our performance characteristics. - 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. From 92c19ce9cf9b6b711de9b4d22e43bc8a987c14ed Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 11 Jul 2024 19:30:27 -0600 Subject: [PATCH 146/249] =?UTF-8?q?Ch.=2017=C2=A706=20initial=20edits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../listing-17-39/src/main.rs | 14 ++-- .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 19 +++-- packages/trpl/src/lib.rs | 6 +- src/ch17-06-futures-tasks-threads.md | 80 +++++++++++-------- 6 files changed, 65 insertions(+), 54 deletions(-) rename listings/ch17-async-await/{listing-17-51 => listing-17-40}/Cargo.lock (100%) rename listings/ch17-async-await/{listing-17-51 => listing-17-40}/Cargo.toml (100%) rename listings/ch17-async-await/{listing-17-51 => listing-17-40}/src/main.rs (79%) 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 597e6f0298..15a3fddd30 100644 --- a/listings/ch17-async-await/listing-17-39/src/main.rs +++ b/listings/ch17-async-await/listing-17-39/src/main.rs @@ -9,16 +9,16 @@ fn main() { .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); - let mut merged = pin!(messages.merge(intervals).take(20)); - - while let Some(result) = merged.next().await { + while let Some(result) = stream.next().await { match result { Ok(item) => println!("{item}"), Err(reason) => eprintln!("Problem: {reason:?}"), } } - }) + }); } // ANCHOR: errors @@ -32,8 +32,7 @@ fn get_messages() -> impl Stream { let time_to_sleep = if index % 2 == 0 { 100 } else { 300 }; trpl::sleep(Duration::from_millis(time_to_sleep)).await; - let result = tx.send(format!("Message: '{message}'")); - if let Err(send_error) = result { + if let Err(send_error) = tx.send(format!("Message: '{message}'")) { eprintln!("Cannot send message '{message}': {send_error}"); break; } @@ -52,8 +51,7 @@ fn get_intervals() -> impl Stream { trpl::sleep(Duration::from_millis(1)).await; count += 1; - let result = tx.send(count); - if let Err(send_error) = result { + if let Err(send_error) = tx.send(count) { eprintln!("Could not send interval {count}: {send_error}"); break; }; diff --git a/listings/ch17-async-await/listing-17-51/Cargo.lock b/listings/ch17-async-await/listing-17-40/Cargo.lock similarity index 100% rename from listings/ch17-async-await/listing-17-51/Cargo.lock rename to listings/ch17-async-await/listing-17-40/Cargo.lock diff --git a/listings/ch17-async-await/listing-17-51/Cargo.toml b/listings/ch17-async-await/listing-17-40/Cargo.toml similarity index 100% rename from listings/ch17-async-await/listing-17-51/Cargo.toml rename to listings/ch17-async-await/listing-17-40/Cargo.toml diff --git a/listings/ch17-async-await/listing-17-51/src/main.rs b/listings/ch17-async-await/listing-17-40/src/main.rs similarity index 79% rename from listings/ch17-async-await/listing-17-51/src/main.rs rename to listings/ch17-async-await/listing-17-40/src/main.rs index 4b44ab723e..d25f8492ce 100644 --- a/listings/ch17-async-await/listing-17-51/src/main.rs +++ b/listings/ch17-async-await/listing-17-40/src/main.rs @@ -1,4 +1,4 @@ -use std::{pin::pin, time::Duration}; +use std::{pin::pin, thread, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; @@ -9,16 +9,16 @@ fn main() { .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); - let mut merged = pin!(messages.merge(intervals).take(20)); - - while let Some(result) = merged.next().await { + while let Some(result) = stream.next().await { match result { Ok(item) => println!("{item}"), Err(reason) => eprintln!("Problem: {reason:?}"), } } - }) + }); } fn get_messages() -> impl Stream { @@ -31,9 +31,7 @@ fn get_messages() -> impl Stream { 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}' after {time_to_sleep}ms")) - { + if let Err(send_error) = tx.send(format!("Message: '{message}'")) { eprintln!("Cannot send message '{message}': {send_error}"); break; } @@ -47,11 +45,12 @@ fn get_messages() -> impl Stream { fn get_intervals() -> impl Stream { let (tx, rx) = trpl::channel(); - trpl::spawn_task(async move { + thread::spawn(move || { let mut count = 0; loop { - trpl::sleep(Duration::from_millis(1)).await; + 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; diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index e95cce16d1..9336a69a19 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -15,9 +15,11 @@ // For direct use within the `trpl` crate, *not* re-exported. use std::{future::Future, pin::pin}; +use futures::future; + // Re-exports, to be used like `trpl::join`. pub use futures::{ - future::{self, join, join3, join_all, Either}, + future::{join, join3, join_all, Either}, join, }; pub use tokio::{ @@ -38,7 +40,7 @@ pub use tokio::{ unbounded_channel as channel, UnboundedReceiver as Receiver, UnboundedSender as Sender, }, - task::{spawn as spawn_task, yield_now}, + task::{spawn as spawn_task, yield_now, JoinHandle}, time::{interval, sleep}, }; diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index a723a022e9..5a65ab66af 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -3,18 +3,17 @@ As we saw in the previous chapter, threads provide one approach to concurrency. We have seen another approach to concurrency in this chapter, using async with futures and streams. You might be wondering why you would choose one or the -other. The answer is: it depends! And in many cases, it is not threads *vs.* +other. The answer is: it depends! And in many cases, it is not threads *or* async but rather threads *and* async. -Threads are an older and more common tool for concurrency. Many operating -systems have supplied threading-based concurrency models for decades now, and -many programming languages have support for them as a result. 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. +Many operating systems have supplied threading-based concurrency models for +decades now, and many programming languages have support for them as a result. +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. The async model provides a different—and ultimately complementary—set of tradeoffs. In the async model, concurrent operations do not require their own @@ -23,18 +22,17 @@ kick off work from a synchronous function throughout the streams section. A task is a lot like a thread—but instead of being managed by the operating system, it is managed by library-level code: the runtime. -In the previous section, we saw that we could build a `Stream` by using a +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! We’ll use a simpler version of the -streams example so we can focus on the differences. In Listing 17-50, we used -`trpl::spawn_task` and `trpl::sleep`. In Listing 17-51, we replace those with -the `thread::spawn` and `thread::sleep` APIs from the standard library, in just -the `get_intervals` function. +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 +the `thread::spawn` and `thread::sleep` APIs from the standard library in the +`get_intervals` function. -+ ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-51/src/main.rs:threads}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:threads}} ``` @@ -42,21 +40,23 @@ the `get_intervals` function. If you run this, the output is identical. And notice how little changes here from the perspective of the calling code! What is more, even though one of our functions spawned an async task on the runtime and the other spawned an -operating system thread, they worked exactly the same way as far as processing -the stream was concerned. +OS thread, the resulting streams were unaffected by the differences. -However, there is a meaningful difference in the way this system -behaves, although we might have a hard time measuring it in this very simple -example. We could spawn hundreds of thousands or even millions of async tasks on -any modern personal computer. If we tried to do that with threads, we would -literally run out of memory! +However, there is a significant difference between these two approaches behave, +although we might have a hard time measuring it in this very simple example. We +could spawn hundreds of thousands or even millions of async tasks on any modern +personal computer. If we tried to do that with threads, we would literally run +out of memory! However, there is a reason these APIs are so similar. Threads act as a boundary for sets of synchronous operations; concurrency is possible *between* threads. Tasks act as a boundary for sets of *asynchronous* operations; concurrency is 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. +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. However, this does not mean that async tasks are always better than threads, any more than that threads are always better than tasks. @@ -71,12 +71,12 @@ 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 [“Building Our Own Async Abstractions”][combining-futures], or the -`throttle` method we used with streams in [“Working With Streams”][streams]. The fact -that futures are richer data structures means they *can* be composed together -more naturally, as we have seen. +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 +[“Building Our Own Async Abstractions”][combining-futures], or the `throttle` +method we used with streams in [“Working With Streams”][streams]. The fact that +futures are richer data structures means they *can* be composed together more +naturally, as we have seen. Tasks then give *additional* control over futures, allowing you to choose where and how to group them. And it turns out that threads and tasks often work very @@ -88,6 +88,18 @@ 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. +As a default way of thinking about which to use when: + +- If the task is *very parallelizable*, like processing a bunch of data where + each part can be processed separately, threads are a better choice. +- If the task is *very concurrent*, like handling messages from a bunch of + different sources which may come in a different intervals or different rates, + async is a better choice. + +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. + ## Summary This isn’t the last you’ll see of concurrency in this book: the project in @@ -95,8 +107,8 @@ Chapter 21 will use the concepts in this chapter in a more realistic situation than the smaller examples discussed here—and compare more directly what it looks like to solve these kinds of problems with threading vs. with tasks and futures. -Whether with threads or with futures and tasks, or combining them for greatest -performance, Rust gives you the tools you need to write safe, fast, concurrent +Whether with threads, with futures and tasks, or with the combination of them +all, Rust gives you the tools you need to write safe, fast, concurrent code—whether for a high-throughput web server or an embedded operating system. Next, we’ll talk about idiomatic ways to model problems and structure solutions From c3c88e4b4f8e17ca5233535dd32b466a9c50c7a7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 15 Jul 2024 17:28:58 -0600 Subject: [PATCH 147/249] =?UTF-8?q?Ch.=2017=20=C2=A703:=20restore=20accide?= =?UTF-8?q?ntally-removed=20Listing=2017-14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch17-async-await/listing-17-14/Cargo.lock | 292 ++++++++++++++++++ .../ch17-async-await/listing-17-14/Cargo.toml | 9 + .../listing-17-14/src/main.rs | 48 +++ src/ch17-03-more-futures.md | 3 +- 4 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 listings/ch17-async-await/listing-17-14/Cargo.lock create mode 100644 listings/ch17-async-await/listing-17-14/Cargo.toml create mode 100644 listings/ch17-async-await/listing-17-14/src/main.rs diff --git a/listings/ch17-async-await/listing-17-14/Cargo.lock b/listings/ch17-async-await/listing-17-14/Cargo.lock new file mode 100644 index 0000000000..2e0f3ebedb --- /dev/null +++ b/listings/ch17-async-await/listing-17-14/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.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[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.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +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.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +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.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 = "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.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +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-14/Cargo.toml b/listings/ch17-async-await/listing-17-14/Cargo.toml new file mode 100644 index 0000000000..349041d3eb --- /dev/null +++ b/listings/ch17-async-await/listing-17-14/Cargo.toml @@ -0,0 +1,9 @@ +[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-14/src/main.rs b/listings/ch17-async-await/listing-17-14/src/main.rs new file mode 100644 index 0000000000..097114bb73 --- /dev/null +++ b/listings/ch17-async-await/listing-17-14/src/main.rs @@ -0,0 +1,48 @@ +use std::time::Duration; + +fn main() { + trpl::block_on(async { + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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; + } + }; + + 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_secs(1)).await; + } + }; + + // ANCHOR: here + let futures = vec![tx1_fut, rx_fut, tx_fut]; + + trpl::join_all(futures).await; + // ANCHOR_END: here + }); +} diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 6475a268fa..3ae03f25ef 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -25,7 +25,7 @@ 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 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 `join3` with `join_all`. +replace `join!` with `join_all`. @@ -39,7 +39,6 @@ Unfortunately, this does not compile. Instead, we get this error: -This crate currently requires at least Rust 1.77. +This crate currently requires at least Rust 1.79. diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs index 9336a69a19..e096d9d2cd 100644 --- a/packages/trpl/src/lib.rs +++ b/packages/trpl/src/lib.rs @@ -1,4 +1,6 @@ -//! A support crate for _The Rust Programming Language_. +//! A support crate for [_The Rust Programming Language_][trpl]. +//! +//! [trpl]: https://doc.rust-lang.org/book //! //! This crate mostly just re-exports items from *other* crates. It exists for //! two main reasons: From 58fff3cc4864aaa50b24726ae2f5c7b23505aadb Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 16 Jul 2024 16:57:45 -0600 Subject: [PATCH 149/249] =?UTF-8?q?Ch.=2017=C2=A703:=20fix=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit htypes! What are htypes? No one will ever know. Co-authored-by: James Munns --- src/ch17-03-more-futures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 3ae03f25ef..afc00eb3e8 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -421,7 +421,7 @@ future for `b` implements `Future`, and the anonymous future for We can use `trpl::join!` to await them, because it allows you to pass in -multiple future types and produces a tuple of those htypes. We *cannot* use +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`!) From 130e6d09a41d6c112348fd7a3df9f78b078c13c6 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 16 Jul 2024 08:12:22 -0600 Subject: [PATCH 150/249] Ch. 17: correct wrapping for a `Note` --- src/ch17-00-async-await.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index bc1a301a6c..52fe3f8468 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -72,10 +72,10 @@ time. Many operating system APIs for interacting with network sockets are program when they are called until they return. > Note: This is how *most* function calls work, if you think about it! However, -we normally reserve the term “blocking” for function calls which interact with -files, network sockets, or other resources on the computer, because those are -the places where an individual program would benefit from the operation being -*non*-blocking. +> we normally reserve the term “blocking” for function calls which interact with +> files, network sockets, or other resources on the computer, because those are +> the places where an individual program would benefit from the operation being +> *non*-blocking. We could use threads to avoid blocking while downloading files, by using a dedicated thread. But it would be nicer if the call were not blocking in the From bb9cdbb0870a8a0301c02073c306a72b051b6b22 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 17 Jul 2024 14:35:24 -0600 Subject: [PATCH 151/249] Ch. 17: Update CI config to support testing the book with `trpl` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mdBook does not currently have particularly good support for “external” crates. To make the test suite work correctly with `trpl`, we must first build `trpl` itself (`mdbook` will not do it), and then explicitly pass its `deps` path as a library search path for `mdbook test`. That will make sure all the crates can be resolved when running the tests. .github/workflows/main.yml --- .github/workflows/main.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 77495c09aa..5e86a76760 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,8 +24,19 @@ jobs: rustup --version rustc -Vv mdbook --version + + # mdBook does not currently have particularly good support for “external” + # crates. To make the test suite work correctly with `trpl`, we must first + # build `trpl` itself (`mdbook` will not do it), and then explicitly pass + # its `deps` path as a library search path for `mdbook test`. That will make + # sure all the crates can be resolved when running the tests. + - name: Build `trpl` crate + run: | + cd packages/trpl + cargo build - name: Run tests - run: mdbook test + run: + mdbook test --library-path packages/trpl/target/debug/deps package_tests: name: Run package tests runs-on: ubuntu-latest From 24ed6e4c1113533c1c32417e6660ace793e0f7b0 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 17 Jul 2024 14:35:24 -0600 Subject: [PATCH 152/249] =?UTF-8?q?Ch.=2017=C2=A701:=20Make=20code/listing?= =?UTF-8?q?s=20pass=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update the contents of the code in the chapter so it is correct, and update the text to match. Given this is about `Future`, this may also warrant moving/simplifying that whole chunk of code, too. - Update the listing to use `extern crate` since it does not otherwise work correctly with `mdbook test`. Alas. --- .../ch17-async-await/listing-17-04/src/main.rs | 2 ++ src/ch17-01-futures-and-syntax.md | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 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 6974137d66..563aee05b7 100644 --- a/listings/ch17-async-await/listing-17-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + // ANCHOR: main fn main() { trpl::block_on(async { diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index f5e912ba79..146697e919 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -41,8 +41,10 @@ In Rust, writing `async fn` is equivalent to writing a function which returns a defined like this instead: ```rust -fn hello(name: &str) -> impl Future { - async { +use std::future::Future; + +fn hello<'a>(name: &'a str) -> impl Future + 'a { + async move { let greeting = format!("Hello, {name}!"); println!("{greeting}"); } @@ -56,9 +58,10 @@ Let’s walk through each part of the transformed version: * 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`. -* The whole body of the function is wrapped in an `async` block. Remember that - blocks are expressions. This whole block is the expression returned from the - function. +* The whole body of the function is wrapped in an `async move` block. Remember + that blocks are expressions. This whole block is the expression returned from + the function. It is an `async move` block +* It names the fact that * 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. @@ -194,6 +197,9 @@ 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; From deefe4d518c99e6070ad957a6c185fb069809798 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 17 Jul 2024 14:54:27 -0600 Subject: [PATCH 153/249] =?UTF-8?q?Ch.=2017=C2=A702:=20Make=20code/listing?= =?UTF-8?q?s=20pass=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update all the listings in the chapter to use `extern crate` since `mdbook test` does not understand Rust 2018. Alas. - Ignore two of the listings because they never stop. --- listings/ch17-async-await/listing-17-05/src/main.rs | 4 ++++ listings/ch17-async-await/listing-17-06/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-07/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-08/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-09/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-10/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-11/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-12/src/main.rs | 2 ++ src/ch17-02-concurrency-with-async.md | 10 +++++++--- 9 files changed, 25 insertions(+), 3 deletions(-) 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 1a727a9a09..2fe6a5f29d 100644 --- a/listings/ch17-async-await/listing-17-05/src/main.rs +++ b/listings/ch17-async-await/listing-17-05/src/main.rs @@ -1,3 +1,6 @@ +extern crate trpl; // required for mdbook test + +// ANCHOR: all use std::time::Duration; fn main() { @@ -15,3 +18,4 @@ fn main() { } }); } +// ANCHOR_END: all 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 c7e74c8233..67c735fd39 100644 --- a/listings/ch17-async-await/listing-17-06/src/main.rs +++ b/listings/ch17-async-await/listing-17-06/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 7f38d5ebdf..ef52e32840 100644 --- a/listings/ch17-async-await/listing-17-07/src/main.rs +++ b/listings/ch17-async-await/listing-17-07/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 bd19c58886..743a22e239 100644 --- a/listings/ch17-async-await/listing-17-08/src/main.rs +++ b/listings/ch17-async-await/listing-17-08/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + fn main() { trpl::block_on(async { // ANCHOR: 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 7a96259e29..2a98d028bb 100644 --- a/listings/ch17-async-await/listing-17-09/src/main.rs +++ b/listings/ch17-async-await/listing-17-09/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 cbcd9ee60b..1eb0a163ef 100644 --- a/listings/ch17-async-await/listing-17-10/src/main.rs +++ b/listings/ch17-async-await/listing-17-10/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 626999e4f8..025ed3a1ab 100644 --- a/listings/ch17-async-await/listing-17-11/src/main.rs +++ b/listings/ch17-async-await/listing-17-11/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 e51b82ac8a..03fa6a61b5 100644 --- a/listings/ch17-async-await/listing-17-12/src/main.rs +++ b/listings/ch17-async-await/listing-17-12/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 40b2927e42..a57d056814 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -21,7 +21,7 @@ to implement the same counting example as with threads, in Listing 17-5. ```rust -{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-05/src/main.rs:all}} ``` @@ -202,9 +202,11 @@ 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: + + -```rust +```rust,ignore {{#rustdoc_include ../listings/ch17-async-await/listing-17-09/src/main.rs:many-messages}} ``` @@ -260,9 +262,11 @@ 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. + + -```rust +```rust,ignore {{#rustdoc_include ../listings/ch17-async-await/listing-17-10/src/main.rs:futures}} ``` From 6a0d07280a99adbf88889ffecc68e9d5c016db9a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 17 Jul 2024 15:12:54 -0600 Subject: [PATCH 154/249] =?UTF-8?q?Ch.=2017=C2=A703:=20Make=20code/listing?= =?UTF-8?q?s=20pass=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update all the listings in the chapter to use `extern crate` since `mdbook test` does not understand Rust 2018. Alas. - Fix one listing which had gotten out of sync somewhere along the way. (This also fixes a comment flagged up by a reviewer!) --- .../ch17-async-await/listing-17-13/Cargo.lock | 12 +++++++++ .../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 ++ .../ch17-async-await/listing-17-17/Cargo.lock | 12 +++++++++ .../listing-17-17/src/main.rs | 2 ++ .../listing-17-18/src/main.rs | 26 ++++++++++++------- .../ch17-async-await/listing-17-19/Cargo.lock | 12 +++++++++ .../listing-17-19/src/main.rs | 2 ++ src/ch17-03-more-futures.md | 3 +++ 11 files changed, 68 insertions(+), 9 deletions(-) diff --git a/listings/ch17-async-await/listing-17-13/Cargo.lock b/listings/ch17-async-await/listing-17-13/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-13/Cargo.lock +++ b/listings/ch17-async-await/listing-17-13/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-13/src/main.rs b/listings/ch17-async-await/listing-17-13/src/main.rs index 945442dd8a..87b244daa8 100644 --- a/listings/ch17-async-await/listing-17-13/src/main.rs +++ b/listings/ch17-async-await/listing-17-13/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 097114bb73..684b174bdc 100644 --- a/listings/ch17-async-await/listing-17-14/src/main.rs +++ b/listings/ch17-async-await/listing-17-14/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 beff676dbe..5bc9c2c3bd 100644 --- a/listings/ch17-async-await/listing-17-15/src/main.rs +++ b/listings/ch17-async-await/listing-17-15/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 b712d344c0..020a4d37f3 100644 --- a/listings/ch17-async-await/listing-17-16/src/main.rs +++ b/listings/ch17-async-await/listing-17-16/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{future::Future, time::Duration}; fn main() { diff --git a/listings/ch17-async-await/listing-17-17/Cargo.lock b/listings/ch17-async-await/listing-17-17/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-17/Cargo.lock +++ b/listings/ch17-async-await/listing-17-17/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-17/src/main.rs b/listings/ch17-async-await/listing-17-17/src/main.rs index 5520a58ca5..b7fed9b427 100644 --- a/listings/ch17-async-await/listing-17-17/src/main.rs +++ b/listings/ch17-async-await/listing-17-17/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{ future::Future, pin::{pin, Pin}, 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 78e17a3846..2c5748960d 100644 --- a/listings/ch17-async-await/listing-17-18/src/main.rs +++ b/listings/ch17-async-await/listing-17-18/src/main.rs @@ -1,11 +1,17 @@ -use std::time::Duration; +extern crate trpl; // required for mdbook test + +use std::{ + future::Future, + pin::{pin, Pin}, + time::Duration, +}; fn main() { trpl::block_on(async { let (tx, mut rx) = trpl::channel(); let tx1 = tx.clone(); - let tx1_fut = async move { + let tx1_fut = pin!(async move { let vals = vec![ String::from("hi"), String::from("from"), @@ -17,15 +23,15 @@ fn main() { tx1.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - }; + }); - let rx_fut = async { + let rx_fut = pin!(async { while let Some(value) = rx.recv().await { println!("received '{value}'"); } - }; + }); - let tx_fut = async move { + let tx_fut = pin!(async move { let vals = vec![ String::from("more"), String::from("messages"), @@ -37,11 +43,13 @@ fn main() { tx.send(val).unwrap(); trpl::sleep(Duration::from_secs(1)).await; } - }; + }); // ANCHOR: here - let futures = vec![tx1_fut, rx_fut, tx_fut]; - trpl::join_all(futures).await; + 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-19/Cargo.lock b/listings/ch17-async-await/listing-17-19/Cargo.lock index c0e8bb2b3f..2e0f3ebedb 100644 --- a/listings/ch17-async-await/listing-17-19/Cargo.lock +++ b/listings/ch17-async-await/listing-17-19/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-19/src/main.rs b/listings/ch17-async-await/listing-17-19/src/main.rs index 6603223a5b..2088dbe21a 100644 --- a/listings/ch17-async-await/listing-17-19/src/main.rs +++ b/listings/ch17-async-await/listing-17-19/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + fn main() { trpl::block_on(async { // ANCHOR: here diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index afc00eb3e8..1b9c377f5c 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -239,6 +239,9 @@ 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; From 0aacb80bf22e36640e07950ebbaaad8fef3a79aa Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 17 Jul 2024 15:12:54 -0600 Subject: [PATCH 155/249] =?UTF-8?q?Ch.=2017=C2=A704:=20Make=20code/listing?= =?UTF-8?q?s=20pass=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update all the listings in the chapter to use `extern crate` since `mdbook test` does not understand Rust 2018. Alas. - Ignore a listing which has a missing body apurpose. --- listings/ch17-async-await/listing-17-20/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-21/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-22/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-23/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-24/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-25/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-26/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-27/src/main.rs | 2 ++ listings/ch17-async-await/listing-17-28/src/main.rs | 2 ++ src/ch17-04-more-ways-of-combining-futures.md | 4 +++- 10 files changed, 21 insertions(+), 1 deletion(-) 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 eb86c1a486..0ac89fe6c1 100644 --- a/listings/ch17-async-await/listing-17-20/src/main.rs +++ b/listings/ch17-async-await/listing-17-20/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 9d8dedfb3b..fa5cfe3c80 100644 --- a/listings/ch17-async-await/listing-17-21/src/main.rs +++ b/listings/ch17-async-await/listing-17-21/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{thread, time::Duration}; fn main() { 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 e9474873c9..55975462fa 100644 --- a/listings/ch17-async-await/listing-17-22/src/main.rs +++ b/listings/ch17-async-await/listing-17-22/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{thread, time::Duration}; fn main() { 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 ae9536c5bd..f9c795fc0c 100644 --- a/listings/ch17-async-await/listing-17-23/src/main.rs +++ b/listings/ch17-async-await/listing-17-23/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{thread, time::Duration}; fn main() { 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 7efd8fff9a..e95e286a39 100644 --- a/listings/ch17-async-await/listing-17-24/src/main.rs +++ b/listings/ch17-async-await/listing-17-24/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{thread, time::Duration}; fn main() { 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 ef99235640..eaea8509c3 100644 --- a/listings/ch17-async-await/listing-17-25/src/main.rs +++ b/listings/ch17-async-await/listing-17-25/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::{Duration, Instant}; fn main() { 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 4727e58c48..58c83229d4 100644 --- a/listings/ch17-async-await/listing-17-26/src/main.rs +++ b/listings/ch17-async-await/listing-17-26/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::time::Duration; fn main() { 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 a53169bfb2..d30da0d226 100644 --- a/listings/ch17-async-await/listing-17-27/src/main.rs +++ b/listings/ch17-async-await/listing-17-27/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{future::Future, time::Duration}; fn main() { 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 639d9c8978..20e81e77c4 100644 --- a/listings/ch17-async-await/listing-17-28/src/main.rs +++ b/listings/ch17-async-await/listing-17-28/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{future::Future, time::Duration}; use trpl::Either; diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index 060cd569f5..6a307f7814 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -223,9 +223,11 @@ Let’s implement this! To begin, let’s think about the API for `timeout`: Listing 17-27 shows this declaration. + + -```rust +```rust,ignore {{#rustdoc_include ../listings/ch17-async-await/listing-17-27/src/main.rs:declaration}} ``` From 40bdda77f8dae1a2142741c7dcabcf6235f95891 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 17 Jul 2024 15:37:01 -0600 Subject: [PATCH 156/249] =?UTF-8?q?Ch.=2017=C2=A705:=20Make=20code/listing?= =?UTF-8?q?s=20pass=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rewrite the `StreamExt` definition to be more correct, and extract it to a standalone “no-listing listing” so we can make sure its definition at least type checks. - Update all the listings in the chapter to use `extern crate` since `mdbook test` does not understand Rust 2018. Alas. - Ignore the listings (inline or otherwise!) which are *intended* not to compile, so mdbook does not try to test them. - Clarify some of the text around the *actual* Tokio definition of the `StreamExt::next` method. --- .../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 | 4 ++ .../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 + .../no-listing-stream-ext/Cargo.lock | 7 +++ .../no-listing-stream-ext/Cargo.toml | 6 +++ .../no-listing-stream-ext/output.txt | 14 +++++ .../no-listing-stream-ext/src/lib.rs | 18 +++++++ src/ch17-05-streams.md | 52 ++++++------------- 16 files changed, 84 insertions(+), 37 deletions(-) create mode 100644 listings/ch17-async-await/no-listing-stream-ext/Cargo.lock create mode 100644 listings/ch17-async-await/no-listing-stream-ext/Cargo.toml create mode 100644 listings/ch17-async-await/no-listing-stream-ext/output.txt create mode 100644 listings/ch17-async-await/no-listing-stream-ext/src/lib.rs 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 db9c724d4f..7900b39ce4 100644 --- a/listings/ch17-async-await/listing-17-29/src/main.rs +++ b/listings/ch17-async-await/listing-17-29/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + fn main() { trpl::block_on(async { // ANCHOR: stream 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 ad546a68fc..8f8dd7d93f 100644 --- a/listings/ch17-async-await/listing-17-30/src/main.rs +++ b/listings/ch17-async-await/listing-17-30/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use trpl::StreamExt; fn main() { 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 5cda39eb4c..d312640b7f 100644 --- a/listings/ch17-async-await/listing-17-31/src/main.rs +++ b/listings/ch17-async-await/listing-17-31/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use trpl::StreamExt; fn main() { 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 5f818ae9f6..dd1693790d 100644 --- a/listings/ch17-async-await/listing-17-32/src/main.rs +++ b/listings/ch17-async-await/listing-17-32/src/main.rs @@ -1,3 +1,6 @@ +extern crate trpl; // required for mdbook test + +// ANCHOR: all use trpl::{ReceiverStream, Stream, StreamExt}; fn main() { @@ -20,3 +23,4 @@ fn get_messages() -> impl Stream { 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 c99c1f3636..6ad2bc72f9 100644 --- a/listings/ch17-async-await/listing-17-33/src/main.rs +++ b/listings/ch17-async-await/listing-17-33/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + // ANCHOR: timeout use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; 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 4dc6ed1fdb..7446a2e795 100644 --- a/listings/ch17-async-await/listing-17-34/src/main.rs +++ b/listings/ch17-async-await/listing-17-34/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; 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 5dbcb1d96e..a2b36ca487 100644 --- a/listings/ch17-async-await/listing-17-35/src/main.rs +++ b/listings/ch17-async-await/listing-17-35/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; 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 dde9b34c6f..b4cb9c094c 100644 --- a/listings/ch17-async-await/listing-17-36/src/main.rs +++ b/listings/ch17-async-await/listing-17-36/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; 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 4d2c747cc7..4e28174860 100644 --- a/listings/ch17-async-await/listing-17-37/src/main.rs +++ b/listings/ch17-async-await/listing-17-37/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; 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 5103787668..899d14fc23 100644 --- a/listings/ch17-async-await/listing-17-38/src/main.rs +++ b/listings/ch17-async-await/listing-17-38/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; 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 15a3fddd30..1b4e686ea2 100644 --- a/listings/ch17-async-await/listing-17-39/src/main.rs +++ b/listings/ch17-async-await/listing-17-39/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{pin::pin, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; diff --git a/listings/ch17-async-await/no-listing-stream-ext/Cargo.lock b/listings/ch17-async-await/no-listing-stream-ext/Cargo.lock new file mode 100644 index 0000000000..d30b928a6c --- /dev/null +++ b/listings/ch17-async-await/no-listing-stream-ext/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "async_await" +version = "0.1.0" diff --git a/listings/ch17-async-await/no-listing-stream-ext/Cargo.toml b/listings/ch17-async-await/no-listing-stream-ext/Cargo.toml new file mode 100644 index 0000000000..67729afc80 --- /dev/null +++ b/listings/ch17-async-await/no-listing-stream-ext/Cargo.toml @@ -0,0 +1,6 @@ +[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 diff --git a/listings/ch17-async-await/no-listing-stream-ext/output.txt b/listings/ch17-async-await/no-listing-stream-ext/output.txt new file mode 100644 index 0000000000..46e6cd3111 --- /dev/null +++ b/listings/ch17-async-await/no-listing-stream-ext/output.txt @@ -0,0 +1,14 @@ +$ 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` 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 new file mode 100644 index 0000000000..e236c99260 --- /dev/null +++ b/listings/ch17-async-await/no-listing-stream-ext/src/lib.rs @@ -0,0 +1,18 @@ +use std::pin::Pin; +use std::task::{Context, Poll}; + +trait Stream { + type Item; + fn poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>; +} + +// ANCHOR: here +trait StreamExt: Stream { + async fn next(&mut self) -> Option + where + Self: Unpin; +} +// ANCHOR_END: here diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index 49b69f6246..7824c391db 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -21,7 +21,7 @@ method, and then awaiting the output, as in Listing 17-29. -```rust,does_not_compile +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch17-async-await/listing-17-29/src/main.rs:stream}} ``` @@ -112,32 +112,6 @@ press time! --> 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. -The `Iterator` trait defines an associated type `Item` and a function `next`, -which produces `Some(Item)` until the underlying iterator is empty, and then -produces `None`. - - - -```rust -trait Iterator { - type Item; - - fn next(&mut self) -> Option; -} -``` - -The `Future` trait defines an associated item `Output` and a function `poll`, -which produces `Poll::Pending` while waiting and then `Poll::Ready(Output)` once -the future is ready. - -```rust -trait Future { - type Output; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; -} -``` - 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 @@ -145,6 +119,9 @@ 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; @@ -178,9 +155,7 @@ is much nicer, though, so the `StreamExt` trait supplies the `next` method so we can do just that. ```rust -trait StreamExt { - async fn next(&mut self) -> Option; -} +{{#rustdoc_include ../listings/ch17-async-await/no-listing-stream-ext/src/lib.rs:here}} ``` + -```rust +```rust,ignore {{#rustdoc_include ../listings/ch17-async-await/listing-17-37/src/main.rs:main}} ``` From 5099e5fb554103a093ded93c126526ea97b41728 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 17 Jul 2024 15:43:14 -0600 Subject: [PATCH 157/249] =?UTF-8?q?Ch.=2017=C2=A706:=20Make=20code=20listi?= =?UTF-8?q?ng=20pass=20tests=20and=20add=20a=20caption?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- listings/ch17-async-await/listing-17-40/src/main.rs | 4 ++++ src/ch17-06-futures-tasks-threads.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) 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 d25f8492ce..7bd605d528 100644 --- a/listings/ch17-async-await/listing-17-40/src/main.rs +++ b/listings/ch17-async-await/listing-17-40/src/main.rs @@ -1,3 +1,5 @@ +extern crate trpl; // required for mdbook test + use std::{pin::pin, thread, time::Duration}; use trpl::{ReceiverStream, Stream, StreamExt}; @@ -45,9 +47,11 @@ fn get_messages() -> impl Stream { 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; diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 5a65ab66af..24c96d1c09 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -29,7 +29,7 @@ could do the exact same thing with a thread! In Listing 17-39, we used the `thread::spawn` and `thread::sleep` APIs from the standard library in the `get_intervals` function. -+ ```rust {{#rustdoc_include ../listings/ch17-async-await/listing-17-40/src/main.rs:threads}} From 45f163588d17506e4536d84f7a57b6e24bfd9d17 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 22 Jul 2024 10:36:12 -0600 Subject: [PATCH 158/249] Ch. 17: fix spelling issues --- ci/dictionary.txt | 23 +++++++++++++++++++ src/ch17-03-more-futures.md | 2 +- src/ch17-04-more-ways-of-combining-futures.md | 2 +- src/ch17-05-streams.md | 4 ++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/ci/dictionary.txt b/ci/dictionary.txt index 6329ed1238..9fd8e33e41 100644 --- a/ci/dictionary.txt +++ b/ci/dictionary.txt @@ -55,6 +55,7 @@ bool boolean Boolean Booleans +booleans Bors BorrowMutError BoxMeUp @@ -109,6 +110,7 @@ deallocate deallocated deallocating deallocation +debounce debuginfo decl decrementing @@ -145,6 +147,7 @@ DisplayBacktrace DivAssign DraftPost DSTs +durations ebook ebooks Edsger @@ -179,6 +182,7 @@ filesystem's filesystems filmmaking Firefox +FirstAwaitPoint FnMut FnOnce formatter @@ -197,6 +201,7 @@ grapheme Grapheme growable gzip +handoff hardcode hardcoded hardcoding @@ -241,6 +246,7 @@ inline instantiation internet interoperate +IntoFuture IntoIterator InvalidDigit invariants @@ -256,6 +262,7 @@ isize iter iterator's JavaScript +JoinAll JoinHandle Kay's kinded @@ -294,6 +301,8 @@ Metadata metaprogramming mibbit Mibbit +microcontroller +microcontrollers millis minigrep mixup @@ -307,10 +316,12 @@ monomorphized MoveMessage Mozilla mpsc +MSRV msvc MulAssign multibyte multithreaded +multithreading mutex mutex's Mutex @@ -318,6 +329,7 @@ mutexes Mutexes MutexGuard mutext +MyAsyncStateMachine MyBox myprogram namespace @@ -359,6 +371,7 @@ OutlinePrint overloadable overread PanicPayload +parallelizable param parameterize ParseIntError @@ -371,6 +384,7 @@ PlaceholderType polymorphism PoolCreationError portia +postfix powershell PowerShell powi @@ -396,6 +410,8 @@ RangeTo RangeFull README READMEs +ReadFinished +ReceiverStream rect recurse recv @@ -438,6 +454,7 @@ sampleproject screenshot searchstring SecondaryColor +SecondAwaitPoint SelectBox semver SemVer @@ -455,6 +472,7 @@ SliceIndex Smalltalk snuck someproject +SomeType someusername SPDX spdx @@ -470,6 +488,7 @@ stdlib stdout steveklabnik's stringify +StreamExt Stroustrup Stroustrup's struct @@ -514,6 +533,8 @@ tlborm tlsv TODO TokenStream +Tokio +tokio toml TOML toolchain @@ -538,6 +559,7 @@ uncomment Uncomment uncommenting unevaluated +unhandled Uninstalling uninstall unittests @@ -556,6 +578,7 @@ username USERPROFILE usize UsState +util utils vals variable's diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 1b9c377f5c..b27e68ad73 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -154,7 +154,7 @@ That already made a big difference. Now when we run the compiler, we only have the errors mentioning `Unpin`. Although there are three of them, notice that each is very similar in its contents. - > Note: The actual definition we will use looks slightly different than this, From 463b819a750d4376eb36305187c67b0c56647cd3 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 22 Jul 2024 12:04:09 -0600 Subject: [PATCH 159/249] Ch. 17: fix internal links with new ch. order Note: this does *not* include all fixes for the text, only for the links themselves. For the text, we will also need to search for references to chapters 17-20. This catches a few of those along the way, but there are no doubt others. --- 2018-edition/src/ch17-03-oo-design-patterns.md | 4 ++-- second-edition/src/ch17-03-oo-design-patterns.md | 4 ++-- second-edition/src/ch18-00-patterns.md | 4 ++-- src/appendix-03-derivable-traits.md | 2 +- src/ch05-03-method-syntax.md | 2 +- src/ch06-02-match.md | 5 +++-- src/ch09-02-recoverable-errors-with-result.md | 2 +- src/ch09-03-to-panic-or-not-to-panic.md | 2 +- src/ch10-02-traits.md | 2 +- src/ch12-00-an-io-project.md | 2 +- src/ch12-03-improving-error-handling-and-modularity.md | 2 +- src/ch15-01-box.md | 2 +- src/ch17-05-streams.md | 2 +- src/ch17-06-futures-tasks-threads.md | 6 +++--- src/ch18-02-trait-objects.md | 2 +- src/ch18-03-oo-design-patterns.md | 2 +- src/ch19-01-all-the-places-for-patterns.md | 2 +- src/ch20-03-advanced-traits.md | 2 +- src/ch20-04-advanced-types.md | 6 +++--- src/ch20-05-advanced-functions-and-closures.md | 6 +++--- src/ch21-02-multithreaded.md | 2 +- 21 files changed, 32 insertions(+), 31 deletions(-) diff --git a/2018-edition/src/ch17-03-oo-design-patterns.md b/2018-edition/src/ch17-03-oo-design-patterns.md index 1b74425fe2..9513538f57 100644 --- a/2018-edition/src/ch17-03-oo-design-patterns.md +++ b/2018-edition/src/ch17-03-oo-design-patterns.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-03-oo-design-patterns.html) instead. +version of the book](../ch18-03-oo-design-patterns.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-03-oo-design-patterns.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-03-oo-design-patterns.html). diff --git a/second-edition/src/ch17-03-oo-design-patterns.md b/second-edition/src/ch17-03-oo-design-patterns.md index 46bec2692f..b29dc2393c 100644 --- a/second-edition/src/ch17-03-oo-design-patterns.md +++ b/second-edition/src/ch17-03-oo-design-patterns.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-03-oo-design-patterns.html) instead. +version of the book](../ch18-03-oo-design-patterns.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-03-oo-design-patterns.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-03-oo-design-patterns.html). diff --git a/second-edition/src/ch18-00-patterns.md b/second-edition/src/ch18-00-patterns.md index 6bd221fa3c..e315b35274 100644 --- a/second-edition/src/ch18-00-patterns.md +++ b/second-edition/src/ch18-00-patterns.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-00-patterns.html) instead. +version of the book](../ch19-00-patterns.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-00-patterns.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-00-patterns.html). diff --git a/src/appendix-03-derivable-traits.md b/src/appendix-03-derivable-traits.md index 8b9b3d3584..d3951f9e5f 100644 --- a/src/appendix-03-derivable-traits.md +++ b/src/appendix-03-derivable-traits.md @@ -184,4 +184,4 @@ ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struc ch04-01-what-is-ownership.html#stack-only-data-copy [ways-variables-and-data-interact-clone]: ch04-01-what-is-ownership.html#ways-variables-and-data-interact-clone -[macros]: ch19-06-macros.html#macros +[macros]: ch20-06-macros.html#macros diff --git a/src/ch05-03-method-syntax.md b/src/ch05-03-method-syntax.md index d25e55b18c..f806021687 100644 --- a/src/ch05-03-method-syntax.md +++ b/src/ch05-03-method-syntax.md @@ -250,6 +250,6 @@ But structs aren’t the only way you can create custom types: let’s turn to Rust’s enum feature to add another tool to your toolbox. [enums]: ch06-00-enums.html -[trait-objects]: ch17-02-trait-objects.md +[trait-objects]: ch18-02-trait-objects.md [public]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword [modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html diff --git a/src/ch06-02-match.md b/src/ch06-02-match.md index 6a510df402..bdb5244100 100644 --- a/src/ch06-02-match.md +++ b/src/ch06-02-match.md @@ -246,9 +246,10 @@ that doesn’t match a pattern in an earlier arm, and we don’t want to run any code in this case. There’s more about patterns and matching that we’ll cover in [Chapter -18][ch18-00-patterns]. For now, we’re going to move on to the +19][ch19-00-patterns]. For now, we’re going to move on to the `if let` syntax, which can be useful in situations where the `match` expression is a bit wordy. [tuples]: ch03-02-data-types.html#the-tuple-type -[ch18-00-patterns]: ch18-00-patterns.html + +[ch19-00-patterns]: ch19-00-patterns.html diff --git a/src/ch09-02-recoverable-errors-with-result.md b/src/ch09-02-recoverable-errors-with-result.md index 35bcd11474..78a87c7392 100644 --- a/src/ch09-02-recoverable-errors-with-result.md +++ b/src/ch09-02-recoverable-errors-with-result.md @@ -533,5 +533,5 @@ let’s return to the topic of how to decide which is appropriate to use in whic cases. [handle_failure]: ch02-00-guessing-game-tutorial.html#handling-potential-failure-with-result -[trait-objects]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[trait-objects]: ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types [termination]: ../std/process/trait.Termination.html diff --git a/src/ch09-03-to-panic-or-not-to-panic.md b/src/ch09-03-to-panic-or-not-to-panic.md index 40f93d67ce..138a783d00 100644 --- a/src/ch09-03-to-panic-or-not-to-panic.md +++ b/src/ch09-03-to-panic-or-not-to-panic.md @@ -219,4 +219,4 @@ Now that you’ve seen useful ways that the standard library uses generics with the `Option` and `Result` enums, we’ll talk about how generics work and how you can use them in your code. -[encoding]: ch17-03-oo-design-patterns.html#encoding-states-and-behavior-as-types +[encoding]: ch18-03-oo-design-patterns.html#encoding-states-and-behavior-as-types diff --git a/src/ch10-02-traits.md b/src/ch10-02-traits.md index 53e9b8115c..855ee1fc4b 100644 --- a/src/ch10-02-traits.md +++ b/src/ch10-02-traits.md @@ -385,5 +385,5 @@ that checks for behavior at runtime because we’ve already checked at compile time. Doing so improves performance without having to give up the flexibility of generics. -[using-trait-objects-that-allow-for-values-of-different-types]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[using-trait-objects-that-allow-for-values-of-different-types]: ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types [methods]: ch05-03-method-syntax.html#defining-methods diff --git a/src/ch12-00-an-io-project.md b/src/ch12-00-an-io-project.md index bae99c75f7..7780ac2738 100644 --- a/src/ch12-00-an-io-project.md +++ b/src/ch12-00-an-io-project.md @@ -47,4 +47,4 @@ detail. [ch10]: ch10-00-generics.html [ch11]: ch11-00-testing.html [ch13]: ch13-00-functional-features.html -[ch17]: ch17-00-oop.html +[ch17]: ch18-00-oop.html diff --git a/src/ch12-03-improving-error-handling-and-modularity.md b/src/ch12-03-improving-error-handling-and-modularity.md index 0de3ec2c22..bcff43a6d9 100644 --- a/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/ch12-03-improving-error-handling-and-modularity.md @@ -491,5 +491,5 @@ write some tests! [ch9-custom-types]: ch09-03-to-panic-or-not-to-panic.html#creating-custom-types-for-validation [ch9-error-guidelines]: ch09-03-to-panic-or-not-to-panic.html#guidelines-for-error-handling [ch9-result]: ch09-02-recoverable-errors-with-result.html -[ch17]: ch17-00-oop.html +[ch17]: ch18-00-oop.html [ch9-question-mark]: ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator diff --git a/src/ch15-01-box.md b/src/ch15-01-box.md index 53e829a4c3..1878f6f195 100644 --- a/src/ch15-01-box.md +++ b/src/ch15-01-box.md @@ -252,4 +252,4 @@ even more important to the functionality provided by the other smart pointer types we’ll discuss in the rest of this chapter. Let’s explore these two traits in more detail. -[trait-objects]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[trait-objects]: ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types diff --git a/src/ch17-05-streams.md b/src/ch17-05-streams.md index 1a3a9b850f..8a44d37059 100644 --- a/src/ch17-05-streams.md +++ b/src/ch17-05-streams.md @@ -508,4 +508,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.md#message-passing diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 24c96d1c09..7ee933c4f7 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -74,7 +74,7 @@ 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 [“Building Our Own Async Abstractions”][combining-futures], or the `throttle` -method we used with streams in [“Working With Streams”][streams]. The fact that +method we used with streams in [“Composing Streams”][streams]. The fact that futures are richer data structures means they *can* be composed together more naturally, as we have seen. @@ -116,5 +116,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#working-with-streams +[combining-futures]: ch17-04-more-ways-of-combining-futures.md#building-our-own-async-abstractions +[streams]: ch17-05-streams.md#composing-streams diff --git a/src/ch18-02-trait-objects.md b/src/ch18-02-trait-objects.md index 2d3fea24a1..c6a90ab2ff 100644 --- a/src/ch18-02-trait-objects.md +++ b/src/ch18-02-trait-objects.md @@ -253,4 +253,4 @@ support in Listing 17-9, so it’s a trade-off to consider. [performance-of-code-using-generics]: ch10-01-syntax.html#performance-of-code-using-generics -[dynamically-sized]: ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait +[dynamically-sized]: ch20-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait diff --git a/src/ch18-03-oo-design-patterns.md b/src/ch18-03-oo-design-patterns.md index 13503ef02b..6044841631 100644 --- a/src/ch18-03-oo-design-patterns.md +++ b/src/ch18-03-oo-design-patterns.md @@ -513,4 +513,4 @@ lots of flexibility. We’ve looked at them briefly throughout the book but haven’t seen their full capability yet. Let’s go! [more-info-than-rustc]: ch09-03-to-panic-or-not-to-panic.html#cases-in-which-you-have-more-information-than-the-compiler -[macros]: ch19-06-macros.html#macros +[macros]: ch20-06-macros.html#macros diff --git a/src/ch19-01-all-the-places-for-patterns.md b/src/ch19-01-all-the-places-for-patterns.md index 58f5af573b..e6f9ebd2cb 100644 --- a/src/ch19-01-all-the-places-for-patterns.md +++ b/src/ch19-01-all-the-places-for-patterns.md @@ -247,4 +247,4 @@ be irrefutable; in other circumstances, they can be refutable. We’ll discuss these two concepts next. [ignoring-values-in-a-pattern]: -ch18-03-pattern-syntax.html#ignoring-values-in-a-pattern +ch19-03-pattern-syntax.html#ignoring-values-in-a-pattern diff --git a/src/ch20-03-advanced-traits.md b/src/ch20-03-advanced-traits.md index 789591357b..a32b0e1da7 100644 --- a/src/ch20-03-advanced-traits.md +++ b/src/ch20-03-advanced-traits.md @@ -459,7 +459,7 @@ behavior—we would have to implement just the methods we do want manually. This newtype pattern is also useful even when traits are not involved. Let’s switch focus and look at some advanced ways to interact with Rust’s type system. -[newtype]: ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types +[newtype]: ch20-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types [implementing-a-trait-on-a-type]: ch10-02-traits.html#implementing-a-trait-on-a-type [traits-defining-shared-behavior]: diff --git a/src/ch20-04-advanced-types.md b/src/ch20-04-advanced-types.md index 2dfed23cca..427c108aa4 100644 --- a/src/ch20-04-advanced-types.md +++ b/src/ch20-04-advanced-types.md @@ -288,10 +288,10 @@ pointer. In this case, we’ve chosen a reference. Next, we’ll talk about functions and closures! [encapsulation-that-hides-implementation-details]: -ch17-01-what-is-oo.html#encapsulation-that-hides-implementation-details +ch18-01-what-is-oo.html#encapsulation-that-hides-implementation-details [string-slices]: ch04-03-slices.html#string-slices [the-match-control-flow-operator]: ch06-02-match.html#the-match-control-flow-operator [using-trait-objects-that-allow-for-values-of-different-types]: -ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types -[using-the-newtype-pattern]: ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types +ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[using-the-newtype-pattern]: ch20-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types diff --git a/src/ch20-05-advanced-functions-and-closures.md b/src/ch20-05-advanced-functions-and-closures.md index 88c46847d5..d0de1dfd0a 100644 --- a/src/ch20-05-advanced-functions-and-closures.md +++ b/src/ch20-05-advanced-functions-and-closures.md @@ -119,12 +119,12 @@ We can use a trait object: This code will compile just fine. For more about trait objects, refer to the section [“Using Trait Objects That Allow for Values of Different Types”][using-trait-objects-that-allow-for-values-of-different-types] in Chapter 17. +ignore --> in Chapter 18. Next, let’s look at macros! [advanced-traits]: -ch19-03-advanced-traits.html#advanced-traits +ch20-03-advanced-traits.html#advanced-traits [enum-values]: ch06-01-defining-an-enum.html#enum-values [using-trait-objects-that-allow-for-values-of-different-types]: -ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types diff --git a/src/ch21-02-multithreaded.md b/src/ch21-02-multithreaded.md index cec2272db5..82d6fdf8f6 100644 --- a/src/ch21-02-multithreaded.md +++ b/src/ch21-02-multithreaded.md @@ -690,7 +690,7 @@ the associated block. In Listing 20-21, the lock remains held for the duration of the call to `job()`, meaning other workers cannot receive jobs. [creating-type-synonyms-with-type-aliases]: -ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases +ch20-04-advanced-types.html#creating-type-synonyms-with-type-aliases [integer-types]: ch03-02-data-types.html#integer-types [fn-traits]: ch13-01-closures.html#moving-captured-values-out-of-the-closure-and-the-fn-traits From 644dbab3d6d8f392905bdb609ea77f5d34d4fc02 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 22 Jul 2024 12:17:39 -0600 Subject: [PATCH 160/249] Ch. 17: fix an internal link reference --- src/ch06-02-match.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch06-02-match.md b/src/ch06-02-match.md index bdb5244100..eec1ac4a89 100644 --- a/src/ch06-02-match.md +++ b/src/ch06-02-match.md @@ -6,7 +6,7 @@ Rust has an extremely powerful control flow construct called `match` that allows you to compare a value against a series of patterns and then execute code based on which pattern matches. Patterns can be made up of literal values, variable names, wildcards, and many other things; [Chapter -18][ch18-00-patterns] covers all the different kinds of patterns +18][ch19-00-patterns] covers all the different kinds of patterns and what they do. The power of `match` comes from the expressiveness of the patterns and the fact that the compiler confirms that all possible cases are handled. From e6692504c64d56437d5395fd78fd39dfcca10cc1 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 23 Jul 2024 16:00:01 -0600 Subject: [PATCH 161/249] =?UTF-8?q?Ch.=2017=C2=A700:=20phrasing/wording-le?= =?UTF-8?q?vel=20improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim McNamara Co-authored-by: James Munns --- src/ch17-00-async-await.md | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 52fe3f8468..3acc65b1c6 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -38,25 +38,25 @@ 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. You are -mostly waiting on data to transfer across the network. You can start reading -from a network socket, but it might take a while for all the data to arrive and -be fed into the socket by the network controller. 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 socket. 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 happen while the network -operation is still ongoing. +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 socket. 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 +happen while the network operation is still ongoing. > Note: The video export is the kind of operation which is often described as -> “CPU-bound”. It is limited by the speed of the computer’s *CPU and GPU*, and -> how much of that speed it can use. The video download is the kind of operation -> which is often described as “IO-bound,” because it is limited by the speed of -> the computer’s *input and output*. It can only go as fast as the data can be -> sent across the network, which means that it can only go as fast as the data -> can be written to the socket by the network controller. +> “CPU-bound” or “compute-bound”. It is limited by the speed of the computer’s +> ability to process data within the *CPU* or *GPU*, and how much of that speed +> it can use. The video download is the kind of operation which is often +> described as “IO-bound,” because it is limited by the speed of the computer’s +> *input and output*. It can only go as fast as the data can be sent across the +> network, which means that it can only go as fast as the data can be written to +> the socket by the network controller. 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 @@ -68,8 +68,8 @@ For example, if we are building a tool to manage file downloads, we should be able to write our program in such a way that starting one download does not lock up the UI, and users should be able to start multiple downloads at the same time. Many operating system APIs for interacting with network sockets are -*blocking*, though. That is, the function calls block further progress in the -program when they are called until they return. +*blocking*, though. That is, these APIs block the program’s progress until the +data that they are processing is completely ready. > Note: This is how *most* function calls work, if you think about it! However, > we normally reserve the term “blocking” for function calls which interact with @@ -77,8 +77,8 @@ program when they are called until they return. > the places where an individual program would benefit from the operation being > *non*-blocking. -We could use threads to avoid blocking while downloading files, by using a -dedicated thread. But it would be nicer if the call were not blocking in the +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. One way to accomplish that would be to use an API built around callbacks. For From 133bb617d7c7c463e3894a25e96f8677fa8e925f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 23 Jul 2024 17:12:12 -0600 Subject: [PATCH 162/249] =?UTF-8?q?Ch.=2017=C2=A700:=20phrasing/wording-le?= =?UTF-8?q?vel=20improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Carol (Nichols || Goulding) Co-authored-by: Will Crichton Co-authored-by: Tim McNamara --- src/ch17-01-futures-and-syntax.md | 34 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 146697e919..272471247a 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -58,10 +58,13 @@ Let’s walk through each part of the transformed version: * 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`. -* The whole body of the function is wrapped in an `async move` block. Remember - that blocks are expressions. This whole block is the expression returned from - the function. It is an `async move` block -* It names the fact that +* 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. +* 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. @@ -73,10 +76,11 @@ return type of the original `async fn`. Thus, calling `hello` in Listing 17-1 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. 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. +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 @@ -130,12 +134,12 @@ However, we get another compiler error here: The problem is that async code needs a *runtime*: a Rust crate which manages the details of executing asynchronous code. -Most languages which support async bundle a runtime with the language. At least -for now, 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 dozens of CPU cores and -terabytes of RAM has very different different needs than a microcontroller with -a single core, one gigabyte of RAM, and no ability to do heap allocations. +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. > ### The `trpl` Crate > @@ -151,7 +155,7 @@ a single core, one gigabyte of RAM, and no ability to do heap allocations. > - 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 good and widely used. +> 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 From 4044534e4fee16692661297aad17919a4d6f0f8c Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Jul 2024 10:45:57 -0600 Subject: [PATCH 163/249] Ch. 16: avoid slightly-dismissive language in transition Use the original transitional paragraph and structure, adding to it instead of rewriting it entirely. HT @timClicks (Tim McNamara ) for pointing out how my rephrasing here made it worse! --- src/ch16-04-extensible-concurrency-sync-and-send.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ch16-04-extensible-concurrency-sync-and-send.md b/src/ch16-04-extensible-concurrency-sync-and-send.md index 1b74554341..ede5c66856 100644 --- a/src/ch16-04-extensible-concurrency-sync-and-send.md +++ b/src/ch16-04-extensible-concurrency-sync-and-send.md @@ -62,6 +62,11 @@ uphold them. ## Summary +This isn’t the last you’ll see of concurrency in this book: the whole next +chapter focuses on async programming, and the project in Chapter 20 will use the +concepts in this chapter in a more realistic situation than the smaller examples +discussed here. + As mentioned earlier, because very little of how Rust handles concurrency is part of the language, many concurrency solutions are implemented as crates. These evolve more quickly than the standard library, so be sure to search @@ -77,9 +82,6 @@ run on multiple threads without the kinds of hard-to-track-down bugs common in other languages. Concurrent programming is no longer a concept to be afraid of: go forth and make your programs concurrent, fearlessly! -This is just your first step into Rust’s concurrency story. In the next chapter, -we will explore a complementary approach, asynchronous programming. - [sharing-a-mutext-between-multiple-threads]: ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads [nomicon]: ../nomicon/index.html From eb41efb333f3c3873b98ee1eecd6395de89d618d Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 24 Jul 2024 10:45:57 -0600 Subject: [PATCH 164/249] =?UTF-8?q?Ch.=2017=C2=A700:=20rework=20the=20intr?= =?UTF-8?q?oduction=20based=20on=20initial=20reviews?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Drop the history lesson and comparisons to other approaches. Focus on what async gives us instead. - Simplify and clarify the - Talk about “the network” instead of “network sockets” and simplify the example code to match. --- src/ch17-00-async-await.md | 182 ++++++++++--------------------------- 1 file changed, 46 insertions(+), 136 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 3acc65b1c6..22f200fa49 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -1,29 +1,5 @@ ## Async and Await -The threading-based concurrency model is one of the oldest concurrency models in -computing, and it was present and well-supported in Rust since 1.0. In the past -few decades, though, many programming languages have been experimenting with -other approaches to concurrency, especially asynchronous programming, or -*async*. - -It took a few years to work out the right design for async in Rust. After a -bunch of experimentation and design work in the library ecosystem, Rust added -language-level support for async in Rust 1.39, in 2019, and there is a thriving -ecosystem of crates supporting all sorts of interesting capabilities offered by -those language primitives. - -In the rest of this chapter, we will: - -* see how to use Rust’s `async` and `.await` syntax -* explore how to use the async model to solve some of the same challenges we - looked at in Chapter 16 -* look at how multithreading and async provide complementary solutions, which - you can even use together in many cases - -First, though, let’s explore what async gives us. - -### Why Async? - Many operations we ask the computer to do can take a while to finish. For example, if you used a video editor to create a video of a family celebration, exporting it could take anywhere from minutes to hours. Similarly, downloading a @@ -42,7 +18,7 @@ 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 socket. Maybe it only takes a second or +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 @@ -55,8 +31,7 @@ happen while the network operation is still ongoing. > it can use. The video download is the kind of operation which is often > described as “IO-bound,” because it is limited by the speed of the computer’s > *input and output*. It can only go as fast as the data can be sent across the -> network, which means that it can only go as fast as the data can be written to -> the socket by the network controller. +> 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 @@ -67,123 +42,48 @@ opportunities for concurrency that the operating system cannot see. For example, if we are building a tool to manage file downloads, we should be able to write our program in such a way that starting one download does not lock up the UI, and users should be able to start multiple downloads at the same -time. Many operating system APIs for interacting with network sockets are +time. Many operating system APIs for interacting with the network are *blocking*, though. That is, these APIs block the program’s progress until the data that they are processing is completely ready. > Note: This is how *most* function calls work, if you think about it! However, > we normally reserve the term “blocking” for function calls which interact with -> files, network sockets, or other resources on the computer, because those are -> the places where an individual program would benefit from the operation being +> files, the network, or other resources on the computer, because those are the +> places where an individual program would benefit from the operation being > *non*-blocking. -We could avoid blocking our main thread, by spawning a dedicated thread to +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. - -One way to accomplish that would be to use an API built around callbacks. For -each blocking operation, we could pass in a function to call once the operation -completes: - -```rust,ignore -network_socket.read_non_blocking(|result| { - // ... -}); -``` - -Or we could register callbacks to run when events happen: - -```rust,ignore -network_socket.add_listener(Event::ReadFinished, |event| { - // ... -}); -``` - -Or we could have our functions return a type with `and_then` method, which in -turn accepts a callback which can do more work of the same sort (Historically, -this was the way that Rust did async): - -```rust,ignore -network_socket.read_non_blocking().and_then(|result| { - /* another non_blocking operation */ -}); -``` - -Each of these makes it harder to understand both the control flow and the flow -of data through the program. You can end up with event handler callbacks -scattered across the code base, or groups of deeply nested callbacks, or long -chains of `and_then` calls. - -There are also no particularly good ways to get data out of those callbacks. -With other common types in Rust, we often use pattern-matching in scenarios like -this. When we are using callbacks we do not yet have the data at the time we -call `read_non_blocking`—and we will not have it until the callback gets called. -That means that there is no way to match on the data it will return: it is not -here yet! - -As an alternative, we might try something like this, imagining a -`read_non_blocking` which has exactly the kind of `and_then` method described -above. If we were to try to do that, though, with code kind of like this, it -would not even compile: - -```rust,ignore,does_not_compile -let mut data = None; -network_socket.read_non_blocking().and_then(|result| { - data = Some(result); -}); -println!("{data:?}"); -``` - -In this very broken code, the callback passed to `and_then` needs a mutable -reference to `data`, but the `println` macro needs to borrow a reference to -`data` to be able to print it. Rust would helpfully tell us that we cannot -borrow `data` immutably to print it because it is still borrowed mutably for the -`and_then` callback. This is not just Rust being fussy, either: the result of -this would normally always just print the `None` value, but if the read -*happened* to go fast enough, it is possible it could sometimes print some -string data instead. That is *definitely* not what we want! - -We also could not cancel `read_non_blocking`: once it has started, it will run -till it finishes unless the whole program stops. - -What we really want to be able to write is something much more direct, like we -would write in blocking code, but with the benefits of getting the data when it -is available and *not* blocking the rest of the program while waiting for the -data to arrive—something like this: +first place. It would also be nice if we could write in the same direct style +we use in blocking code. Something like this: ```rust,ignore,does_not_compile -let data = network_socket.read(&path).await; +let data = fetch_data_from(url).await; println!("{data}"); ``` -That is exactly what Rust’s async abstraction gives us. It is designed to help -us solve all of these issues. Before we will see how this works in practice, -though, we need to dig a little deeper into the differences between parallelism -and concurrency. +That is exactly what Rust’s async abstraction gives us. Before we see how this +works in practice, though, we need to take a short detour into the differences +between parallelism and concurrency. ### Parallelism and Concurrency 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: +the differences will show up as we start working. -* *Parallelism* is when operations can happen simultaneously. +Think about working on a software project as a team. -* *Concurrency* is when operations can make progress without having to wait for - all other operations to complete. +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 +tasks at the exact same time—but you can multi-task, making progress on multiple +tasks by switching between them. -Think about working on a software project as a team. When you agree to split up -a group of tasks between a group of people, with each person working on one task -and delivering them separately, this is *parallelism*. Each person on the team -can be making progress at the exact same time. On the other hand, 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 tasks at -the exact same time—but you can multi-task, making progress on multiple tasks by -switching between them. Work on one does not necessarily *block* working on the -other. +When you agree to split up a group of tasks between the people on the team, with +each person taking one task and working on it alone, this is *parallelism*. Each +person on the team can make progress at the exact same time. With both of these situations, you might have to coordinate between different tasks. Maybe you *thought* the task that one person was working on was totally @@ -195,20 +95,30 @@ working on needs the result from 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, then -you might need to focus on that project and not give any time to your other task -until it is done, so your own work stops being concurrent. - -On a machine with a single CPU core, the CPU can only do one operation at a -time, but we can still have concurrency. Using tools like threads, processes, -and async, the computer can pause one activity and switch to others before -eventually cycling back to that first activity again. On a machine with multiple -CPU cores, we can actually do work in parallel. One core can be doing one thing -while another core does something completely unrelated, and those actually -happen at the same time. +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. + +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 +still work concurrently. Using tools like threads, processes, and async, the +computer can pause one activity and switch to others before eventually cycling +back to that first activity again. On a machine with multiple CPU cores, it can +also do work in parallel. One core can be doing one thing while another core +does something completely unrelated, and those actually happen at the same +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. Now, let’s dive into how async programming in Rust -actually works! +parallelism under the hood. + +Now, let’s dive into how async programming in Rust actually works! In the rest +of this chapter, we will: + +* see how to use Rust’s `async` and `.await` syntax +* explore how to use the async model to solve some of the same challenges we + looked at in Chapter 16 +* look at how multithreading and async provide complementary solutions, which + you can even use together in many cases From cfaf187bbc3a1515f517498657d127fae247d8ff Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 25 Jul 2024 15:28:27 -0600 Subject: [PATCH 165/249] Ch. 17: diagrams for concurrent and parallel execution --- dot/trpl17-01.dot | 21 +++++++++++++++++++++ dot/trpl17-02.dot | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 dot/trpl17-01.dot create mode 100644 dot/trpl17-02.dot diff --git a/dot/trpl17-01.dot b/dot/trpl17-01.dot new file mode 100644 index 0000000000..d90c85b8ee --- /dev/null +++ b/dot/trpl17-01.dot @@ -0,0 +1,21 @@ +digraph { + dpi = 300.0; + + Parallel [label = "Parallel";shape = "plaintext";]; + rankdir = "TB"; + splines = false; + cluster = true; + + node [shape = diamond;]; + + 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/dot/trpl17-02.dot b/dot/trpl17-02.dot new file mode 100644 index 0000000000..3c8d2a18a3 --- /dev/null +++ b/dot/trpl17-02.dot @@ -0,0 +1,46 @@ +digraph { + dpi = 300.0; + + Concurrent [label = "Concurrent";shape = "plaintext";]; + rankdir = "TB"; + splines = false; + cluster = true; + + node [shape = diamond;]; + + subgraph cluster_task_a { + label = "Task A"; + + // makes ordering between subgraphs work + newrank = true; + + A1; + A2; + A3; + A4; + + // for vertical alignment purposes only + A0 [style = invis;]; + + edge [style = invis;]; + } + + subgraph cluster_task_b { + label = "Task B"; + cluster = true; + + // for vertical alignment purposes only + newrank = true; + + B0 [style = invis;]; + + B1; + B2; + B3; + } + + A1 -> B1 -> A2 -> B2 -> A3 -> A4 -> B3; + + // Makes the heights line up between the boxes. + A4 -> A0 [style = invis;]; +} \ No newline at end of file From 472f152eaec3d93a2ec0e73751eadead477f54d7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 26 Jul 2024 08:12:41 -0600 Subject: [PATCH 166/249] Ch. 17: fix diagrams and embed them in the text - Swap the ordering to match the order in the text (concurrent is first, at least for now). - Make them go left-to-right instead of top-to-bottom for compactness in the text. - Fix rendering issues resulting from the VS Code extension doing things that normal `dot` does not, for who knows what reasons. --- dot/trpl17-01.dot | 45 +++++++++++---- dot/trpl17-02.dot | 40 +++----------- src/ch17-00-async-await.md | 16 ++++++ src/img/trp17-02.svg | 1 + src/img/trpl17-01.svg | 110 +++++++++++++++++++++++++++++++++++++ src/img/trpl17-02.svg | 94 +++++++++++++++++++++++++++++++ 6 files changed, 262 insertions(+), 44 deletions(-) create mode 100644 src/img/trp17-02.svg create mode 100644 src/img/trpl17-01.svg create mode 100644 src/img/trpl17-02.svg diff --git a/dot/trpl17-01.dot b/dot/trpl17-01.dot index d90c85b8ee..97bd15e894 100644 --- a/dot/trpl17-01.dot +++ b/dot/trpl17-01.dot @@ -1,21 +1,44 @@ digraph { dpi = 300.0; - Parallel [label = "Parallel";shape = "plaintext";]; - rankdir = "TB"; - splines = false; - cluster = true; + rankdir = "LR"; + + // makes ordering between subgraphs work + newrank = true; node [shape = diamond;]; - subgraph cluster_ColleagueA { - newrank = true; - label = "Task 1"; - A1 -> A2 -> A3 -> A4; + subgraph cluster_task_a { + label = "Task A"; + + A1; + A2; + A3; + A4; + + A1 -> A2 -> A3 -> A4 -> A0 [style = invis;]; + + // for vertical alignment purposes only + A0 [style = invis;]; + + // Makes the heights line up between the boxes. + A4 -> A0 [style = invis;]; } - subgraph cluster_ColleagueB { - label = "Task 2"; - B1 -> B2 -> B3; + subgraph cluster_task_b { + label = "Task B"; + + // for horizontal alignment purposes only + // newrank = true; + + B0 [style = invis;]; + + B1; + B2; + B3; + + B0 -> B1 -> B2 -> B3 [style = invis;]; } + + A1 -> B1 -> A2 -> B2 -> A3 -> A4 -> B3; } \ No newline at end of file diff --git a/dot/trpl17-02.dot b/dot/trpl17-02.dot index 3c8d2a18a3..512f33cb9b 100644 --- a/dot/trpl17-02.dot +++ b/dot/trpl17-02.dot @@ -1,46 +1,20 @@ digraph { dpi = 300.0; - Concurrent [label = "Concurrent";shape = "plaintext";]; - rankdir = "TB"; + rankdir = "LR"; splines = false; cluster = true; node [shape = diamond;]; - subgraph cluster_task_a { - label = "Task A"; - - // makes ordering between subgraphs work + subgraph cluster_ColleagueA { newrank = true; - - A1; - A2; - A3; - A4; - - // for vertical alignment purposes only - A0 [style = invis;]; - - edge [style = invis;]; + label = "Task 1"; + A1 -> A2 -> A3 -> A4; } - subgraph cluster_task_b { - label = "Task B"; - cluster = true; - - // for vertical alignment purposes only - newrank = true; - - B0 [style = invis;]; - - B1; - B2; - B3; + subgraph cluster_ColleagueB { + label = "Task 2"; + B1 -> B2 -> B3; } - - A1 -> B1 -> A2 -> B2 -> A3 -> A4 -> B3; - - // Makes the heights line up between the boxes. - A4 -> A0 [style = invis;]; } \ No newline at end of file diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 22f200fa49..e68c7420fc 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -81,10 +81,26 @@ to the other. You are just one person, and you cannot make progress on both tasks at the exact same time—but you can multi-task, making progress on multiple tasks by switching between them. +
+ +Concurrent work flow + +
Figure 17-1: A concurrent workflow, switching between Task A and Task B
+ +
+ When you agree to split up a group of tasks between the people on the team, with each person taking one task and working on it alone, this is *parallelism*. Each person on the team can make progress at the exact same time. +
+ +Concurrent work flow + +
Figure 17-2: A parallel workflow, where work happens on Task A and Task B independently
+ +
+ With both of these situations, you might have to coordinate between different 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 diff --git a/src/img/trp17-02.svg b/src/img/trp17-02.svg new file mode 100644 index 0000000000..1ad970d72c --- /dev/null +++ b/src/img/trp17-02.svg @@ -0,0 +1 @@ +Task 1Task 2ParallelA1A2A3A4B1B2B3 \ No newline at end of file diff --git a/src/img/trpl17-01.svg b/src/img/trpl17-01.svg new file mode 100644 index 0000000000..c99989ec31 --- /dev/null +++ b/src/img/trpl17-01.svg @@ -0,0 +1,110 @@ + + + + + + + + +cluster_task_a + +Task A + + +cluster_task_b + +Task B + + + +A1 + +A1 + + + +A2 + +A2 + + + + +B1 + +B1 + + + +A1->B1 + + + + + +A3 + +A3 + + + + +B2 + +B2 + + + +A2->B2 + + + + + +A4 + +A4 + + + + +A3->A4 + + + + + + + + +B3 + +B3 + + + +A4->B3 + + + + + + + +B1->A2 + + + + + + +B2->A3 + + + + + + diff --git a/src/img/trpl17-02.svg b/src/img/trpl17-02.svg new file mode 100644 index 0000000000..1ddb5d4cad --- /dev/null +++ b/src/img/trpl17-02.svg @@ -0,0 +1,94 @@ + + + + + + + + +cluster_ColleagueA + +Task 1 + + +cluster_ColleagueB + +Task 2 + + + +A1 + +A1 + + + +A2 + +A2 + + + +A1->A2 + + + + + +A3 + +A3 + + + +A2->A3 + + + + + +A4 + +A4 + + + +A3->A4 + + + + + +B1 + +B1 + + + +B2 + +B2 + + + +B1->B2 + + + + + +B3 + +B3 + + + +B2->B3 + + + + + From a42f27bd552126bb15a6f7ed7bcf5163ba010aee Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Sat, 24 Aug 2024 07:42:06 -0600 Subject: [PATCH 167/249] 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 168/249] =?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 1de14c81c6c14204216ef28dddeca2579165e106 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Sat, 24 Aug 2024 08:26:56 -0600 Subject: [PATCH 169/249] 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 c552952e9fd1300b05080d1a761ceb8face681d7 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Sat, 24 Aug 2024 08:26:56 -0600 Subject: [PATCH 170/249] 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 171/249] 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 172/249] 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 173/249] 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 174/249] 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 175/249] 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 176/249] 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 177/249] 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 178/249] 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 179/249] =?UTF-8?q?Ch.=2017:=20address=20the=20rest=20of?= =?UTF-8?q?=20James=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 180/249] 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 181/249] 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 182/249] 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 183/249] 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 184/249] 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 185/249] 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 186/249] 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 From 42b59635d223abd7c065798c719451a31dda640b Mon Sep 17 00:00:00 2001 From: Chris Krycho <hello@chriskrycho.com> Date: Mon, 23 Sep 2024 15:07:44 -0600 Subject: [PATCH 187/249] Ch. 17: General cleanup and edits to esp. 17.05 - Introduce diagrams into 17.05 to break up the wall of text and make it easier to visualize. - Extract the state machine code to make it easier to reference. - Standardize on `await` instead of `.await` for inline code references. - Move note about `race` and `select` up to 17.01 since the text now references it there, and update the text in 17.03 to account for already having introduced the function. - Fix up a number of code samples to avoid showing `extern crate trpl;`. - Rewrite the transition between 17.04 and 17.05 to account for having restructured the chapter. - Rework the example code in 17.05 to refer to the `page_title` example from the rewritten 17.01 instead of the (now-removed) `hello`. - When discussing the `Future::poll` method, explicitly address the `cx` parameter: note what it is used for, and then move on. --- dot/trpl17-01.dot | 3 - dot/trpl17-03.dot | 19 + dot/trpl17-04.dot | 32 + .../listing-17-31/src/main.rs | 2 + .../listing-17-32/src/main.rs | 2 + .../no-listing-state-machine/Cargo.lock | 1793 +++++++++++++++++ .../no-listing-state-machine/Cargo.toml | 8 + .../no-listing-state-machine/output.txt | 2 + .../no-listing-state-machine/src/lib.rs | 8 + src/ch17-00-async-await.md | 2 +- src/ch17-01-futures-and-syntax.md | 20 +- src/ch17-02-concurrency-with-async.md | 14 +- src/ch17-03-more-futures.md | 30 +- src/ch17-04-streams.md | 14 +- src/ch17-05-traits-for-async.md | 169 +- src/ch17-06-futures-tasks-threads.md | 4 +- src/img/trpl17-03.svg | 30 + src/img/trpl17-04.svg | 46 + 18 files changed, 2081 insertions(+), 117 deletions(-) create mode 100644 dot/trpl17-03.dot create mode 100644 dot/trpl17-04.dot create mode 100644 listings/ch17-async-await/no-listing-state-machine/Cargo.lock create mode 100644 listings/ch17-async-await/no-listing-state-machine/Cargo.toml create mode 100644 listings/ch17-async-await/no-listing-state-machine/output.txt create mode 100644 listings/ch17-async-await/no-listing-state-machine/src/lib.rs create mode 100644 src/img/trpl17-03.svg create mode 100644 src/img/trpl17-04.svg diff --git a/dot/trpl17-01.dot b/dot/trpl17-01.dot index 97bd15e894..ed2d969f2f 100644 --- a/dot/trpl17-01.dot +++ b/dot/trpl17-01.dot @@ -28,9 +28,6 @@ digraph { subgraph cluster_task_b { label = "Task B"; - // for horizontal alignment purposes only - // newrank = true; - B0 [style = invis;]; B1; diff --git a/dot/trpl17-03.dot b/dot/trpl17-03.dot new file mode 100644 index 0000000000..6c63b7bde4 --- /dev/null +++ b/dot/trpl17-03.dot @@ -0,0 +1,19 @@ +digraph { + rankdir = RL; + overlap = false; + dpi = 300.0; + splines = false; + cluster = true; + + node [shape = "plaintext";]; + + fut1 [label = <<table border="0" cellborder="1" cellspacing="0"> + <tr><td sides="B">fut1</td></tr> + <tr><td>0</td></tr> + <tr><td port="target">1</td></tr> + <tr><td port="source"> </td></tr> + </table>>;]; + + edge [tailclip = "false";]; + fut1:source:c -> fut1:target [dir = forward;]; +} \ No newline at end of file diff --git a/dot/trpl17-04.dot b/dot/trpl17-04.dot new file mode 100644 index 0000000000..afcf8e77a1 --- /dev/null +++ b/dot/trpl17-04.dot @@ -0,0 +1,32 @@ +digraph { + rankdir = RL; + overlap = false; + dpi = 300.0; + splines = false; + cluster = true; + + node [shape = "plaintext";]; + + // Group the two together, which results in the desired alignment. + subgraph { + // But don't show the frame! + style = "invis"; + + fut1 [label = <<table border="0" cellborder="1" cellspacing="0" bgcolor="gray"> + <tr><td sides="B">fut1</td></tr> + <tr><td>?</td></tr> + <tr><td port="target">?</td></tr> + <tr><td>?</td></tr> + </table>>;]; + + fut2 [label = <<table border="0" cellborder="1" cellspacing="0"> + <tr><td sides="B">fut2</td></tr> + <tr><td>0</td></tr> + <tr><td>1</td></tr> + <tr><td port="source"> </td></tr> + </table>>;]; + + edge [tailclip = "false"; dir = forward]; + fut2:source:c -> fut1:target:e; + } +} \ No newline at end of file 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 0a7fc87c21..f03a460aa8 100644 --- a/listings/ch17-async-await/listing-17-31/src/main.rs +++ b/listings/ch17-async-await/listing-17-31/src/main.rs @@ -1,5 +1,6 @@ extern crate trpl; // required for mdbook test +// ANCHOR: all use trpl::StreamExt; fn main() { @@ -13,3 +14,4 @@ fn main() { } }); } +// ANCHOR_END: all 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 017185bed5..2667c5e9ae 100644 --- a/listings/ch17-async-await/listing-17-32/src/main.rs +++ b/listings/ch17-async-await/listing-17-32/src/main.rs @@ -1,5 +1,6 @@ extern crate trpl; // required for mdbook test +// ANCHOR: all use trpl::StreamExt; fn main() { @@ -16,3 +17,4 @@ fn main() { } }); } +// ANCHOR_END: all diff --git a/listings/ch17-async-await/no-listing-state-machine/Cargo.lock b/listings/ch17-async-await/no-listing-state-machine/Cargo.lock new file mode 100644 index 0000000000..5e72795fea --- /dev/null +++ b/listings/ch17-async-await/no-listing-state-machine/Cargo.lock @@ -0,0 +1,1793 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +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 = "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.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 = "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.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.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.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 = "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/no-listing-state-machine/Cargo.toml b/listings/ch17-async-await/no-listing-state-machine/Cargo.toml new file mode 100644 index 0000000000..e094f067f1 --- /dev/null +++ b/listings/ch17-async-await/no-listing-state-machine/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/no-listing-state-machine/output.txt b/listings/ch17-async-await/no-listing-state-machine/output.txt new file mode 100644 index 0000000000..10a18bc488 --- /dev/null +++ b/listings/ch17-async-await/no-listing-state-machine/output.txt @@ -0,0 +1,2 @@ +$ cargo run +error: a bin target must be available for `cargo run` diff --git a/listings/ch17-async-await/no-listing-state-machine/src/lib.rs b/listings/ch17-async-await/no-listing-state-machine/src/lib.rs new file mode 100644 index 0000000000..f718ba8e08 --- /dev/null +++ b/listings/ch17-async-await/no-listing-state-machine/src/lib.rs @@ -0,0 +1,8 @@ +extern crate trpl; // required for mdbook test + +// ANCHOR: enum +enum PageTitleFuture<'a> { + GetAwaitPoint { url: &'a str }, + TextAwaitPoint { response: trpl::Response }, +} +// ANCHOR_END: enum diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 1749cc17a7..ecd9fb14b3 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -136,7 +136,7 @@ under the hood. Now, let’s dive into how async programming in Rust actually works! In the rest of this chapter, we will: -* see how to use Rust’s `async` and `.await` syntax +* see how to use Rust’s `async` and `await` syntax * explore how to use the async model to solve some of the same challenges we looked at in Chapter 16 * look at how multithreading and async provide complementary solutions, which diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index a072263732..8197b8e6c0 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -279,15 +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, - }, - TextAwaitPoint { - response: trpl::Response, - }, -} +{{#rustdoc_include ../listings/ch17-async-await/no-listing-state-machine/src/lib.rs:enum}} ``` Writing that out by hand would be tedious and error-prone, especially when @@ -331,8 +323,14 @@ and racing it. 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. +and we have not yet awaited them. Then we pass the futures to `trpl::race`, +which returns a value to indicate which of the futures passed to it finishes +first. + +> 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. 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, diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index a302b5aa2e..a222b851d8 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -37,7 +37,7 @@ that our top-level function can be async. 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 message. We put one loop in the body of a `trpl::spawn_task` and the other in a -top-level `for` loop. We also add an `.await` after the `sleep` calls. +top-level `for` loop. We also add an `await` after the `sleep` calls. This does something similar to the thread-based implementation—including the fact that you may see the messages appear in a different order in your own @@ -68,7 +68,7 @@ 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-7" 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-07/src/main.rs:handle}} @@ -99,7 +99,7 @@ hi number 9 from the first task! ``` So far, it looks like async and threads give us the same basic outcomes, just -with different syntax: using `.await` instead of calling `join` on the join +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 @@ -220,7 +220,7 @@ between them, as shown in Listing 17-10: <!-- We cannot test this one because it never stops! --> -<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"> +<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-10/src/main.rs:many-messages}} @@ -266,14 +266,14 @@ class="keystroke">ctrl-c</span>. 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 -async block, the order that `.await` keywords appear in the code is also the +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-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 -`.await` points on the `recv` calls. +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 35e919249f..ea9c7460ad 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -291,22 +291,16 @@ syntax for working with them, and that is a good thing. 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. - -> 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-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!) 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. +one future against another. + +In Listing 17-21, we once again 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!) +Unlike when 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-21" caption="Using `race` to get the result of whichever future finishes first" file-name="src/main.rs"> @@ -322,7 +316,7 @@ 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 +fair, though, *one* of the futures will run up to the first `await` in its body before another task can start. Recall from [Our First Async Program][async-program] that at each await point, @@ -575,7 +569,7 @@ 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! -In practice, you will usually work directly with `async` and `.await`, and +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. diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index b3e4cac9a7..28e8d9793f 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -88,13 +88,13 @@ method and also many other utility methods like those from `Iterator`. We will 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-31. +All we need to do is add a `use` statement for `trpl::StreamExt`, as in 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-31/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs:all}} ``` </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-32/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-32/src/main.rs:all}} ``` </Listing> @@ -439,8 +439,8 @@ you have a strategy. </Listing> -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. +Now that we have seen a bunch of async in practice, let’s take a step back and +dig into a few of the details of how `Future`, `Stream`, and the other key +traits which Rust uses to make async work. [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 91193a4542..56e3def6bb 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -56,14 +56,16 @@ available. > becoming ready! Futures which are safe to poll again will say so explicitly in > 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 <!-- TODO: describe `IntoFuture`? -->) -like this: +Under the hood, when you see code which uses `await`, Rust compiles that to code +which calls `poll`. If you look back at Listing 17-4, where we printed out the +page title for a single URL once it resolved, Rust compiles it into something +kind of (although not exactly) like this: ```rust,ignore -match hello("async").poll() { - Ready(_) => { - // We’re done! +match page_title(url).poll() { + Ready(page_title) => match page_title { + Some(title) => println!("The title for {url} was {title}"), + None => println!("{url} had no title"), } Pending => { // But what goes here? @@ -76,11 +78,12 @@ again… and again, and again, until the future is finally ready. In other words a loop: ```rust,ignore -let hello_fut = hello("async"); +let mut page_title_fut = page_title(url); loop { - match hello_fut.poll() { - Ready(_) => { - break; + match page_title_fut.poll() { + Ready(value) => match page_title { + Some(title) => println!("The title for {url} was {title}"), + None => println!("{url} had no title"), } Pending => { // continue @@ -89,7 +92,7 @@ loop { } ``` -If Rust compiled it to exactly that code, though, every `.await` would be +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 @@ -119,7 +122,7 @@ 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-18 +cd listings/ch17-async-await/listing-17-17 cargo build copy *only* the final `error` block from the errors --> @@ -156,8 +159,7 @@ directly awaiting a Future requires that the future in question implement the further into how the `Future` type actually works, in particular around *pinning*. -Let’s look again at the definition of `Future`, focusing specifically on the -`poll` method’s `self` type: +Let’s look again at the definition of `Future`: ```rust use std::pin::Pin; @@ -171,33 +173,38 @@ pub trait Future { } ``` -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, 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`. +The `cx` parameter and its `Context` type is interesting, but is beyond the +scope of this chapter: you generally only need to worry about it when writing a +custom `Future` implementation. + +Instead, we will focus on the type for `self`. This is the first time we have +seen a method where `self` has a type annotation. A type annotation for `self` +is similar to type annotations for other function parameters, with two key +differences. First, when we specify the type of `self` like this, we are telling +Rust what type `self` must be to call this method. Second, a type annotation on +`self` cannot be just any type. It is only allowed to be the type on which the +method is 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 +those, however, `Pin` only works with *pointer types* like references (`&` 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`? +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 [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 @@ -212,33 +219,58 @@ 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. +`join_all`, the way we did back in—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. +themselves in the fields of any given variant, as in Figure 17-3 (a simplified +illustration to help you get a feel for the idea, rather than digging into what +are often fairly complicated details). + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-03.svg" class="center" /> + +<figcaption>Figure 17-3: A self-referential data type.</figcaption> + +</figure> + +By default, though, any object which has a reference to itself is unsafe to +move, because references always point to the actual memory address of the thing +they refer to. If you move the data structure itself, those internal references +will be left pointing to the old location. However, that memory location is now +invalid. For one thing, its value will not be updated when you make changes to +the data structure. For another—and more importantly!—the computer is now free +to reuse that memory for other things! You could end up reading completely +unrelated data later. + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-04.svg" class="center" /> + +<figcaption>Figure 17-4: The unsafe result of moving a self-referential data type.</figcaption> + +</figure> + +In principle, the Rust compiler could 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. +This is exactly what Rust’s borrow checker requires: 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<Box<SomeType>>`, 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. +value by wrapping a pointer to that value in `Pin`, it can no longer move. Thus, +if you have `Pin<Box<SomeType>>`, you actually pin the `SomeType` value, *not* +the `Box` pointer. In fact, the `Box` pointer can still 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. + +<!-- TODO: diagram of `Pin` --> 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 @@ -247,10 +279,10 @@ 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<Vec<String>>`, you would have to do -everything via Pin’s safe but restrictive APIs, even though a `Vec<String>` 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`. +everything via the safe but restrictive APIs provided by `Pin`, even though a +`Vec<String>` 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 @@ -259,6 +291,8 @@ 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. +<!-- TODO: a diagram for `Unpin`? I have no idea what or how, though. Hmm. --> + 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 @@ -281,9 +315,10 @@ When you see them, though, now you will know what to do! > 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. +> The specifics of how `Pin` and `Unpin` work, and the rules they are required +> to uphold, 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 @@ -355,9 +390,9 @@ TODO: update this if/when tokio/etc. update their MSRV and switch to using async in traits, since the lack thereof is the reason they do not yet have this. --> -> 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: +> Note: The actual definition we used earlier in the chapter 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; @@ -365,7 +400,7 @@ in traits, since the lack thereof is the reason they do not yet have this. > > 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! +> 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 diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index a10b391bf6..b54117ccc4 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -1,4 +1,4 @@ -# Futures, Tasks, and Threads +## Futures, Tasks, and Threads As we saw in the previous chapter, threads provide one approach to concurrency. We have seen another approach to concurrency in this chapter, using async with @@ -101,8 +101,6 @@ choose between threads and async. You can use them together freely, letting each 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. -<!-- TODO: extract into a listing file! --> - <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 diff --git a/src/img/trpl17-03.svg b/src/img/trpl17-03.svg new file mode 100644 index 0000000000..fed6c36040 --- /dev/null +++ b/src/img/trpl17-03.svg @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by graphviz version 12.1.1 (20240910.0053) + --> +<!-- Pages: 1 --> +<svg height="150pt" + viewBox="0.00 0.00 371.00 442.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 102)"> +<polygon fill="white" stroke="none" points="-4,4 -4,-102 85,-102 85,4 -4,4"/> +<!-- fut1 --> +<g id="node1" class="node"> +<title>fut1 + +fut1 + +0 + +1 + +   + + + +fut1:c->fut1:target + + + + + diff --git a/src/img/trpl17-04.svg b/src/img/trpl17-04.svg new file mode 100644 index 0000000000..e3472baa7c --- /dev/null +++ b/src/img/trpl17-04.svg @@ -0,0 +1,46 @@ + + + + + + + + +%3 + + + +fut1 + + +fut1 + +? + +? + +? + + + +fut2 + +fut2 + +0 + +1 + + + + + +fut2:c->fut1:c + + + + + From beac73a818a459ce5e3dd3f7eeb6bf7518552e8e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 23 Sep 2024 15:07:44 -0600 Subject: [PATCH 188/249] Ch. 17: introduce diagrams for `Pin` and `Unpin`. --- dot/trpl17-05.dot | 42 ++++++++++++++++ dot/trpl17-06.dot | 64 ++++++++++++++++++++++++ dot/trpl17-07.dot | 39 +++++++++++++++ dot/trpl17-08.dot | 62 ++++++++++++++++++++++++ src/ch17-05-traits-for-async.md | 70 ++++++++++++++++++++++----- src/img/trpl17-05.svg | 69 ++++++++++++++++++++++++++ src/img/trpl17-06.svg | 86 +++++++++++++++++++++++++++++++++ src/img/trpl17-07.svg | 57 ++++++++++++++++++++++ src/img/trpl17-08.svg | 85 ++++++++++++++++++++++++++++++++ 9 files changed, 561 insertions(+), 13 deletions(-) create mode 100644 dot/trpl17-05.dot create mode 100644 dot/trpl17-06.dot create mode 100644 dot/trpl17-07.dot create mode 100644 dot/trpl17-08.dot create mode 100644 src/img/trpl17-05.svg create mode 100644 src/img/trpl17-06.svg create mode 100644 src/img/trpl17-07.svg create mode 100644 src/img/trpl17-08.svg diff --git a/dot/trpl17-05.dot b/dot/trpl17-05.dot new file mode 100644 index 0000000000..e036a385c3 --- /dev/null +++ b/dot/trpl17-05.dot @@ -0,0 +1,42 @@ +digraph { + rankdir = LR; + dpi = 300.0; + + node [shape = "plaintext";]; + + pinned_box [label = < + + +
Pin
>;]; + + subgraph cluster_box { + label = ""; + peripheries = 0; + + subgraph cluster_box_internal { + peripheries = 1; + label = "b1"; + shape = box; + style = solid; + pin [shape = "point";]; + } + } + + subgraph cluster_deref { + style = bold; + label = "pinned"; + + box [label = < + + + + + +
fut
0
...
1
>;]; + } + + edge [tailclip = false;]; + pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; + pin -> box [headport = "target";]; + box -> box [tailport = "source:c"; headport = "internal";]; +} \ No newline at end of file diff --git a/dot/trpl17-06.dot b/dot/trpl17-06.dot new file mode 100644 index 0000000000..11b79574c4 --- /dev/null +++ b/dot/trpl17-06.dot @@ -0,0 +1,64 @@ +digraph { + rankdir = LR; + newrank = true; + dpi = 300.0; + + node [shape = "plaintext";]; + + + subgraph cluster_not_fut { + peripheries = 0; + + pin [label = < + + +
Pin
>;]; + + subgraph cluster_boxes { + peripheries = 0; + rank = same; + + subgraph cluster_box_1 { + subgraph cluster_box_2_internal { + label = "b1"; + shape = box; + style = solid; + style = filled; + peripheries = 1; + box1 [shape = "point";style = "invis";]; + } + } + + subgraph cluster_box_2 { + subgraph cluster_box_2_internal { + label = "b2"; + shape = box; + style = solid; + peripheries = 1; + box2 [shape = "point";]; + } + } + } + } + subgraph cluster_target { + style = bold; + label = "pinned"; + + fut [label = < + + + + + +
fut
0
...
1
>;]; + } + + + box1 -> box2 [rankdir = TB; style = invis;]; + + edge [tailclip = false;]; + pin -> box1 [style = "invis";]; + pin -> box2 [tailport = "source:c"; arrowhead = "none";]; + box2 -> fut [headport = "target";]; + fut -> fut [tailport = "source:c"; headport = "internal";]; +} \ No newline at end of file diff --git a/dot/trpl17-07.dot b/dot/trpl17-07.dot new file mode 100644 index 0000000000..8e9897f46d --- /dev/null +++ b/dot/trpl17-07.dot @@ -0,0 +1,39 @@ +digraph { + rankdir = LR; + overlap = false; + dpi = 300.0; + splines = false; + cluster = true; + newrank = true; + outputorder = in; + compound = true; + labelloc = "c"; + + node [shape = "plaintext";]; + + pinned_box [label = < + + +
Pin
>;]; + + + subgraph cluster_deref { + style = dashed; + label = "String"; + + pin [shape = "point";]; + + fut [label = < + + + + + + +
5usizehello
>;]; + } + + edge [tailclip = false;]; + pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; + pin -> fut [headport = "target";]; +} \ No newline at end of file diff --git a/dot/trpl17-08.dot b/dot/trpl17-08.dot new file mode 100644 index 0000000000..de73007511 --- /dev/null +++ b/dot/trpl17-08.dot @@ -0,0 +1,62 @@ +digraph { + rankdir = LR; + overlap = false; + dpi = 300.0; + splines = false; + cluster = true; + newrank = true; + outputorder = in; + compound = true; + labelloc = "c"; + + node [shape = "plaintext";]; + + pinned_box [label = < + + +
Pin
>;]; + + subgraph cluster_both { + peripheries = 0; + + + + string1 [label = < + + + + + + + + + +
s1
5usizehello
>;]; + + subgraph cluster_deref { + style = dashed; + label = "String"; + peripheries = 1; + + pin [shape = "point";]; + + string2 [label = < + + + + + + + + + + + +
s2
7usizegoodbye
>;]; + } + } + + edge [tailclip = false;]; + pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; + pin -> string2 [headport = "target";]; +} \ No newline at end of file diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 56e3def6bb..91a78a7a56 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -265,12 +265,33 @@ 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 that value 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 `Box` pointer can still 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. +the `Box` pointer. Figure 17-5 illustrates this: - +
+ +Concurrent work flow + +
Figure 17-5: Pinning a `Box` which points to a self-referential future type.
+ +
+ +In fact, the `Box` pointer can still 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, as in +Figure 17-6, there is no potential problem. (How you would do this with a `Pin` +wrapping a `Box` is more than we will get into in this particular discussion, +but it would make for a good exercise! If you look at the docs for the types as +well as the `std::pin` module, you might be able to work out how you would do +that.) The key is that the self-referential type itself cannot move, because it +is still pinned. + +
+ +Concurrent work flow + +
Figure 17-6: Moving a `Box` which points to a self-referential future type.
+ +
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 @@ -291,20 +312,43 @@ 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! -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. +To make that concrete, think about a `String`: it has a length and the Unicode +characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure +17-7. However + +
+ +Concurrent work flow + +
Figure 17-7: Pinning a String, with a dotted line indicating that the String implements the `Unpin` trait, so it is not pinned.
+ +
+ +This means that we can do things like replace one string with another at the +exact same location in memory as in Figure 17-8. This does not violate the `Pin` +contract because `String`—like most other types in Rust—implements `Unpin`, +because it has no internal references that make it unsafe to move around! + +
+ +Concurrent work flow + +
Figure 17-8: Replacing the String with an entirely different String in memory.
+ +
+ +Now we know enough to understand the errors reported for that `join_all` call +from back in Listing 17-17. 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. `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. diff --git a/src/img/trpl17-05.svg b/src/img/trpl17-05.svg new file mode 100644 index 0000000000..443bb568dc --- /dev/null +++ b/src/img/trpl17-05.svg @@ -0,0 +1,69 @@ + + + + + + + + +cluster_box + + +cluster_box_internal + +b1 + + +cluster_deref + +pinned + + + +pinned_box + +Pin + + + + + +pin + + + + +pinned_box:c->pin + + + + +box + +fut + +0 + + + +... + +1 + + + +pin->box:target + + + + + +box:c->box:internal + + + + + diff --git a/src/img/trpl17-06.svg b/src/img/trpl17-06.svg new file mode 100644 index 0000000000..712e3006f6 --- /dev/null +++ b/src/img/trpl17-06.svg @@ -0,0 +1,86 @@ + + + + + + + + +cluster_not_fut + + +cluster_boxes + + +cluster_box_1 + + +cluster_box_2_internal + +b1 + + +cluster_box_2 + + +cluster_box_2_internal + +b2 + + +cluster_target + +pinned + + + +pin + +Pin + + + + + + + +box2 + + + + +pin:c->box2 + + + + + +fut + +fut + +0 + + + +... + +1 + + + +box2->fut:target + + + + + +fut:c->fut:internal + + + + + diff --git a/src/img/trpl17-07.svg b/src/img/trpl17-07.svg new file mode 100644 index 0000000000..b2275ac19f --- /dev/null +++ b/src/img/trpl17-07.svg @@ -0,0 +1,57 @@ + + + + + + + + +cluster_deref + +String + + + +pinned_box + +Pin + + + + + +pin + + + + +pinned_box:c->pin + + + + +fut + +5usize + +h + +e + +l + +l + +o + + + +pin->fut:target + + + + + diff --git a/src/img/trpl17-08.svg b/src/img/trpl17-08.svg new file mode 100644 index 0000000000..997d9b82e1 --- /dev/null +++ b/src/img/trpl17-08.svg @@ -0,0 +1,85 @@ + + + + + + + + +cluster_both + + +cluster_deref + +String + + + +pinned_box + +Pin + + + + + +pin + + + + +pinned_box:c->pin + + + + +string1 + + +s1 + +5usize + +h + +e + +l + +l + +o + + + +string2 + +s2 + +7usize + +g + +o + +o + +d + +b + +y + +e + + + +pin->string2:target + + + + + From 0388426c51de9be7f489ccff9701f0d1e3d4747f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 25 Sep 2024 15:19:16 -0600 Subject: [PATCH 189/249] Ch. 17: Fix no-listing code for state machine enum --- listings/ch17-async-await/no-listing-state-machine/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/listings/ch17-async-await/no-listing-state-machine/src/lib.rs b/listings/ch17-async-await/no-listing-state-machine/src/lib.rs index f718ba8e08..1273283140 100644 --- a/listings/ch17-async-await/no-listing-state-machine/src/lib.rs +++ b/listings/ch17-async-await/no-listing-state-machine/src/lib.rs @@ -2,6 +2,7 @@ extern crate trpl; // required for mdbook test // ANCHOR: enum enum PageTitleFuture<'a> { + Initial { url: &'a str }, GetAwaitPoint { url: &'a str }, TextAwaitPoint { response: trpl::Response }, } From 75ec154789ea6fe3b1ffe5d7e1e49e884b4f5f3e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Wed, 25 Sep 2024 15:21:27 -0600 Subject: [PATCH 190/249] infra: publish trpl@0.2.0 w/new features from edits --- packages/trpl/Cargo.lock | 2 +- packages/trpl/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/trpl/Cargo.lock b/packages/trpl/Cargo.lock index bc42cb8b60..475f5d6d00 100644 --- a/packages/trpl/Cargo.lock +++ b/packages/trpl/Cargo.lock @@ -1478,7 +1478,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/packages/trpl/Cargo.toml b/packages/trpl/Cargo.toml index 62a602ea19..61c46319cc 100644 --- a/packages/trpl/Cargo.toml +++ b/packages/trpl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trpl" -version = "0.1.0" +version = "0.2.0" edition = "2021" license = "MIT OR Apache-2.0" description = "A support crate for The Rust Programming Language book" From aca71b65a1bd0ac33b68723eed9bf9e35f5cd611 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 1 Oct 2024 09:48:54 -0600 Subject: [PATCH 191/249] Ch. 17: correct a missing word --- src/ch17-01-futures-and-syntax.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 8197b8e6c0..c595ded829 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -55,9 +55,9 @@ crates. 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 +focused on the details relevant to this 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: From 8df8d8ecb6894d57a7482da47af8fac912d10995 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Tue, 1 Oct 2024 11:35:39 -0400 Subject: [PATCH 192/249] Be more explicit about creating a new project --- src/ch17-01-futures-and-syntax.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index c595ded829..ed2386d642 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -60,9 +60,12 @@ 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: +Create a new binary project named `hello-async` and add the `trpl` crate as a +dependency: ```console +$ cargo new hello-async +$ cd hello-async $ cargo add trpl ``` From e8e0c6beba433498b011123a2dd2c6a28026604a Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Tue, 1 Oct 2024 11:37:26 -0400 Subject: [PATCH 193/249] Introduce the listing more explicitly --- src/ch17-01-futures-and-syntax.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index ed2386d642..16349d943a 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -74,6 +74,9 @@ 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. +Let's start by writing a function that takes one page URL as a parameter, makes +a request to it, and returns the text of the title element: + <Listing number="17-1" file-name="src/main.rs" caption="Defining an async function to get the title element from an HTML page"> ```rust From f7276278082ff279b69581ebbe0704fad4f8f481 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 11:45:13 -0400 Subject: [PATCH 194/249] There is no name argument, but there is a url parameter --- src/ch17-01-futures-and-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 16349d943a..4a7a59ff96 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -184,7 +184,7 @@ Let’s walk through each part of the transformed version: 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. (We will talk about `async` vs. `async move` much more later + `url` parameter. (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 From a37e1a73c111b3cfee40a63f2586ffafe0b737fa Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 11:47:16 -0400 Subject: [PATCH 195/249] Rust not allowing main to be async isn't due to the first part of the sentence Change from "so" to "and" to avoid that implication. --- src/ch17-01-futures-and-syntax.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 4a7a59ff96..9467c7532e 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -210,8 +210,8 @@ account for whether the page had a `<title>`. </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`. +keyword is in async functions or blocks, and Rust will not let us mark the +special `main` function as `async`. <!-- manual-regeneration cd listings/ch17-async-await/listing-17-03 From 2f8e266749b1540f15b069be2905301b0818960c Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 11:49:44 -0400 Subject: [PATCH 196/249] Clarify which reason we're talking about and what Rust programs have runtimes --- src/ch17-01-futures-and-syntax.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 9467c7532e..394a3c378b 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -227,11 +227,12 @@ error[E0752]: `main` function is not allowed to be `async` | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` ``` -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. +The reason `main` can't be marked `async` 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 Rust program +that executes async code 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 From e4e5a4b0160a5e19bc25994a207db186f9f51d42 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 11:54:18 -0400 Subject: [PATCH 197/249] We haven't added 2 calls yet; remove some text that's jumping ahead --- src/ch17-01-futures-and-syntax.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 394a3c378b..0e6b35f762 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -273,10 +273,8 @@ When we run this, we get the behavior we might have expected initially: ``` 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. +it. Before we add code to race two sites against each other, let’s briefly turn +our attention back to how futures work. 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 From 9fca5aa6f45519981eb776a74a0b550aedbdca2a Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 11:54:55 -0400 Subject: [PATCH 198/249] Add a bit more detail about why we'd want a state machine enum --- src/ch17-01-futures-and-syntax.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 0e6b35f762..3684451360 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -281,7 +281,8 @@ 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: +as if you wrote an enum like this to save the current state at each `await` +point: ```rust {{#rustdoc_include ../listings/ch17-async-await/no-listing-state-machine/src/lib.rs:enum}} From 01f089aa2bf6b6f4502b4225db7d1faea1924a9f Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 11:56:23 -0400 Subject: [PATCH 199/249] Clarify writing what would be tedious, and what changes later would be made --- src/ch17-01-futures-and-syntax.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 3684451360..4aed657e4d 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -288,12 +288,13 @@ point: {{#rustdoc_include ../listings/ch17-async-await/no-listing-state-machine/src/lib.rs:enum}} ``` -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. 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! +Writing the code to transition between each state by hand would be tedious and +error-prone, especially when adding more functionality and more states to the +code later. Instead, the Rust compiler creates and manages the 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! Ultimately, something has to execute that state machine. That something is a runtime. (This is why you may sometimes come across references to *executors* From 502adbf52087c5cdccb9302ef404b1e924461deb Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 12:03:52 -0400 Subject: [PATCH 200/249] Be clearer about where we're using trpl::run and what it's running --- src/ch17-01-futures-and-syntax.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 4aed657e4d..f29237f195 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -304,9 +304,9 @@ executing the async code.) Now we can understand why the compiler stopped us from making `main` itself an 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`. +but `main` is the starting point for the program! Instead, we call the +`trpl::run` function in `main`, which sets up a runtime and runs the future +returned by the `async` block 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 From 9ad373ff7b51f49f6a3773e54600fb4932ab670c Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 12:04:33 -0400 Subject: [PATCH 201/249] Correct function name and pronoun number --- src/ch17-01-futures-and-syntax.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index f29237f195..2124b69000 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -314,8 +314,8 @@ returned by the `async` block until it returns `Ready`. > function which runs a future to completion the way `trpl::run` does. 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. +calling `page_title` with two different URLs passed in from the command line +and racing them. <Listing number="17-5" caption="" file-name="src/main.rs"> From a25f57614ec65a99232101815f214c34c09bb5c9 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 12:06:08 -0400 Subject: [PATCH 202/249] This sounds like 1 call with 2 URLs but it's 2 calls with 1 URL each --- src/ch17-01-futures-and-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 2124b69000..b920963f0e 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -327,7 +327,7 @@ and racing them. </Listing> -In Listing 17-5, we begin by calling `page_title` with both of the user-supplied +In Listing 17-5, we begin by calling `page_title` for each 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 to `trpl::race`, From 15f353c1efe09a08b296ab5a256a1c5baa236d35 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 12:07:50 -0400 Subject: [PATCH 203/249] Add a trailing comma on the last variant --- src/ch17-01-futures-and-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index b920963f0e..fc8ae2c0da 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -349,7 +349,7 @@ other”. ```rust enum Either<A, B> { Left(A), - Right(B) + Right(B), } ``` From d34446d51f7230914252e45706a8028f02fa4f36 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 12:08:59 -0400 Subject: [PATCH 204/249] Correct another instance of an old function name --- src/ch17-01-futures-and-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index fc8ae2c0da..9ecdc3437a 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -358,7 +358,7 @@ that future’s output, and `Right` with the second future argument’s output i *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 +We also update `page_title` 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 From f713c79b4bc3bdc38627d4fb86cd0234e58d5a41 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 12:11:05 -0400 Subject: [PATCH 205/249] Put back the invitation to race URLs at the end --- src/ch17-01-futures-and-syntax.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 9ecdc3437a..157fd26193 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -364,10 +364,11 @@ 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. +You have built a small working web scraper now! 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. 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 From 78679a78880619e04a608cac943506cd79208364 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 12:27:10 -0400 Subject: [PATCH 206/249] Clarify why the block only borrows and remove an unneeded word --- src/ch17-02-concurrency-with-async.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index a222b851d8..c0cd4ee2c8 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -319,12 +319,13 @@ 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 -ends. In Chapter 13, we learned how to use the `move` keyword with closures, and -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. +Right now, the async block where we send the messages only borrows `tx` because +sending a message doesn't require ownership, but if we could move `tx` into +that async block, it would be dropped once that block ends. In Chapter 13, we +learned how to use the `move` keyword with closures, and in Chapter 16, we saw +that we often need to 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-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, From f01527c27164326bcd97f8b78dce67984559d9ca Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 13:15:26 -0400 Subject: [PATCH 207/249] Since -> because because none of these are time-based --- src/ch17-00-async-await.md | 2 +- src/ch17-01-futures-and-syntax.md | 12 ++++++------ src/ch17-02-concurrency-with-async.md | 2 +- src/ch17-03-more-futures.md | 2 +- src/ch17-04-streams.md | 22 +++++++++++----------- src/ch17-05-traits-for-async.md | 6 +++--- src/ch17-06-futures-tasks-threads.md | 6 +++--- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index ecd9fb14b3..2a28792819 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -36,7 +36,7 @@ happen while the network operation is still ongoing. 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 +programs get work done. In many cases, because 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. diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 157fd26193..6768962fc9 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -117,7 +117,7 @@ Once we have `response_text`, we can then parse it into an instance of the 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 in the document, if there is one. Because 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 @@ -194,11 +194,11 @@ Let’s walk through each part of the transformed version: 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 +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. Because 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"> diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index c0cd4ee2c8..5e79143724 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -1,7 +1,7 @@ ## Concurrency With Async In this section, we will apply async to some of the same concurrency challenges -we tackled with threads in chapter 16. Since we already talked about a lot of +we tackled with threads in chapter 16. Because we already talked about a lot of the key ideas there, in this section we will focus on what is different between threads and futures. diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index ea9c7460ad..3d3c83fcdb 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -86,7 +86,7 @@ generated by the compiler. To make this work, we need to use *trait objects*, just as we did in [“Returning Errors from the run function”][dyn] in Chapter 12. (We will cover trait objects in detail in Chapter 18.) Using trait objects lets us treat each of the -anonymous futures produced by these types as the same type, since all of them +anonymous futures produced by these types as the same type, because all of them implement the `Future` trait. > Note: In Chapter 8, we discussed another way to include multiple types in a diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 28e8d9793f..1635044d97 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -186,7 +186,7 @@ be polled. </Listing> -However, since there are no delays between messages, this timeout does not +However, because 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 `messages` array so that we can get the index of each item we are sending along @@ -278,7 +278,7 @@ 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 -it over the channel. Since this is all wrapped in the task created by +it over the channel. Because 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. @@ -318,15 +318,15 @@ 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-38, we rework with the `intervals` stream, since `messages` is +In Listing 17-38, we rework with the `intervals` stream, because `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 -*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 -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 pin it so that it is safe to do so. +Second, we need to match the `Timeout` from `messages`. Because 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 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 pin it so that it is safe to do so. <!-- We cannot directly test this one, because it never stops. --> @@ -365,8 +365,8 @@ 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 -hundred milliseconds should do, since that is in the same ballpark as how often -our messages arrive. +hundred milliseconds should do, because that is in the same ballpark as how +often our messages arrive. 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 diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 91a78a7a56..a6eecf6f7b 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -195,7 +195,7 @@ those, however, `Pin` only works with *pointer types* like references (`&` 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 +pointers, though, because 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 @@ -410,8 +410,8 @@ 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 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 +type is `Poll`, because it has to be checked for readiness, just like a future. +The inner type is `Option`, because 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 diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index b54117ccc4..1d4876d2c0 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -117,9 +117,9 @@ 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! +a set of video encoding tasks using a dedicated thread, because 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 c2c083cb65f10fa7e45c39db2d34ae28952e97ca Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 13:19:30 -0400 Subject: [PATCH 208/249] Removing code style around futures; not sure what this refers to --- src/ch17-03-more-futures.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 3d3c83fcdb..b799aa30d3 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -112,8 +112,8 @@ Unfortunately, this still does not compile. In fact, we have the same basic 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-17). +`Box::new` calls, by explicitly annotating the type of the futures as a trait +object: <Listing number="17-17" caption="Fixing the rest of the type mismatch errors by using an explicit type declaration" file-name="src/main.rs"> From 63e7ab1ed30b53841754f2e6e1e5c00cb5c4ed45 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 13:20:32 -0400 Subject: [PATCH 209/249] Oh I see, it's the futures variable, but then I wouldn't call it a trait object --- src/ch17-03-more-futures.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index b799aa30d3..f18cca72c2 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -112,8 +112,7 @@ Unfortunately, this still does not compile. In fact, we have the same basic 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 annotating the type of the futures as a trait -object: +`Box::new` calls, by explicitly annotating the type of the `futures` variable: <Listing number="17-17" caption="Fixing the rest of the type mismatch errors by using an explicit type declaration" file-name="src/main.rs"> From db93cd0af315bba175da137b0691bdef55a4df4b Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:39:52 -0400 Subject: [PATCH 210/249] Caveat specificity of recv earlier, so we don't get WELL ACTUALLY poll_next --- src/ch17-04-streams.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 1635044d97..92cd9bf763 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -11,8 +11,9 @@ A sequence of items is something we have seen before, when we looked at the 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. 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. +its synchronous `next` method. With the `trpl::Receiver` stream in particular, +we called 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, From a97d72a75389eb15216777992c71ae8060ceaea0 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:43:48 -0400 Subject: [PATCH 211/249] Change future tense to past tense or whatever these tenses are The needs-to-be sense made it sort of sound like the stream was something the reader needed to create. --- src/ch17-04-streams.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 92cd9bf763..6c53c50f4c 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -17,11 +17,11 @@ 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 +though, the general-purpose stream API is much more general: it provides the +next item like `Iterator` does, but asynchronously. The similarity between +iterators and streams in Rust means 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-30. +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"> From 048717a75750869b7765d011a8993dfb2bfe7149 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:49:52 -0400 Subject: [PATCH 212/249] Missing period --- src/ch17-04-streams.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 6c53c50f4c..1cb54f67e4 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -34,7 +34,7 @@ method and then awaiting the output, as in Listing 17-30. We start with an array of numbers, which we convert to an iterator and then call `map` on to double all the values. Then we convert the iterator into a stream using the `trpl::stream_from_iter` function. Then we loop over the items in the -stream as they arrive with the `while let` loop +stream as they arrive with the `while let` loop. 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. From b3aef45d7b71ed19827471957bba2d03a2ddc4c0 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:50:30 -0400 Subject: [PATCH 213/249] Stream is a trait --- src/ch17-04-streams.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 1cb54f67e4..1d1ffc31be 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -81,7 +81,7 @@ reasonably expect that to be `Stream`, but the trait we need *here* is actually the Rust community for extending one trait with another. You might be wondering why `StreamExt` instead of `Stream`, and for that matter -whether there is a `Stream` type at all. Briefly, the answer is that throughout +whether there is a `Stream` trait at all. Briefly, the answer is that throughout the Rust ecosystem, the `Stream` trait defines a low-level interface which effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait supplies a higher-level set of APIs on top of `Stream`, including the `next` From 428d6deab415d82f5a8ac6a3d3bad8ef1babf14b Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:51:09 -0400 Subject: [PATCH 214/249] like -> similar to --- src/ch17-04-streams.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 1d1ffc31be..b79fe7d38c 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -85,9 +85,10 @@ whether there is a `Stream` trait at all. Briefly, the answer is that throughout the Rust ecosystem, the `Stream` trait defines a low-level interface which effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait supplies a higher-level set of APIs on top of `Stream`, including the `next` -method and also many other utility methods like those from `Iterator`. We will -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. +method as well as other utility methods similar to those provided by the +`Iterator` trait. We will 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 is add a `use` statement for `trpl::StreamExt`, as in Listing 17-31. From 6cd340c60eba81fc4125290c549fc3ffdd3b7404 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:51:39 -0400 Subject: [PATCH 215/249] 'All we need to do' makes it sound easy, but it might not be Knowing what trait to add feels hard to me sometimes. --- src/ch17-04-streams.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index b79fe7d38c..697b544764 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -90,8 +90,8 @@ method as well as other utility methods similar to those provided by the bit more detail at the end of the chapter. For now, this is enough to let us keep moving. -All we need to do is add a `use` statement for `trpl::StreamExt`, as in Listing -17-31. +The fix to the compiler error is to add a `use` statement for `trpl::StreamExt`, +as in Listing 17-31. <Listing number="17-31" caption="Successfully using an iterator as the basis for a stream" file-name="src/main.rs"> From cec24f5c349fe417019d6280be1faa3de0cd11cd Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:52:13 -0400 Subject: [PATCH 216/249] Be more specific than things --- src/ch17-04-streams.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 697b544764..f0b383097b 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -101,10 +101,10 @@ as in Listing 17-31. </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-32, we use the `filter` -method to filter out everything but multiples of three and five. +With all those pieces put together, this code works the way we want! What's +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-32, we use the +`filter` 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"> @@ -120,7 +120,7 @@ do which are unique to streams. ### Composing Streams -Lots of things are naturally represented as streams: items becoming available in +Many concepts are naturally represented as streams: items becoming available in 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 From 79c2110983b5a8b51584e7661649422abb7fe945 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 16:56:56 -0400 Subject: [PATCH 217/249] Say more about why we're building a stream instead of WebSockets --- src/ch17-04-streams.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index f0b383097b..ed2c26acf5 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -129,11 +129,12 @@ 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. -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-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. +Let’s start by building a little stream of messages, as a stand-in for a stream +of data we might see from a WebSocket or another real-time communication +protocol. In Listing 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. 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 From 9070b7fe951f4f940b00c629f263e3d45794c1e1 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 17:05:40 -0400 Subject: [PATCH 218/249] Add an explicit definition of poll so we can use it later --- src/ch17-01-futures-and-syntax.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 6768962fc9..7adff3b01c 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -16,7 +16,8 @@ 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. +place that async block or function may get paused and resumed. The process of +checking with a future to see if its value is available yet is called *polling*. Some other languages also use `async` and `await` keywords for async programming. If you are familiar with those languages, you may notice some From 7aa0f88cad34af9737c3b6d82a7118467f570ae9 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 17:14:08 -0400 Subject: [PATCH 219/249] Add a quick explanation of the semantics of merge --- src/ch17-04-streams.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index ed2c26acf5..b25ecbd0ea 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -299,9 +299,11 @@ 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. -Finally, we loop over that combined stream instead of over `messages` (Listing -17-37). +Then we merge the `messages` and `intervals` streams with the `merge` method, +which combines multiple streams into one stream that produces items from any of +the source streams as soon as the items are available, without imposing any +particular ordering. Finally, we loop over that combined stream instead of over +`messages` (Listing 17-37). <Listing number="17-37" caption="Attempting to merge streams of messages and intervals" file-name="src/main.rs"> From ff5f4875a040daae4ce6b1d91fe88a9c8dbfbb9f Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 17:16:27 -0400 Subject: [PATCH 220/249] Remove an extra 'with' --- src/ch17-04-streams.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index b25ecbd0ea..dfb0016789 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -323,7 +323,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-38, we rework with the `intervals` stream, because `messages` is +In Listing 17-38, we rework the `intervals` stream, because `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`. Because we do not From 796e5349ea07d2058c275ce5ad5ec5eba66c255b Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 17:19:04 -0400 Subject: [PATCH 221/249] Correct subj/verb agreement and remove a 'simply' --- src/ch17-04-streams.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index dfb0016789..74c83e8063 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -385,17 +385,17 @@ output, not just one stream or the other. </Listing> -Now when we run the program, it stop after pulling twenty items from the stream, -and the intervals do not overwhelm the messages. We also do not get `Interval: -100` or `Interval: 200` or so on, but instead simply get `Interval: 1`, -`Interval: 2`, and so on—even though we have a source stream which *can* produce -an event every millisecond. That is because the `throttle` call produces a new -stream, wrapping the original stream, so that the original stream only gets -polled at the throttle rate, not its own “native” rate. We do not have a bunch -of unhandled interval messages we are simply choosing to ignore. Instead, we -never produce those interval messages in the first place! This is the inherent -“laziness” of Rust’s futures at work again, allowing us to choose our -performance characteristics. +Now when we run the program, it stops after pulling twenty items from the +stream, and the intervals do not overwhelm the messages. We also do not get +`Interval: 100` or `Interval: 200` or so on, but instead get `Interval: 1`, +`Interval: 2`, and so on—even though we have a source stream which *can* +produce an event every millisecond. That is because the `throttle` call +produces a new stream, wrapping the original stream, so that the original +stream only gets polled at the throttle rate, not its own “native” rate. We do +not have a bunch of unhandled interval messages we are simply choosing to +ignore. Instead, we never produce those interval messages in the first place! +This is the inherent “laziness” of Rust’s futures at work again, allowing us to +choose our performance characteristics. <!-- manual-regeneration cd listings/listing-17-39 From 48379d38aac5b6e0aecf2eb2c6bfed07a36b16d4 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 17:21:41 -0400 Subject: [PATCH 222/249] Update code and output to match text --- .../listing-17-39/src/main.rs | 2 +- src/ch17-04-streams.md | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) 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 a5f51618f5..57ed7bed4a 100644 --- a/listings/ch17-async-await/listing-17-39/src/main.rs +++ b/listings/ch17-async-await/listing-17-39/src/main.rs @@ -9,7 +9,7 @@ fn main() { // ANCHOR: throttle let messages = get_messages().timeout(Duration::from_millis(200)); let intervals = get_intervals() - .map(|count| format!("Interval #{count}")) + .map(|count| format!("Interval: {count}")) .throttle(Duration::from_millis(100)) .timeout(Duration::from_secs(10)); let merged = messages.merge(intervals).take(20); diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 74c83e8063..1f1de6e2d3 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -404,26 +404,26 @@ copy and paste only the program output --> ```text -Interval #1 +Interval: 1 Message: 'a' -Interval #2 -Interval #3 +Interval: 2 +Interval: 3 Problem: Elapsed(()) -Interval #4 +Interval: 4 Message: 'b' -Interval #5 +Interval: 5 Message: 'c' -Interval #6 -Interval #7 +Interval: 6 +Interval: 7 Problem: Elapsed(()) -Interval #8 +Interval: 8 Message: 'd' -Interval #9 +Interval: 9 Message: 'e' -Interval #10 -Interval #11 +Interval: 10 +Interval: 11 Problem: Elapsed(()) -Interval #12 +Interval: 12 ``` There is one last thing we need to handle: errors! With both of these From 4647c8b3f15394f139538b502871d344d5a6e90a Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 20:35:00 -0400 Subject: [PATCH 223/249] Add trailing comma --- src/ch17-05-traits-for-async.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index a6eecf6f7b..b0851c3e7c 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -40,7 +40,7 @@ the `Poll` type: ```rust enum Poll<T> { Ready(T), - Pending + Pending, } ``` From afe43caa25c4d05ecbe066403caa47566f00d70b Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Tue, 1 Oct 2024 22:32:31 -0400 Subject: [PATCH 224/249] Use contractions more; a few tiny fixes The rest of the book's style, and No Starch's style, is more casual and uses contractions. --- src/ch17-00-async-await.md | 22 ++--- src/ch17-01-futures-and-syntax.md | 82 +++++++++--------- src/ch17-02-concurrency-with-async.md | 58 ++++++------- src/ch17-03-more-futures.md | 74 ++++++++-------- src/ch17-04-streams.md | 59 +++++++------ src/ch17-05-traits-for-async.md | 117 +++++++++++++------------- src/ch17-06-futures-tasks-threads.md | 60 ++++++------- 7 files changed, 236 insertions(+), 236 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 2a28792819..b754dc39cd 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -9,7 +9,7 @@ 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. +completed, you couldn’t do anything else on your computer while it was running. That would be a pretty frustrating experience, though. Instead, your computer’s operating system can—and does!—invisibly interrupt the export often enough to let you get other work done along the way. @@ -19,17 +19,17 @@ the CPU needs to wait on data to arrive from the network. While you can start 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 +that’s 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 -> “CPU-bound” or “compute-bound”. It is limited by the speed of the computer’s +> “CPU-bound” or “compute-bound”. It’s limited by the speed of the computer’s > ability to process data within the *CPU* or *GPU*, and how much of that speed > it can use. The video download is the kind of operation which is often -> described as “IO-bound,” because it is limited by the speed of the computer’s +> described as “IO-bound,” because it’s limited by the speed of the computer’s > *input and output*. It can only go as fast as the data can be sent across the > network. @@ -40,7 +40,7 @@ programs get work done. In many cases, because 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. -For example, if we are building a tool to manage file downloads, we should be +For example, if we’re building a tool to manage file downloads, we should be able to write our program in such a way that starting one download does not lock up the UI, and users should be able to start multiple downloads at the same time. Many operating system APIs for interacting with the network are @@ -70,7 +70,7 @@ between parallelism and concurrency. ### Parallelism and Concurrency -In the previous chapter we treated parallelism and concurrency as mostly +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. @@ -81,8 +81,8 @@ 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, so you cannot make progress on both tasks -tasks at the exact same time—but you can multi-task, making progress on multiple +to the other. You’re just one person, so you can’t make progress on both tasks +at the exact same time—but you can multi-task, making progress on multiple tasks by switching between them. <figure> @@ -114,9 +114,9 @@ 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. If you learn -that a colleague is stuck until you finish one of your tasks, you will probably +that a colleague is stuck until you finish one of your tasks, you’ll 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 +coworker are no longer able to work in parallel, and you’re 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 @@ -128,7 +128,7 @@ also do work in parallel. One core can be doing one thing while another core does something completely unrelated, and those actually happen at the same time. -When working with async in Rust, we are always dealing with concurrency. +When working with async in Rust, we’re 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 also use parallelism under the hood. diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 7adff3b01c..0f3145e85c 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -20,31 +20,31 @@ place that async block or function may get paused and resumed. The process of checking with a future to see if its value is available yet is called *polling*. Some other languages also use `async` and `await` keywords for async -programming. If you are familiar with those languages, you may notice some +programming. If you’re 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! +syntax. That’s for good reason, as we’ll 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 +your own data types when you need to. Many of the functions we’ll 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 +We’ll 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. We will pass in two URLs from the command line, fetch both of them +web scraper. We’ll 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 +example will have a fair bit of new syntax, but don’t worry. We’ll 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] +Programming Language”). It re-exports all the types, traits, and functions +you’ll need, primarily from the [`futures`][futures-crate] and [`tokio`][tokio] crates. - The `futures` crate is an official home for Rust experimentation for async @@ -53,12 +53,12 @@ crates. - 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. + for `trpl` because it’s well-tested and widely used. In some cases, `trpl` also renames or wraps the original APIs to let us stay focused on the details relevant to this 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 +You’ll be able to see what crate each re-export comes from, and we’ve left extensive comments explaining what the crate does. Create a new binary project named `hello-async` and add the `trpl` crate as a @@ -71,11 +71,11 @@ $ cargo add trpl ``` 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, +program. We’ll build a little command line tool which fetches two web pages, pulls the `<title>` element from each, and prints out the title of whichever finishes that whole process first. -Let's start by writing a function that takes one page URL as a parameter, makes +Let’s start by writing a function that takes one page URL as a parameter, makes a request to it, and returns the text of the title element: <Listing number="17-1" file-name="src/main.rs" caption="Defining an async function to get the title element from an HTML page"> @@ -100,34 +100,34 @@ 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 +Rust will show a compiler warning if you don’t 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 +them to. This laziness allows Rust to avoid running async code until it’s 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. +> running immediately. It’s also different from how many other languages +> approach async! But it’s important for Rust. We’ll see why that is later. 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>` +selector. By passing the string `"title"`, we’ll get the first `<title>` element in the document, if there is one. Because 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 +`Option::map` method, which lets us work with the item in the `Option` if it’s +present, and do nothing if it isn’t. (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 +Notice that Rust’s `await` keyword goes after the expression you’re awaiting, +not before it. That is, it’s 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` @@ -142,7 +142,7 @@ function calls together with `await` between them, as shown in Listing 17-2: </Listing> 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 +some code in `main` to call it, let’s talk a little more about what we’ve written and what it means. When Rust sees a block marked with the `async` keyword, it compiles it into a @@ -185,17 +185,17 @@ Let’s walk through each part of the transformed version: 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 - `url` parameter. (We will talk about `async` vs. `async move` much more later + `url` parameter. (We’ll 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 +* The new version of the function has a kind of lifetime we haven’t 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 + tell Rust that we mean for that reference to be included. We don’t 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 +Now we can call `page_title` in `main`. To start, we’ll 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. Because the value produced by the future is @@ -210,8 +210,8 @@ account for whether the page had a `<title>`. </Listing> -Unfortunately, this does not compile. The only place we can use the `await` -keyword is in async functions or blocks, and Rust will not let us mark the +Unfortunately, this doesn’t compile. The only place we can use the `await` +keyword is in async functions or blocks, and Rust won’t let us mark the special `main` function as `async`. <!-- manual-regeneration @@ -228,10 +228,10 @@ error[E0752]: `main` function is not allowed to be `async` | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` ``` -The reason `main` can't be marked `async` is that async code needs a *runtime*: +The reason `main` can’t be marked `async` 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 Rust program +program’s `main` function can *initialize* a runtime, but it’s not a runtime +*itself*. (We’ll see more about why this is a bit later.) Every Rust program that executes async code has at least one place where it sets up a runtime and executes the futures. @@ -244,7 +244,7 @@ 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. -Here, and throughout the rest of this chapter, we will use the `run` function +Here, and throughout the rest of this chapter, we’ll 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 @@ -253,8 +253,8 @@ future produced. 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 +(and most async code in the real world!), we’ll be doing more than just one +async function call, so instead we’ll pass an `async` block and explicitly 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"> @@ -281,7 +281,7 @@ 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, +it’s ready to try advancing this one again. This is an invisible state machine, as if you wrote an enum like this to save the current state at each `await` point: @@ -295,7 +295,7 @@ code later. Instead, the Rust compiler creates and manages the 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! +We’ll 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* @@ -331,17 +331,17 @@ and racing them. In Listing 17-5, we begin by calling `page_title` for each 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 to `trpl::race`, +and we haven’t yet awaited them. Then we pass the futures to `trpl::race`, which returns a value to indicate which of the futures passed to it finishes first. > 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 +> function can do a lot of things that `trpl::race` function can’t, but it also > has some additional complexity that we can skip over for now. -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, +Either future can legitimately “win,” so it doesn’t make sense to return a +`Result`. Instead, `race` returns a type we haven’t 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 @@ -368,7 +368,7 @@ what the `<title>` was for the web page at that URL, if any. You have built a small working web scraper now! 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. More -importantly, you have learned the basics of working with futures, so we can now +importantly, you’ve 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 diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 5e79143724..62f2a0bc82 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -1,8 +1,8 @@ ## Concurrency With Async -In this section, we will apply async to some of the same concurrency challenges +In this section, we’ll apply async to some of the same concurrency challenges we tackled with threads in chapter 16. Because we already talked about a lot of -the key ideas there, in this section we will focus on what is different between +the key ideas there, in this section we’ll focus on what’s different between threads and futures. In many cases, the APIs for working with concurrency using async are very @@ -31,7 +31,7 @@ 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::run` in `main`, so we will often skip it +> exact same wrapping code with `trpl::run` in `main`, so we’ll 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, @@ -102,8 +102,8 @@ So far, it looks like async and threads give us the same basic outcomes, just 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 need to spawn a task here. Because +The bigger difference is that we didn’t need to spawn another operating system +thread to do this. In fact, we don’t 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. @@ -115,7 +115,7 @@ future whose output is a tuple with the output of each of the futures you passed 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. +it’s just a tuple with two unit values in it. <Listing number="17-8" caption="Using `trpl::join` to await two anonymous futures" file-name="src/main.rs"> @@ -147,7 +147,7 @@ hi number 8 from the first task! hi number 9 from the first task! ``` -Here, you will see the exact same order every time, which is very different from +Here, you’ll see the exact same order every time, which is very different from 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 @@ -155,7 +155,7 @@ decides which thread to check and how long to let it run. With async Rust, the 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 +for a runtime—but it’s still possible!) Runtimes don’t have to guarantee fairness for any given operation, and runtimes often offer different APIs to let you choose whether you want fairness or not. @@ -172,11 +172,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. We will take a +Sharing data between futures will also be familiar: we’ll use message passing +again, but this with async versions of the types and functions. We’ll 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-9, -we will begin with just a single async block—*not* spawning a separate task like +we’ll begin with just a single async block—*not* spawning a separate task like we spawned a separate thread. <Listing number="17-9" caption="Creating an async channel and assigning the two halves to `tx` and `rx`" file-name="src/main.rs"> @@ -192,16 +192,16 @@ 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 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 +we can send messages from the sender to the receiver. Notice that we don’t have 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 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, -because the channel we are sending it into is unbounded. +a message is received or the send side of the channel closes. By contrast, we +don’t await the `send` call, because it doesn’t block. It doesn’t need to, +because the channel we’re sending it into is unbounded. > Note: Because all of this async code runs in an async block in a `trpl::run` > call, everything within it can avoid blocking. However, the code *outside* it @@ -211,7 +211,7 @@ because the channel we are sending it into is unbounded. > runtimes, `run` is actually named `block_on` for exactly this reason. 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 +Second, although we use a future here, there’s no concurrency yet. Everything in the listing happens in sequence, just as it would if there were no futures involved. @@ -230,12 +230,12 @@ between them, as shown in Listing 17-10: In addition to sending the messages, we need to receive them. In this case, we could do that manually, by just doing `rx.recv().await` four times, because we -know how many messages are coming in. In the real world, though, we will +know how many messages are coming in. In the real world, though, we’ll 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 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 +synchronous channel. However, Rust doesn’t 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 @@ -269,8 +269,8 @@ 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-10, so everything in it runs -linearly. There is still no concurrency. All the `tx.send` calls happen, +There’s only one async block in Listing 17-10, so everything in it runs +linearly. There’s 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. @@ -280,7 +280,7 @@ 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. 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 +in sequence, we would just end up back in a sequential flow—exactly what we’re trying *not* to do. <!-- We cannot test this one because it never stops! --> @@ -303,24 +303,24 @@ interacts with `trpl::join`: 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 awaiting `rx.recv` produces `None`. +* The `rx` future won’t complete until the `while let` loop ends. +* The `while let` loop won’t 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 +* We don’t call `rx.close` anywhere, and `tx` won’t 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 +* The block can’t 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 +We could manually close `rx` by calling `rx.close` somewhere, but that doesn’t 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` because -sending a message doesn't require ownership, but if we could move `tx` into +sending a message doesn’t require ownership, but if we could move `tx` into that async block, it would be dropped once that block ends. In Chapter 13, we learned how to use the `move` keyword with closures, and in Chapter 16, we saw that we often need to move data into closures when working with threads. The @@ -345,11 +345,11 @@ 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. They key is the order of the +messages, but it could go before it just as well. The 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 +that both `tx` and `tx1` get dropped when those blocks finish. Otherwise we’ll 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. diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index f18cca72c2..80c3b116f8 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -22,7 +22,7 @@ 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 common pattern. -To check all the futures in some collection, we will need to iterate over and +To check all the futures in some collection, we’ll need to iterate over and join on *all* of them. The `trpl::join_all` function accepts any type which 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 @@ -36,7 +36,7 @@ replace `join!` with `join_all`. </Listing> -Unfortunately, this does not compile. Instead, we get this error: +Unfortunately, this doesn’t compile. Instead, we get this error: <!-- manual-regeneration cd listings/ch17-async-await/listing-17-16/ @@ -76,25 +76,25 @@ error[E0308]: mismatched types = help: consider pinning your async block and and casting it to a trait object ``` -This might be surprising. After all, none of them returns anything, so each +This might be surprising. After all, none of them return anything, so each block produces a `Future<Output = ()>`. However, `Future` is a trait, not a concrete type. The concrete types are the individual data structures generated -by the compiler for async blocks. You cannot put two different hand-written +by the compiler for async blocks. You can’t put two different hand-written structs in a `Vec`, and the same thing applies to the different structs generated by the compiler. To make this work, we need to use *trait objects*, just as we did in [“Returning -Errors from the run function”][dyn] in Chapter 12. (We will cover trait objects +Errors from the run function”][dyn] in Chapter 12. (We’ll cover trait objects in detail in Chapter 18.) Using trait objects lets us treat each of the anonymous futures produced by these types as the same type, because all of them implement the `Future` trait. > Note: In Chapter 8, we discussed another way to include multiple types in a > `Vec`: using an enum to represent each of the different types which can -> appear in the vector. We cannot do that here, though. For one thing, we have +> appear in the vector. We can’t do that here, though. For one thing, we have > no way to name the different types, because they are anonymous. For another, > the reason we reached for a vector and `join_all` in the first place was to be -> able to work with a dynamic collection of futures where we do not know what +> able to work with a dynamic collection of futures where we don’t 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 @@ -108,7 +108,7 @@ in Listing 17-16. </Listing> -Unfortunately, this still does not compile. In fact, we have the same basic +Unfortunately, this still doesn’t compile. In fact, we have the same basic 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 @@ -204,7 +204,7 @@ 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. Later in the chapter, we will dig into a few more details about `Pin` and +it. Later in the chapter, we’ll 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-18, we start by updating the type annotation for `futures`, with a `Pin` wrapping each `Box`. Second, we use `Box::pin` to pin @@ -237,9 +237,9 @@ received 'you' Phew! -There is a bit more we can explore here. For one thing, using `Pin<Box<T>>` +There’s a bit more we can explore here. For one thing, using `Pin<Box<T>>` 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 +heap with `Box`—and we’re 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 wrapper type, so we can get the benefit of having a single type in the `Vec`—the original reason we @@ -311,16 +311,16 @@ interesting behavior happens in the body of the async blocks. 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 +first. That’s because the implementation of this particular `race` function is +not fair. It always runs the futures passed as arguments in the order they’re 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 +to poll first. Regardless of whether the implementation of race we’re 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 [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 +future being awaited isn’t 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. @@ -329,7 +329,7 @@ that future will block any other futures from making progress. You may sometimes 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 +particular task indefinitely, you’ll 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 @@ -387,13 +387,13 @@ copy just the output '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! +As with our earlier example, `race` still finishes as soon as `a` is done. +There’s 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-23: if we removed the `trpl::sleep` at the end of the `a` future, it would complete @@ -435,7 +435,7 @@ 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 +We don’t 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-25, we replace all those `sleep` calls with `yield_now`. @@ -456,9 +456,9 @@ 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-26. (This is not an especially rigorous way to do performance +Listing 17-26. (This isn’t 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 +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`. @@ -481,20 +481,22 @@ 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 +In real-world code, you won’t usually be alternating function calls with 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 +is relatively inexpensive, it’s not free! In many cases, trying to break up a +compute-bound task might make it significantly slower, so sometimes it’s 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! +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 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. +build a `timeout` function with async building blocks we already have. When +we’re done, the result will be another building block we could use to build up +yet further async abstractions. Listing 17-27 shows how we would expect this `timeout` to work with a slow future. @@ -570,11 +572,11 @@ calls—one of the examples from the beginning of the chapter! 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 +on. You’ll 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 +We’ve now seen a number of ways to work with multiple futures at the same +time. Up next, we’ll 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: diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 1f1de6e2d3..1f0ca66342 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -6,7 +6,7 @@ async channel in the [“Message Passing”][17-02-messages] earlier in the chap 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 +A sequence of items is something we’ve 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 @@ -15,7 +15,7 @@ its synchronous `next` method. With the `trpl::Receiver` stream in particular, we called 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 +That similarity isn’t a coincidence. A stream is like an asynchronous form of iteration. Whereas the `trpl::Receiver` specifically waits to receive messages, though, the general-purpose stream API is much more general: it provides the next item like `Iterator` does, but asynchronously. The similarity between @@ -36,7 +36,7 @@ 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, when we try to run the code, it does not compile. Instead, as we +Unfortunately, when we try to run the code, it doesn’t compile. Instead, as we can see in the output, it reports that there is no `next` method available. <!-- TODO: fix up the path here? --> @@ -86,7 +86,7 @@ the Rust ecosystem, the `Stream` trait defines a low-level interface which effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait supplies a higher-level set of APIs on top of `Stream`, including the `next` method as well as other utility methods similar to those provided by the -`Iterator` trait. We will return to the `Stream` and `StreamExt` traits in a +`Iterator` trait. We’ll 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. @@ -101,7 +101,7 @@ as in Listing 17-31. </Listing> -With all those pieces put together, this code works the way we want! What's +With all those pieces put together, this code works the way we want! What’s 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-32, we use the `filter` method to filter out everything but multiples of three and five. @@ -114,7 +114,7 @@ methods, just like with iterators. For example, in Listing 17-32, we use the </Listing> -Of course, this is not very interesting. We could do that with normal iterators +Of course, this isn’t 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. @@ -207,8 +207,8 @@ for 200 milliseconds, this should affect half of the messages. </Listing> To sleep between messages in the `get_messages` function without blocking, we -need to use async. However, we cannot make `get_messages` itself into an async -function, because then we would return a `Future<Output = Stream<Item = +need to use async. However, we can’t make `get_messages` itself into an async +function, because then we’d return a `Future<Output = Stream<Item = String>>` instead of just a `Stream<Item = String>>`. 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* @@ -256,9 +256,9 @@ Problem: Elapsed(()) Message: 'j' ``` -The timeout does not prevent the messages from arriving in the end—we still get +The timeout doesn’t prevent the messages from arriving in the end—we still get all of the original messages. This is because our channel is unbounded: it can -hold as many messages as we can fit in memory. If the message does not arrive +hold as many messages as we can fit in memory. If the message doesn’t arrive before the timeout, our stream handler will account for that, but when it polls the stream again, the message may now have arrived. @@ -272,14 +272,14 @@ this stream of messages. 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 +from a channel we used in `get_messages`. The difference is that this time, +we’re 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-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 +variable.) Then we create an infinite loop. Each iteration of the loop asynchronously sleeps for one millisecond, increments the count, and then sends it over the channel. Because this is all wrapped in the task created by `spawn_task`, all of it will get cleaned up along with the runtime, including @@ -295,7 +295,7 @@ 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, as long as there is +indefinitely. With async, this doesn’t 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`. @@ -316,7 +316,7 @@ particular ordering. Finally, we loop over that combined stream instead of over 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 compile! (Neither does the `next` call in the `while -let` loop, but we will come back to that after fixing this.) The two streams +let` loop, but we’ll come back to that after fixing this.) The two streams have different types. The `messages` stream has the type `Timeout<impl Stream<Item = String>>`, where `Timeout` is the type which implements `Stream` for a `timeout` call. Meanwhile, the `intervals` stream has the type `impl @@ -326,12 +326,12 @@ them to match the other. In Listing 17-38, we rework the `intervals` stream, because `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`. Because we do not +Second, we need to match the `Timeout` from `messages`. Because we don’t 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 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 pin it so that it is safe to do so. +through the stream, and pin it so that it’s safe to do so. <!-- We cannot directly test this one, because it never stops. --> @@ -343,10 +343,9 @@ through the stream, and pin it so that it is safe to do so. </Listing> - That gets us *almost* to where we need to be. Everything type checks. If you run -this, though, there will be two problems. First, it will never stop! You will -need to stop it with <span class="keystroke">ctrl-c</span>. Second, the +this, though, there will be two problems. First, it will never stop! You’ll +need to stop it with <span class="keystroke">ctrl-c</span>. Second, the messages from the English alphabet will be buried in the midst of all the interval counter messages: @@ -367,7 +366,7 @@ Interval: 43 ``` 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 +`throttle` method on the `intervals` stream, so that it doesn’t 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 hundred milliseconds should do, because that is in the same ballpark as how @@ -386,13 +385,13 @@ output, not just one stream or the other. </Listing> Now when we run the program, it stops after pulling twenty items from the -stream, and the intervals do not overwhelm the messages. We also do not get +stream, and the intervals don’t overwhelm the messages. We also don’t get `Interval: 100` or `Interval: 200` or so on, but instead get `Interval: 1`, `Interval: 2`, and so on—even though we have a source stream which *can* -produce an event every millisecond. That is because the `throttle` call +produce an event every millisecond. That’s because the `throttle` call produces a new stream, wrapping the original stream, so that the original -stream only gets polled at the throttle rate, not its own “native” rate. We do -not have a bunch of unhandled interval messages we are simply choosing to +stream only gets polled at the throttle rate, not its own “native” rate. We +don’t have a bunch of unhandled interval messages we’re choosing to ignore. Instead, we never produce those interval messages in the first place! This is the inherent “laziness” of Rust’s futures at work again, allowing us to choose our performance characteristics. @@ -426,12 +425,12 @@ Problem: Elapsed(()) Interval: 12 ``` -There is one last thing we need to handle: errors! With both of these +There’s one last thing we need to handle: errors! With both of these 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`, +channel closes—and that’s just a matter of how the runtime executes the futures +which make up the stream. Up until 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-40 shows +ending the loop so we don’t 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. @@ -444,7 +443,7 @@ you have a strategy. </Listing> -Now that we have seen a bunch of async in practice, let’s take a step back and +Now that we’ve seen a bunch of async in practice, let’s take a step back and dig into a few of the details of how `Future`, `Stream`, and the other key traits which Rust uses to make async work. diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index b0851c3e7c..e7cc3b16f2 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -1,14 +1,13 @@ ## Digging Into the Traits for Async -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 +Throughout the chapter, we’ve used the `Future`, `Pin`, `Unpin`, `Stream`, and +`StreamExt` traits in various ways. So far, though, we’ve 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 +when writing Rust day to day, this is fine. Sometimes, though, you’ll 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 +section, we’ll dig down *enough* further to help with those situations—while still leaving the *really* deep dive for other documentation! - ### Future Back in [Futures and the Async Syntax][futures-syntax], we noted that `Future` @@ -26,14 +25,14 @@ pub trait Future { } ``` -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. +That trait definition includes a bunch of new types and also some syntax we +haven’t 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<Self::Output>`. We will talk a little more about `Pin` and +and returns a `Poll<Self::Output>`. We’ll 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: @@ -101,10 +100,10 @@ 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 +initial discussion, we noted that a runtime will pause the future until it’s 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 +can see how that works. The runtime knows the future isn’t 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)`. @@ -151,9 +150,9 @@ 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, +pin the values, but also tells 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 @@ -177,29 +176,29 @@ The `cx` parameter and its `Context` type is interesting, but is beyond the scope of this chapter: you generally only need to worry about it when writing a custom `Future` implementation. -Instead, we will focus on the type for `self`. This is the first time we have +Instead, we’ll focus on the type for `self`. This is the first time we’ve seen a method where `self` has a type annotation. A type annotation for `self` is similar to type annotations for other function parameters, with two key -differences. First, when we specify the type of `self` like this, we are telling +differences. First, when we specify the type of `self` like this, we’re telling Rust what type `self` must be to call this method. Second, a type annotation on -`self` cannot be just any type. It is only allowed to be the type on which the -method is 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 +`self` can’t be just any type. It’s only allowed to be the type on which the +method is implemented, a reference or smart pointer to that type, or a `Pin` +wrapping a reference to that type. We’ll see more on this syntax in Chapter +18. For now, it’s 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 *pointer types* like references (`&` 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, because 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. +`Pin` is a wrapper type. In some ways, it’s similar to 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 *pointer types* such as references +(`&` 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, because implementing `Deref` or `DerefMut` +means your type behaves like a pointer type. `Pin` is also not a pointer itself, +and it doesn’t have any behavior of its own like the ref counting of `Rc` or +`Arc`. It’s 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 @@ -258,8 +257,8 @@ In principle, the Rust compiler could 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. -This is exactly what Rust’s borrow checker requires: you cannot move an item +question *doesn’t move in memory*, we don’t have to update any references. +This is exactly what Rust’s borrow checker requires: you can’t 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 @@ -278,8 +277,8 @@ the `Box` pointer. Figure 17-5 illustrates this: In fact, the `Box` pointer can still 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, as in -Figure 17-6, there is no potential problem. (How you would do this with a `Pin` -wrapping a `Box` is more than we will get into in this particular discussion, +Figure 17-6, there’s no potential problem. (How you would do this with a `Pin` +wrapping a `Box` is more than we’ll get into in this particular discussion, but it would make for a good exercise! If you look at the docs for the types as well as the `std::pin` module, you might be able to work out how you would do that.) The key is that the self-referential type itself cannot move, because it @@ -296,18 +295,18 @@ is still pinned. 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 +internal structure like that, so they’re obviously safe. Neither do most types +you normally work with in Rust. A `Vec`, for example, doesn’t 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<Vec<String>>`, you would have to do +without worrying. If you have a `Pin<Vec<String>>`, you’d have to do everything via the safe but restrictive APIs provided by `Pin`, even though a `Vec<String>` 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 +need a way to tell the compiler that it’s 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 +tell the compiler that it’s 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. @@ -331,7 +330,7 @@ characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure </figure> This means that we can do things like replace one string with another at the -exact same location in memory as in Figure 17-8. This does not violate the `Pin` +exact same location in memory as in Figure 17-8. This doesn’t violate the `Pin` contract because `String`—like most other types in Rust—implements `Unpin`, because it has no internal references that make it unsafe to move around! @@ -345,31 +344,30 @@ because it has no internal references that make it unsafe to move around! Now we know enough to understand the errors reported for that `join_all` call from back in Listing 17-17. We originally tried to move the futures produced by -an async blocks into a `Vec<Box<dyn Future<Output = ()>>>`, but as we have seen, -those futures may have internal references, so they do not implement `Unpin`. +async blocks into a `Vec<Box<dyn Future<Output = ()>>>`, but as we’ve seen, +those futures may have internal references, so they don’t 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! +when you’re building a runtime itself, rather than for day to day Rust code. +When you see them, though, now you’ll 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 +> they’re 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 specifics of how `Pin` and `Unpin` work, and the rules they are required +> The specifics of how `Pin` and `Unpin` work, and the rules they’re required > to uphold, 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’d like to understand them more deeply, that’s 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]. +> - [Chapter 4: Pinning][pinning] ### The Stream Trait @@ -404,21 +402,21 @@ 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 is always a single `Output` (even if it -the unit type `()`). +these, and unlike `Future`, where there is always a single `Output` (even if +it’s 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 combines `Poll`with `Option`. The outer +like `Iterator::next`. Its return type combines `Poll` with `Option`. The outer type is `Poll`, because it has to be checked for readiness, just like a future. The inner type is `Option`, because 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, +standard library. In the meantime, it’s 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 in the section on streaming, though, we did not use +In the example we saw in the section on streaming, though, we didn’t 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 @@ -442,14 +440,15 @@ in traits, since the lack thereof is the reason they do not yet have this. > 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! +> That `Next` type is a `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 method! 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. +which implements `Stream`, but these traits are defined separately 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 diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 1d4876d2c0..7b0e7af9ab 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -1,10 +1,10 @@ ## Futures, Tasks, and Threads As we saw in the previous chapter, threads provide one approach to concurrency. -We have seen another approach to concurrency in this chapter, using async with +We’ve seen another approach to concurrency in this chapter, using async with futures and streams. You might be wondering why you would choose one or the -other. The answer is: it depends! And in many cases, it is not threads *or* -async but rather threads *and* async. +other. The answer is: it depends! And in many cases, the choice isn’t threads +*or* async but rather threads *and* async. Many operating systems have supplied threading-based concurrency models for decades now, and many programming languages have support for them as a result. @@ -12,15 +12,15 @@ 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 -computers, some embedded systems do not have an OS at all, so they also do not +computers, some embedded systems don’t have an OS at all, so they also don’t 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 +tradeoffs. In the async model, concurrent operations don’t require their own threads. Instead, they can run on tasks, as when we used `trpl::spawn_task` to -kick off work from a synchronous function throughout the streams section. A task -is a lot like a thread—but instead of being managed by the operating system, it -is managed by library-level code: the runtime. +kick off work from a synchronous function throughout the streams section. A +*task* is a lot like a thread—but instead of being managed by the operating +system, it’s 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 @@ -38,17 +38,17 @@ the `thread::spawn` and `thread::sleep` APIs from the standard library in the </Listing> If you run this, the output is identical. And notice how little changes here -from the perspective of the calling code! What is more, even though one of our +from the perspective of the calling code! What’s more, even though one of our functions spawned an async task on the runtime and the other spawned an OS thread, the resulting streams were unaffected by the differences. -However, there is a significant difference between these two approaches behave, -although we might have a hard time measuring it in this very simple example. We -could spawn hundreds of thousands or even millions of async tasks on any modern -personal computer. If we tried to do that with threads, we would literally run -out of memory! +However, there’s a significant difference between how these two approaches +behave, although we might have a hard time measuring it in this very simple +example. We could spawn hundreds of thousands or even millions of async tasks +on any modern personal computer. If we tried to do that with threads, we would +literally run out of memory! -However, there is a reason these APIs are so similar. Threads act as a boundary +However, there’s a reason these APIs are so similar. Threads act as a boundary for sets of synchronous operations; concurrency is possible *between* threads. Tasks act as a boundary for sets of *asynchronous* operations; concurrency is possible both *between* and *within* tasks. In that regard, tasks are kind of @@ -58,7 +58,7 @@ even more granular unit of concurrency, where each future may represent a tree 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 +However, this doesn’t 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 @@ -66,11 +66,11 @@ 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 +mechanisms for cancellation—a subject we haven’t 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 +These limitations make threads harder to compose than futures. It’s much more difficult, for example, to build something like the `timeout` we built in [“Building Our Own Async Abstractions”][combining-futures], or the `throttle` method we used with streams in [“Composing Streams”][streams]. The fact that @@ -78,15 +78,15 @@ futures are richer data structures means they *can* be composed together more naturally, as we have seen. Tasks then give *additional* control over futures, allowing you to choose where -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, 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. +and how to group the futures. 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 haven’t mentioned it up until now, but under the +hood the `Runtime` we have been using, including the `spawn_blocking` and +`spawn_task` 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: @@ -96,15 +96,15 @@ As a default way of thinking about which to use when: different sources which may come in a different intervals or different rates, async is a better choice. -And if you need some mix of parallelism and concurrency, you do not have to +And if you need some mix of parallelism and concurrency, you don’t have to choose between threads and async. You can use them together freely, letting each -one serve the part it is best at. For example, Listing 17-TODO shows a fairly +one serve the part it is best at. For example, Listing 17-42 shows a fairly common example of this kind of mix in real-world Rust code. <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 -{{#rustdoc_include ../listings/ch17-async-await/listing-17-42/src/main.rs}} +{{#rustdoc_include ../listings/ch17-async-await/listing-17-42/src/main.rs:all}} ``` </Listing> From 84eab3232cc69c4ce3508f472ac7b3c24314fbc0 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Wed, 2 Oct 2024 20:52:59 -0400 Subject: [PATCH 225/249] Be more specific about 'them' --- src/ch17-05-traits-for-async.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index e7cc3b16f2..f054de233e 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -351,7 +351,8 @@ 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’re building a runtime itself, rather than for day to day Rust code. -When you see them, though, now you’ll know what to do! +When you see these traits in error messages, though, now you’ll have a better +idea of how to fix the code! > 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 From 13e7c88811c27eaa26c90d9b23542bb5b00dbe09 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Wed, 2 Oct 2024 20:54:39 -0400 Subject: [PATCH 226/249] Clarify where the commonly used Stream definition comes from --- src/ch17-05-traits-for-async.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index f054de233e..5724103776 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -377,7 +377,8 @@ 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,<!-- TODO: verify before press time! --> but there -*is* a very common definition used throughout the ecosystem. +*is* a very common definition from the `futures` crate 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 95728278331b2e10136bcb1f830af538f66c644c Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Wed, 2 Oct 2024 21:57:52 -0400 Subject: [PATCH 227/249] Minimize the word 'like' when other words would fit --- src/ch17-00-async-await.md | 4 +- src/ch17-01-futures-and-syntax.md | 34 +++++----- src/ch17-02-concurrency-with-async.md | 10 +-- src/ch17-03-more-futures.md | 26 ++++---- src/ch17-04-streams.md | 20 +++--- src/ch17-05-traits-for-async.md | 89 ++++++++++++++------------- src/ch17-06-futures-tasks-threads.md | 18 +++--- 7 files changed, 101 insertions(+), 100 deletions(-) diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index b754dc39cd..920486d333 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -57,7 +57,7 @@ We could avoid blocking our main thread by spawning a dedicated thread to 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: +same direct style we use in blocking code. Something similar to this: ```rust,ignore,does_not_compile let data = fetch_data_from(url).await; @@ -121,7 +121,7 @@ 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 -still work concurrently. Using tools like threads, processes, and async, the +still work concurrently. Using tools such as threads, processes, and async, the computer can pause one activity and switch to others before eventually cycling back to that first activity again. On a machine with multiple CPU cores, it can also do work in parallel. One core can be doing one thing while another core diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 0f3145e85c..2799ff3276 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -5,12 +5,12 @@ The key elements of asynchronous programming in Rust are *futures* and Rust’s 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. +under other names such as “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 @@ -26,7 +26,7 @@ syntax. That’s for good reason, as we’ll 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. +as 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’ll see throughout this chapter return types with their own implementations of `Future`. @@ -103,7 +103,7 @@ We have to explicitly await both of these futures, because futures in Rust are Rust will show a compiler warning if you don’t 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 +using `for` loops or methods such as `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’s actually needed. @@ -152,9 +152,9 @@ whose body is an async block. Thus, an async function’s return type is the typ of the anonymous data type the compiler creates for that async block. 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: +*future* of the return type. When the compiler sees a function definition such +as the `async fn page_title` in Listing 17-1, it’s equivalent to a non-async +function defined like this: ```rust # extern crate trpl; // required for mdbook test @@ -242,7 +242,7 @@ 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. The crates which provide those runtimes also often supply async versions of common functionality -like file or network I/O. +such as file or network I/O. Here, and throughout the rest of this chapter, we’ll use the `run` function from the `trpl` crate, which takes a future as an argument and runs it to @@ -282,7 +282,7 @@ 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’s ready to try advancing this one again. This is an invisible state machine, -as if you wrote an enum like this to save the current state at each `await` +as if you wrote an enum in this way to save the current state at each `await` point: ```rust @@ -342,10 +342,10 @@ first. Either future can legitimately “win,” so it doesn’t make sense to return a `Result`. Instead, `race` returns a type we haven’t 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”. +`trpl::Either`. The `Either` type is somewhat similar to 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> { diff --git a/src/ch17-02-concurrency-with-async.md b/src/ch17-02-concurrency-with-async.md index 62f2a0bc82..7683bf5bf4 100644 --- a/src/ch17-02-concurrency-with-async.md +++ b/src/ch17-02-concurrency-with-async.md @@ -32,7 +32,7 @@ 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::run` in `main`, so we’ll often skip it -> just like we do with `main`. Don’t forget to include it in your code! +> just as 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 @@ -176,7 +176,7 @@ Sharing data between futures will also be familiar: we’ll use message passing again, but this with async versions of the types and functions. We’ll 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-9, -we’ll begin with just a single async block—*not* spawning a separate task like +we’ll begin with just a single async block—*not* spawning a separate task as we spawned a separate thread. <Listing number="17-9" caption="Creating an async channel and assigning the two halves to `tx` and `rx`" file-name="src/main.rs"> @@ -253,7 +253,7 @@ 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 -use it in the loop body, just like we could with `if let`. If the result is +use it in the loop body, just as we could with `if let`. If the result is `None`, the loop ends. Every time the loop completes, it hits the await point again, so the runtime pauses it again until another message arrives. @@ -278,7 +278,7 @@ 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. Once again, we await the result of calling +just as 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’re trying *not* to do. @@ -325,7 +325,7 @@ that async block, it would be dropped once that block ends. In Chapter 13, we learned how to use the `move` keyword with closures, and in Chapter 16, we saw that we often need to 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. +async blocks just as it does with closures. 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, diff --git a/src/ch17-03-more-futures.md b/src/ch17-03-more-futures.md index 80c3b116f8..fecb73d035 100644 --- a/src/ch17-03-more-futures.md +++ b/src/ch17-03-more-futures.md @@ -289,8 +289,8 @@ syntax for working with them, and that is a good thing. 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. +need *some* future from a set to finish before we move on—kind of similar to +racing one future against another. In Listing 17-21, we once again use `trpl::race` to run two futures, `slow` and `fast`, against each other. Each one prints a message when it starts running, @@ -449,14 +449,14 @@ directly, using the `yield_now` function. In Listing 17-25, we replace all those </Listing> 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 +than using `sleep`, because timers such as 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-26. (This isn’t an especially rigorous way to do performance +You can see this for yourself by setting up a little benchmark, such as the one +in Listing 17-26. (This isn’t 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 @@ -481,9 +481,9 @@ 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 won’t usually be alternating function calls with -await points on every single line, of course. While yielding control like this -is relatively inexpensive, it’s not free! In many cases, trying to break up a +In real-world code, you won’t usually be alternating function calls with await +points on every single line, of course. While yielding control in this way is +relatively inexpensive, it’s not free! In many cases, trying to break up a compute-bound task might make it significantly slower, so sometimes it’s 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 @@ -566,13 +566,13 @@ 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! +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 +such as network calls—one of the examples from the beginning of the chapter! 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’ll only need to reach for `pin` now and again to use them with those +secondarily with functions and macros such as `join`, `join_all`, `race`, and +so on. You’ll only need to reach for `pin` now and again to use them with those APIs. We’ve now seen a number of ways to work with multiple futures at the same diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 1f0ca66342..7bcc24ee4e 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -15,13 +15,13 @@ its synchronous `next` method. With the `trpl::Receiver` stream in particular, we called an asynchronous `recv` method instead, but these APIs otherwise feel very similar. -That similarity isn’t a coincidence. A stream is like an asynchronous form of -iteration. Whereas the `trpl::Receiver` specifically waits to receive messages, -though, the general-purpose stream API is much more general: it provides the -next item like `Iterator` does, but asynchronously. The similarity between -iterators and streams in Rust means 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-30. +That similarity isn’t a coincidence. A stream is similar to an asynchronous +form of iteration. Whereas the `trpl::Receiver` specifically waits to receive +messages, though, the general-purpose stream API is much more general: it +provides the next item the way `Iterator` does, but asynchronously. The +similarity between iterators and streams in Rust means 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-30. <Listing number="17-30" caption="Creating a stream from an iterator and printing its values" file-name="src/main.rs"> @@ -103,7 +103,7 @@ as in Listing 17-31. With all those pieces put together, this code works the way we want! What’s 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-32, we use the +methods, just as 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-32" caption="Filtering a `Stream` with the `StreamExt::filter` method" file-name="src/main.rs"> @@ -168,7 +168,7 @@ Message: 'j' ``` 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 +API, though. Let’s add something that requires streams: adding a timeout which applies to every item in the stream, and a delay on the items we emit. In Listing 17-34, we start by adding a timeout to the stream with the `timeout` @@ -221,7 +221,7 @@ available. Instead, we leave `get_messages` as a regular function which returns a stream, and spawn a task to handle the async `sleep` calls. -> Note: calling `spawn_task` like this works because we already set up our +> Note: calling `spawn_task` in this way works because we already set up our > runtime. Calling this particular implementation of `spawn_task` *without* > first setting up a runtime will cause a panic. Other implementations choose > different tradeoffs: they might spawn a new runtime and so avoid the panic but diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 5724103776..7cc3825886 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -43,7 +43,7 @@ enum Poll<T> { } ``` -This `Poll` type is a lot like an `Option`: it has one variant which has a value +This `Poll` type is similar to 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 @@ -176,17 +176,17 @@ The `cx` parameter and its `Context` type is interesting, but is beyond the scope of this chapter: you generally only need to worry about it when writing a custom `Future` implementation. -Instead, we’ll focus on the type for `self`. This is the first time we’ve -seen a method where `self` has a type annotation. A type annotation for `self` -is similar to type annotations for other function parameters, with two key -differences. First, when we specify the type of `self` like this, we’re telling -Rust what type `self` must be to call this method. Second, a type annotation on -`self` can’t be just any type. It’s only allowed to be the type on which the -method is implemented, a reference or smart pointer to that type, or a `Pin` -wrapping a reference to that type. We’ll see more on this syntax in Chapter -18. For now, it’s 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`. +Instead, we’ll focus on the type for `self`. This is the first time we’ve seen +a method where `self` has a type annotation. A type annotation for `self` is +similar to type annotations for other function parameters, with two key +differences. First, when we specify the type of `self` in this way, we’re +telling Rust what type `self` must be to call this method. Second, a type +annotation on `self` can’t be just any type. It’s only allowed to be the type +on which the method is implemented, a reference or smart pointer to that type, +or a `Pin` wrapping a reference to that type. We’ll see more on this syntax in +Chapter 18. For now, it’s 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’s similar to the `Box`, `Rc`, and other smart pointer types we saw in Chapter 15, which also wrap other types. @@ -195,10 +195,10 @@ Unlike those, however, `Pin` only works with *pointer types* such as references `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, because implementing `Deref` or `DerefMut` -means your type behaves like a pointer type. `Pin` is also not a pointer itself, -and it doesn’t have any behavior of its own like the ref counting of `Rc` or -`Arc`. It’s purely a tool the compiler can use to uphold the relevant -guarantees, by wrapping pointers in the type. +means your type behaves similarly to a pointer type. `Pin` is also not a +pointer itself, and it doesn’t have any behavior of its own as the ref counting +of `Rc` or `Arc` does. It’s 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 @@ -292,30 +292,30 @@ is still pinned. </figure> -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’re obviously safe. Neither do most types -you normally work with in Rust. A `Vec`, for example, doesn’t have any internal +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 such as numbers and booleans don’t have +any internal references, so they’re obviously safe. Neither do most types you +normally work with in Rust. A `Vec`, for example, doesn’t 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<Vec<String>>`, you’d have to do -everything via the safe but restrictive APIs provided by `Pin`, even though a +without worrying. If you have a `Pin<Vec<String>>`, you’d have to do everything +via the safe but restrictive APIs provided by `Pin`, even though a `Vec<String>` is always safe to move if there are no other references to it. We need a way to tell the compiler that it’s actually just fine to move items -around in cases like these. For that, we have `Unpin`. +around in cases such as these. For that, we have `Unpin`. -`Unpin` is a marker trait, like `Send` and `Sync`, which we saw in Chapter 16. +`Unpin` is a marker trait, as `Send` and `Sync` are, 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’s 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! +Just as with `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! To make that concrete, think about a `String`: it has a length and the Unicode characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure @@ -329,7 +329,7 @@ characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure </figure> -This means that we can do things like replace one string with another at the +This means that we can do things such as replace one string with another at the exact same location in memory as in Figure 17-8. This doesn’t violate the `Pin` contract because `String`—like most other types in Rust—implements `Unpin`, because it has no internal references that make it unsafe to move around! @@ -374,11 +374,11 @@ idea of how to fix the code! 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,<!-- TODO: verify before press time! --> but there -*is* a very common definition from the `futures` crate used throughout the -ecosystem. +introducing streams, streams are similar to asynchronous iterators. Unlike +`Iterator` and `Future`, there is no definition of a `Stream` trait in the +standard library as of the time of writing,<!-- TODO: verify before press time! +--> but there *is* a very common definition from the `futures` crate 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 @@ -403,16 +403,17 @@ 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 is always a single `Output` (even if -it’s the unit type `()`). +produced by the stream. This is similar to `Iterator`: there may be zero to +many of these, and unlike `Future`, where there is always a single `Output` +(even if it’s 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 combines `Poll` with `Option`. The outer -type is `Poll`, because it has to be checked for readiness, just like a future. -The inner type is `Option`, because it needs to signal whether there are more -messages, just like an iterator. +make it clear that it polls in the same way `Future::poll` does and produces a +sequence of items in the same way `Iterator::next` does. Its return type +combines `Poll` with `Option`. The outer type is `Poll`, because it has to be +checked for readiness, just as a future does. The inner type is `Option`, +because it needs to signal whether there are more messages, just as an iterator +does. Something very similar to this will likely end up standardized as part of Rust’s standard library. In the meantime, it’s part of the toolkit of most runtimes, diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 7b0e7af9ab..428eb61c9c 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -19,7 +19,7 @@ The async model provides a different—and ultimately complementary—set of tradeoffs. In the async model, concurrent operations don’t require their own threads. Instead, they can run on tasks, as when we used `trpl::spawn_task` to kick off work from a synchronous function throughout the streams section. A -*task* is a lot like a thread—but instead of being managed by the operating +*task* is similar to a thread—but instead of being managed by the operating system, it’s managed by library-level code: the runtime. In the previous section, we saw that we could build a `Stream` by using an async @@ -51,8 +51,8 @@ literally run out of memory! However, there’s a reason these APIs are so similar. Threads act as a boundary for sets of synchronous operations; concurrency is possible *between* threads. Tasks act as a boundary for sets of *asynchronous* operations; concurrency is -possible both *between* and *within* tasks. In that regard, tasks are kind of -like lightweight, runtime-managed threads with added capabilities that come from +possible both *between* and *within* tasks. In that regard, tasks are similar to +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. That is, the runtime—specifically, its executor—manages tasks, @@ -65,13 +65,13 @@ 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,” 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 +no *intra-task concurrency* as futures can. Threads in Rust also have no mechanisms for cancellation—a subject we haven’t 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’s much more -difficult, for example, to build something like the `timeout` we built in +difficult, for example, to build something similar to the `timeout` we built in [“Building Our Own Async Abstractions”][combining-futures], or the `throttle` method we used with streams in [“Composing Streams”][streams]. The fact that futures are richer data structures means they *can* be composed together more @@ -90,9 +90,9 @@ requires threads *and* tasks, and therefore futures. As a default way of thinking about which to use when: -- If the task is *very parallelizable*, like processing a bunch of data where +- If the task is *very parallelizable*, such as processing a bunch of data where each part can be processed separately, threads are a better choice. -- If the task is *very concurrent*, like handling messages from a bunch of +- If the task is *very concurrent*, such as handling messages from a bunch of different sources which may come in a different intervals or different rates, async is a better choice. @@ -112,8 +112,8 @@ common example of this kind of mix in real-world Rust code. 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 +future created with an async block passed to `trpl::run` just as we have +throughout the chapter. In that future, we await those messages, just as in the other message-passing examples we have seen. To return to the examples we opened the chapter with: you could imagine running From fa97cab9dd12358b4843f7d01b1d0a4f423cc230 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Thu, 3 Oct 2024 21:22:12 -0400 Subject: [PATCH 228/249] Change nostarch snapshot chapter numbers to make room for the async chapter --- nostarch/chapter17.md | 1233 --------------- nostarch/chapter18.md | 2029 ++++++++++++------------ nostarch/chapter19.md | 2770 +++++++++++---------------------- nostarch/chapter20.md | 3384 ++++++++++++++++++++++------------------- nostarch/chapter21.md | 1994 ++++++++++++++++++++++++ 5 files changed, 5705 insertions(+), 5705 deletions(-) delete mode 100644 nostarch/chapter17.md create mode 100644 nostarch/chapter21.md diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md deleted file mode 100644 index 946d20a112..0000000000 --- a/nostarch/chapter17.md +++ /dev/null @@ -1,1233 +0,0 @@ -<!-- DO NOT EDIT THIS FILE. - -This file is periodically generated from the content in the `/src/` -directory, so all fixes need to be made in `/src/`. ---> - -[TOC] - -# Object-Oriented Programming Features - -Object-oriented programming (OOP) is a way of modeling programs. Objects as a -programmatic concept were introduced in the programming language Simula in the -1960s. Those objects influenced Alan Kay’s programming architecture in which -objects pass messages to each other. To describe this architecture, he coined -the term *object-oriented programming* in 1967. Many competing definitions -describe what OOP is, and by some of these definitions Rust is object oriented -but by others it is not. In this chapter, we’ll explore certain characteristics -that are commonly considered object oriented and how those characteristics -translate to idiomatic Rust. We’ll then show you how to implement an -object-oriented design pattern in Rust and discuss the trade-offs of doing so -versus implementing a solution using some of Rust’s strengths instead. - -## Characteristics of Object-Oriented Languages - -There is no consensus in the programming community about what features a -language must have to be considered object oriented. Rust is influenced by many -programming paradigms, including OOP; for example, we explored the features -that came from functional programming in Chapter 13. Arguably, OOP languages -share certain common characteristics, namely objects, encapsulation, and -inheritance. Let’s look at what each of those characteristics means and whether -Rust supports it. - -### Objects Contain Data and Behavior - -The book *Design Patterns: Elements of Reusable Object-Oriented Software* by -Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley, -1994), colloquially referred to as *The Gang of Four* book, is a catalog of -object-oriented design patterns. It defines OOP in this way: - -Object-oriented programs are made up of objects. An *object* packages both data -and the procedures that operate on that data. The procedures are typically -called *methods* or *operations*. - -Using this definition, Rust is object oriented: structs and enums have data, -and `impl` blocks provide methods on structs and enums. Even though structs and -enums with methods aren’t *called* objects, they provide the same -functionality, according to the Gang of Four’s definition of objects. - -### Encapsulation That Hides Implementation Details - -Another aspect commonly associated with OOP is the idea of *encapsulation*, -which means that the implementation details of an object aren’t accessible to -code using that object. Therefore, the only way to interact with an object is -through its public API; code using the object shouldn’t be able to reach into -the object’s internals and change data or behavior directly. This enables the -programmer to change and refactor an object’s internals without needing to -change the code that uses the object. - -We discussed how to control encapsulation in Chapter 7: we can use the `pub` -keyword to decide which modules, types, functions, and methods in our code -should be public, and by default everything else is private. For example, we -can define a struct `AveragedCollection` that has a field containing a vector -of `i32` values. The struct can also have a field that contains the average of -the values in the vector, meaning the average doesn’t have to be computed on -demand whenever anyone needs it. In other words, `AveragedCollection` will -cache the calculated average for us. Listing 17-1 has the definition of the -`AveragedCollection` struct. - -Filename: src/lib.rs - -``` -pub struct AveragedCollection { - list: Vec<i32>, - average: f64, -} -``` - -Listing 17-1: An `AveragedCollection` struct that maintains a list of integers -and the average of the items in the collection - -The struct is marked `pub` so that other code can use it, but the fields within -the struct remain private. This is important in this case because we want to -ensure that whenever a value is added or removed from the list, the average is -also updated. We do this by implementing `add`, `remove`, and `average` methods -on the struct, as shown in Listing 17-2. - -Filename: src/lib.rs - -``` -impl AveragedCollection { - pub fn add(&mut self, value: i32) { - self.list.push(value); - self.update_average(); - } - - pub fn remove(&mut self) -> Option<i32> { - let result = self.list.pop(); - match result { - Some(value) => { - self.update_average(); - Some(value) - } - None => None, - } - } - - pub fn average(&self) -> f64 { - self.average - } - - fn update_average(&mut self) { - let total: i32 = self.list.iter().sum(); - self.average = total as f64 / self.list.len() as f64; - } -} -``` - -Listing 17-2: Implementations of the public methods `add`, `remove`, and -`average` on `AveragedCollection` - -The public methods `add`, `remove`, and `average` are the only ways to access -or modify data in an instance of `AveragedCollection`. When an item is added to -`list` using the `add` method or removed using the `remove` method, the -implementations of each call the private `update_average` method that handles -updating the `average` field as well. - -We leave the `list` and `average` fields private so there is no way for -external code to add or remove items to or from the `list` field directly; -otherwise, the `average` field might become out of sync when the `list` -changes. The `average` method returns the value in the `average` field, -allowing external code to read the `average` but not modify it. - -Because we’ve encapsulated the implementation details of the struct -`AveragedCollection`, we can easily change aspects, such as the data structure, -in the future. For instance, we could use a `HashSet<i32>` instead of a -`Vec<i32>` for the `list` field. As long as the signatures of the `add`, -`remove`, and `average` public methods stayed the same, code using -`AveragedCollection` wouldn’t need to change. If we made `list` public instead, -this wouldn’t necessarily be the case: `HashSet<i32>` and `Vec<i32>` have -different methods for adding and removing items, so the external code would -likely have to change if it were modifying `list` directly. - -If encapsulation is a required aspect for a language to be considered object -oriented, then Rust meets that requirement. The option to use `pub` or not for -different parts of code enables encapsulation of implementation details. - -### Inheritance as a Type System and as Code Sharing - -*Inheritance* is a mechanism whereby an object can inherit elements from -another object’s definition, thus gaining the parent object’s data and behavior -without you having to define them again. - -If a language must have inheritance to be object oriented, then Rust is not -such a language. There is no way to define a struct that inherits the parent -struct’s fields and method implementations without using a macro. - -However, if you’re used to having inheritance in your programming toolbox, you -can use other solutions in Rust, depending on your reason for reaching for -inheritance in the first place. - -You would choose inheritance for two main reasons. One is for reuse of code: -you can implement particular behavior for one type, and inheritance enables you -to reuse that implementation for a different type. You can do this in a limited -way in Rust code using default trait method implementations, which you saw in -Listing 10-14 when we added a default implementation of the `summarize` method -on the `Summary` trait. Any type implementing the `Summary` trait would have -the `summarize` method available on it without any further code. This is -similar to a parent class having an implementation of a method and an -inheriting child class also having the implementation of the method. We can -also override the default implementation of the `summarize` method when we -implement the `Summary` trait, which is similar to a child class overriding the -implementation of a method inherited from a parent class. - -The other reason to use inheritance relates to the type system: to enable a -child type to be used in the same places as the parent type. This is also -called *polymorphism*, which means that you can substitute multiple objects for -each other at runtime if they share certain characteristics. - -> ### Polymorphism -> -> To many people, polymorphism is synonymous with inheritance. But it’s -actually a more general concept that refers to code that can work with data of -multiple types. For inheritance, those types are generally subclasses. -> -> Rust instead uses generics to abstract over different possible types and -trait bounds to impose constraints on what those types must provide. This is -sometimes called *bounded parametric polymorphism*. - -Inheritance has recently fallen out of favor as a programming design solution -in many programming languages because it’s often at risk of sharing more code -than necessary. Subclasses shouldn’t always share all characteristics of their -parent class but will do so with inheritance. This can make a program’s design -less flexible. It also introduces the possibility of calling methods on -subclasses that don’t make sense or that cause errors because the methods don’t -apply to the subclass. In addition, some languages will only allow single -inheritance (meaning a subclass can only inherit from one class), further -restricting the flexibility of a program’s design. - -For these reasons, Rust takes the different approach of using trait objects -instead of inheritance. Let’s look at how trait objects enable polymorphism in -Rust. - -## Using Trait Objects That Allow for Values of Different Types - -In Chapter 8, we mentioned that one limitation of vectors is that they can -store elements of only one type. We created a workaround in Listing 8-9 where -we defined a `SpreadsheetCell` enum that had variants to hold integers, floats, -and text. This meant we could store different types of data in each cell and -still have a vector that represented a row of cells. This is a perfectly good -solution when our interchangeable items are a fixed set of types that we know -when our code is compiled. - -However, sometimes we want our library user to be able to extend the set of -types that are valid in a particular situation. To show how we might achieve -this, we’ll create an example graphical user interface (GUI) tool that iterates -through a list of items, calling a `draw` method on each one to draw it to the -screen—a common technique for GUI tools. We’ll create a library crate called -`gui` that contains the structure of a GUI library. This crate might include -some types for people to use, such as `Button` or `TextField`. In addition, -`gui` users will want to create their own types that can be drawn: for -instance, one programmer might add an `Image` and another might add a -`SelectBox`. - -We won’t implement a full-fledged GUI library for this example but will show -how the pieces would fit together. At the time of writing the library, we can’t -know and define all the types other programmers might want to create. But we do -know that `gui` needs to keep track of many values of different types, and it -needs to call a `draw` method on each of these differently typed values. It -doesn’t need to know exactly what will happen when we call the `draw` method, -just that the value will have that method available for us to call. - -To do this in a language with inheritance, we might define a class named -`Component` that has a method named `draw` on it. The other classes, such as -`Button`, `Image`, and `SelectBox`, would inherit from `Component` and thus -inherit the `draw` method. They could each override the `draw` method to define -their custom behavior, but the framework could treat all of the types as if -they were `Component` instances and call `draw` on them. But because Rust -doesn’t have inheritance, we need another way to structure the `gui` library to -allow users to extend it with new types. - -### Defining a Trait for Common Behavior - -To implement the behavior we want `gui` to have, we’ll define a trait named -`Draw` that will have one method named `draw`. Then we can define a vector that -takes a *trait object*. A trait object points to both an instance of a type -implementing our specified trait and a table used to look up trait methods on -that type at runtime. We create a trait object by specifying some sort of -pointer, such as a `&` reference or a `Box<T>` smart pointer, then the `dyn` -keyword, and then specifying the relevant trait. (We’ll talk about the reason -trait objects must use a pointer in “Dynamically Sized Types and the Sized -Trait” on page XX.) We can use trait objects in place of a generic or concrete -type. Wherever we use a trait object, Rust’s type system will ensure at compile -time that any value used in that context will implement the trait object’s -trait. Consequently, we don’t need to know all the possible types at compile -time. - -We’ve mentioned that, in Rust, we refrain from calling structs and enums -“objects” to distinguish them from other languages’ objects. In a struct or -enum, the data in the struct fields and the behavior in `impl` blocks are -separated, whereas in other languages, the data and behavior combined into one -concept is often labeled an object. However, trait objects *are* more like -objects in other languages in the sense that they combine data and behavior. -But trait objects differ from traditional objects in that we can’t add data to -a trait object. Trait objects aren’t as generally useful as objects in other -languages: their specific purpose is to allow abstraction across common -behavior. - -Listing 17-3 shows how to define a trait named `Draw` with one method named -`draw`. - -Filename: src/lib.rs - -``` -pub trait Draw { - fn draw(&self); -} -``` - -Listing 17-3: Definition of the `Draw` trait - -This syntax should look familiar from our discussions on how to define traits -in Chapter 10. Next comes some new syntax: Listing 17-4 defines a struct named -`Screen` that holds a vector named `components`. This vector is of type -`Box<dyn Draw>`, which is a trait object; it’s a stand-in for any type inside a -`Box` that implements the `Draw` trait. - -Filename: src/lib.rs - -``` -pub struct Screen { - pub components: Vec<Box<dyn Draw>>, -} -``` - -Listing 17-4: Definition of the `Screen` struct with a `components` field -holding a vector of trait objects that implement the `Draw` trait - -On the `Screen` struct, we’ll define a method named `run` that will call the -`draw` method on each of its `components`, as shown in Listing 17-5. - -Filename: src/lib.rs - -``` -impl Screen { - pub fn run(&self) { - for component in self.components.iter() { - component.draw(); - } - } -} -``` - -Listing 17-5: A `run` method on `Screen` that calls the `draw` method on each -component - -This works differently from defining a struct that uses a generic type -parameter with trait bounds. A generic type parameter can only be substituted -with one concrete type at a time, whereas trait objects allow for multiple -concrete types to fill in for the trait object at runtime. For example, we -could have defined the `Screen` struct using a generic type and a trait bound, -as in Listing 17-6. - -Filename: src/lib.rs - -``` -pub struct Screen<T: Draw> { - pub components: Vec<T>, -} - -impl<T> Screen<T> -where - T: Draw, -{ - pub fn run(&self) { - for component in self.components.iter() { - component.draw(); - } - } -} -``` - -Listing 17-6: An alternate implementation of the `Screen` struct and its `run` -method using generics and trait bounds - -This restricts us to a `Screen` instance that has a list of components all of -type `Button` or all of type `TextField`. If you’ll only ever have homogeneous -collections, using generics and trait bounds is preferable because the -definitions will be monomorphized at compile time to use the concrete types. - -On the other hand, with the method using trait objects, one `Screen` instance -can hold a `Vec<T>` that contains a `Box<Button>` as well as a -`Box<TextField>`. Let’s look at how this works, and then we’ll talk about the -runtime performance implications. - -### Implementing the Trait - -Now we’ll add some types that implement the `Draw` trait. We’ll provide the -`Button` type. Again, actually implementing a GUI library is beyond the scope -of this book, so the `draw` method won’t have any useful implementation in its -body. To imagine what the implementation might look like, a `Button` struct -might have fields for `width`, `height`, and `label`, as shown in Listing 17-7. - -Filename: src/lib.rs - -``` -pub struct Button { - pub width: u32, - pub height: u32, - pub label: String, -} - -impl Draw for Button { - fn draw(&self) { - // code to actually draw a button - } -} -``` - -Listing 17-7: A `Button` struct that implements the `Draw` trait - -The `width`, `height`, and `label` fields on `Button` will differ from the -fields on other components; for example, a `TextField` type might have those -same fields plus a `placeholder` field. Each of the types we want to draw on -the screen will implement the `Draw` trait but will use different code in the -`draw` method to define how to draw that particular type, as `Button` has here -(without the actual GUI code, as mentioned). The `Button` type, for instance, -might have an additional `impl` block containing methods related to what -happens when a user clicks the button. These kinds of methods won’t apply to -types like `TextField`. - -If someone using our library decides to implement a `SelectBox` struct that has -`width`, `height`, and `options` fields, they would implement the `Draw` trait -on the `SelectBox` type as well, as shown in Listing 17-8. - -Filename: src/main.rs - -``` -use gui::Draw; - -struct SelectBox { - width: u32, - height: u32, - options: Vec<String>, -} - -impl Draw for SelectBox { - fn draw(&self) { - // code to actually draw a select box - } -} -``` - -Listing 17-8: Another crate using `gui` and implementing the `Draw` trait on a -`SelectBox` struct - -Our library’s user can now write their `main` function to create a `Screen` -instance. To the `Screen` instance, they can add a `SelectBox` and a `Button` -by putting each in a `Box<T>` to become a trait object. They can then call the -`run` method on the `Screen` instance, which will call `draw` on each of the -components. Listing 17-9 shows this implementation. - -Filename: src/main.rs - -``` -use gui::{Button, Screen}; - -fn main() { - let screen = Screen { - components: vec![ - Box::new(SelectBox { - width: 75, - height: 10, - options: vec![ - String::from("Yes"), - String::from("Maybe"), - String::from("No"), - ], - }), - Box::new(Button { - width: 50, - height: 10, - label: String::from("OK"), - }), - ], - }; - - screen.run(); -} -``` - -Listing 17-9: Using trait objects to store values of different types that -implement the same trait - -When we wrote the library, we didn’t know that someone might add the -`SelectBox` type, but our `Screen` implementation was able to operate on the -new type and draw it because `SelectBox` implements the `Draw` trait, which -means it implements the `draw` method. - -This concept—of being concerned only with the messages a value responds to -rather than the value’s concrete type—is similar to the concept of *duck -typing* in dynamically typed languages: if it walks like a duck and quacks like -a duck, then it must be a duck! In the implementation of `run` on `Screen` in -Listing 17-5, `run` doesn’t need to know what the concrete type of each -component is. It doesn’t check whether a component is an instance of a `Button` -or a `SelectBox`, it just calls the `draw` method on the component. By -specifying `Box<dyn Draw>` as the type of the values in the `components` -vector, we’ve defined `Screen` to need values that we can call the `draw` -method on. - -The advantage of using trait objects and Rust’s type system to write code -similar to code using duck typing is that we never have to check whether a -value implements a particular method at runtime or worry about getting errors -if a value doesn’t implement a method but we call it anyway. Rust won’t compile -our code if the values don’t implement the traits that the trait objects need. - -For example, Listing 17-10 shows what happens if we try to create a `Screen` -with a `String` as a component. - -Filename: src/main.rs - -``` -use gui::Screen; - -fn main() { - let screen = Screen { - components: vec![Box::new(String::from("Hi"))], - }; - - screen.run(); -} -``` - -Listing 17-10: Attempting to use a type that doesn’t implement the trait -object’s trait - -We’ll get this error because `String` doesn’t implement the `Draw` trait: - -``` -error[E0277]: the trait bound `String: Draw` is not satisfied - --> src/main.rs:5:26 - | -5 | components: vec![Box::new(String::from("Hi"))], - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Draw` is -not implemented for `String` - | - = note: required for the cast to the object type `dyn Draw` -``` - -This error lets us know that either we’re passing something to `Screen` that we -didn’t mean to pass and so should pass a different type, or we should implement -`Draw` on `String` so that `Screen` is able to call `draw` on it. - -### Trait Objects Perform Dynamic Dispatch - -Recall in “Performance of Code Using Generics” on page XX our discussion on the -monomorphization process performed by the compiler when we use trait bounds on -generics: the compiler generates nongeneric implementations of functions and -methods for each concrete type that we use in place of a generic type -parameter. The code that results from monomorphization is doing *static -dispatch*, which is when the compiler knows what method you’re calling at -compile time. This is opposed to *dynamic dispatch*, which is when the compiler -can’t tell at compile time which method you’re calling. In dynamic dispatch -cases, the compiler emits code that at runtime will figure out which method to -call. - -When we use trait objects, Rust must use dynamic dispatch. The compiler doesn’t -know all the types that might be used with the code that’s using trait objects, -so it doesn’t know which method implemented on which type to call. Instead, at -runtime, Rust uses the pointers inside the trait object to know which method to -call. This lookup incurs a runtime cost that doesn’t occur with static -dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a -method’s code, which in turn prevents some optimizations. However, we did get -extra flexibility in the code that we wrote in Listing 17-5 and were able to -support in Listing 17-9, so it’s a trade-off to consider. - -## Implementing an Object-Oriented Design Pattern - -The *state pattern* is an object-oriented design pattern. The crux of the -pattern is that we define a set of states a value can have internally. The -states are represented by a set of *state objects*, and the value’s behavior -changes based on its state. We’re going to work through an example of a blog -post struct that has a field to hold its state, which will be a state object -from the set “draft,” “review,” or “published.” - -The state objects share functionality: in Rust, of course, we use structs and -traits rather than objects and inheritance. Each state object is responsible -for its own behavior and for governing when it should change into another -state. The value that holds a state object knows nothing about the different -behavior of the states or when to transition between states. - -The advantage of using the state pattern is that, when the business -requirements of the program change, we won’t need to change the code of the -value holding the state or the code that uses the value. We’ll only need to -update the code inside one of the state objects to change its rules or perhaps -add more state objects. - -First we’re going to implement the state pattern in a more traditional -object-oriented way, then we’ll use an approach that’s a bit more natural in -Rust. Let’s dig in to incrementally implement a blog post workflow using the -state pattern. - -The final functionality will look like this: - -1. A blog post starts as an empty draft. -1. When the draft is done, a review of the post is requested. -1. When the post is approved, it gets published. -1. Only published blog posts return content to print, so unapproved posts can’t -accidentally be published. - -Any other changes attempted on a post should have no effect. For example, if we -try to approve a draft blog post before we’ve requested a review, the post -should remain an unpublished draft. - -Listing 17-11 shows this workflow in code form: this is an example usage of the -API we’ll implement in a library crate named `blog`. This won’t compile yet -because we haven’t implemented the `blog` crate. - -Filename: src/main.rs - -``` -use blog::Post; - -fn main() { - 1 let mut post = Post::new(); - - 2 post.add_text("I ate a salad for lunch today"); - 3 assert_eq!("", post.content()); - - 4 post.request_review(); - 5 assert_eq!("", post.content()); - - 6 post.approve(); - 7 assert_eq!("I ate a salad for lunch today", post.content()); -} -``` - -Listing 17-11: Code that demonstrates the desired behavior we want our `blog` -crate to have - -We want to allow the user to create a new draft blog post with `Post::new` [1]. -We want to allow text to be added to the blog post [2]. If we try to get the -post’s content immediately, before approval, we shouldn’t get any text because -the post is still a draft. We’ve added `assert_eq!` in the code for -demonstration purposes [3]. An excellent unit test for this would be to assert -that a draft blog post returns an empty string from the `content` method, but -we’re not going to write tests for this example. - -Next, we want to enable a request for a review of the post [4], and we want -`content` to return an empty string while waiting for the review [5]. When the -post receives approval [6], it should get published, meaning the text of the -post will be returned when `content` is called [7]. - -Notice that the only type we’re interacting with from the crate is the `Post` -type. This type will use the state pattern and will hold a value that will be -one of three state objects representing the various states a post can be -in—draft, review, or published. Changing from one state to another will be -managed internally within the `Post` type. The states change in response to the -methods called by our library’s users on the `Post` instance, but they don’t -have to manage the state changes directly. Also, users can’t make a mistake -with the states, such as publishing a post before it’s reviewed. - -### Defining Post and Creating a New Instance in the Draft State - -Let’s get started on the implementation of the library! We know we need a -public `Post` struct that holds some content, so we’ll start with the -definition of the struct and an associated public `new` function to create an -instance of `Post`, as shown in Listing 17-12. We’ll also make a private -`State` trait that will define the behavior that all state objects for a `Post` -must have. - -Then `Post` will hold a trait object of `Box<dyn State>` inside an `Option<T>` -in a private field named `state` to hold the state object. You’ll see why the -`Option<T>` is necessary in a bit. - -Filename: src/lib.rs - -``` -pub struct Post { - state: Option<Box<dyn State>>, - content: String, -} - -impl Post { - pub fn new() -> Post { - Post { - 1 state: Some(Box::new(Draft {})), - 2 content: String::new(), - } - } -} - -trait State {} - -struct Draft {} - -impl State for Draft {} -``` - -Listing 17-12: Definition of a `Post` struct and a `new` function that creates -a new `Post` instance, a `State` trait, and a `Draft` struct - -The `State` trait defines the behavior shared by different post states. The -state objects are `Draft`, `PendingReview`, and `Published`, and they will all -implement the `State` trait. For now, the trait doesn’t have any methods, and -we’ll start by defining just the `Draft` state because that is the state we -want a post to start in. - -When we create a new `Post`, we set its `state` field to a `Some` value that -holds a `Box` [1]. This `Box` points to a new instance of the `Draft` struct. -This ensures that whenever we create a new instance of `Post`, it will start -out as a draft. Because the `state` field of `Post` is private, there is no way -to create a `Post` in any other state! In the `Post::new` function, we set the -`content` field to a new, empty `String` [2]. - -### Storing the Text of the Post Content - -We saw in Listing 17-11 that we want to be able to call a method named -`add_text` and pass it a `&str` that is then added as the text content of the -blog post. We implement this as a method, rather than exposing the `content` -field as `pub`, so that later we can implement a method that will control how -the `content` field’s data is read. The `add_text` method is pretty -straightforward, so let’s add the implementation in Listing 17-13 to the `impl -Post` block. - -Filename: src/lib.rs - -``` -impl Post { - --snip-- - pub fn add_text(&mut self, text: &str) { - self.content.push_str(text); - } -} -``` - -Listing 17-13: Implementing the `add_text` method to add text to a post’s -`content` - -The `add_text` method takes a mutable reference to `self` because we’re -changing the `Post` instance that we’re calling `add_text` on. We then call -`push_str` on the `String` in `content` and pass the `text` argument to add to -the saved `content`. This behavior doesn’t depend on the state the post is in, -so it’s not part of the state pattern. The `add_text` method doesn’t interact -with the `state` field at all, but it is part of the behavior we want to -support. - -### Ensuring the Content of a Draft Post Is Empty - -Even after we’ve called `add_text` and added some content to our post, we still -want the `content` method to return an empty string slice because the post is -still in the draft state, as shown at [3] in Listing 17-11. For now, let’s -implement the `content` method with the simplest thing that will fulfill this -requirement: always returning an empty string slice. We’ll change this later -once we implement the ability to change a post’s state so it can be published. -So far, posts can only be in the draft state, so the post content should always -be empty. Listing 17-14 shows this placeholder implementation. - -Filename: src/lib.rs - -``` -impl Post { - --snip-- - pub fn content(&self) -> &str { - "" - } -} -``` - -Listing 17-14: Adding a placeholder implementation for the `content` method on -`Post` that always returns an empty string slice - -With this added `content` method, everything in Listing 17-11 up to the line at -[3] works as intended. - -### Requesting a Review Changes the Post’s State - -Next, we need to add functionality to request a review of a post, which should -change its state from `Draft` to `PendingReview`. Listing 17-15 shows this code. - -Filename: src/lib.rs - -``` -impl Post { - --snip-- - 1 pub fn request_review(&mut self) { - 2 if let Some(s) = self.state.take() { - 3 self.state = Some(s.request_review()) - } - } -} - -trait State { - 4 fn request_review(self: Box<Self>) -> Box<dyn State>; -} - -struct Draft {} - -impl State for Draft { - fn request_review(self: Box<Self>) -> Box<dyn State> { - 5 Box::new(PendingReview {}) - } -} - -struct PendingReview {} - -impl State for PendingReview { - fn request_review(self: Box<Self>) -> Box<dyn State> { - 6 self - } -} -``` - -Listing 17-15: Implementing `request_review` methods on `Post` and the `State` -trait - -We give `Post` a public method named `request_review` that will take a mutable -reference to `self` [1]. Then we call an internal `request_review` method on -the current state of `Post` [3], and this second `request_review` method -consumes the current state and returns a new state. - -We add the `request_review` method to the `State` trait [4]; all types that -implement the trait will now need to implement the `request_review` method. -Note that rather than having `self`, `&self`, or `&mut self` as the first -parameter of the method, we have `self: Box<Self>`. This syntax means the -method is only valid when called on a `Box` holding the type. This syntax takes -ownership of `Box<Self>`, invalidating the old state so the state value of the -`Post` can transform into a new state. - -To consume the old state, the `request_review` method needs to take ownership -of the state value. This is where the `Option` in the `state` field of `Post` -comes in: we call the `take` method to take the `Some` value out of the `state` -field and leave a `None` in its place because Rust doesn’t let us have -unpopulated fields in structs [2]. This lets us move the `state` value out of -`Post` rather than borrowing it. Then we’ll set the post’s `state` value to the -result of this operation. - -We need to set `state` to `None` temporarily rather than setting it directly -with code like `self.state = self.state.request_review();` to get ownership of -the `state` value. This ensures `Post` can’t use the old `state` value after -we’ve transformed it into a new state. - -The `request_review` method on `Draft` returns a new, boxed instance of a new -`PendingReview` struct [5], which represents the state when a post is waiting -for a review. The `PendingReview` struct also implements the `request_review` -method but doesn’t do any transformations. Rather, it returns itself [6] -because when we request a review on a post already in the `PendingReview` -state, it should stay in the `PendingReview` state. - -Now we can start seeing the advantages of the state pattern: the -`request_review` method on `Post` is the same no matter its `state` value. Each -state is responsible for its own rules. - -We’ll leave the `content` method on `Post` as is, returning an empty string -slice. We can now have a `Post` in the `PendingReview` state as well as in the -`Draft` state, but we want the same behavior in the `PendingReview` state. -Listing 17-11 now works up to the line at [5]! - -### Adding approve to Change the Behavior of content - -The `approve` method will be similar to the `request_review` method: it will -set `state` to the value that the current state says it should have when that -state is approved, as shown in Listing 17-16. - -Filename: src/lib.rs - -``` -impl Post { - --snip-- - pub fn approve(&mut self) { - if let Some(s) = self.state.take() { - self.state = Some(s.approve()) - } - } -} - -trait State { - fn request_review(self: Box<Self>) -> Box<dyn State>; - fn approve(self: Box<Self>) -> Box<dyn State>; -} - -struct Draft {} - -impl State for Draft { - --snip-- - fn approve(self: Box<Self>) -> Box<dyn State> { - 1 self - } -} - -struct PendingReview {} - -impl State for PendingReview { - --snip-- - fn approve(self: Box<Self>) -> Box<dyn State> { - 2 Box::new(Published {}) - } -} - -struct Published {} - -impl State for Published { - fn request_review(self: Box<Self>) -> Box<dyn State> { - self - } - - fn approve(self: Box<Self>) -> Box<dyn State> { - self - } -} -``` - -Listing 17-16: Implementing the `approve` method on `Post` and the `State` trait - -We add the `approve` method to the `State` trait and add a new struct that -implements `State`, the `Published` state. - -Similar to the way `request_review` on `PendingReview` works, if we call the -`approve` method on a `Draft`, it will have no effect because `approve` will -return `self` [1]. When we call `approve` on `PendingReview`, it returns a new, -boxed instance of the `Published` struct [2]. The `Published` struct implements -the `State` trait, and for both the `request_review` method and the `approve` -method, it returns itself because the post should stay in the `Published` state -in those cases. - -Now we need to update the `content` method on `Post`. We want the value -returned from `content` to depend on the current state of the `Post`, so we’re -going to have the `Post` delegate to a `content` method defined on its `state`, -as shown in Listing 17-17. - -Filename: src/lib.rs - -``` -impl Post { - --snip-- - pub fn content(&self) -> &str { - self.state.as_ref().unwrap().content(self) - } - --snip-- -} -``` - -Listing 17-17: Updating the `content` method on `Post` to delegate to a -`content` method on `State` - -Because the goal is to keep all of these rules inside the structs that -implement `State`, we call a `content` method on the value in `state` and pass -the post instance (that is, `self`) as an argument. Then we return the value -that’s returned from using the `content` method on the `state` value. - -We call the `as_ref` method on the `Option` because we want a reference to the -value inside the `Option` rather than ownership of the value. Because `state` -is an `Option<Box<dyn State>>`, when we call `as_ref`, an `Option<&Box<dyn -State>>` is returned. If we didn’t call `as_ref`, we would get an error because -we can’t move `state` out of the borrowed `&self` of the function parameter. - -We then call the `unwrap` method, which we know will never panic because we -know the methods on `Post` ensure that `state` will always contain a `Some` -value when those methods are done. This is one of the cases we talked about in -“Cases in Which You Have More Information Than the Compiler” on page XX when we -know that a `None` value is never possible, even though the compiler isn’t able -to understand that. - -At this point, when we call `content` on the `&Box<dyn State>`, deref coercion -will take effect on the `&` and the `Box` so the `content` method will -ultimately be called on the type that implements the `State` trait. That means -we need to add `content` to the `State` trait definition, and that is where -we’ll put the logic for what content to return depending on which state we -have, as shown in Listing 17-18. - -Filename: src/lib.rs - -``` -trait State { - --snip-- - fn content<'a>(&self, post: &'a Post) -> &'a str { - 1 "" - } -} - ---snip-- -struct Published {} - -impl State for Published { - --snip-- - fn content<'a>(&self, post: &'a Post) -> &'a str { - 2 &post.content - } -} -``` - -Listing 17-18: Adding the `content` method to the `State` trait - -We add a default implementation for the `content` method that returns an empty -string slice [1]. That means we don’t need to implement `content` on the -`Draft` and `PendingReview` structs. The `Published` struct will override the -`content` method and return the value in `post.content` [2]. - -Note that we need lifetime annotations on this method, as we discussed in -Chapter 10. We’re taking a reference to a `post` as an argument and returning a -reference to part of that `post`, so the lifetime of the returned reference is -related to the lifetime of the `post` argument. - -And we’re done—all of Listing 17-11 now works! We’ve implemented the state -pattern with the rules of the blog post workflow. The logic related to the -rules lives in the state objects rather than being scattered throughout `Post`. - -> ### Why Not An Enum? -> -> You may have been wondering why we didn’t use an `enum` with the different -possible post states as variants. That’s certainly a possible solution; try it -and compare the end results to see which you prefer! One disadvantage of using -an enum is that every place that checks the value of the enum will need a -`match` expression or similar to handle every possible variant. This could get -more repetitive than this trait object solution. - -### Trade-offs of the State Pattern - -We’ve shown that Rust is capable of implementing the object-oriented state -pattern to encapsulate the different kinds of behavior a post should have in -each state. The methods on `Post` know nothing about the various behaviors. The -way we organized the code, we have to look in only one place to know the -different ways a published post can behave: the implementation of the `State` -trait on the `Published` struct. - -If we were to create an alternative implementation that didn’t use the state -pattern, we might instead use `match` expressions in the methods on `Post` or -even in the `main` code that checks the state of the post and changes behavior -in those places. That would mean we would have to look in several places to -understand all the implications of a post being in the published state! This -would only increase the more states we added: each of those `match` expressions -would need another arm. - -With the state pattern, the `Post` methods and the places we use `Post` don’t -need `match` expressions, and to add a new state, we would only need to add a -new struct and implement the trait methods on that one struct. - -The implementation using the state pattern is easy to extend to add more -functionality. To see the simplicity of maintaining code that uses the state -pattern, try a few of these suggestions: - -* Add a `reject` method that changes the post’s state from `PendingReview` back -to `Draft`. -* Require two calls to `approve` before the state can be changed to `Published`. -* Allow users to add text content only when a post is in the `Draft` state. -Hint: have the state object responsible for what might change about the content -but not responsible for modifying the `Post`. - -One downside of the state pattern is that, because the states implement the -transitions between states, some of the states are coupled to each other. If we -add another state between `PendingReview` and `Published`, such as `Scheduled`, -we would have to change the code in `PendingReview` to transition to -`Scheduled` instead. It would be less work if `PendingReview` didn’t need to -change with the addition of a new state, but that would mean switching to -another design pattern. - -Another downside is that we’ve duplicated some logic. To eliminate some of the -duplication, we might try to make default implementations for the -`request_review` and `approve` methods on the `State` trait that return `self`. -However, this wouldn’t work: when using `State` as a trait object, the trait -doesn’t know what the concrete `self` will be exactly, so the return type isn’t -known at compile time. - -Other duplication includes the similar implementations of the `request_review` -and `approve` methods on `Post`. Both methods delegate to the implementation of -the same method on the value in the `state` field of `Option` and set the new -value of the `state` field to the result. If we had a lot of methods on `Post` -that followed this pattern, we might consider defining a macro to eliminate the -repetition (see “Macros” on page XX). - -By implementing the state pattern exactly as it’s defined for object-oriented -languages, we’re not taking as full advantage of Rust’s strengths as we could. -Let’s look at some changes we can make to the `blog` crate that can make -invalid states and transitions into compile-time errors. - -#### Encoding States and Behavior as Types - -We’ll show you how to rethink the state pattern to get a different set of -trade-offs. Rather than encapsulating the states and transitions completely so -outside code has no knowledge of them, we’ll encode the states into different -types. Consequently, Rust’s type checking system will prevent attempts to use -draft posts where only published posts are allowed by issuing a compiler error. - -Let’s consider the first part of `main` in Listing 17-11: - -Filename: src/main.rs - -``` -fn main() { - let mut post = Post::new(); - - post.add_text("I ate a salad for lunch today"); - assert_eq!("", post.content()); -} -``` - -We still enable the creation of new posts in the draft state using `Post::new` -and the ability to add text to the post’s content. But instead of having a -`content` method on a draft post that returns an empty string, we’ll make it so -draft posts don’t have the `content` method at all. That way, if we try to get -a draft post’s content, we’ll get a compiler error telling us the method -doesn’t exist. As a result, it will be impossible for us to accidentally -display draft post content in production because that code won’t even compile. -Listing 17-19 shows the definition of a `Post` struct and a `DraftPost` struct, -as well as methods on each. - -Filename: src/lib.rs - -``` -pub struct Post { - content: String, -} - -pub struct DraftPost { - content: String, -} - -impl Post { - 1 pub fn new() -> DraftPost { - DraftPost { - content: String::new(), - } - } - - 2 pub fn content(&self) -> &str { - &self.content - } -} - -impl DraftPost { - 3 pub fn add_text(&mut self, text: &str) { - self.content.push_str(text); - } -} -``` - -Listing 17-19: A `Post` with a `content` method and a `DraftPost` without a -`content` method - -Both the `Post` and `DraftPost` structs have a private `content` field that -stores the blog post text. The structs no longer have the `state` field because -we’re moving the encoding of the state to the types of the structs. The `Post` -struct will represent a published post, and it has a `content` method that -returns the `content` [2]. - -We still have a `Post::new` function, but instead of returning an instance of -`Post`, it returns an instance of `DraftPost` [1]. Because `content` is private -and there aren’t any functions that return `Post`, it’s not possible to create -an instance of `Post` right now. - -The `DraftPost` struct has an `add_text` method, so we can add text to -`content` as before [3], but note that `DraftPost` does not have a `content` -method defined! So now the program ensures all posts start as draft posts, and -draft posts don’t have their content available for display. Any attempt to get -around these constraints will result in a compiler error. - -#### Implementing Transitions as Transformations into Different Types - -So how do we get a published post? We want to enforce the rule that a draft -post has to be reviewed and approved before it can be published. A post in the -pending review state should still not display any content. Let’s implement -these constraints by adding another struct, `PendingReviewPost`, defining the -`request_review` method on `DraftPost` to return a `PendingReviewPost` and -defining an `approve` method on `PendingReviewPost` to return a `Post`, as -shown in Listing 17-20. - -Filename: src/lib.rs - -``` -impl DraftPost { - --snip-- - pub fn request_review(self) -> PendingReviewPost { - PendingReviewPost { - content: self.content, - } - } -} - -pub struct PendingReviewPost { - content: String, -} - -impl PendingReviewPost { - pub fn approve(self) -> Post { - Post { - content: self.content, - } - } -} -``` - -Listing 17-20: A `PendingReviewPost` that gets created by calling -`request_review` on `DraftPost` and an `approve` method that turns a -`PendingReviewPost` into a published `Post` - -The `request_review` and `approve` methods take ownership of `self`, thus -consuming the `DraftPost` and `PendingReviewPost` instances and transforming -them into a `PendingReviewPost` and a published `Post`, respectively. This way, -we won’t have any lingering `DraftPost` instances after we’ve called -`request_review` on them, and so forth. The `PendingReviewPost` struct doesn’t -have a `content` method defined on it, so attempting to read its content -results in a compiler error, as with `DraftPost`. Because the only way to get a -published `Post` instance that does have a `content` method defined is to call -the `approve` method on a `PendingReviewPost`, and the only way to get a -`PendingReviewPost` is to call the `request_review` method on a `DraftPost`, -we’ve now encoded the blog post workflow into the type system. - -But we also have to make some small changes to `main`. The `request_review` and -`approve` methods return new instances rather than modifying the struct they’re -called on, so we need to add more `let post =` shadowing assignments to save -the returned instances. We also can’t have the assertions about the draft and -pending review posts’ contents be empty strings, nor do we need them: we can’t -compile code that tries to use the content of posts in those states any longer. -The updated code in `main` is shown in Listing 17-21. - -Filename: src/main.rs - -``` -use blog::Post; - -fn main() { - let mut post = Post::new(); - - post.add_text("I ate a salad for lunch today"); - - let post = post.request_review(); - - let post = post.approve(); - - assert_eq!("I ate a salad for lunch today", post.content()); -} -``` - -Listing 17-21: Modifications to `main` to use the new implementation of the -blog post workflow - -The changes we needed to make to `main` to reassign `post` mean that this -implementation doesn’t quite follow the object-oriented state pattern anymore: -the transformations between the states are no longer encapsulated entirely -within the `Post` implementation. However, our gain is that invalid states are -now impossible because of the type system and the type checking that happens at -compile time! This ensures that certain bugs, such as display of the content of -an unpublished post, will be discovered before they make it to production. - -Try the tasks suggested at the start of this section on the `blog` crate as it -is after Listing 17-21 to see what you think about the design of this version -of the code. Note that some of the tasks might be completed already in this -design. - -We’ve seen that even though Rust is capable of implementing object-oriented -design patterns, other patterns, such as encoding state into the type system, -are also available in Rust. These patterns have different trade-offs. Although -you might be very familiar with object-oriented patterns, rethinking the -problem to take advantage of Rust’s features can provide benefits, such as -preventing some bugs at compile time. Object-oriented patterns won’t always be -the best solution in Rust due to certain features, like ownership, that -object-oriented languages don’t have. - -## Summary - -Regardless of whether you think Rust is an object-oriented language after -reading this chapter, you now know that you can use trait objects to get some -object-oriented features in Rust. Dynamic dispatch can give your code some -flexibility in exchange for a bit of runtime performance. You can use this -flexibility to implement object-oriented patterns that can help your code’s -maintainability. Rust also has other features, like ownership, that -object-oriented languages don’t have. An object-oriented pattern won’t always -be the best way to take advantage of Rust’s strengths, but it is an available -option. - -Next, we’ll look at patterns, which are another of Rust’s features that enable -lots of flexibility. We’ve looked at them briefly throughout the book but -haven’t seen their full capability yet. Let’s go! - diff --git a/nostarch/chapter18.md b/nostarch/chapter18.md index 40c7f10a1c..946d20a112 100644 --- a/nostarch/chapter18.md +++ b/nostarch/chapter18.md @@ -6,1287 +6,1228 @@ directory, so all fixes need to be made in `/src/`. [TOC] -# Patterns and Matching - -*Patterns* are a special syntax in Rust for matching against the structure of -types, both complex and simple. Using patterns in conjunction with `match` -expressions and other constructs gives you more control over a program’s -control flow. A pattern consists of some combination of the following: - -* Literals -* Destructured arrays, enums, structs, or tuples -* Variables -* Wildcards -* Placeholders - -Some example patterns include `x`, `(a, 3)`, and `Some(Color::Red)`. In the -contexts in which patterns are valid, these components describe the shape of -data. Our program then matches values against the patterns to determine whether -it has the correct shape of data to continue running a particular piece of code. +# Object-Oriented Programming Features + +Object-oriented programming (OOP) is a way of modeling programs. Objects as a +programmatic concept were introduced in the programming language Simula in the +1960s. Those objects influenced Alan Kay’s programming architecture in which +objects pass messages to each other. To describe this architecture, he coined +the term *object-oriented programming* in 1967. Many competing definitions +describe what OOP is, and by some of these definitions Rust is object oriented +but by others it is not. In this chapter, we’ll explore certain characteristics +that are commonly considered object oriented and how those characteristics +translate to idiomatic Rust. We’ll then show you how to implement an +object-oriented design pattern in Rust and discuss the trade-offs of doing so +versus implementing a solution using some of Rust’s strengths instead. + +## Characteristics of Object-Oriented Languages + +There is no consensus in the programming community about what features a +language must have to be considered object oriented. Rust is influenced by many +programming paradigms, including OOP; for example, we explored the features +that came from functional programming in Chapter 13. Arguably, OOP languages +share certain common characteristics, namely objects, encapsulation, and +inheritance. Let’s look at what each of those characteristics means and whether +Rust supports it. + +### Objects Contain Data and Behavior + +The book *Design Patterns: Elements of Reusable Object-Oriented Software* by +Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley, +1994), colloquially referred to as *The Gang of Four* book, is a catalog of +object-oriented design patterns. It defines OOP in this way: + +Object-oriented programs are made up of objects. An *object* packages both data +and the procedures that operate on that data. The procedures are typically +called *methods* or *operations*. + +Using this definition, Rust is object oriented: structs and enums have data, +and `impl` blocks provide methods on structs and enums. Even though structs and +enums with methods aren’t *called* objects, they provide the same +functionality, according to the Gang of Four’s definition of objects. + +### Encapsulation That Hides Implementation Details + +Another aspect commonly associated with OOP is the idea of *encapsulation*, +which means that the implementation details of an object aren’t accessible to +code using that object. Therefore, the only way to interact with an object is +through its public API; code using the object shouldn’t be able to reach into +the object’s internals and change data or behavior directly. This enables the +programmer to change and refactor an object’s internals without needing to +change the code that uses the object. + +We discussed how to control encapsulation in Chapter 7: we can use the `pub` +keyword to decide which modules, types, functions, and methods in our code +should be public, and by default everything else is private. For example, we +can define a struct `AveragedCollection` that has a field containing a vector +of `i32` values. The struct can also have a field that contains the average of +the values in the vector, meaning the average doesn’t have to be computed on +demand whenever anyone needs it. In other words, `AveragedCollection` will +cache the calculated average for us. Listing 17-1 has the definition of the +`AveragedCollection` struct. + +Filename: src/lib.rs + +``` +pub struct AveragedCollection { + list: Vec<i32>, + average: f64, +} +``` -To use a pattern, we compare it to some value. If the pattern matches the -value, we use the value parts in our code. Recall the `match` expressions in -Chapter 6 that used patterns, such as the coin-sorting machine example. If the -value fits the shape of the pattern, we can use the named pieces. If it -doesn’t, the code associated with the pattern won’t run. +Listing 17-1: An `AveragedCollection` struct that maintains a list of integers +and the average of the items in the collection -This chapter is a reference on all things related to patterns. We’ll cover the -valid places to use patterns, the difference between refutable and irrefutable -patterns, and the different kinds of pattern syntax that you might see. By the -end of the chapter, you’ll know how to use patterns to express many concepts in -a clear way. +The struct is marked `pub` so that other code can use it, but the fields within +the struct remain private. This is important in this case because we want to +ensure that whenever a value is added or removed from the list, the average is +also updated. We do this by implementing `add`, `remove`, and `average` methods +on the struct, as shown in Listing 17-2. -## All the Places Patterns Can Be Used +Filename: src/lib.rs -Patterns pop up in a number of places in Rust, and you’ve been using them a lot -without realizing it! This section discusses all the places where patterns are -valid. +``` +impl AveragedCollection { + pub fn add(&mut self, value: i32) { + self.list.push(value); + self.update_average(); + } -### match Arms + pub fn remove(&mut self) -> Option<i32> { + let result = self.list.pop(); + match result { + Some(value) => { + self.update_average(); + Some(value) + } + None => None, + } + } -As discussed in Chapter 6, we use patterns in the arms of `match` expressions. -Formally, `match` expressions are defined as the keyword `match`, a value to -match on, and one or more match arms that consist of a pattern and an -expression to run if the value matches that arm’s pattern, like this: + pub fn average(&self) -> f64 { + self.average + } -``` -match VALUE { - PATTERN => EXPRESSION, - PATTERN => EXPRESSION, - PATTERN => EXPRESSION, + fn update_average(&mut self) { + let total: i32 = self.list.iter().sum(); + self.average = total as f64 / self.list.len() as f64; + } } ``` -For example, here’s the `match` expression from Listing 6-5 that matches on an -`Option<i32>` value in the variable `x`: - -``` -match x { - None => None, - Some(i) => Some(i + 1), +Listing 17-2: Implementations of the public methods `add`, `remove`, and +`average` on `AveragedCollection` + +The public methods `add`, `remove`, and `average` are the only ways to access +or modify data in an instance of `AveragedCollection`. When an item is added to +`list` using the `add` method or removed using the `remove` method, the +implementations of each call the private `update_average` method that handles +updating the `average` field as well. + +We leave the `list` and `average` fields private so there is no way for +external code to add or remove items to or from the `list` field directly; +otherwise, the `average` field might become out of sync when the `list` +changes. The `average` method returns the value in the `average` field, +allowing external code to read the `average` but not modify it. + +Because we’ve encapsulated the implementation details of the struct +`AveragedCollection`, we can easily change aspects, such as the data structure, +in the future. For instance, we could use a `HashSet<i32>` instead of a +`Vec<i32>` for the `list` field. As long as the signatures of the `add`, +`remove`, and `average` public methods stayed the same, code using +`AveragedCollection` wouldn’t need to change. If we made `list` public instead, +this wouldn’t necessarily be the case: `HashSet<i32>` and `Vec<i32>` have +different methods for adding and removing items, so the external code would +likely have to change if it were modifying `list` directly. + +If encapsulation is a required aspect for a language to be considered object +oriented, then Rust meets that requirement. The option to use `pub` or not for +different parts of code enables encapsulation of implementation details. + +### Inheritance as a Type System and as Code Sharing + +*Inheritance* is a mechanism whereby an object can inherit elements from +another object’s definition, thus gaining the parent object’s data and behavior +without you having to define them again. + +If a language must have inheritance to be object oriented, then Rust is not +such a language. There is no way to define a struct that inherits the parent +struct’s fields and method implementations without using a macro. + +However, if you’re used to having inheritance in your programming toolbox, you +can use other solutions in Rust, depending on your reason for reaching for +inheritance in the first place. + +You would choose inheritance for two main reasons. One is for reuse of code: +you can implement particular behavior for one type, and inheritance enables you +to reuse that implementation for a different type. You can do this in a limited +way in Rust code using default trait method implementations, which you saw in +Listing 10-14 when we added a default implementation of the `summarize` method +on the `Summary` trait. Any type implementing the `Summary` trait would have +the `summarize` method available on it without any further code. This is +similar to a parent class having an implementation of a method and an +inheriting child class also having the implementation of the method. We can +also override the default implementation of the `summarize` method when we +implement the `Summary` trait, which is similar to a child class overriding the +implementation of a method inherited from a parent class. + +The other reason to use inheritance relates to the type system: to enable a +child type to be used in the same places as the parent type. This is also +called *polymorphism*, which means that you can substitute multiple objects for +each other at runtime if they share certain characteristics. + +> ### Polymorphism +> +> To many people, polymorphism is synonymous with inheritance. But it’s +actually a more general concept that refers to code that can work with data of +multiple types. For inheritance, those types are generally subclasses. +> +> Rust instead uses generics to abstract over different possible types and +trait bounds to impose constraints on what those types must provide. This is +sometimes called *bounded parametric polymorphism*. + +Inheritance has recently fallen out of favor as a programming design solution +in many programming languages because it’s often at risk of sharing more code +than necessary. Subclasses shouldn’t always share all characteristics of their +parent class but will do so with inheritance. This can make a program’s design +less flexible. It also introduces the possibility of calling methods on +subclasses that don’t make sense or that cause errors because the methods don’t +apply to the subclass. In addition, some languages will only allow single +inheritance (meaning a subclass can only inherit from one class), further +restricting the flexibility of a program’s design. + +For these reasons, Rust takes the different approach of using trait objects +instead of inheritance. Let’s look at how trait objects enable polymorphism in +Rust. + +## Using Trait Objects That Allow for Values of Different Types + +In Chapter 8, we mentioned that one limitation of vectors is that they can +store elements of only one type. We created a workaround in Listing 8-9 where +we defined a `SpreadsheetCell` enum that had variants to hold integers, floats, +and text. This meant we could store different types of data in each cell and +still have a vector that represented a row of cells. This is a perfectly good +solution when our interchangeable items are a fixed set of types that we know +when our code is compiled. + +However, sometimes we want our library user to be able to extend the set of +types that are valid in a particular situation. To show how we might achieve +this, we’ll create an example graphical user interface (GUI) tool that iterates +through a list of items, calling a `draw` method on each one to draw it to the +screen—a common technique for GUI tools. We’ll create a library crate called +`gui` that contains the structure of a GUI library. This crate might include +some types for people to use, such as `Button` or `TextField`. In addition, +`gui` users will want to create their own types that can be drawn: for +instance, one programmer might add an `Image` and another might add a +`SelectBox`. + +We won’t implement a full-fledged GUI library for this example but will show +how the pieces would fit together. At the time of writing the library, we can’t +know and define all the types other programmers might want to create. But we do +know that `gui` needs to keep track of many values of different types, and it +needs to call a `draw` method on each of these differently typed values. It +doesn’t need to know exactly what will happen when we call the `draw` method, +just that the value will have that method available for us to call. + +To do this in a language with inheritance, we might define a class named +`Component` that has a method named `draw` on it. The other classes, such as +`Button`, `Image`, and `SelectBox`, would inherit from `Component` and thus +inherit the `draw` method. They could each override the `draw` method to define +their custom behavior, but the framework could treat all of the types as if +they were `Component` instances and call `draw` on them. But because Rust +doesn’t have inheritance, we need another way to structure the `gui` library to +allow users to extend it with new types. + +### Defining a Trait for Common Behavior + +To implement the behavior we want `gui` to have, we’ll define a trait named +`Draw` that will have one method named `draw`. Then we can define a vector that +takes a *trait object*. A trait object points to both an instance of a type +implementing our specified trait and a table used to look up trait methods on +that type at runtime. We create a trait object by specifying some sort of +pointer, such as a `&` reference or a `Box<T>` smart pointer, then the `dyn` +keyword, and then specifying the relevant trait. (We’ll talk about the reason +trait objects must use a pointer in “Dynamically Sized Types and the Sized +Trait” on page XX.) We can use trait objects in place of a generic or concrete +type. Wherever we use a trait object, Rust’s type system will ensure at compile +time that any value used in that context will implement the trait object’s +trait. Consequently, we don’t need to know all the possible types at compile +time. + +We’ve mentioned that, in Rust, we refrain from calling structs and enums +“objects” to distinguish them from other languages’ objects. In a struct or +enum, the data in the struct fields and the behavior in `impl` blocks are +separated, whereas in other languages, the data and behavior combined into one +concept is often labeled an object. However, trait objects *are* more like +objects in other languages in the sense that they combine data and behavior. +But trait objects differ from traditional objects in that we can’t add data to +a trait object. Trait objects aren’t as generally useful as objects in other +languages: their specific purpose is to allow abstraction across common +behavior. + +Listing 17-3 shows how to define a trait named `Draw` with one method named +`draw`. + +Filename: src/lib.rs + +``` +pub trait Draw { + fn draw(&self); } ``` -The patterns in this `match` expression are the `None` and `Some(i)` to the -left of each arrow. - -One requirement for `match` expressions is that they need to be *exhaustive* in -the sense that all possibilities for the value in the `match` expression must -be accounted for. One way to ensure you’ve covered every possibility is to have -a catchall pattern for the last arm: for example, a variable name matching any -value can never fail and thus covers every remaining case. - -The particular pattern `_` will match anything, but it never binds to a -variable, so it’s often used in the last match arm. The `_` pattern can be -useful when you want to ignore any value not specified, for example. We’ll -cover the `_` pattern in more detail in “Ignoring Values in a Pattern” on page -XX. - -### Conditional if let Expressions - -In Chapter 6, we discussed how to use `if let` expressions mainly as a shorter -way to write the equivalent of a `match` that only matches one case. -Optionally, `if let` can have a corresponding `else` containing code to run if -the pattern in the `if let` doesn’t match. +Listing 17-3: Definition of the `Draw` trait -Listing 18-1 shows that it’s also possible to mix and match `if let`, `else -if`, and `else if let` expressions. Doing so gives us more flexibility than a -`match` expression in which we can express only one value to compare with the -patterns. Also, Rust doesn’t require that the conditions in a series of `if -let`, `else if`, and `else if let` arms relate to each other. +This syntax should look familiar from our discussions on how to define traits +in Chapter 10. Next comes some new syntax: Listing 17-4 defines a struct named +`Screen` that holds a vector named `components`. This vector is of type +`Box<dyn Draw>`, which is a trait object; it’s a stand-in for any type inside a +`Box` that implements the `Draw` trait. -The code in Listing 18-1 determines what color to make your background based on -a series of checks for several conditions. For this example, we’ve created -variables with hardcoded values that a real program might receive from user -input. - -Filename: src/main.rs +Filename: src/lib.rs ``` -fn main() { - let favorite_color: Option<&str> = None; - let is_tuesday = false; - let age: Result<u8, _> = "34".parse(); - - 1 if let Some(color) = favorite_color { - 2 println!( - "Using your favorite, {color}, as the background" - ); - 3 } else if is_tuesday { - 4 println!("Tuesday is green day!"); - 5 } else if let Ok(age) = age { - 6 if age > 30 { - 7 println!("Using purple as the background color"); - } else { - 8 println!("Using orange as the background color"); - } - 9 } else { - 10 println!("Using blue as the background color"); - } +pub struct Screen { + pub components: Vec<Box<dyn Draw>>, } ``` -Listing 18-1: Mixing `if let`, `else if`, `else if let`, and `else` - -If the user specifies a favorite color [1], that color is used as the -background [2]. If no favorite color is specified and today is Tuesday [3], the -background color is green [4]. Otherwise, if the user specifies their age as a -string and we can parse it as a number successfully [5], the color is either -purple [7] or orange [8] depending on the value of the number [6]. If none of -these conditions apply [9], the background color is blue [10]. - -This conditional structure lets us support complex requirements. With the -hardcoded values we have here, this example will print `Using purple as the -background color`. - -You can see that `if let` can also introduce shadowed variables in the same way -that `match` arms can: the line `if let Ok(age) = age` [5] introduces a new -shadowed `age` variable that contains the value inside the `Ok` variant. This -means we need to place the `if age > 30` condition [6] within that block: we -can’t combine these two conditions into `if let Ok(age) = age && age > 30`. The -shadowed `age` we want to compare to 30 isn’t valid until the new scope starts -with the curly bracket. - -The downside of using `if let` expressions is that the compiler doesn’t check -for exhaustiveness, whereas with `match` expressions it does. If we omitted the -last `else` block [9] and therefore missed handling some cases, the compiler -would not alert us to the possible logic bug. +Listing 17-4: Definition of the `Screen` struct with a `components` field +holding a vector of trait objects that implement the `Draw` trait -### while let Conditional Loops +On the `Screen` struct, we’ll define a method named `run` that will call the +`draw` method on each of its `components`, as shown in Listing 17-5. -Similar in construction to `if let`, the `while let` conditional loop allows a -`while` loop to run for as long as a pattern continues to match. In Listing -18-2, we code a `while let` loop that uses a vector as a stack and prints the -values in the vector in the opposite order in which they were pushed. - -Filename: src/main.rs +Filename: src/lib.rs ``` -let mut stack = Vec::new(); - -stack.push(1); -stack.push(2); -stack.push(3); - -while let Some(top) = stack.pop() { - println!("{top}"); +impl Screen { + pub fn run(&self) { + for component in self.components.iter() { + component.draw(); + } + } } ``` -Listing 18-2: Using a `while let` loop to print values for as long as -`stack.pop()` returns `Some` +Listing 17-5: A `run` method on `Screen` that calls the `draw` method on each +component -This example prints `3`, `2`, and then `1`. The `pop` method takes the last -element out of the vector and returns `Some(value)`. If the vector is empty, -`pop` returns `None`. The `while` loop continues running the code in its block -as long as `pop` returns `Some`. When `pop` returns `None`, the loop stops. We -can use `while let` to pop every element off our stack. +This works differently from defining a struct that uses a generic type +parameter with trait bounds. A generic type parameter can only be substituted +with one concrete type at a time, whereas trait objects allow for multiple +concrete types to fill in for the trait object at runtime. For example, we +could have defined the `Screen` struct using a generic type and a trait bound, +as in Listing 17-6. -### for Loops - -In a `for` loop, the value that directly follows the keyword `for` is a -pattern. For example, in `for x in y`, the `x` is the pattern. Listing 18-3 -demonstrates how to use a pattern in a `for` loop to *destructure*, or break -apart, a tuple as part of the `for` loop. - -Filename: src/main.rs +Filename: src/lib.rs ``` -let v = vec!['a', 'b', 'c']; +pub struct Screen<T: Draw> { + pub components: Vec<T>, +} -for (index, value) in v.iter().enumerate() { - println!("{value} is at index {index}"); +impl<T> Screen<T> +where + T: Draw, +{ + pub fn run(&self) { + for component in self.components.iter() { + component.draw(); + } + } } ``` -Listing 18-3: Using a pattern in a `for` loop to destructure a tuple +Listing 17-6: An alternate implementation of the `Screen` struct and its `run` +method using generics and trait bounds -The code in Listing 18-3 will print the following: +This restricts us to a `Screen` instance that has a list of components all of +type `Button` or all of type `TextField`. If you’ll only ever have homogeneous +collections, using generics and trait bounds is preferable because the +definitions will be monomorphized at compile time to use the concrete types. -``` -a is at index 0 -b is at index 1 -c is at index 2 -``` +On the other hand, with the method using trait objects, one `Screen` instance +can hold a `Vec<T>` that contains a `Box<Button>` as well as a +`Box<TextField>`. Let’s look at how this works, and then we’ll talk about the +runtime performance implications. -We adapt an iterator using the `enumerate` method so it produces a value and -the index for that value, placed into a tuple. The first value produced is the -tuple `(0, 'a')`. When this value is matched to the pattern `(index, value)`, -`index` will be `0` and `value` will be `'a'`, printing the first line of the -output. +### Implementing the Trait -### let Statements +Now we’ll add some types that implement the `Draw` trait. We’ll provide the +`Button` type. Again, actually implementing a GUI library is beyond the scope +of this book, so the `draw` method won’t have any useful implementation in its +body. To imagine what the implementation might look like, a `Button` struct +might have fields for `width`, `height`, and `label`, as shown in Listing 17-7. -Prior to this chapter, we had only explicitly discussed using patterns with -`match` and `if let`, but in fact, we’ve used patterns in other places as well, -including in `let` statements. For example, consider this straightforward -variable assignment with `let`: +Filename: src/lib.rs ``` -let x = 5; -``` - -Every time you’ve used a `let` statement like this you’ve been using patterns, -although you might not have realized it! More formally, a `let` statement looks -like this: - -``` -let PATTERN = EXPRESSION; -``` - -In statements like `let x = 5;` with a variable name in the PATTERN slot, the -variable name is just a particularly simple form of a pattern. Rust compares -the expression against the pattern and assigns any names it finds. So, in the -`let x = 5;` example, `x` is a pattern that means “bind what matches here to -the variable `x`.” Because the name `x` is the whole pattern, this pattern -effectively means “bind everything to the variable `x`, whatever the value is.” - -To see the pattern-matching aspect of `let` more clearly, consider Listing -18-4, which uses a pattern with `let` to destructure a tuple. +pub struct Button { + pub width: u32, + pub height: u32, + pub label: String, +} -``` -let (x, y, z) = (1, 2, 3); +impl Draw for Button { + fn draw(&self) { + // code to actually draw a button + } +} ``` -Listing 18-4: Using a pattern to destructure a tuple and create three variables -at once +Listing 17-7: A `Button` struct that implements the `Draw` trait -Here, we match a tuple against a pattern. Rust compares the value `(1, 2, 3)` -to the pattern `(x, y, z)` and sees that the value matches the pattern, in that -it sees that the number of elements is the same in both, so Rust binds `1` to -`x`, `2` to `y`, and `3` to `z`. You can think of this tuple pattern as nesting -three individual variable patterns inside it. +The `width`, `height`, and `label` fields on `Button` will differ from the +fields on other components; for example, a `TextField` type might have those +same fields plus a `placeholder` field. Each of the types we want to draw on +the screen will implement the `Draw` trait but will use different code in the +`draw` method to define how to draw that particular type, as `Button` has here +(without the actual GUI code, as mentioned). The `Button` type, for instance, +might have an additional `impl` block containing methods related to what +happens when a user clicks the button. These kinds of methods won’t apply to +types like `TextField`. -If the number of elements in the pattern doesn’t match the number of elements -in the tuple, the overall type won’t match and we’ll get a compiler error. For -example, Listing 18-5 shows an attempt to destructure a tuple with three -elements into two variables, which won’t work. +If someone using our library decides to implement a `SelectBox` struct that has +`width`, `height`, and `options` fields, they would implement the `Draw` trait +on the `SelectBox` type as well, as shown in Listing 17-8. -``` -let (x, y) = (1, 2, 3); -``` - -Listing 18-5: Incorrectly constructing a pattern whose variables don’t match -the number of elements in the tuple - -Attempting to compile this code results in this type error: +Filename: src/main.rs ``` -error[E0308]: mismatched types - --> src/main.rs:2:9 - | -2 | let (x, y) = (1, 2, 3); - | ^^^^^^ --------- this expression has type `({integer}, {integer}, -{integer})` - | | - | expected a tuple with 3 elements, found one with 2 elements - | - = note: expected tuple `({integer}, {integer}, {integer})` - found tuple `(_, _)` -``` - -To fix the error, we could ignore one or more of the values in the tuple using -`_` or `..`, as you’ll see in “Ignoring Values in a Pattern” on page XX. If the -problem is that we have too many variables in the pattern, the solution is to -make the types match by removing variables so the number of variables equals -the number of elements in the tuple. +use gui::Draw; -### Function Parameters - -Function parameters can also be patterns. The code in Listing 18-6, which -declares a function named `foo` that takes one parameter named `x` of type -`i32`, should by now look familiar. +struct SelectBox { + width: u32, + height: u32, + options: Vec<String>, +} -``` -fn foo(x: i32) { - // code goes here +impl Draw for SelectBox { + fn draw(&self) { + // code to actually draw a select box + } } ``` -Listing 18-6: A function signature using patterns in the parameters +Listing 17-8: Another crate using `gui` and implementing the `Draw` trait on a +`SelectBox` struct -The `x` part is a pattern! As we did with `let`, we could match a tuple in a -function’s arguments to the pattern. Listing 18-7 splits the values in a tuple -as we pass it to a function. +Our library’s user can now write their `main` function to create a `Screen` +instance. To the `Screen` instance, they can add a `SelectBox` and a `Button` +by putting each in a `Box<T>` to become a trait object. They can then call the +`run` method on the `Screen` instance, which will call `draw` on each of the +components. Listing 17-9 shows this implementation. Filename: src/main.rs ``` -fn print_coordinates(&(x, y): &(i32, i32)) { - println!("Current location: ({x}, {y})"); -} +use gui::{Button, Screen}; fn main() { - let point = (3, 5); - print_coordinates(&point); + let screen = Screen { + components: vec![ + Box::new(SelectBox { + width: 75, + height: 10, + options: vec![ + String::from("Yes"), + String::from("Maybe"), + String::from("No"), + ], + }), + Box::new(Button { + width: 50, + height: 10, + label: String::from("OK"), + }), + ], + }; + + screen.run(); } ``` -Listing 18-7: A function with parameters that destructure a tuple - -This code prints `Current location: (3, 5)`. The values `&(3, 5)` match the -pattern `&(x, y)`, so `x` is the value `3` and `y` is the value `5`. - -We can also use patterns in closure parameter lists in the same way as in -function parameter lists because closures are similar to functions, as -discussed in Chapter 13. - -At this point, you’ve seen several ways to use patterns, but patterns don’t -work the same in every place we can use them. In some places, the patterns must -be irrefutable; in other circumstances, they can be refutable. We’ll discuss -these two concepts next. - -## Refutability: Whether a Pattern Might Fail to Match - -Patterns come in two forms: refutable and irrefutable. Patterns that will match -for any possible value passed are *irrefutable*. An example would be `x` in the -statement `let x = 5;` because `x` matches anything and therefore cannot fail -to match. Patterns that can fail to match for some possible value are -*refutable*. An example would be `Some(x)` in the expression `if let Some(x) = -a_value` because if the value in the `a_value` variable is `None` rather than -`Some`, the `Some(x)` pattern will not match. - -Function parameters, `let` statements, and `for` loops can only accept -irrefutable patterns because the program cannot do anything meaningful when -values don’t match. The `if let` and `while let` expressions accept refutable -and irrefutable patterns, but the compiler warns against irrefutable patterns -because, by definition, they’re intended to handle possible failure: the -functionality of a conditional is in its ability to perform differently -depending on success or failure. - -In general, you shouldn’t have to worry about the distinction between refutable -and irrefutable patterns; however, you do need to be familiar with the concept -of refutability so you can respond when you see it in an error message. In -those cases, you’ll need to change either the pattern or the construct you’re -using the pattern with, depending on the intended behavior of the code. - -Let’s look at an example of what happens when we try to use a refutable pattern -where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a -`let` statement, but for the pattern, we’ve specified `Some(x)`, a refutable -pattern. As you might expect, this code will not compile. +Listing 17-9: Using trait objects to store values of different types that +implement the same trait -``` -let Some(x) = some_option_value; -``` +When we wrote the library, we didn’t know that someone might add the +`SelectBox` type, but our `Screen` implementation was able to operate on the +new type and draw it because `SelectBox` implements the `Draw` trait, which +means it implements the `draw` method. -Listing 18-8: Attempting to use a refutable pattern with `let` +This concept—of being concerned only with the messages a value responds to +rather than the value’s concrete type—is similar to the concept of *duck +typing* in dynamically typed languages: if it walks like a duck and quacks like +a duck, then it must be a duck! In the implementation of `run` on `Screen` in +Listing 17-5, `run` doesn’t need to know what the concrete type of each +component is. It doesn’t check whether a component is an instance of a `Button` +or a `SelectBox`, it just calls the `draw` method on the component. By +specifying `Box<dyn Draw>` as the type of the values in the `components` +vector, we’ve defined `Screen` to need values that we can call the `draw` +method on. -If `some_option_value` were a `None` value, it would fail to match the pattern -`Some(x)`, meaning the pattern is refutable. However, the `let` statement can -only accept an irrefutable pattern because there is nothing valid the code can -do with a `None` value. At compile time, Rust will complain that we’ve tried to -use a refutable pattern where an irrefutable pattern is required: +The advantage of using trait objects and Rust’s type system to write code +similar to code using duck typing is that we never have to check whether a +value implements a particular method at runtime or worry about getting errors +if a value doesn’t implement a method but we call it anyway. Rust won’t compile +our code if the values don’t implement the traits that the trait objects need. -``` -error[E0005]: refutable pattern in local binding: `None` not covered - --> src/main.rs:3:9 - | -3 | let Some(x) = some_option_value; - | ^^^^^^^ pattern `None` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or -an `enum` with only one variant - = note: for more information, visit -https://doc.rust-lang.org/book/ch18-02-refutability.html - = note: the matched value is of type `Option<i32>` -help: you might want to use `if let` to ignore the variant that isn't matched - | -3 | let x = if let Some(x) = some_option_value { x } else { todo!() }; - | ++++++++++ ++++++++++++++++++++++ -``` - -Because we didn’t cover (and couldn’t cover!) every valid value with the -pattern `Some(x)`, Rust rightfully produces a compiler error. +For example, Listing 17-10 shows what happens if we try to create a `Screen` +with a `String` as a component. -If we have a refutable pattern where an irrefutable pattern is needed, we can -fix it by changing the code that uses the pattern: instead of using `let`, we -can use `if let`. Then, if the pattern doesn’t match, the code will just skip -the code in the curly brackets, giving it a way to continue validly. Listing -18-9 shows how to fix the code in Listing 18-8. +Filename: src/main.rs ``` -if let Some(x) = some_option_value { - println!("{x}"); -} -``` +use gui::Screen; -Listing 18-9: Using `if let` and a block with refutable patterns instead of -`let` - -We’ve given the code an out! This code is perfectly valid, although it means we -cannot use an irrefutable pattern without receiving an error. If we give `if -let` a pattern that will always match, such as `x`, as shown in Listing 18-10, -the compiler will give a warning. +fn main() { + let screen = Screen { + components: vec![Box::new(String::from("Hi"))], + }; -``` -if let x = 5 { - println!("{x}"); -}; + screen.run(); +} ``` -Listing 18-10: Attempting to use an irrefutable pattern with `if let` +Listing 17-10: Attempting to use a type that doesn’t implement the trait +object’s trait -Rust complains that it doesn’t make sense to use `if let` with an irrefutable -pattern: +We’ll get this error because `String` doesn’t implement the `Draw` trait: ``` -warning: irrefutable `if let` pattern - --> src/main.rs:2:8 +error[E0277]: the trait bound `String: Draw` is not satisfied + --> src/main.rs:5:26 | -2 | if let x = 5 { - | ^^^^^^^^^ +5 | components: vec![Box::new(String::from("Hi"))], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Draw` is +not implemented for `String` | - = note: `#[warn(irrefutable_let_patterns)]` on by default - = note: this pattern will always match, so the `if let` is -useless - = help: consider replacing the `if let` with a `let` -``` - -For this reason, match arms must use refutable patterns, except for the last -arm, which should match any remaining values with an irrefutable pattern. Rust -allows us to use an irrefutable pattern in a `match` with only one arm, but -this syntax isn’t particularly useful and could be replaced with a simpler -`let` statement. - -Now that you know where to use patterns and the difference between refutable -and irrefutable patterns, let’s cover all the syntax we can use to create -patterns. - -## Pattern Syntax - -In this section, we gather all the syntax that is valid in patterns and discuss -why and when you might want to use each one. - -### Matching Literals - -As you saw in Chapter 6, you can match patterns against literals directly. The -following code gives some examples: + = note: required for the cast to the object type `dyn Draw` +``` + +This error lets us know that either we’re passing something to `Screen` that we +didn’t mean to pass and so should pass a different type, or we should implement +`Draw` on `String` so that `Screen` is able to call `draw` on it. + +### Trait Objects Perform Dynamic Dispatch + +Recall in “Performance of Code Using Generics” on page XX our discussion on the +monomorphization process performed by the compiler when we use trait bounds on +generics: the compiler generates nongeneric implementations of functions and +methods for each concrete type that we use in place of a generic type +parameter. The code that results from monomorphization is doing *static +dispatch*, which is when the compiler knows what method you’re calling at +compile time. This is opposed to *dynamic dispatch*, which is when the compiler +can’t tell at compile time which method you’re calling. In dynamic dispatch +cases, the compiler emits code that at runtime will figure out which method to +call. + +When we use trait objects, Rust must use dynamic dispatch. The compiler doesn’t +know all the types that might be used with the code that’s using trait objects, +so it doesn’t know which method implemented on which type to call. Instead, at +runtime, Rust uses the pointers inside the trait object to know which method to +call. This lookup incurs a runtime cost that doesn’t occur with static +dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a +method’s code, which in turn prevents some optimizations. However, we did get +extra flexibility in the code that we wrote in Listing 17-5 and were able to +support in Listing 17-9, so it’s a trade-off to consider. + +## Implementing an Object-Oriented Design Pattern + +The *state pattern* is an object-oriented design pattern. The crux of the +pattern is that we define a set of states a value can have internally. The +states are represented by a set of *state objects*, and the value’s behavior +changes based on its state. We’re going to work through an example of a blog +post struct that has a field to hold its state, which will be a state object +from the set “draft,” “review,” or “published.” + +The state objects share functionality: in Rust, of course, we use structs and +traits rather than objects and inheritance. Each state object is responsible +for its own behavior and for governing when it should change into another +state. The value that holds a state object knows nothing about the different +behavior of the states or when to transition between states. + +The advantage of using the state pattern is that, when the business +requirements of the program change, we won’t need to change the code of the +value holding the state or the code that uses the value. We’ll only need to +update the code inside one of the state objects to change its rules or perhaps +add more state objects. + +First we’re going to implement the state pattern in a more traditional +object-oriented way, then we’ll use an approach that’s a bit more natural in +Rust. Let’s dig in to incrementally implement a blog post workflow using the +state pattern. + +The final functionality will look like this: + +1. A blog post starts as an empty draft. +1. When the draft is done, a review of the post is requested. +1. When the post is approved, it gets published. +1. Only published blog posts return content to print, so unapproved posts can’t +accidentally be published. + +Any other changes attempted on a post should have no effect. For example, if we +try to approve a draft blog post before we’ve requested a review, the post +should remain an unpublished draft. + +Listing 17-11 shows this workflow in code form: this is an example usage of the +API we’ll implement in a library crate named `blog`. This won’t compile yet +because we haven’t implemented the `blog` crate. Filename: src/main.rs ``` -let x = 1; - -match x { - 1 => println!("one"), - 2 => println!("two"), - 3 => println!("three"), - _ => println!("anything"), -} -``` - -This code prints `one` because the value in `x` is `1`. This syntax is useful -when you want your code to take an action if it gets a particular concrete -value. - -### Matching Named Variables - -Named variables are irrefutable patterns that match any value, and we’ve used -them many times in this book. However, there is a complication when you use -named variables in `match` expressions. Because `match` starts a new scope, -variables declared as part of a pattern inside the `match` expression will -shadow those with the same name outside the `match` construct, as is the case -with all variables. In Listing 18-11, we declare a variable named `x` with the -value `Some(5)` and a variable `y` with the value `10`. We then create a -`match` expression on the value `x`. Look at the patterns in the match arms and -`println!` at the end, and try to figure out what the code will print before -running this code or reading further. +use blog::Post; -Filename: src/main.rs - -``` fn main() { - 1 let x = Some(5); - 2 let y = 10; - - match x { - 3 Some(50) => println!("Got 50"), - 4 Some(y) => println!("Matched, y = {y}"), - 5 _ => println!("Default case, x = {:?}", x), - } - - 6 println!("at the end: x = {:?}, y = {y}", x); -} -``` - -Listing 18-11: A `match` expression with an arm that introduces a shadowed -variable `y` - -Let’s walk through what happens when the `match` expression runs. The pattern -in the first match arm [3] doesn’t match the defined value of `x` [1], so the -code continues. - -The pattern in the second match arm [4] introduces a new variable named `y` -that will match any value inside a `Some` value. Because we’re in a new scope -inside the `match` expression, this is a new `y` variable, not the `y` we -declared at the beginning with the value `10` [2]. This new `y` binding will -match any value inside a `Some`, which is what we have in `x`. Therefore, this -new `y` binds to the inner value of the `Some` in `x`. That value is `5`, so -the expression for that arm executes and prints `Matched, y = 5`. - -If `x` had been a `None` value instead of `Some(5)`, the patterns in the first -two arms wouldn’t have matched, so the value would have matched to the -underscore [5]. We didn’t introduce the `x` variable in the pattern of the -underscore arm, so the `x` in the expression is still the outer `x` that hasn’t -been shadowed. In this hypothetical case, the `match` would print `Default -case, x = None`. - -When the `match` expression is done, its scope ends, and so does the scope of -the inner `y`. The last `println!` [6] produces `at the end: x = Some(5), y = -10`. - -To create a `match` expression that compares the values of the outer `x` and -`y`, rather than introducing a shadowed variable, we would need to use a match -guard conditional instead. We’ll talk about match guards in “Extra Conditionals -with Match Guards” on page XX. - -### Multiple Patterns - -In `match` expressions, you can match multiple patterns using the `|` syntax, -which is the pattern *or* operator. For example, in the following code we match -the value of `x` against the match arms, the first of which has an *or* option, -meaning if the value of `x` matches either of the values in that arm, that -arm’s code will run: - -Filename: src/main.rs - -``` -let x = 1; - -match x { - 1 | 2 => println!("one or two"), - 3 => println!("three"), - _ => println!("anything"), -} -``` - -This code prints `one or two`. + 1 let mut post = Post::new(); -### Matching Ranges of Values with ..= + 2 post.add_text("I ate a salad for lunch today"); + 3 assert_eq!("", post.content()); -The `..=` syntax allows us to match to an inclusive range of values. In the -following code, when a pattern matches any of the values within the given -range, that arm will execute: - -Filename: src/main.rs - -``` -let x = 5; + 4 post.request_review(); + 5 assert_eq!("", post.content()); -match x { - 1..=5 => println!("one through five"), - _ => println!("something else"), + 6 post.approve(); + 7 assert_eq!("I ate a salad for lunch today", post.content()); } ``` -If `x` is `1`, `2`, `3`, `4`, or `5`, the first arm will match. This syntax is -more convenient for multiple match values than using the `|` operator to -express the same idea; if we were to use `|`, we would have to specify `1 | 2 | -3 | 4 | 5`. Specifying a range is much shorter, especially if we want to match, -say, any number between 1 and 1,000! +Listing 17-11: Code that demonstrates the desired behavior we want our `blog` +crate to have -The compiler checks that the range isn’t empty at compile time, and because the -only types for which Rust can tell if a range is empty or not are `char` and -numeric values, ranges are only allowed with numeric or `char` values. - -Here is an example using ranges of `char` values: - -Filename: src/main.rs - -``` -let x = 'c'; - -match x { - 'a'..='j' => println!("early ASCII letter"), - 'k'..='z' => println!("late ASCII letter"), - _ => println!("something else"), -} -``` +We want to allow the user to create a new draft blog post with `Post::new` [1]. +We want to allow text to be added to the blog post [2]. If we try to get the +post’s content immediately, before approval, we shouldn’t get any text because +the post is still a draft. We’ve added `assert_eq!` in the code for +demonstration purposes [3]. An excellent unit test for this would be to assert +that a draft blog post returns an empty string from the `content` method, but +we’re not going to write tests for this example. -Rust can tell that `'c'` is within the first pattern’s range and prints `early -ASCII letter`. +Next, we want to enable a request for a review of the post [4], and we want +`content` to return an empty string while waiting for the review [5]. When the +post receives approval [6], it should get published, meaning the text of the +post will be returned when `content` is called [7]. -### Destructuring to Break Apart Values +Notice that the only type we’re interacting with from the crate is the `Post` +type. This type will use the state pattern and will hold a value that will be +one of three state objects representing the various states a post can be +in—draft, review, or published. Changing from one state to another will be +managed internally within the `Post` type. The states change in response to the +methods called by our library’s users on the `Post` instance, but they don’t +have to manage the state changes directly. Also, users can’t make a mistake +with the states, such as publishing a post before it’s reviewed. -We can also use patterns to destructure structs, enums, and tuples to use -different parts of these values. Let’s walk through each value. +### Defining Post and Creating a New Instance in the Draft State -#### Destructuring Structs +Let’s get started on the implementation of the library! We know we need a +public `Post` struct that holds some content, so we’ll start with the +definition of the struct and an associated public `new` function to create an +instance of `Post`, as shown in Listing 17-12. We’ll also make a private +`State` trait that will define the behavior that all state objects for a `Post` +must have. -Listing 18-12 shows a `Point` struct with two fields, `x` and `y`, that we can -break apart using a pattern with a `let` statement. +Then `Post` will hold a trait object of `Box<dyn State>` inside an `Option<T>` +in a private field named `state` to hold the state object. You’ll see why the +`Option<T>` is necessary in a bit. -Filename: src/main.rs +Filename: src/lib.rs ``` -struct Point { - x: i32, - y: i32, +pub struct Post { + state: Option<Box<dyn State>>, + content: String, } -fn main() { - let p = Point { x: 0, y: 7 }; - - let Point { x: a, y: b } = p; - assert_eq!(0, a); - assert_eq!(7, b); +impl Post { + pub fn new() -> Post { + Post { + 1 state: Some(Box::new(Draft {})), + 2 content: String::new(), + } + } } -``` - -Listing 18-12: Destructuring a struct’s fields into separate variables -This code creates the variables `a` and `b` that match the values of the `x` -and `y` fields of the `p` struct. This example shows that the names of the -variables in the pattern don’t have to match the field names of the struct. -However, it’s common to match the variable names to the field names to make it -easier to remember which variables came from which fields. Because of this -common usage, and because writing `let Point { x: x, y: y } = p;` contains a -lot of duplication, Rust has a shorthand for patterns that match struct fields: -you only need to list the name of the struct field, and the variables created -from the pattern will have the same names. Listing 18-13 behaves in the same -way as the code in Listing 18-12, but the variables created in the `let` -pattern are `x` and `y` instead of `a` and `b`. +trait State {} -Filename: src/main.rs +struct Draft {} +impl State for Draft {} ``` -struct Point { - x: i32, - y: i32, -} -fn main() { - let p = Point { x: 0, y: 7 }; - - let Point { x, y } = p; - assert_eq!(0, x); - assert_eq!(7, y); -} -``` +Listing 17-12: Definition of a `Post` struct and a `new` function that creates +a new `Post` instance, a `State` trait, and a `Draft` struct -Listing 18-13: Destructuring struct fields using struct field shorthand +The `State` trait defines the behavior shared by different post states. The +state objects are `Draft`, `PendingReview`, and `Published`, and they will all +implement the `State` trait. For now, the trait doesn’t have any methods, and +we’ll start by defining just the `Draft` state because that is the state we +want a post to start in. -This code creates the variables `x` and `y` that match the `x` and `y` fields -of the `p` variable. The outcome is that the variables `x` and `y` contain the -values from the `p` struct. +When we create a new `Post`, we set its `state` field to a `Some` value that +holds a `Box` [1]. This `Box` points to a new instance of the `Draft` struct. +This ensures that whenever we create a new instance of `Post`, it will start +out as a draft. Because the `state` field of `Post` is private, there is no way +to create a `Post` in any other state! In the `Post::new` function, we set the +`content` field to a new, empty `String` [2]. -We can also destructure with literal values as part of the struct pattern -rather than creating variables for all the fields. Doing so allows us to test -some of the fields for particular values while creating variables to -destructure the other fields. +### Storing the Text of the Post Content -In Listing 18-14, we have a `match` expression that separates `Point` values -into three cases: points that lie directly on the `x` axis (which is true when -`y = 0`), on the `y` axis (`x = 0`), or on neither axis. +We saw in Listing 17-11 that we want to be able to call a method named +`add_text` and pass it a `&str` that is then added as the text content of the +blog post. We implement this as a method, rather than exposing the `content` +field as `pub`, so that later we can implement a method that will control how +the `content` field’s data is read. The `add_text` method is pretty +straightforward, so let’s add the implementation in Listing 17-13 to the `impl +Post` block. -Filename: src/main.rs +Filename: src/lib.rs ``` -fn main() { - let p = Point { x: 0, y: 7 }; - - match p { - Point { x, y: 0 } => println!("On the x axis at {x}"), - Point { x: 0, y } => println!("On the y axis at {y}"), - Point { x, y } => { - println!("On neither axis: ({x}, {y})"); - } +impl Post { + --snip-- + pub fn add_text(&mut self, text: &str) { + self.content.push_str(text); } } ``` -Listing 18-14: Destructuring and matching literal values in one pattern +Listing 17-13: Implementing the `add_text` method to add text to a post’s +`content` -The first arm will match any point that lies on the `x` axis by specifying that -the `y` field matches if its value matches the literal `0`. The pattern still -creates an `x` variable that we can use in the code for this arm. +The `add_text` method takes a mutable reference to `self` because we’re +changing the `Post` instance that we’re calling `add_text` on. We then call +`push_str` on the `String` in `content` and pass the `text` argument to add to +the saved `content`. This behavior doesn’t depend on the state the post is in, +so it’s not part of the state pattern. The `add_text` method doesn’t interact +with the `state` field at all, but it is part of the behavior we want to +support. -Similarly, the second arm matches any point on the `y` axis by specifying that -the `x` field matches if its value is `0` and creates a variable `y` for the -value of the `y` field. The third arm doesn’t specify any literals, so it -matches any other `Point` and creates variables for both the `x` and `y` fields. +### Ensuring the Content of a Draft Post Is Empty -In this example, the value `p` matches the second arm by virtue of `x` -containing a `0`, so this code will print `On the y axis at 7`. +Even after we’ve called `add_text` and added some content to our post, we still +want the `content` method to return an empty string slice because the post is +still in the draft state, as shown at [3] in Listing 17-11. For now, let’s +implement the `content` method with the simplest thing that will fulfill this +requirement: always returning an empty string slice. We’ll change this later +once we implement the ability to change a post’s state so it can be published. +So far, posts can only be in the draft state, so the post content should always +be empty. Listing 17-14 shows this placeholder implementation. -Remember that a `match` expression stops checking arms once it has found the -first matching pattern, so even though `Point { x: 0, y: 0}` is on the `x` axis -and the `y` axis, this code would only print `On the x axis at 0`. - -#### Destructuring Enums - -We’ve destructured enums in this book (for example, Listing 6-5), but we -haven’t yet explicitly discussed that the pattern to destructure an enum -corresponds to the way the data stored within the enum is defined. As an -example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write -a `match` with patterns that will destructure each inner value. - -Filename: src/main.rs +Filename: src/lib.rs ``` -enum Message { - Quit, - Move { x: i32, y: i32 }, - Write(String), - ChangeColor(i32, i32, i32), -} - -fn main() { - 1 let msg = Message::ChangeColor(0, 160, 255); - - match msg { - 2 Message::Quit => { - println!( - "The Quit variant has no data to destructure." - ); - } - 3 Message::Move { x, y } => { - println!( - "Move in the x dir {x}, in the y dir {y}" - ); - } - 4 Message::Write(text) => { - println!("Text message: {text}"); - } - 5 Message::ChangeColor(r, g, b) => println!( - "Change color to red {r}, green {g}, and blue {b}" - ), +impl Post { + --snip-- + pub fn content(&self) -> &str { + "" } } ``` -Listing 18-15: Destructuring enum variants that hold different kinds of values - -This code will print `Change color to red 0, green 160, and blue 255`. Try -changing the value of `msg` [1] to see the code from the other arms run. +Listing 17-14: Adding a placeholder implementation for the `content` method on +`Post` that always returns an empty string slice -For enum variants without any data, like `Message::Quit` [2], we can’t -destructure the value any further. We can only match on the literal -`Message::Quit` value, and no variables are in that pattern. +With this added `content` method, everything in Listing 17-11 up to the line at +[3] works as intended. -For struct-like enum variants, such as `Message::Move` [3], we can use a -pattern similar to the pattern we specify to match structs. After the variant -name, we place curly brackets and then list the fields with variables so we -break apart the pieces to use in the code for this arm. Here we use the -shorthand form as we did in Listing 18-13. +### Requesting a Review Changes the Post’s State -For tuple-like enum variants, like `Message::Write` that holds a tuple with one -element [4] and `Message::ChangeColor` that holds a tuple with three elements -[5], the pattern is similar to the pattern we specify to match tuples. The -number of variables in the pattern must match the number of elements in the -variant we’re matching. +Next, we need to add functionality to request a review of a post, which should +change its state from `Draft` to `PendingReview`. Listing 17-15 shows this code. -#### Destructuring Nested Structs and Enums - -So far, our examples have all been matching structs or enums one level deep, -but matching can work on nested items too! For example, we can refactor the -code in Listing 18-15 to support RGB and HSV colors in the `ChangeColor` -message, as shown in Listing 18-16. - -Filename: src/main.rs +Filename: src/lib.rs ``` -enum Color { - Rgb(i32, i32, i32), - Hsv(i32, i32, i32), +impl Post { + --snip-- + 1 pub fn request_review(&mut self) { + 2 if let Some(s) = self.state.take() { + 3 self.state = Some(s.request_review()) + } + } } -enum Message { - Quit, - Move { x: i32, y: i32 }, - Write(String), - ChangeColor(Color), +trait State { + 4 fn request_review(self: Box<Self>) -> Box<dyn State>; } -fn main() { - let msg = Message::ChangeColor(Color::Hsv(0, 160, 255)); - - match msg { - Message::ChangeColor(Color::Rgb(r, g, b)) => println!( - "Change color to red {r}, green {g}, and blue {b}" - ), - Message::ChangeColor(Color::Hsv(h, s, v)) => println!( - "Change color to hue {h}, saturation {s}, value {v}" - ), - _ => (), +struct Draft {} + +impl State for Draft { + fn request_review(self: Box<Self>) -> Box<dyn State> { + 5 Box::new(PendingReview {}) } } -``` - -Listing 18-16: Matching on nested enums - -The pattern of the first arm in the `match` expression matches a -`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then -the pattern binds to the three inner `i32` values. The pattern of the second -arm also matches a `Message::ChangeColor` enum variant, but the inner enum -matches `Color::Hsv` instead. We can specify these complex conditions in one -`match` expression, even though two enums are involved. - -#### Destructuring Structs and Tuples -We can mix, match, and nest destructuring patterns in even more complex ways. -The following example shows a complicated destructure where we nest structs and -tuples inside a tuple and destructure all the primitive values out: +struct PendingReview {} +impl State for PendingReview { + fn request_review(self: Box<Self>) -> Box<dyn State> { + 6 self + } +} ``` -let ((feet, inches), Point { x, y }) = - ((3, 10), Point { x: 3, y: -10 }); -``` - -This code lets us break complex types into their component parts so we can use -the values we’re interested in separately. -Destructuring with patterns is a convenient way to use pieces of values, such -as the value from each field in a struct, separately from each other. - -### Ignoring Values in a Pattern - -You’ve seen that it’s sometimes useful to ignore values in a pattern, such as -in the last arm of a `match`, to get a catchall that doesn’t actually do -anything but does account for all remaining possible values. There are a few -ways to ignore entire values or parts of values in a pattern: using the `_` -pattern (which you’ve seen), using the `_` pattern within another pattern, -using a name that starts with an underscore, or using `..` to ignore remaining -parts of a value. Let’s explore how and why to use each of these patterns. - -#### An Entire Value with _ - -We’ve used the underscore as a wildcard pattern that will match any value but -not bind to the value. This is especially useful as the last arm in a `match` -expression, but we can also use it in any pattern, including function -parameters, as shown in Listing 18-17. - -Filename: src/main.rs - -``` -fn foo(_: i32, y: i32) { - println!("This code only uses the y parameter: {y}"); +Listing 17-15: Implementing `request_review` methods on `Post` and the `State` +trait + +We give `Post` a public method named `request_review` that will take a mutable +reference to `self` [1]. Then we call an internal `request_review` method on +the current state of `Post` [3], and this second `request_review` method +consumes the current state and returns a new state. + +We add the `request_review` method to the `State` trait [4]; all types that +implement the trait will now need to implement the `request_review` method. +Note that rather than having `self`, `&self`, or `&mut self` as the first +parameter of the method, we have `self: Box<Self>`. This syntax means the +method is only valid when called on a `Box` holding the type. This syntax takes +ownership of `Box<Self>`, invalidating the old state so the state value of the +`Post` can transform into a new state. + +To consume the old state, the `request_review` method needs to take ownership +of the state value. This is where the `Option` in the `state` field of `Post` +comes in: we call the `take` method to take the `Some` value out of the `state` +field and leave a `None` in its place because Rust doesn’t let us have +unpopulated fields in structs [2]. This lets us move the `state` value out of +`Post` rather than borrowing it. Then we’ll set the post’s `state` value to the +result of this operation. + +We need to set `state` to `None` temporarily rather than setting it directly +with code like `self.state = self.state.request_review();` to get ownership of +the `state` value. This ensures `Post` can’t use the old `state` value after +we’ve transformed it into a new state. + +The `request_review` method on `Draft` returns a new, boxed instance of a new +`PendingReview` struct [5], which represents the state when a post is waiting +for a review. The `PendingReview` struct also implements the `request_review` +method but doesn’t do any transformations. Rather, it returns itself [6] +because when we request a review on a post already in the `PendingReview` +state, it should stay in the `PendingReview` state. + +Now we can start seeing the advantages of the state pattern: the +`request_review` method on `Post` is the same no matter its `state` value. Each +state is responsible for its own rules. + +We’ll leave the `content` method on `Post` as is, returning an empty string +slice. We can now have a `Post` in the `PendingReview` state as well as in the +`Draft` state, but we want the same behavior in the `PendingReview` state. +Listing 17-11 now works up to the line at [5]! + +### Adding approve to Change the Behavior of content + +The `approve` method will be similar to the `request_review` method: it will +set `state` to the value that the current state says it should have when that +state is approved, as shown in Listing 17-16. + +Filename: src/lib.rs + +``` +impl Post { + --snip-- + pub fn approve(&mut self) { + if let Some(s) = self.state.take() { + self.state = Some(s.approve()) + } + } } -fn main() { - foo(3, 4); +trait State { + fn request_review(self: Box<Self>) -> Box<dyn State>; + fn approve(self: Box<Self>) -> Box<dyn State>; } -``` - -Listing 18-17: Using `_` in a function signature -This code will completely ignore the value `3` passed as the first argument, -and will print `This code only uses the y parameter: 4`. +struct Draft {} -In most cases when you no longer need a particular function parameter, you -would change the signature so it doesn’t include the unused parameter. Ignoring -a function parameter can be especially useful in cases when, for example, -you’re implementing a trait when you need a certain type signature but the -function body in your implementation doesn’t need one of the parameters. You -then avoid getting a compiler warning about unused function parameters, as you -would if you used a name instead. - -#### Parts of a Value with a Nested _ +impl State for Draft { + --snip-- + fn approve(self: Box<Self>) -> Box<dyn State> { + 1 self + } +} -We can also use `_` inside another pattern to ignore just part of a value, for -example, when we want to test for only part of a value but have no use for the -other parts in the corresponding code we want to run. Listing 18-18 shows code -responsible for managing a setting’s value. The business requirements are that -the user should not be allowed to overwrite an existing customization of a -setting but can unset the setting and give it a value if it is currently unset. +struct PendingReview {} -Filename: src/main.rs +impl State for PendingReview { + --snip-- + fn approve(self: Box<Self>) -> Box<dyn State> { + 2 Box::new(Published {}) + } +} -``` -let mut setting_value = Some(5); -let new_setting_value = Some(10); +struct Published {} -match (setting_value, new_setting_value) { - (Some(_), Some(_)) => { - println!("Can't overwrite an existing customized value"); +impl State for Published { + fn request_review(self: Box<Self>) -> Box<dyn State> { + self } - _ => { - setting_value = new_setting_value; + + fn approve(self: Box<Self>) -> Box<dyn State> { + self } } - -println!("setting is {:?}", setting_value); ``` -Listing 18-18: Using an underscore within patterns that match `Some` variants -when we don’t need to use the value inside the `Some` +Listing 17-16: Implementing the `approve` method on `Post` and the `State` trait -This code will print `Can't overwrite an existing customized value` and then -`setting is Some(5)`. In the first match arm, we don’t need to match on or use -the values inside either `Some` variant, but we do need to test for the case -when `setting_value` and `new_setting_value` are the `Some` variant. In that -case, we print the reason for not changing `setting_value`, and it doesn’t get -changed. +We add the `approve` method to the `State` trait and add a new struct that +implements `State`, the `Published` state. -In all other cases (if either `setting_value` or `new_setting_value` is `None`) -expressed by the `_` pattern in the second arm, we want to allow -`new_setting_value` to become `setting_value`. +Similar to the way `request_review` on `PendingReview` works, if we call the +`approve` method on a `Draft`, it will have no effect because `approve` will +return `self` [1]. When we call `approve` on `PendingReview`, it returns a new, +boxed instance of the `Published` struct [2]. The `Published` struct implements +the `State` trait, and for both the `request_review` method and the `approve` +method, it returns itself because the post should stay in the `Published` state +in those cases. -We can also use underscores in multiple places within one pattern to ignore -particular values. Listing 18-19 shows an example of ignoring the second and -fourth values in a tuple of five items. +Now we need to update the `content` method on `Post`. We want the value +returned from `content` to depend on the current state of the `Post`, so we’re +going to have the `Post` delegate to a `content` method defined on its `state`, +as shown in Listing 17-17. -Filename: src/main.rs +Filename: src/lib.rs ``` -let numbers = (2, 4, 8, 16, 32); - -match numbers { - (first, _, third, _, fifth) => { - println!("Some numbers: {first}, {third}, {fifth}"); +impl Post { + --snip-- + pub fn content(&self) -> &str { + self.state.as_ref().unwrap().content(self) } + --snip-- } ``` -Listing 18-19: Ignoring multiple parts of a tuple +Listing 17-17: Updating the `content` method on `Post` to delegate to a +`content` method on `State` -This code will print `Some numbers: 2, 8, 32`, and the values `4` and `16` will -be ignored. +Because the goal is to keep all of these rules inside the structs that +implement `State`, we call a `content` method on the value in `state` and pass +the post instance (that is, `self`) as an argument. Then we return the value +that’s returned from using the `content` method on the `state` value. -#### An Unused Variable by Starting Its Name with _ +We call the `as_ref` method on the `Option` because we want a reference to the +value inside the `Option` rather than ownership of the value. Because `state` +is an `Option<Box<dyn State>>`, when we call `as_ref`, an `Option<&Box<dyn +State>>` is returned. If we didn’t call `as_ref`, we would get an error because +we can’t move `state` out of the borrowed `&self` of the function parameter. -If you create a variable but don’t use it anywhere, Rust will usually issue a -warning because an unused variable could be a bug. However, sometimes it’s -useful to be able to create a variable you won’t use yet, such as when you’re -prototyping or just starting a project. In this situation, you can tell Rust -not to warn you about the unused variable by starting the name of the variable -with an underscore. In Listing 18-20, we create two unused variables, but when -we compile this code, we should only get a warning about one of them. +We then call the `unwrap` method, which we know will never panic because we +know the methods on `Post` ensure that `state` will always contain a `Some` +value when those methods are done. This is one of the cases we talked about in +“Cases in Which You Have More Information Than the Compiler” on page XX when we +know that a `None` value is never possible, even though the compiler isn’t able +to understand that. -Filename: src/main.rs +At this point, when we call `content` on the `&Box<dyn State>`, deref coercion +will take effect on the `&` and the `Box` so the `content` method will +ultimately be called on the type that implements the `State` trait. That means +we need to add `content` to the `State` trait definition, and that is where +we’ll put the logic for what content to return depending on which state we +have, as shown in Listing 17-18. + +Filename: src/lib.rs ``` -fn main() { - let _x = 5; - let y = 10; +trait State { + --snip-- + fn content<'a>(&self, post: &'a Post) -> &'a str { + 1 "" + } } -``` - -Listing 18-20: Starting a variable name with an underscore to avoid getting -unused variable warnings -Here, we get a warning about not using the variable `y`, but we don’t get a -warning about not using `_x`. +--snip-- +struct Published {} -Note that there is a subtle difference between using only `_` and using a name -that starts with an underscore. The syntax `_x` still binds the value to the -variable, whereas `_` doesn’t bind at all. To show a case where this -distinction matters, Listing 18-21 will provide us with an error. - -Filename: src/main.rs - -``` -let s = Some(String::from("Hello!")); - -if let Some(_s) = s { - println!("found a string"); +impl State for Published { + --snip-- + fn content<'a>(&self, post: &'a Post) -> &'a str { + 2 &post.content + } } - -println!("{:?}", s); ``` -Listing 18-21: An unused variable starting with an underscore still binds the -value, which might take ownership of the value. - -We’ll receive an error because the `s` value will still be moved into `_s`, -which prevents us from using `s` again. However, using the underscore by itself -doesn’t ever bind to the value. Listing 18-22 will compile without any errors -because `s` doesn’t get moved into `_`. +Listing 17-18: Adding the `content` method to the `State` trait + +We add a default implementation for the `content` method that returns an empty +string slice [1]. That means we don’t need to implement `content` on the +`Draft` and `PendingReview` structs. The `Published` struct will override the +`content` method and return the value in `post.content` [2]. + +Note that we need lifetime annotations on this method, as we discussed in +Chapter 10. We’re taking a reference to a `post` as an argument and returning a +reference to part of that `post`, so the lifetime of the returned reference is +related to the lifetime of the `post` argument. + +And we’re done—all of Listing 17-11 now works! We’ve implemented the state +pattern with the rules of the blog post workflow. The logic related to the +rules lives in the state objects rather than being scattered throughout `Post`. + +> ### Why Not An Enum? +> +> You may have been wondering why we didn’t use an `enum` with the different +possible post states as variants. That’s certainly a possible solution; try it +and compare the end results to see which you prefer! One disadvantage of using +an enum is that every place that checks the value of the enum will need a +`match` expression or similar to handle every possible variant. This could get +more repetitive than this trait object solution. + +### Trade-offs of the State Pattern + +We’ve shown that Rust is capable of implementing the object-oriented state +pattern to encapsulate the different kinds of behavior a post should have in +each state. The methods on `Post` know nothing about the various behaviors. The +way we organized the code, we have to look in only one place to know the +different ways a published post can behave: the implementation of the `State` +trait on the `Published` struct. + +If we were to create an alternative implementation that didn’t use the state +pattern, we might instead use `match` expressions in the methods on `Post` or +even in the `main` code that checks the state of the post and changes behavior +in those places. That would mean we would have to look in several places to +understand all the implications of a post being in the published state! This +would only increase the more states we added: each of those `match` expressions +would need another arm. + +With the state pattern, the `Post` methods and the places we use `Post` don’t +need `match` expressions, and to add a new state, we would only need to add a +new struct and implement the trait methods on that one struct. + +The implementation using the state pattern is easy to extend to add more +functionality. To see the simplicity of maintaining code that uses the state +pattern, try a few of these suggestions: + +* Add a `reject` method that changes the post’s state from `PendingReview` back +to `Draft`. +* Require two calls to `approve` before the state can be changed to `Published`. +* Allow users to add text content only when a post is in the `Draft` state. +Hint: have the state object responsible for what might change about the content +but not responsible for modifying the `Post`. + +One downside of the state pattern is that, because the states implement the +transitions between states, some of the states are coupled to each other. If we +add another state between `PendingReview` and `Published`, such as `Scheduled`, +we would have to change the code in `PendingReview` to transition to +`Scheduled` instead. It would be less work if `PendingReview` didn’t need to +change with the addition of a new state, but that would mean switching to +another design pattern. + +Another downside is that we’ve duplicated some logic. To eliminate some of the +duplication, we might try to make default implementations for the +`request_review` and `approve` methods on the `State` trait that return `self`. +However, this wouldn’t work: when using `State` as a trait object, the trait +doesn’t know what the concrete `self` will be exactly, so the return type isn’t +known at compile time. + +Other duplication includes the similar implementations of the `request_review` +and `approve` methods on `Post`. Both methods delegate to the implementation of +the same method on the value in the `state` field of `Option` and set the new +value of the `state` field to the result. If we had a lot of methods on `Post` +that followed this pattern, we might consider defining a macro to eliminate the +repetition (see “Macros” on page XX). + +By implementing the state pattern exactly as it’s defined for object-oriented +languages, we’re not taking as full advantage of Rust’s strengths as we could. +Let’s look at some changes we can make to the `blog` crate that can make +invalid states and transitions into compile-time errors. + +#### Encoding States and Behavior as Types + +We’ll show you how to rethink the state pattern to get a different set of +trade-offs. Rather than encapsulating the states and transitions completely so +outside code has no knowledge of them, we’ll encode the states into different +types. Consequently, Rust’s type checking system will prevent attempts to use +draft posts where only published posts are allowed by issuing a compiler error. + +Let’s consider the first part of `main` in Listing 17-11: Filename: src/main.rs ``` -let s = Some(String::from("Hello!")); +fn main() { + let mut post = Post::new(); -if let Some(_) = s { - println!("found a string"); + post.add_text("I ate a salad for lunch today"); + assert_eq!("", post.content()); } - -println!("{:?}", s); ``` -Listing 18-22: Using an underscore does not bind the value. - -This code works just fine because we never bind `s` to anything; it isn’t moved. - -#### Remaining Parts of a Value with .. +We still enable the creation of new posts in the draft state using `Post::new` +and the ability to add text to the post’s content. But instead of having a +`content` method on a draft post that returns an empty string, we’ll make it so +draft posts don’t have the `content` method at all. That way, if we try to get +a draft post’s content, we’ll get a compiler error telling us the method +doesn’t exist. As a result, it will be impossible for us to accidentally +display draft post content in production because that code won’t even compile. +Listing 17-19 shows the definition of a `Post` struct and a `DraftPost` struct, +as well as methods on each. -With values that have many parts, we can use the `..` syntax to use specific -parts and ignore the rest, avoiding the need to list underscores for each -ignored value. The `..` pattern ignores any parts of a value that we haven’t -explicitly matched in the rest of the pattern. In Listing 18-23, we have a -`Point` struct that holds a coordinate in three-dimensional space. In the -`match` expression, we want to operate only on the `x` coordinate and ignore -the values in the `y` and `z` fields. - -Filename: src/main.rs +Filename: src/lib.rs ``` -struct Point { - x: i32, - y: i32, - z: i32, +pub struct Post { + content: String, } -let origin = Point { x: 0, y: 0, z: 0 }; - -match origin { - Point { x, .. } => println!("x is {x}"), +pub struct DraftPost { + content: String, } -``` - -Listing 18-23: Ignoring all fields of a `Point` except for `x` by using `..` - -We list the `x` value and then just include the `..` pattern. This is quicker -than having to list `y: _` and `z: _`, particularly when we’re working with -structs that have lots of fields in situations where only one or two fields are -relevant. - -The syntax `..` will expand to as many values as it needs to be. Listing 18-24 -shows how to use `..` with a tuple. - -Filename: src/main.rs -``` -fn main() { - let numbers = (2, 4, 8, 16, 32); - - match numbers { - (first, .., last) => { - println!("Some numbers: {first}, {last}"); +impl Post { + 1 pub fn new() -> DraftPost { + DraftPost { + content: String::new(), } } -} -``` - -Listing 18-24: Matching only the first and last values in a tuple and ignoring -all other values - -In this code, the first and last values are matched with `first` and `last`. -The `..` will match and ignore everything in the middle. - -However, using `..` must be unambiguous. If it is unclear which values are -intended for matching and which should be ignored, Rust will give us an error. -Listing 18-25 shows an example of using `..` ambiguously, so it will not -compile. -Filename: src/main.rs - -``` -fn main() { - let numbers = (2, 4, 8, 16, 32); + 2 pub fn content(&self) -> &str { + &self.content + } +} - match numbers { - (.., second, ..) => { - println!("Some numbers: {second}"); - }, +impl DraftPost { + 3 pub fn add_text(&mut self, text: &str) { + self.content.push_str(text); } } ``` -Listing 18-25: An attempt to use `..` in an ambiguous way +Listing 17-19: A `Post` with a `content` method and a `DraftPost` without a +`content` method -When we compile this example, we get this error: +Both the `Post` and `DraftPost` structs have a private `content` field that +stores the blog post text. The structs no longer have the `state` field because +we’re moving the encoding of the state to the types of the structs. The `Post` +struct will represent a published post, and it has a `content` method that +returns the `content` [2]. -``` -error: `..` can only be used once per tuple pattern - --> src/main.rs:5:22 - | -5 | (.., second, ..) => { - | -- ^^ can only be used once per tuple pattern - | | - | previously used here -``` +We still have a `Post::new` function, but instead of returning an instance of +`Post`, it returns an instance of `DraftPost` [1]. Because `content` is private +and there aren’t any functions that return `Post`, it’s not possible to create +an instance of `Post` right now. -It’s impossible for Rust to determine how many values in the tuple to ignore -before matching a value with `second` and then how many further values to -ignore thereafter. This code could mean that we want to ignore `2`, bind -`second` to `4`, and then ignore `8`, `16`, and `32`; or that we want to ignore -`2` and `4`, bind `second` to `8`, and then ignore `16` and `32`; and so forth. -The variable name `second` doesn’t mean anything special to Rust, so we get a -compiler error because using `..` in two places like this is ambiguous. +The `DraftPost` struct has an `add_text` method, so we can add text to +`content` as before [3], but note that `DraftPost` does not have a `content` +method defined! So now the program ensures all posts start as draft posts, and +draft posts don’t have their content available for display. Any attempt to get +around these constraints will result in a compiler error. -### Extra Conditionals with Match Guards +#### Implementing Transitions as Transformations into Different Types -A *match guard* is an additional `if` condition, specified after the pattern in -a `match` arm, that must also match for that arm to be chosen. Match guards are -useful for expressing more complex ideas than a pattern alone allows. +So how do we get a published post? We want to enforce the rule that a draft +post has to be reviewed and approved before it can be published. A post in the +pending review state should still not display any content. Let’s implement +these constraints by adding another struct, `PendingReviewPost`, defining the +`request_review` method on `DraftPost` to return a `PendingReviewPost` and +defining an `approve` method on `PendingReviewPost` to return a `Post`, as +shown in Listing 17-20. -The condition can use variables created in the pattern. Listing 18-26 shows a -`match` where the first arm has the pattern `Some(x)` and also has a match -guard of `if x % 2 == 0` (which will be `true` if the number is even). - -Filename: src/main.rs +Filename: src/lib.rs ``` -let num = Some(4); - -match num { - Some(x) if x % 2 == 0 => println!("The number {x} is even"), - Some(x) => println!("The number {x} is odd"), - None => (), +impl DraftPost { + --snip-- + pub fn request_review(self) -> PendingReviewPost { + PendingReviewPost { + content: self.content, + } + } } -``` - -Listing 18-26: Adding a match guard to a pattern - -This example will print `The number 4 is even`. When `num` is compared to the -pattern in the first arm, it matches because `Some(4)` matches `Some(x)`. Then -the match guard checks whether the remainder of dividing `x` by 2 is equal to -0, and because it is, the first arm is selected. -If `num` had been `Some(5)` instead, the match guard in the first arm would -have been `false` because the remainder of 5 divided by 2 is 1, which is not -equal to 0. Rust would then go to the second arm, which would match because the -second arm doesn’t have a match guard and therefore matches any `Some` variant. - -There is no way to express the `if x % 2 == 0` condition within a pattern, so -the match guard gives us the ability to express this logic. The downside of -this additional expressiveness is that the compiler doesn’t try to check for -exhaustiveness when match guard expressions are involved. - -In Listing 18-11, we mentioned that we could use match guards to solve our -pattern-shadowing problem. Recall that we created a new variable inside the -pattern in the `match` expression instead of using the variable outside the -`match`. That new variable meant we couldn’t test against the value of the -outer variable. Listing 18-27 shows how we can use a match guard to fix this -problem. - -Filename: src/main.rs - -``` -fn main() { - let x = Some(5); - let y = 10; +pub struct PendingReviewPost { + content: String, +} - match x { - Some(50) => println!("Got 50"), - Some(n) if n == y => println!("Matched, n = {n}"), - _ => println!("Default case, x = {:?}", x), +impl PendingReviewPost { + pub fn approve(self) -> Post { + Post { + content: self.content, + } } - - println!("at the end: x = {:?}, y = {y}", x); } ``` -Listing 18-27: Using a match guard to test for equality with an outer variable - -This code will now print `Default case, x = Some(5)`. The pattern in the second -match arm doesn’t introduce a new variable `y` that would shadow the outer `y`, -meaning we can use the outer `y` in the match guard. Instead of specifying the -pattern as `Some(y)`, which would have shadowed the outer `y`, we specify -`Some(n)`. This creates a new variable `n` that doesn’t shadow anything because -there is no `n` variable outside the `match`. - -The match guard `if n == y` is not a pattern and therefore doesn’t introduce -new variables. This `y` *is* the outer `y` rather than a new shadowed `y`, and -we can look for a value that has the same value as the outer `y` by comparing -`n` to `y`. - -You can also use the *or* operator `|` in a match guard to specify multiple -patterns; the match guard condition will apply to all the patterns. Listing -18-28 shows the precedence when combining a pattern that uses `|` with a match -guard. The important part of this example is that the `if y` match guard -applies to `4`, `5`, *and* `6`, even though it might look like `if y` only -applies to `6`. +Listing 17-20: A `PendingReviewPost` that gets created by calling +`request_review` on `DraftPost` and an `approve` method that turns a +`PendingReviewPost` into a published `Post` + +The `request_review` and `approve` methods take ownership of `self`, thus +consuming the `DraftPost` and `PendingReviewPost` instances and transforming +them into a `PendingReviewPost` and a published `Post`, respectively. This way, +we won’t have any lingering `DraftPost` instances after we’ve called +`request_review` on them, and so forth. The `PendingReviewPost` struct doesn’t +have a `content` method defined on it, so attempting to read its content +results in a compiler error, as with `DraftPost`. Because the only way to get a +published `Post` instance that does have a `content` method defined is to call +the `approve` method on a `PendingReviewPost`, and the only way to get a +`PendingReviewPost` is to call the `request_review` method on a `DraftPost`, +we’ve now encoded the blog post workflow into the type system. + +But we also have to make some small changes to `main`. The `request_review` and +`approve` methods return new instances rather than modifying the struct they’re +called on, so we need to add more `let post =` shadowing assignments to save +the returned instances. We also can’t have the assertions about the draft and +pending review posts’ contents be empty strings, nor do we need them: we can’t +compile code that tries to use the content of posts in those states any longer. +The updated code in `main` is shown in Listing 17-21. Filename: src/main.rs ``` -let x = 4; -let y = false; - -match x { - 4 | 5 | 6 if y => println!("yes"), - _ => println!("no"), -} -``` - -Listing 18-28: Combining multiple patterns with a match guard - -The match condition states that the arm only matches if the value of `x` is -equal to `4`, `5`, or `6` *and* if `y` is `true`. When this code runs, the -pattern of the first arm matches because `x` is `4`, but the match guard `if y` -is `false`, so the first arm is not chosen. The code moves on to the second -arm, which does match, and this program prints `no`. The reason is that the -`if` condition applies to the whole pattern `4 | 5 | 6`, not just to the last -value `6`. In other words, the precedence of a match guard in relation to a -pattern behaves like this: - -``` -(4 | 5 | 6) if y => ... -``` - -rather than this: - -``` -4 | 5 | (6 if y) => ... -``` - -After running the code, the precedence behavior is evident: if the match guard -were applied only to the final value in the list of values specified using the -`|` operator, the arm would have matched and the program would have printed -`yes`. +use blog::Post; -### @ Bindings - -The *at* operator `@` lets us create a variable that holds a value at the same -time we’re testing that value for a pattern match. In Listing 18-29, we want to -test that a `Message::Hello` `id` field is within the range `3..=7`. We also -want to bind the value to the variable `id_variable` so we can use it in the -code associated with the arm. We could name this variable `id`, the same as the -field, but for this example we’ll use a different name. +fn main() { + let mut post = Post::new(); -Filename: src/main.rs + post.add_text("I ate a salad for lunch today"); -``` -enum Message { - Hello { id: i32 }, -} + let post = post.request_review(); -let msg = Message::Hello { id: 5 }; + let post = post.approve(); -match msg { - Message::Hello { - id: id_variable @ 3..=7, - } => println!("Found an id in range: {id_variable}"), - Message::Hello { id: 10..=12 } => { - println!("Found an id in another range") - } - Message::Hello { id } => println!("Some other id: {id}"), + assert_eq!("I ate a salad for lunch today", post.content()); } ``` -Listing 18-29: Using `@` to bind to a value in a pattern while also testing it +Listing 17-21: Modifications to `main` to use the new implementation of the +blog post workflow -This example will print `Found an id in range: 5`. By specifying `id_variable -@` before the range `3..=7`, we’re capturing whatever value matched the range -while also testing that the value matched the range pattern. +The changes we needed to make to `main` to reassign `post` mean that this +implementation doesn’t quite follow the object-oriented state pattern anymore: +the transformations between the states are no longer encapsulated entirely +within the `Post` implementation. However, our gain is that invalid states are +now impossible because of the type system and the type checking that happens at +compile time! This ensures that certain bugs, such as display of the content of +an unpublished post, will be discovered before they make it to production. -In the second arm, where we only have a range specified in the pattern, the -code associated with the arm doesn’t have a variable that contains the actual -value of the `id` field. The `id` field’s value could have been 10, 11, or 12, -but the code that goes with that pattern doesn’t know which it is. The pattern -code isn’t able to use the value from the `id` field because we haven’t saved -the `id` value in a variable. +Try the tasks suggested at the start of this section on the `blog` crate as it +is after Listing 17-21 to see what you think about the design of this version +of the code. Note that some of the tasks might be completed already in this +design. -In the last arm, where we’ve specified a variable without a range, we do have -the value available to use in the arm’s code in a variable named `id`. The -reason is that we’ve used the struct field shorthand syntax. But we haven’t -applied any test to the value in the `id` field in this arm, as we did with the -first two arms: any value would match this pattern. - -Using `@` lets us test a value and save it in a variable within one pattern. +We’ve seen that even though Rust is capable of implementing object-oriented +design patterns, other patterns, such as encoding state into the type system, +are also available in Rust. These patterns have different trade-offs. Although +you might be very familiar with object-oriented patterns, rethinking the +problem to take advantage of Rust’s features can provide benefits, such as +preventing some bugs at compile time. Object-oriented patterns won’t always be +the best solution in Rust due to certain features, like ownership, that +object-oriented languages don’t have. ## Summary -Rust’s patterns are very useful in distinguishing between different kinds of -data. When used in `match` expressions, Rust ensures your patterns cover every -possible value, or your program won’t compile. Patterns in `let` statements and -function parameters make those constructs more useful, enabling the -destructuring of values into smaller parts at the same time as assigning to -variables. We can create simple or complex patterns to suit our needs. - -Next, for the penultimate chapter of the book, we’ll look at some advanced -aspects of a variety of Rust’s features. +Regardless of whether you think Rust is an object-oriented language after +reading this chapter, you now know that you can use trait objects to get some +object-oriented features in Rust. Dynamic dispatch can give your code some +flexibility in exchange for a bit of runtime performance. You can use this +flexibility to implement object-oriented patterns that can help your code’s +maintainability. Rust also has other features, like ownership, that +object-oriented languages don’t have. An object-oriented pattern won’t always +be the best way to take advantage of Rust’s strengths, but it is an available +option. + +Next, we’ll look at patterns, which are another of Rust’s features that enable +lots of flexibility. We’ve looked at them briefly throughout the book but +haven’t seen their full capability yet. Let’s go! diff --git a/nostarch/chapter19.md b/nostarch/chapter19.md index 410e7eb62d..40c7f10a1c 100644 --- a/nostarch/chapter19.md +++ b/nostarch/chapter19.md @@ -6,2291 +6,1287 @@ directory, so all fixes need to be made in `/src/`. [TOC] -# Advanced Features - -By now, you’ve learned the most commonly used parts of the Rust programming -language. Before we do one more project, in Chapter 20, we’ll look at a few -aspects of the language you might run into every once in a while, but may not -use every day. You can use this chapter as a reference for when you encounter -any unknowns. The features covered here are useful in very specific situations. -Although you might not reach for them often, we want to make sure you have a -grasp of all the features Rust has to offer. - -In this chapter, we’ll cover: - -* Unsafe Rust: how to opt out of some of Rust’s guarantees and take -responsibility for manually upholding those guarantees -* Advanced traits: associated types, default type parameters, fully qualified -syntax, supertraits, and the newtype pattern in relation to traits -* Advanced types: more about the newtype pattern, type aliases, the never type, -and dynamically sized types -* Advanced functions and closures: function pointers and returning closures -* Macros: ways to define code that defines more code at compile time - -It’s a panoply of Rust features with something for everyone! Let’s dive in! - -## Unsafe Rust - -All the code we’ve discussed so far has had Rust’s memory safety guarantees -enforced at compile time. However, Rust has a second language hidden inside it -that doesn’t enforce these memory safety guarantees: it’s called *unsafe Rust* -and works just like regular Rust, but gives us extra superpowers. - -Unsafe Rust exists because, by nature, static analysis is conservative. When -the compiler tries to determine whether or not code upholds the guarantees, -it’s better for it to reject some valid programs than to accept some invalid -programs. Although the code *might* be okay, if the Rust compiler doesn’t have -enough information to be confident, it will reject the code. In these cases, -you can use unsafe code to tell the compiler, “Trust me, I know what I’m -doing.” Be warned, however, that you use unsafe Rust at your own risk: if you -use unsafe code incorrectly, problems can occur due to memory unsafety, such as -null pointer dereferencing. - -Another reason Rust has an unsafe alter ego is that the underlying computer -hardware is inherently unsafe. If Rust didn’t let you do unsafe operations, you -couldn’t do certain tasks. Rust needs to allow you to do low-level systems -programming, such as directly interacting with the operating system or even -writing your own operating system. Working with low-level systems programming -is one of the goals of the language. Let’s explore what we can do with unsafe -Rust and how to do it. - -### Unsafe Superpowers - -To switch to unsafe Rust, use the `unsafe` keyword and then start a new block -that holds the unsafe code. You can take five actions in unsafe Rust that you -can’t in safe Rust, which we call *unsafe superpowers*. Those superpowers -include the ability to: - -1. Dereference a raw pointer -1. Call an unsafe function or method -1. Access or modify a mutable static variable -1. Implement an unsafe trait -1. Access fields of `union`s - -It’s important to understand that `unsafe` doesn’t turn off the borrow checker -or disable any of Rust’s other safety checks: if you use a reference in unsafe -code, it will still be checked. The `unsafe` keyword only gives you access to -these five features that are then not checked by the compiler for memory -safety. You’ll still get some degree of safety inside an unsafe block. - -In addition, `unsafe` does not mean the code inside the block is necessarily -dangerous or that it will definitely have memory safety problems: the intent is -that as the programmer, you’ll ensure the code inside an `unsafe` block will -access memory in a valid way. - -People are fallible and mistakes will happen, but by requiring these five -unsafe operations to be inside blocks annotated with `unsafe`, you’ll know that -any errors related to memory safety must be within an `unsafe` block. Keep -`unsafe` blocks small; you’ll be thankful later when you investigate memory -bugs. - -To isolate unsafe code as much as possible, it’s best to enclose such code -within a safe abstraction and provide a safe API, which we’ll discuss later in -the chapter when we examine unsafe functions and methods. Parts of the standard -library are implemented as safe abstractions over unsafe code that has been -audited. Wrapping unsafe code in a safe abstraction prevents uses of `unsafe` -from leaking out into all the places that you or your users might want to use -the functionality implemented with `unsafe` code, because using a safe -abstraction is safe. - -Let’s look at each of the five unsafe superpowers in turn. We’ll also look at -some abstractions that provide a safe interface to unsafe code. - -### Dereferencing a Raw Pointer - -In “Dangling References” on page XX, we mentioned that the compiler ensures -references are always valid. Unsafe Rust has two new types called *raw -pointers* that are similar to references. As with references, raw pointers can -be immutable or mutable and are written as `*const T` and `*mut T`, -respectively. The asterisk isn’t the dereference operator; it’s part of the -type name. In the context of raw pointers, *immutable* means that the pointer -can’t be directly assigned to after being dereferenced. - -Different from references and smart pointers, raw pointers: - -* Are allowed to ignore the borrowing rules by having both immutable and -mutable pointers or multiple mutable pointers to the same location -* Aren’t guaranteed to point to valid memory -* Are allowed to be null -* Don’t implement any automatic cleanup +# Patterns and Matching -By opting out of having Rust enforce these guarantees, you can give up -guaranteed safety in exchange for greater performance or the ability to -interface with another language or hardware where Rust’s guarantees don’t apply. +*Patterns* are a special syntax in Rust for matching against the structure of +types, both complex and simple. Using patterns in conjunction with `match` +expressions and other constructs gives you more control over a program’s +control flow. A pattern consists of some combination of the following: -Listing 19-1 shows how to create an immutable and a mutable raw pointer from -references. - -``` -let mut num = 5; - -let r1 = &num as *const i32; -let r2 = &mut num as *mut i32; -``` +* Literals +* Destructured arrays, enums, structs, or tuples +* Variables +* Wildcards +* Placeholders -Listing 19-1: Creating raw pointers from references +Some example patterns include `x`, `(a, 3)`, and `Some(Color::Red)`. In the +contexts in which patterns are valid, these components describe the shape of +data. Our program then matches values against the patterns to determine whether +it has the correct shape of data to continue running a particular piece of code. -Notice that we don’t include the `unsafe` keyword in this code. We can create -raw pointers in safe code; we just can’t dereference raw pointers outside an -unsafe block, as you’ll see in a bit. +To use a pattern, we compare it to some value. If the pattern matches the +value, we use the value parts in our code. Recall the `match` expressions in +Chapter 6 that used patterns, such as the coin-sorting machine example. If the +value fits the shape of the pattern, we can use the named pieces. If it +doesn’t, the code associated with the pattern won’t run. -We’ve created raw pointers by using `as` to cast an immutable and a mutable -reference into their corresponding raw pointer types. Because we created them -directly from references guaranteed to be valid, we know these particular raw -pointers are valid, but we can’t make that assumption about just any raw -pointer. +This chapter is a reference on all things related to patterns. We’ll cover the +valid places to use patterns, the difference between refutable and irrefutable +patterns, and the different kinds of pattern syntax that you might see. By the +end of the chapter, you’ll know how to use patterns to express many concepts in +a clear way. -To demonstrate this, next we’ll create a raw pointer whose validity we can’t be -so certain of. Listing 19-2 shows how to create a raw pointer to an arbitrary -location in memory. Trying to use arbitrary memory is undefined: there might be -data at that address or there might not, the compiler might optimize the code -so there is no memory access, or the program might terminate with a -segmentation fault. Usually, there is no good reason to write code like this, -but it is possible. +## All the Places Patterns Can Be Used -``` -let address = 0x012345usize; -let r = address as *const i32; -``` +Patterns pop up in a number of places in Rust, and you’ve been using them a lot +without realizing it! This section discusses all the places where patterns are +valid. -Listing 19-2: Creating a raw pointer to an arbitrary memory address +### match Arms -Recall that we can create raw pointers in safe code, but we can’t *dereference* -raw pointers and read the data being pointed to. In Listing 19-3, we use the -dereference operator `*` on a raw pointer that requires an `unsafe` block. +As discussed in Chapter 6, we use patterns in the arms of `match` expressions. +Formally, `match` expressions are defined as the keyword `match`, a value to +match on, and one or more match arms that consist of a pattern and an +expression to run if the value matches that arm’s pattern, like this: ``` -let mut num = 5; - -let r1 = &num as *const i32; -let r2 = &mut num as *mut i32; - -unsafe { - println!("r1 is: {}", *r1); - println!("r2 is: {}", *r2); +match VALUE { + PATTERN => EXPRESSION, + PATTERN => EXPRESSION, + PATTERN => EXPRESSION, } ``` -Listing 19-3: Dereferencing raw pointers within an `unsafe` block - -Creating a pointer does no harm; it’s only when we try to access the value that -it points at that we might end up dealing with an invalid value. - -Note also that in Listings 19-1 and 19-3, we created `*const i32` and `*mut -i32` raw pointers that both pointed to the same memory location, where `num` is -stored. If we instead tried to create an immutable and a mutable reference to -`num`, the code would not have compiled because Rust’s ownership rules don’t -allow a mutable reference at the same time as any immutable references. With -raw pointers, we can create a mutable pointer and an immutable pointer to the -same location and change data through the mutable pointer, potentially creating -a data race. Be careful! - -With all of these dangers, why would you ever use raw pointers? One major use -case is when interfacing with C code, as you’ll see in “Calling an Unsafe -Function or Method” on page XX. Another case is when building up safe -abstractions that the borrow checker doesn’t understand. We’ll introduce unsafe -functions and then look at an example of a safe abstraction that uses unsafe -code. - -### Calling an Unsafe Function or Method - -The second type of operation you can perform in an unsafe block is calling -unsafe functions. Unsafe functions and methods look exactly like regular -functions and methods, but they have an extra `unsafe` before the rest of the -definition. The `unsafe` keyword in this context indicates the function has -requirements we need to uphold when we call this function, because Rust can’t -guarantee we’ve met these requirements. By calling an unsafe function within an -`unsafe` block, we’re saying that we’ve read this function’s documentation and -we take responsibility for upholding the function’s contracts. - -Here is an unsafe function named `dangerous` that doesn’t do anything in its -body: - -``` -unsafe fn dangerous() {} - -unsafe { - dangerous(); -} -``` - -We must call the `dangerous` function within a separate `unsafe` block. If we -try to call `dangerous` without the `unsafe` block, we’ll get an error: - -``` -error[E0133]: call to unsafe function is unsafe and requires -unsafe function or block - --> src/main.rs:4:5 - | -4 | dangerous(); - | ^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on -how to avoid undefined behavior -``` - -With the `unsafe` block, we’re asserting to Rust that we’ve read the function’s -documentation, we understand how to use it properly, and we’ve verified that -we’re fulfilling the contract of the function. - -Bodies of unsafe functions are effectively `unsafe` blocks, so to perform other -unsafe operations within an unsafe function, we don’t need to add another -`unsafe` block. - -#### Creating a Safe Abstraction over Unsafe Code - -Just because a function contains unsafe code doesn’t mean we need to mark the -entire function as unsafe. In fact, wrapping unsafe code in a safe function is -a common abstraction. As an example, let’s study the `split_at_mut` function -from the standard library, which requires some unsafe code. We’ll explore how -we might implement it. This safe method is defined on mutable slices: it takes -one slice and makes it two by splitting the slice at the index given as an -argument. Listing 19-4 shows how to use `split_at_mut`. - -``` -let mut v = vec![1, 2, 3, 4, 5, 6]; - -let r = &mut v[..]; - -let (a, b) = r.split_at_mut(3); +For example, here’s the `match` expression from Listing 6-5 that matches on an +`Option<i32>` value in the variable `x`: -assert_eq!(a, &mut [1, 2, 3]); -assert_eq!(b, &mut [4, 5, 6]); ``` - -Listing 19-4: Using the safe `split_at_mut` function - -We can’t implement this function using only safe Rust. An attempt might look -something like Listing 19-5, which won’t compile. For simplicity, we’ll -implement `split_at_mut` as a function rather than a method and only for slices -of `i32` values rather than for a generic type `T`. - -``` -fn split_at_mut( - values: &mut [i32], - mid: usize, -) -> (&mut [i32], &mut [i32]) { - let len = values.len(); - - assert!(mid <= len); - - (&mut values[..mid], &mut values[mid..]) +match x { + None => None, + Some(i) => Some(i + 1), } ``` -Listing 19-5: An attempted implementation of `split_at_mut` using only safe Rust - -This function first gets the total length of the slice. Then it asserts that -the index given as a parameter is within the slice by checking whether it’s -less than or equal to the length. The assertion means that if we pass an index -that is greater than the length to split the slice at, the function will panic -before it attempts to use that index. - -Then we return two mutable slices in a tuple: one from the start of the -original slice to the `mid` index and another from `mid` to the end of the -slice. - -When we try to compile the code in Listing 19-5, we’ll get an error: - -``` -error[E0499]: cannot borrow `*values` as mutable more than once at a time - --> src/main.rs:9:31 - | -2 | values: &mut [i32], - | - let's call the lifetime of this reference `'1` -... -9 | (&mut values[..mid], &mut values[mid..]) - | --------------------------^^^^^^-------- - | | | | - | | | second mutable borrow occurs here - | | first mutable borrow occurs here - | returning this value requires that `*values` is borrowed for `'1` -``` - -Rust’s borrow checker can’t understand that we’re borrowing different parts of -the slice; it only knows that we’re borrowing from the same slice twice. -Borrowing different parts of a slice is fundamentally okay because the two -slices aren’t overlapping, but Rust isn’t smart enough to know this. When we -know code is okay, but Rust doesn’t, it’s time to reach for unsafe code. - -Listing 19-6 shows how to use an `unsafe` block, a raw pointer, and some calls -to unsafe functions to make the implementation of `split_at_mut` work. - -``` -use std::slice; - -fn split_at_mut( - values: &mut [i32], - mid: usize, -) -> (&mut [i32], &mut [i32]) { - 1 let len = values.len(); - 2 let ptr = values.as_mut_ptr(); - - 3 assert!(mid <= len); - - 4 unsafe { - ( - 5 slice::from_raw_parts_mut(ptr, mid), - 6 slice::from_raw_parts_mut(ptr.add(mid), len - mid), - ) - } -} -``` +The patterns in this `match` expression are the `None` and `Some(i)` to the +left of each arrow. -Listing 19-6: Using unsafe code in the implementation of the `split_at_mut` -function - -Recall from “The Slice Type” on page XX that a slice is a pointer to some data -and the length of the slice. We use the `len` method to get the length of a -slice [1] and the `as_mut_ptr` method to access the raw pointer of a slice [2]. -In this case, because we have a mutable slice to `i32` values, `as_mut_ptr` -returns a raw pointer with the type `*mut i32`, which we’ve stored in the -variable `ptr`. - -We keep the assertion that the `mid` index is within the slice [3]. Then we get -to the unsafe code [4]: the `slice::from_raw_parts_mut` function takes a raw -pointer and a length, and it creates a slice. We use it to create a slice that -starts from `ptr` and is `mid` items long [5]. Then we call the `add` method on -`ptr` with `mid` as an argument to get a raw pointer that starts at `mid`, and -we create a slice using that pointer and the remaining number of items after -`mid` as the length [6]. - -The function `slice::from_raw_parts_mut` is unsafe because it takes a raw -pointer and must trust that this pointer is valid. The `add` method on raw -pointers is also unsafe because it must trust that the offset location is also -a valid pointer. Therefore, we had to put an `unsafe` block around our calls to -`slice::from_raw_parts_mut` and `add` so we could call them. By looking at the -code and by adding the assertion that `mid` must be less than or equal to -`len`, we can tell that all the raw pointers used within the `unsafe` block -will be valid pointers to data within the slice. This is an acceptable and -appropriate use of `unsafe`. - -Note that we don’t need to mark the resultant `split_at_mut` function as -`unsafe`, and we can call this function from safe Rust. We’ve created a safe -abstraction to the unsafe code with an implementation of the function that uses -`unsafe` code in a safe way, because it creates only valid pointers from the -data this function has access to. - -In contrast, the use of `slice::from_raw_parts_mut` in Listing 19-7 would -likely crash when the slice is used. This code takes an arbitrary memory -location and creates a slice 10,000 items long. - -``` -use std::slice; - -let address = 0x01234usize; -let r = address as *mut i32; - -let values: &[i32] = unsafe { - slice::from_raw_parts_mut(r, 10000) -}; -``` +One requirement for `match` expressions is that they need to be *exhaustive* in +the sense that all possibilities for the value in the `match` expression must +be accounted for. One way to ensure you’ve covered every possibility is to have +a catchall pattern for the last arm: for example, a variable name matching any +value can never fail and thus covers every remaining case. -Listing 19-7: Creating a slice from an arbitrary memory location +The particular pattern `_` will match anything, but it never binds to a +variable, so it’s often used in the last match arm. The `_` pattern can be +useful when you want to ignore any value not specified, for example. We’ll +cover the `_` pattern in more detail in “Ignoring Values in a Pattern” on page +XX. -We don’t own the memory at this arbitrary location, and there is no guarantee -that the slice this code creates contains valid `i32` values. Attempting to use -`values` as though it’s a valid slice results in undefined behavior. +### Conditional if let Expressions -#### Using extern Functions to Call External Code +In Chapter 6, we discussed how to use `if let` expressions mainly as a shorter +way to write the equivalent of a `match` that only matches one case. +Optionally, `if let` can have a corresponding `else` containing code to run if +the pattern in the `if let` doesn’t match. -Sometimes your Rust code might need to interact with code written in another -language. For this, Rust has the keyword `extern` that facilitates the creation -and use of a *Foreign Function Interface* *(FFI)*, which is a way for a -programming language to define functions and enable a different (foreign) -programming language to call those functions. +Listing 18-1 shows that it’s also possible to mix and match `if let`, `else +if`, and `else if let` expressions. Doing so gives us more flexibility than a +`match` expression in which we can express only one value to compare with the +patterns. Also, Rust doesn’t require that the conditions in a series of `if +let`, `else if`, and `else if let` arms relate to each other. -Listing 19-8 demonstrates how to set up an integration with the `abs` function -from the C standard library. Functions declared within `extern` blocks are -always unsafe to call from Rust code. The reason is that other languages don’t -enforce Rust’s rules and guarantees, and Rust can’t check them, so -responsibility falls on the programmer to ensure safety. +The code in Listing 18-1 determines what color to make your background based on +a series of checks for several conditions. For this example, we’ve created +variables with hardcoded values that a real program might receive from user +input. Filename: src/main.rs ``` -extern "C" { - fn abs(input: i32) -> i32; -} - fn main() { - unsafe { - println!( - "Absolute value of -3 according to C: {}", - abs(-3) + let favorite_color: Option<&str> = None; + let is_tuesday = false; + let age: Result<u8, _> = "34".parse(); + + 1 if let Some(color) = favorite_color { + 2 println!( + "Using your favorite, {color}, as the background" ); + 3 } else if is_tuesday { + 4 println!("Tuesday is green day!"); + 5 } else if let Ok(age) = age { + 6 if age > 30 { + 7 println!("Using purple as the background color"); + } else { + 8 println!("Using orange as the background color"); + } + 9 } else { + 10 println!("Using blue as the background color"); } } ``` -Listing 19-8: Declaring and calling an `extern` function defined in another -language - -Within the `extern "C"` block, we list the names and signatures of external -functions from another language we want to call. The `"C"` part defines which -*application binary interface* *(ABI)* the external function uses: the ABI -defines how to call the function at the assembly level. The `"C"` ABI is the -most common and follows the C programming language’s ABI. - -> ### Calling Rust Functions from Other Languages -> -> We can also use `extern` to create an interface that allows other languages -to call Rust functions. Instead of creating a whole `extern` block, we add the -`extern` keyword and specify the ABI to use just before the `fn` keyword for -the relevant function. We also need to add a `#[no_mangle]` annotation to tell -the Rust compiler not to mangle the name of this function. *Mangling* is when a -compiler changes the name we’ve given a function to a different name that -contains more information for other parts of the compilation process to consume -but is less human readable. Every programming language compiler mangles names -slightly differently, so for a Rust function to be nameable by other languages, -we must disable the Rust compiler’s name mangling. -> -> In the following example, we make the `call_from_c` function accessible from -C code, after it’s compiled to a shared library and linked from C: -> -> ``` -> #[no_mangle] -> pub extern "C" fn call_from_c() { -> println!("Just called a Rust function from C!"); -> } -> ``` -> -> This usage of `extern` does not require `unsafe`. - -### Accessing or Modifying a Mutable Static Variable - -In this book, we’ve not yet talked about global variables, which Rust does -support but can be problematic with Rust’s ownership rules. If two threads are -accessing the same mutable global variable, it can cause a data race. - -In Rust, global variables are called *static* variables. Listing 19-9 shows an -example declaration and use of a static variable with a string slice as a value. +Listing 18-1: Mixing `if let`, `else if`, `else if let`, and `else` -Filename: src/main.rs +If the user specifies a favorite color [1], that color is used as the +background [2]. If no favorite color is specified and today is Tuesday [3], the +background color is green [4]. Otherwise, if the user specifies their age as a +string and we can parse it as a number successfully [5], the color is either +purple [7] or orange [8] depending on the value of the number [6]. If none of +these conditions apply [9], the background color is blue [10]. -``` -static HELLO_WORLD: &str = "Hello, world!"; +This conditional structure lets us support complex requirements. With the +hardcoded values we have here, this example will print `Using purple as the +background color`. -fn main() { - println!("value is: {HELLO_WORLD}"); -} -``` +You can see that `if let` can also introduce shadowed variables in the same way +that `match` arms can: the line `if let Ok(age) = age` [5] introduces a new +shadowed `age` variable that contains the value inside the `Ok` variant. This +means we need to place the `if age > 30` condition [6] within that block: we +can’t combine these two conditions into `if let Ok(age) = age && age > 30`. The +shadowed `age` we want to compare to 30 isn’t valid until the new scope starts +with the curly bracket. -Listing 19-9: Defining and using an immutable static variable +The downside of using `if let` expressions is that the compiler doesn’t check +for exhaustiveness, whereas with `match` expressions it does. If we omitted the +last `else` block [9] and therefore missed handling some cases, the compiler +would not alert us to the possible logic bug. -Static variables are similar to constants, which we discussed in “Constants” on -page XX. The names of static variables are in `SCREAMING_SNAKE_CASE` by -convention. Static variables can only store references with the `'static` -lifetime, which means the Rust compiler can figure out the lifetime and we -aren’t required to annotate it explicitly. Accessing an immutable static -variable is safe. +### while let Conditional Loops -A subtle difference between constants and immutable static variables is that -values in a static variable have a fixed address in memory. Using the value -will always access the same data. Constants, on the other hand, are allowed to -duplicate their data whenever they’re used. Another difference is that static -variables can be mutable. Accessing and modifying mutable static variables is -*unsafe*. Listing 19-10 shows how to declare, access, and modify a mutable -static variable named `COUNTER`. +Similar in construction to `if let`, the `while let` conditional loop allows a +`while` loop to run for as long as a pattern continues to match. In Listing +18-2, we code a `while let` loop that uses a vector as a stack and prints the +values in the vector in the opposite order in which they were pushed. Filename: src/main.rs ``` -static mut COUNTER: u32 = 0; +let mut stack = Vec::new(); -fn add_to_count(inc: u32) { - unsafe { - COUNTER += inc; - } -} - -fn main() { - add_to_count(3); +stack.push(1); +stack.push(2); +stack.push(3); - unsafe { - println!("COUNTER: {COUNTER}"); - } +while let Some(top) = stack.pop() { + println!("{top}"); } ``` -Listing 19-10: Reading from or writing to a mutable static variable is unsafe. +Listing 18-2: Using a `while let` loop to print values for as long as +`stack.pop()` returns `Some` -As with regular variables, we specify mutability using the `mut` keyword. Any -code that reads or writes from `COUNTER` must be within an `unsafe` block. This -code compiles and prints `COUNTER: 3` as we would expect because it’s single -threaded. Having multiple threads access `COUNTER` would likely result in data -races. +This example prints `3`, `2`, and then `1`. The `pop` method takes the last +element out of the vector and returns `Some(value)`. If the vector is empty, +`pop` returns `None`. The `while` loop continues running the code in its block +as long as `pop` returns `Some`. When `pop` returns `None`, the loop stops. We +can use `while let` to pop every element off our stack. -With mutable data that is globally accessible, it’s difficult to ensure there -are no data races, which is why Rust considers mutable static variables to be -unsafe. Where possible, it’s preferable to use the concurrency techniques and -thread-safe smart pointers we discussed in Chapter 16 so the compiler checks -that data access from different threads is done safely. +### for Loops -### Implementing an Unsafe Trait +In a `for` loop, the value that directly follows the keyword `for` is a +pattern. For example, in `for x in y`, the `x` is the pattern. Listing 18-3 +demonstrates how to use a pattern in a `for` loop to *destructure*, or break +apart, a tuple as part of the `for` loop. -We can use `unsafe` to implement an unsafe trait. A trait is unsafe when at -least one of its methods has some invariant that the compiler can’t verify. We -declare that a trait is `unsafe` by adding the `unsafe` keyword before `trait` -and marking the implementation of the trait as `unsafe` too, as shown in -Listing 19-11. +Filename: src/main.rs ``` -unsafe trait Foo { - // methods go here -} +let v = vec!['a', 'b', 'c']; -unsafe impl Foo for i32 { - // method implementations go here +for (index, value) in v.iter().enumerate() { + println!("{value} is at index {index}"); } ``` -Listing 19-11: Defining and implementing an unsafe trait - -By using `unsafe impl`, we’re promising that we’ll uphold the invariants that -the compiler can’t verify. - -As an example, recall the `Send` and `Sync` marker traits we discussed in -“Extensible Concurrency with the Send and Sync Traits” on page XX: the compiler -implements these traits automatically if our types are composed entirely of -`Send` and `Sync` types. If we implement a type that contains a type that is -not `Send` or `Sync`, such as raw pointers, and we want to mark that type as -`Send` or `Sync`, we must use `unsafe`. Rust can’t verify that our type upholds -the guarantees that it can be safely sent across threads or accessed from -multiple threads; therefore, we need to do those checks manually and indicate -as such with `unsafe`. - -### Accessing Fields of a Union - -The final action that works only with `unsafe` is accessing fields of a union. -A `union` is similar to a `struct`, but only one declared field is used in a -particular instance at one time. Unions are primarily used to interface with -unions in C code. Accessing union fields is unsafe because Rust can’t guarantee -the type of the data currently being stored in the union instance. You can -learn more about unions in the Rust Reference at -*https://doc.rust-lang.org/reference/items/unions.html**.* +Listing 18-3: Using a pattern in a `for` loop to destructure a tuple -### When to Use Unsafe Code - -Using `unsafe` to use one of the five superpowers just discussed isn’t wrong or -even frowned upon, but it is trickier to get `unsafe` code correct because the -compiler can’t help uphold memory safety. When you have a reason to use -`unsafe` code, you can do so, and having the explicit `unsafe` annotation makes -it easier to track down the source of problems when they occur. - -## Advanced Traits - -We first covered traits in “Traits: Defining Shared Behavior” on page XX, but -we didn’t discuss the more advanced details. Now that you know more about Rust, -we can get into the nitty-gritty. - -### Associated Types - -*Associated types* connect a type placeholder with a trait such that the trait -method definitions can use these placeholder types in their signatures. The -implementor of a trait will specify the concrete type to be used instead of the -placeholder type for the particular implementation. That way, we can define a -trait that uses some types without needing to know exactly what those types are -until the trait is implemented. - -We’ve described most of the advanced features in this chapter as being rarely -needed. Associated types are somewhere in the middle: they’re used more rarely -than features explained in the rest of the book but more commonly than many of -the other features discussed in this chapter. - -One example of a trait with an associated type is the `Iterator` trait that the -standard library provides. The associated type is named `Item` and stands in -for the type of the values the type implementing the `Iterator` trait is -iterating over. The definition of the `Iterator` trait is as shown in Listing -19-12. +The code in Listing 18-3 will print the following: ``` -pub trait Iterator { - type Item; - - fn next(&mut self) -> Option<Self::Item>; -} +a is at index 0 +b is at index 1 +c is at index 2 ``` -Listing 19-12: The definition of the `Iterator` trait that has an associated -type `Item` +We adapt an iterator using the `enumerate` method so it produces a value and +the index for that value, placed into a tuple. The first value produced is the +tuple `(0, 'a')`. When this value is matched to the pattern `(index, value)`, +`index` will be `0` and `value` will be `'a'`, printing the first line of the +output. -The type `Item` is a placeholder, and the `next` method’s definition shows that -it will return values of type `Option<Self::Item>`. Implementors of the -`Iterator` trait will specify the concrete type for `Item`, and the `next` -method will return an `Option` containing a value of that concrete type. +### let Statements -Associated types might seem like a similar concept to generics, in that the -latter allow us to define a function without specifying what types it can -handle. To examine the difference between the two concepts, we’ll look at an -implementation of the `Iterator` trait on a type named `Counter` that specifies -the `Item` type is `u32`: - -Filename: src/lib.rs +Prior to this chapter, we had only explicitly discussed using patterns with +`match` and `if let`, but in fact, we’ve used patterns in other places as well, +including in `let` statements. For example, consider this straightforward +variable assignment with `let`: ``` -impl Iterator for Counter { - type Item = u32; - - fn next(&mut self) -> Option<Self::Item> { - --snip-- +let x = 5; ``` -This syntax seems comparable to that of generics. So why not just define the -`Iterator` trait with generics, as shown in Listing 19-13? +Every time you’ve used a `let` statement like this you’ve been using patterns, +although you might not have realized it! More formally, a `let` statement looks +like this: ``` -pub trait Iterator<T> { - fn next(&mut self) -> Option<T>; -} +let PATTERN = EXPRESSION; ``` -Listing 19-13: A hypothetical definition of the `Iterator` trait using generics - -The difference is that when using generics, as in Listing 19-13, we must -annotate the types in each implementation; because we can also implement -`Iterator<``String``> for Counter` or any other type, we could have multiple -implementations of `Iterator` for `Counter`. In other words, when a trait has a -generic parameter, it can be implemented for a type multiple times, changing -the concrete types of the generic type parameters each time. When we use the -`next` method on `Counter`, we would have to provide type annotations to -indicate which implementation of `Iterator` we want to use. - -With associated types, we don’t need to annotate types because we can’t -implement a trait on a type multiple times. In Listing 19-12 with the -definition that uses associated types, we can choose what the type of `Item` -will be only once because there can be only one `impl Iterator for Counter`. We -don’t have to specify that we want an iterator of `u32` values everywhere we -call `next` on `Counter`. - -Associated types also become part of the trait’s contract: implementors of the -trait must provide a type to stand in for the associated type placeholder. -Associated types often have a name that describes how the type will be used, -and documenting the associated type in the API documentation is a good practice. - -### Default Generic Type Parameters and Operator Overloading - -When we use generic type parameters, we can specify a default concrete type for -the generic type. This eliminates the need for implementors of the trait to -specify a concrete type if the default type works. You specify a default type -when declaring a generic type with the `<`PlaceholderType`=`ConcreteType`>` -syntax. - -A great example of a situation where this technique is useful is with *operator -overloading*, in which you customize the behavior of an operator (such as `+`) -in particular situations. - -Rust doesn’t allow you to create your own operators or overload arbitrary -operators. But you can overload the operations and corresponding traits listed -in `std::ops` by implementing the traits associated with the operator. For -example, in Listing 19-14 we overload the `+` operator to add two `Point` -instances together. We do this by implementing the `Add` trait on a `Point` -struct. +In statements like `let x = 5;` with a variable name in the PATTERN slot, the +variable name is just a particularly simple form of a pattern. Rust compares +the expression against the pattern and assigns any names it finds. So, in the +`let x = 5;` example, `x` is a pattern that means “bind what matches here to +the variable `x`.” Because the name `x` is the whole pattern, this pattern +effectively means “bind everything to the variable `x`, whatever the value is.” -Filename: src/main.rs +To see the pattern-matching aspect of `let` more clearly, consider Listing +18-4, which uses a pattern with `let` to destructure a tuple. ``` -use std::ops::Add; - -#[derive(Debug, Copy, Clone, PartialEq)] -struct Point { - x: i32, - y: i32, -} - -impl Add for Point { - type Output = Point; - - fn add(self, other: Point) -> Point { - Point { - x: self.x + other.x, - y: self.y + other.y, - } - } -} - -fn main() { - assert_eq!( - Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, - Point { x: 3, y: 3 } - ); -} +let (x, y, z) = (1, 2, 3); ``` -Listing 19-14: Implementing the `Add` trait to overload the `+` operator for -`Point` instances +Listing 18-4: Using a pattern to destructure a tuple and create three variables +at once -The `add` method adds the `x` values of two `Point` instances and the `y` -values of two `Point` instances to create a new `Point`. The `Add` trait has an -associated type named `Output` that determines the type returned from the `add` -method. +Here, we match a tuple against a pattern. Rust compares the value `(1, 2, 3)` +to the pattern `(x, y, z)` and sees that the value matches the pattern, in that +it sees that the number of elements is the same in both, so Rust binds `1` to +`x`, `2` to `y`, and `3` to `z`. You can think of this tuple pattern as nesting +three individual variable patterns inside it. -The default generic type in this code is within the `Add` trait. Here is its -definition: +If the number of elements in the pattern doesn’t match the number of elements +in the tuple, the overall type won’t match and we’ll get a compiler error. For +example, Listing 18-5 shows an attempt to destructure a tuple with three +elements into two variables, which won’t work. ``` -trait Add<Rhs=Self> { - type Output; - - fn add(self, rhs: Rhs) -> Self::Output; -} +let (x, y) = (1, 2, 3); ``` -This code should look generally familiar: a trait with one method and an -associated type. The new part is `Rhs=Self`: this syntax is called *default -type parameters*. The `Rhs` generic type parameter (short for “right-hand -side”) defines the type of the `rhs` parameter in the `add` method. If we don’t -specify a concrete type for `Rhs` when we implement the `Add` trait, the type -of `Rhs` will default to `Self`, which will be the type we’re implementing -`Add` on. +Listing 18-5: Incorrectly constructing a pattern whose variables don’t match +the number of elements in the tuple -When we implemented `Add` for `Point`, we used the default for `Rhs` because we -wanted to add two `Point` instances. Let’s look at an example of implementing -the `Add` trait where we want to customize the `Rhs` type rather than using the -default. - -We have two structs, `Millimeters` and `Meters`, holding values in different -units. This thin wrapping of an existing type in another struct is known as the -*newtype pattern*, which we describe in more detail in “Using the Newtype -Pattern to Implement External Traits on External Types” on page XX. We want to -add values in millimeters to values in meters and have the implementation of -`Add` do the conversion correctly. We can implement `Add` for `Millimeters` -with `Meters` as the `Rhs`, as shown in Listing 19-15. - -Filename: src/lib.rs +Attempting to compile this code results in this type error: ``` -use std::ops::Add; - -struct Millimeters(u32); -struct Meters(u32); - -impl Add<Meters> for Millimeters { - type Output = Millimeters; - - fn add(self, other: Meters) -> Millimeters { - Millimeters(self.0 + (other.0 * 1000)) - } -} +error[E0308]: mismatched types + --> src/main.rs:2:9 + | +2 | let (x, y) = (1, 2, 3); + | ^^^^^^ --------- this expression has type `({integer}, {integer}, +{integer})` + | | + | expected a tuple with 3 elements, found one with 2 elements + | + = note: expected tuple `({integer}, {integer}, {integer})` + found tuple `(_, _)` ``` -Listing 19-15: Implementing the `Add` trait on `Millimeters` to add -`Millimeters` and `Meters` - -To add `Millimeters` and `Meters`, we specify `impl Add<Meters>` to set the -value of the `Rhs` type parameter instead of using the default of `Self`. - -You’ll use default type parameters in two main ways: - -1. To extend a type without breaking existing code -1. To allow customization in specific cases most users won’t need +To fix the error, we could ignore one or more of the values in the tuple using +`_` or `..`, as you’ll see in “Ignoring Values in a Pattern” on page XX. If the +problem is that we have too many variables in the pattern, the solution is to +make the types match by removing variables so the number of variables equals +the number of elements in the tuple. -The standard library’s `Add` trait is an example of the second purpose: -usually, you’ll add two like types, but the `Add` trait provides the ability to -customize beyond that. Using a default type parameter in the `Add` trait -definition means you don’t have to specify the extra parameter most of the -time. In other words, a bit of implementation boilerplate isn’t needed, making -it easier to use the trait. +### Function Parameters -The first purpose is similar to the second but in reverse: if you want to add a -type parameter to an existing trait, you can give it a default to allow -extension of the functionality of the trait without breaking the existing -implementation code. - -### Disambiguating Between Methods with the Same Name - -Nothing in Rust prevents a trait from having a method with the same name as -another trait’s method, nor does Rust prevent you from implementing both traits -on one type. It’s also possible to implement a method directly on the type with -the same name as methods from traits. - -When calling methods with the same name, you’ll need to tell Rust which one you -want to use. Consider the code in Listing 19-16 where we’ve defined two traits, -`Pilot` and `Wizard`, that both have a method called `fly`. We then implement -both traits on a type `Human` that already has a method named `fly` implemented -on it. Each `fly` method does something different. - -Filename: src/main.rs +Function parameters can also be patterns. The code in Listing 18-6, which +declares a function named `foo` that takes one parameter named `x` of type +`i32`, should by now look familiar. ``` -trait Pilot { - fn fly(&self); -} - -trait Wizard { - fn fly(&self); -} - -struct Human; - -impl Pilot for Human { - fn fly(&self) { - println!("This is your captain speaking."); - } -} - -impl Wizard for Human { - fn fly(&self) { - println!("Up!"); - } -} - -impl Human { - fn fly(&self) { - println!("*waving arms furiously*"); - } +fn foo(x: i32) { + // code goes here } ``` -Listing 19-16: Two traits are defined to have a `fly` method and are -implemented on the `Human` type, and a `fly` method is implemented on `Human` -directly. +Listing 18-6: A function signature using patterns in the parameters -When we call `fly` on an instance of `Human`, the compiler defaults to calling -the method that is directly implemented on the type, as shown in Listing 19-17. +The `x` part is a pattern! As we did with `let`, we could match a tuple in a +function’s arguments to the pattern. Listing 18-7 splits the values in a tuple +as we pass it to a function. Filename: src/main.rs ``` -fn main() { - let person = Human; - person.fly(); +fn print_coordinates(&(x, y): &(i32, i32)) { + println!("Current location: ({x}, {y})"); } -``` - -Listing 19-17: Calling `fly` on an instance of `Human` -Running this code will print `*waving arms furiously*`, showing that Rust -called the `fly` method implemented on `Human` directly. - -To call the `fly` methods from either the `Pilot` trait or the `Wizard` trait, -we need to use more explicit syntax to specify which `fly` method we mean. -Listing 19-18 demonstrates this syntax. - -Filename: src/main.rs - -``` fn main() { - let person = Human; - Pilot::fly(&person); - Wizard::fly(&person); - person.fly(); + let point = (3, 5); + print_coordinates(&point); } ``` -Listing 19-18: Specifying which trait’s `fly` method we want to call +Listing 18-7: A function with parameters that destructure a tuple -Specifying the trait name before the method name clarifies to Rust which -implementation of `fly` we want to call. We could also write -`Human::fly(&person)`, which is equivalent to the `person.fly()` that we used -in Listing 19-18, but this is a bit longer to write if we don’t need to -disambiguate. +This code prints `Current location: (3, 5)`. The values `&(3, 5)` match the +pattern `&(x, y)`, so `x` is the value `3` and `y` is the value `5`. -Running this code prints the following: +We can also use patterns in closure parameter lists in the same way as in +function parameter lists because closures are similar to functions, as +discussed in Chapter 13. -``` -This is your captain speaking. -Up! -*waving arms furiously* -``` +At this point, you’ve seen several ways to use patterns, but patterns don’t +work the same in every place we can use them. In some places, the patterns must +be irrefutable; in other circumstances, they can be refutable. We’ll discuss +these two concepts next. -Because the `fly` method takes a `self` parameter, if we had two *types* that -both implement one *trait*, Rust could figure out which implementation of a -trait to use based on the type of `self`. +## Refutability: Whether a Pattern Might Fail to Match -However, associated functions that are not methods don’t have a `self` -parameter. When there are multiple types or traits that define non-method -functions with the same function name, Rust doesn’t always know which type you -mean unless you use fully qualified syntax. For example, in Listing 19-19 we -create a trait for an animal shelter that wants to name all baby dogs Spot. We -make an `Animal` trait with an associated non-method function `baby_name`. The -`Animal` trait is implemented for the struct `Dog`, on which we also provide an -associated non-method function `baby_name` directly. +Patterns come in two forms: refutable and irrefutable. Patterns that will match +for any possible value passed are *irrefutable*. An example would be `x` in the +statement `let x = 5;` because `x` matches anything and therefore cannot fail +to match. Patterns that can fail to match for some possible value are +*refutable*. An example would be `Some(x)` in the expression `if let Some(x) = +a_value` because if the value in the `a_value` variable is `None` rather than +`Some`, the `Some(x)` pattern will not match. -Filename: src/main.rs +Function parameters, `let` statements, and `for` loops can only accept +irrefutable patterns because the program cannot do anything meaningful when +values don’t match. The `if let` and `while let` expressions accept refutable +and irrefutable patterns, but the compiler warns against irrefutable patterns +because, by definition, they’re intended to handle possible failure: the +functionality of a conditional is in its ability to perform differently +depending on success or failure. -``` -trait Animal { - fn baby_name() -> String; -} - -struct Dog; - -impl Dog { - fn baby_name() -> String { - String::from("Spot") - } -} +In general, you shouldn’t have to worry about the distinction between refutable +and irrefutable patterns; however, you do need to be familiar with the concept +of refutability so you can respond when you see it in an error message. In +those cases, you’ll need to change either the pattern or the construct you’re +using the pattern with, depending on the intended behavior of the code. -impl Animal for Dog { - fn baby_name() -> String { - String::from("puppy") - } -} +Let’s look at an example of what happens when we try to use a refutable pattern +where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a +`let` statement, but for the pattern, we’ve specified `Some(x)`, a refutable +pattern. As you might expect, this code will not compile. -fn main() { - println!("A baby dog is called a {}", Dog::baby_name()); -} ``` - -Listing 19-19: A trait with an associated function and a type with an -associated function of the same name that also implements the trait - -We implement the code for naming all puppies Spot in the `baby_name` associated -function that is defined on `Dog`. The `Dog` type also implements the trait -`Animal`, which describes characteristics that all animals have. Baby dogs are -called puppies, and that is expressed in the implementation of the `Animal` -trait on `Dog` in the `baby_name` function associated with the `Animal` trait. - -In `main`, we call the `Dog::baby_name` function, which calls the associated -function defined on `Dog` directly. This code prints the following: - -``` -A baby dog is called a Spot +let Some(x) = some_option_value; ``` -This output isn’t what we wanted. We want to call the `baby_name` function that -is part of the `Animal` trait that we implemented on `Dog` so the code prints -`A baby dog is called a puppy`. The technique of specifying the trait name that -we used in Listing 19-18 doesn’t help here; if we change `main` to the code in -Listing 19-20, we’ll get a compilation error. +Listing 18-8: Attempting to use a refutable pattern with `let` -Filename: src/main.rs +If `some_option_value` were a `None` value, it would fail to match the pattern +`Some(x)`, meaning the pattern is refutable. However, the `let` statement can +only accept an irrefutable pattern because there is nothing valid the code can +do with a `None` value. At compile time, Rust will complain that we’ve tried to +use a refutable pattern where an irrefutable pattern is required: ``` -fn main() { - println!("A baby dog is called a {}", Animal::baby_name()); -} +error[E0005]: refutable pattern in local binding: `None` not covered + --> src/main.rs:3:9 + | +3 | let Some(x) = some_option_value; + | ^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or +an `enum` with only one variant + = note: for more information, visit +https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Option<i32>` +help: you might want to use `if let` to ignore the variant that isn't matched + | +3 | let x = if let Some(x) = some_option_value { x } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ ``` -Listing 19-20: Attempting to call the `baby_name` function from the `Animal` -trait, but Rust doesn’t know which implementation to use +Because we didn’t cover (and couldn’t cover!) every valid value with the +pattern `Some(x)`, Rust rightfully produces a compiler error. -Because `Animal::baby_name` doesn’t have a `self` parameter, and there could be -other types that implement the `Animal` trait, Rust can’t figure out which -implementation of `Animal::baby_name` we want. We’ll get this compiler error: +If we have a refutable pattern where an irrefutable pattern is needed, we can +fix it by changing the code that uses the pattern: instead of using `let`, we +can use `if let`. Then, if the pattern doesn’t match, the code will just skip +the code in the curly brackets, giving it a way to continue validly. Listing +18-9 shows how to fix the code in Listing 18-8. ``` -error[E0283]: type annotations needed - --> src/main.rs:20:43 - | -20 | println!("A baby dog is called a {}", Animal::baby_name()); - | ^^^^^^^^^^^^^^^^^ cannot infer -type - | - = note: cannot satisfy `_: Animal` -``` - -To disambiguate and tell Rust that we want to use the implementation of -`Animal` for `Dog` as opposed to the implementation of `Animal` for some other -type, we need to use fully qualified syntax. Listing 19-21 demonstrates how to -use fully qualified syntax. - -Filename: src/main.rs - -``` -fn main() { - println!( - "A baby dog is called a {}", - <Dog as Animal>::baby_name() - ); +if let Some(x) = some_option_value { + println!("{x}"); } ``` -Listing 19-21: Using fully qualified syntax to specify that we want to call the -`baby_name` function from the `Animal` trait as implemented on `Dog` +Listing 18-9: Using `if let` and a block with refutable patterns instead of +`let` -We’re providing Rust with a type annotation within the angle brackets, which -indicates we want to call the `baby_name` method from the `Animal` trait as -implemented on `Dog` by saying that we want to treat the `Dog` type as an -`Animal` for this function call. This code will now print what we want: +We’ve given the code an out! This code is perfectly valid, although it means we +cannot use an irrefutable pattern without receiving an error. If we give `if +let` a pattern that will always match, such as `x`, as shown in Listing 18-10, +the compiler will give a warning. ``` -A baby dog is called a puppy +if let x = 5 { + println!("{x}"); +}; ``` -In general, fully qualified syntax is defined as follows: +Listing 18-10: Attempting to use an irrefutable pattern with `if let` + +Rust complains that it doesn’t make sense to use `if let` with an irrefutable +pattern: ``` -<Type as Trait>::function(receiver_if_method, next_arg, ...); +warning: irrefutable `if let` pattern + --> src/main.rs:2:8 + | +2 | if let x = 5 { + | ^^^^^^^^^ + | + = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this pattern will always match, so the `if let` is +useless + = help: consider replacing the `if let` with a `let` ``` -For associated functions that aren’t methods, there would not be a `receiver`: -there would only be the list of other arguments. You could use fully qualified -syntax everywhere that you call functions or methods. However, you’re allowed -to omit any part of this syntax that Rust can figure out from other information -in the program. You only need to use this more verbose syntax in cases where -there are multiple implementations that use the same name and Rust needs help -to identify which implementation you want to call. +For this reason, match arms must use refutable patterns, except for the last +arm, which should match any remaining values with an irrefutable pattern. Rust +allows us to use an irrefutable pattern in a `match` with only one arm, but +this syntax isn’t particularly useful and could be replaced with a simpler +`let` statement. -### Using Supertraits +Now that you know where to use patterns and the difference between refutable +and irrefutable patterns, let’s cover all the syntax we can use to create +patterns. -Sometimes you might write a trait definition that depends on another trait: for -a type to implement the first trait, you want to require that type to also -implement the second trait. You would do this so that your trait definition can -make use of the associated items of the second trait. The trait your trait -definition is relying on is called a *supertrait* of your trait. +## Pattern Syntax -For example, let’s say we want to make an `OutlinePrint` trait with an -`outline_print` method that will print a given value formatted so that it’s -framed in asterisks. That is, given a `Point` struct that implements the -standard library trait `Display` to result in `(x, y)`, when we call -`outline_print` on a `Point` instance that has `1` for `x` and `3` for `y`, it -should print the following: +In this section, we gather all the syntax that is valid in patterns and discuss +why and when you might want to use each one. -``` -********** -* * -* (1, 3) * -* * -********** -``` +### Matching Literals -In the implementation of the `outline_print` method, we want to use the -`Display` trait’s functionality. Therefore, we need to specify that the -`OutlinePrint` trait will work only for types that also implement `Display` and -provide the functionality that `OutlinePrint` needs. We can do that in the -trait definition by specifying `OutlinePrint: Display`. This technique is -similar to adding a trait bound to the trait. Listing 19-22 shows an -implementation of the `OutlinePrint` trait. +As you saw in Chapter 6, you can match patterns against literals directly. The +following code gives some examples: Filename: src/main.rs ``` -use std::fmt; +let x = 1; -trait OutlinePrint: fmt::Display { - fn outline_print(&self) { - let output = self.to_string(); - let len = output.len(); - println!("{}", "*".repeat(len + 4)); - println!("*{}*", " ".repeat(len + 2)); - println!("* {} *", output); - println!("*{}*", " ".repeat(len + 2)); - println!("{}", "*".repeat(len + 4)); - } +match x { + 1 => println!("one"), + 2 => println!("two"), + 3 => println!("three"), + _ => println!("anything"), } ``` -Listing 19-22: Implementing the `OutlinePrint` trait that requires the -functionality from `Display` +This code prints `one` because the value in `x` is `1`. This syntax is useful +when you want your code to take an action if it gets a particular concrete +value. -Because we’ve specified that `OutlinePrint` requires the `Display` trait, we -can use the `to_string` function that is automatically implemented for any type -that implements `Display`. If we tried to use `to_string` without adding a -colon and specifying the `Display` trait after the trait name, we’d get an -error saying that no method named `to_string` was found for the type `&Self` in -the current scope. +### Matching Named Variables -Let’s see what happens when we try to implement `OutlinePrint` on a type that -doesn’t implement `Display`, such as the `Point` struct: +Named variables are irrefutable patterns that match any value, and we’ve used +them many times in this book. However, there is a complication when you use +named variables in `match` expressions. Because `match` starts a new scope, +variables declared as part of a pattern inside the `match` expression will +shadow those with the same name outside the `match` construct, as is the case +with all variables. In Listing 18-11, we declare a variable named `x` with the +value `Some(5)` and a variable `y` with the value `10`. We then create a +`match` expression on the value `x`. Look at the patterns in the match arms and +`println!` at the end, and try to figure out what the code will print before +running this code or reading further. Filename: src/main.rs ``` -struct Point { - x: i32, - y: i32, -} - -impl OutlinePrint for Point {} -``` +fn main() { + 1 let x = Some(5); + 2 let y = 10; -We get an error saying that `Display` is required but not implemented: + match x { + 3 Some(50) => println!("Got 50"), + 4 Some(y) => println!("Matched, y = {y}"), + 5 _ => println!("Default case, x = {:?}", x), + } -``` -error[E0277]: `Point` doesn't implement `std::fmt::Display` - --> src/main.rs:20:6 - | -20 | impl OutlinePrint for Point {} - | ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter - | - = help: the trait `std::fmt::Display` is not implemented for `Point` - = note: in format strings you may be able to use `{:?}` (or {:#?} for -pretty-print) instead -note: required by a bound in `OutlinePrint` - --> src/main.rs:3:21 - | -3 | trait OutlinePrint: fmt::Display { - | ^^^^^^^^^^^^ required by this bound in `OutlinePrint` + 6 println!("at the end: x = {:?}, y = {y}", x); +} ``` -To fix this, we implement `Display` on `Point` and satisfy the constraint that -`OutlinePrint` requires, like so: +Listing 18-11: A `match` expression with an arm that introduces a shadowed +variable `y` -Filename: src/main.rs +Let’s walk through what happens when the `match` expression runs. The pattern +in the first match arm [3] doesn’t match the defined value of `x` [1], so the +code continues. -``` -use std::fmt; +The pattern in the second match arm [4] introduces a new variable named `y` +that will match any value inside a `Some` value. Because we’re in a new scope +inside the `match` expression, this is a new `y` variable, not the `y` we +declared at the beginning with the value `10` [2]. This new `y` binding will +match any value inside a `Some`, which is what we have in `x`. Therefore, this +new `y` binds to the inner value of the `Some` in `x`. That value is `5`, so +the expression for that arm executes and prints `Matched, y = 5`. -impl fmt::Display for Point { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({}, {})", self.x, self.y) - } -} -``` +If `x` had been a `None` value instead of `Some(5)`, the patterns in the first +two arms wouldn’t have matched, so the value would have matched to the +underscore [5]. We didn’t introduce the `x` variable in the pattern of the +underscore arm, so the `x` in the expression is still the outer `x` that hasn’t +been shadowed. In this hypothetical case, the `match` would print `Default +case, x = None`. -Then, implementing the `OutlinePrint` trait on `Point` will compile -successfully, and we can call `outline_print` on a `Point` instance to display -it within an outline of asterisks. +When the `match` expression is done, its scope ends, and so does the scope of +the inner `y`. The last `println!` [6] produces `at the end: x = Some(5), y = +10`. -### Using the Newtype Pattern to Implement External Traits +To create a `match` expression that compares the values of the outer `x` and +`y`, rather than introducing a shadowed variable, we would need to use a match +guard conditional instead. We’ll talk about match guards in “Extra Conditionals +with Match Guards” on page XX. -In “Implementing a Trait on a Type” on page XX, we mentioned the orphan rule -that states we’re only allowed to implement a trait on a type if either the -trait or the type, or both, are local to our crate. It’s possible to get around -this restriction using the *newtype pattern*, which involves creating a new -type in a tuple struct. (We covered tuple structs in “Using Tuple Structs -Without Named Fields to Create Different Types” on page XX.) The tuple struct -will have one field and be a thin wrapper around the type for which we want to -implement a trait. Then the wrapper type is local to our crate, and we can -implement the trait on the wrapper. *Newtype* is a term that originates from -the Haskell programming language. There is no runtime performance penalty for -using this pattern, and the wrapper type is elided at compile time. +### Multiple Patterns -As an example, let’s say we want to implement `Display` on `Vec<T>`, which the -orphan rule prevents us from doing directly because the `Display` trait and the -`Vec<T>` type are defined outside our crate. We can make a `Wrapper` struct -that holds an instance of `Vec<T>`; then we can implement `Display` on -`Wrapper` and use the `Vec<T>` value, as shown in Listing 19-23. +In `match` expressions, you can match multiple patterns using the `|` syntax, +which is the pattern *or* operator. For example, in the following code we match +the value of `x` against the match arms, the first of which has an *or* option, +meaning if the value of `x` matches either of the values in that arm, that +arm’s code will run: Filename: src/main.rs ``` -use std::fmt; - -struct Wrapper(Vec<String>); - -impl fmt::Display for Wrapper { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{}]", self.0.join(", ")) - } -} +let x = 1; -fn main() { - let w = Wrapper(vec![ - String::from("hello"), - String::from("world"), - ]); - println!("w = {w}"); +match x { + 1 | 2 => println!("one or two"), + 3 => println!("three"), + _ => println!("anything"), } ``` -Listing 19-23: Creating a `Wrapper` type around `Vec<String>` to implement -`Display` - -The implementation of `Display` uses `self.0` to access the inner `Vec<T>` -because `Wrapper` is a tuple struct and `Vec<T>` is the item at index 0 in the -tuple. Then we can use the functionality of the `Display` type on `Wrapper`. - -The downside of using this technique is that `Wrapper` is a new type, so it -doesn’t have the methods of the value it’s holding. We would have to implement -all the methods of `Vec<T>` directly on `Wrapper` such that the methods -delegate to `self.0`, which would allow us to treat `Wrapper` exactly like a -`Vec<T>`. If we wanted the new type to have every method the inner type has, -implementing the `Deref` trait on the `Wrapper` to return the inner type would -be a solution (we discussed implementing the `Deref` trait in “Treating Smart -Pointers Like Regular References with Deref” on page XX). If we didn’t want the -`Wrapper` type to have all the methods of the inner type—for example, to -restrict the `Wrapper` type’s behavior—we would have to implement just the -methods we do want manually. - -This newtype pattern is also useful even when traits are not involved. Let’s -switch focus and look at some advanced ways to interact with Rust’s type system. - -## Advanced Types - -The Rust type system has some features that we’ve so far mentioned but haven’t -yet discussed. We’ll start by discussing newtypes in general as we examine why -newtypes are useful as types. Then we’ll move on to type aliases, a feature -similar to newtypes but with slightly different semantics. We’ll also discuss -the `!` type and dynamically sized types. +This code prints `one or two`. -### Using the Newtype Pattern for Type Safety and Abstraction +### Matching Ranges of Values with ..= -> Note: This section assumes you’ve read the earlier section “Using the Newtype -Pattern to Implement External Traits” on page XX. +The `..=` syntax allows us to match to an inclusive range of values. In the +following code, when a pattern matches any of the values within the given +range, that arm will execute: -The newtype pattern is also useful for tasks beyond those we’ve discussed so -far, including statically enforcing that values are never confused and -indicating the units of a value. You saw an example of using newtypes to -indicate units in Listing 19-15: recall that the `Millimeters` and `Meters` -structs wrapped `u32` values in a newtype. If we wrote a function with a -parameter of type `Millimeters`, we wouldn’t be able to compile a program that -accidentally tried to call that function with a value of type `Meters` or a -plain `u32`. - -We can also use the newtype pattern to abstract away some implementation -details of a type: the new type can expose a public API that is different from -the API of the private inner type. - -Newtypes can also hide internal implementation. For example, we could provide a -`People` type to wrap a `HashMap<i32, String>` that stores a person’s ID -associated with their name. Code using `People` would only interact with the -public API we provide, such as a method to add a name string to the `People` -collection; that code wouldn’t need to know that we assign an `i32` ID to names -internally. The newtype pattern is a lightweight way to achieve encapsulation -to hide implementation details, which we discussed in “Encapsulation That Hides -Implementation Details” on page XX. - -### Creating Type Synonyms with Type Aliases - -Rust provides the ability to declare a *type alias* to give an existing type -another name. For this we use the `type` keyword. For example, we can create -the alias `Kilometers` to `i32` like so: - -``` -type Kilometers = i32; -``` - -Now the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters` -and `Meters` types we created in Listing 19-15, `Kilometers` is not a separate, -new type. Values that have the type `Kilometers` will be treated the same as -values of type `i32`: +Filename: src/main.rs ``` -type Kilometers = i32; +let x = 5; -let x: i32 = 5; -let y: Kilometers = 5; - -println!("x + y = {}", x + y); +match x { + 1..=5 => println!("one through five"), + _ => println!("something else"), +} ``` -Because `Kilometers` and `i32` are the same type, we can add values of both -types and we can pass `Kilometers` values to functions that take `i32` -parameters. However, using this method, we don’t get the type-checking benefits -that we get from the newtype pattern discussed earlier. In other words, if we -mix up `Kilometers` and `i32` values somewhere, the compiler will not give us -an error. +If `x` is `1`, `2`, `3`, `4`, or `5`, the first arm will match. This syntax is +more convenient for multiple match values than using the `|` operator to +express the same idea; if we were to use `|`, we would have to specify `1 | 2 | +3 | 4 | 5`. Specifying a range is much shorter, especially if we want to match, +say, any number between 1 and 1,000! -The main use case for type synonyms is to reduce repetition. For example, we -might have a lengthy type like this: +The compiler checks that the range isn’t empty at compile time, and because the +only types for which Rust can tell if a range is empty or not are `char` and +numeric values, ranges are only allowed with numeric or `char` values. -``` -Box<dyn Fn() + Send + 'static> -``` +Here is an example using ranges of `char` values: -Writing this lengthy type in function signatures and as type annotations all -over the code can be tiresome and error prone. Imagine having a project full of -code like that in Listing 19-24. +Filename: src/main.rs ``` -let f: Box<dyn Fn() + Send + 'static> = Box::new(|| { - println!("hi"); -}); +let x = 'c'; -fn takes_long_type(f: Box<dyn Fn() + Send + 'static>) { - --snip-- +match x { + 'a'..='j' => println!("early ASCII letter"), + 'k'..='z' => println!("late ASCII letter"), + _ => println!("something else"), } - -fn returns_long_type() -> Box<dyn Fn() + Send + 'static> { - --snip-- -} -``` - -Listing 19-24: Using a long type in many places - -A type alias makes this code more manageable by reducing the repetition. In -Listing 19-25, we’ve introduced an alias named `Thunk` for the verbose type and -can replace all uses of the type with the shorter alias `Thunk`. - ``` -type Thunk = Box<dyn Fn() + Send + 'static>; -let f: Thunk = Box::new(|| println!("hi")); +Rust can tell that `'c'` is within the first pattern’s range and prints `early +ASCII letter`. -fn takes_long_type(f: Thunk) { - --snip-- -} +### Destructuring to Break Apart Values -fn returns_long_type() -> Thunk { - --snip-- -} -``` +We can also use patterns to destructure structs, enums, and tuples to use +different parts of these values. Let’s walk through each value. -Listing 19-25: Introducing a type alias `Thunk` to reduce repetition +#### Destructuring Structs -This code is much easier to read and write! Choosing a meaningful name for a -type alias can help communicate your intent as well (*thunk* is a word for code -to be evaluated at a later time, so it’s an appropriate name for a closure that -gets stored). +Listing 18-12 shows a `Point` struct with two fields, `x` and `y`, that we can +break apart using a pattern with a `let` statement. -Type aliases are also commonly used with the `Result<T, E>` type for reducing -repetition. Consider the `std::io` module in the standard library. I/O -operations often return a `Result<T, E>` to handle situations when operations -fail to work. This library has a `std::io::Error` struct that represents all -possible I/O errors. Many of the functions in `std::io` will be returning -`Result<T, E>` where the `E` is `std::io::Error`, such as these functions in -the `Write` trait: +Filename: src/main.rs ``` -use std::fmt; -use std::io::Error; +struct Point { + x: i32, + y: i32, +} -pub trait Write { - fn write(&mut self, buf: &[u8]) -> Result<usize, Error>; - fn flush(&mut self) -> Result<(), Error>; +fn main() { + let p = Point { x: 0, y: 7 }; - fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>; - fn write_fmt( - &mut self, - fmt: fmt::Arguments, - ) -> Result<(), Error>; + let Point { x: a, y: b } = p; + assert_eq!(0, a); + assert_eq!(7, b); } ``` -The `Result<..., Error>` is repeated a lot. As such, `std::io` has this type -alias declaration: +Listing 18-12: Destructuring a struct’s fields into separate variables -``` -type Result<T> = std::result::Result<T, std::io::Error>; -``` +This code creates the variables `a` and `b` that match the values of the `x` +and `y` fields of the `p` struct. This example shows that the names of the +variables in the pattern don’t have to match the field names of the struct. +However, it’s common to match the variable names to the field names to make it +easier to remember which variables came from which fields. Because of this +common usage, and because writing `let Point { x: x, y: y } = p;` contains a +lot of duplication, Rust has a shorthand for patterns that match struct fields: +you only need to list the name of the struct field, and the variables created +from the pattern will have the same names. Listing 18-13 behaves in the same +way as the code in Listing 18-12, but the variables created in the `let` +pattern are `x` and `y` instead of `a` and `b`. -Because this declaration is in the `std::io` module, we can use the fully -qualified alias `std::io::Result<T>`; that is, a `Result<T, E>` with the `E` -filled in as `std::io::Error`. The `Write` trait function signatures end up -looking like this: +Filename: src/main.rs ``` -pub trait Write { - fn write(&mut self, buf: &[u8]) -> Result<usize>; - fn flush(&mut self) -> Result<()>; - - fn write_all(&mut self, buf: &[u8]) -> Result<()>; - fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()>; +struct Point { + x: i32, + y: i32, } -``` -The type alias helps in two ways: it makes code easier to write *and* it gives -us a consistent interface across all of `std::io`. Because it’s an alias, it’s -just another `Result<T, E>`, which means we can use any methods that work on -`Result<T, E>` with it, as well as special syntax like the `?` operator. - -### The Never Type That Never Returns - -Rust has a special type named `!` that’s known in type theory lingo as the -*empty type* because it has no values. We prefer to call it the *never type* -because it stands in the place of the return type when a function will never -return. Here is an example: +fn main() { + let p = Point { x: 0, y: 7 }; -``` -fn bar() -> ! { - --snip-- + let Point { x, y } = p; + assert_eq!(0, x); + assert_eq!(7, y); } ``` -This code is read as “the function `bar` returns never.” Functions that return -never are called *diverging functions*. We can’t create values of the type `!`, -so `bar` can never possibly return. +Listing 18-13: Destructuring struct fields using struct field shorthand -But what use is a type you can never create values for? Recall the code from -Listing 2-5, part of the number-guessing game; we’ve reproduced a bit of it -here in Listing 19-26. +This code creates the variables `x` and `y` that match the `x` and `y` fields +of the `p` variable. The outcome is that the variables `x` and `y` contain the +values from the `p` struct. -``` -let guess: u32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, -}; -``` +We can also destructure with literal values as part of the struct pattern +rather than creating variables for all the fields. Doing so allows us to test +some of the fields for particular values while creating variables to +destructure the other fields. -Listing 19-26: A `match` with an arm that ends in `continue` +In Listing 18-14, we have a `match` expression that separates `Point` values +into three cases: points that lie directly on the `x` axis (which is true when +`y = 0`), on the `y` axis (`x = 0`), or on neither axis. -At the time, we skipped over some details in this code. In “The match Control -Flow Construct” on page XX, we discussed that `match` arms must all return the -same type. So, for example, the following code doesn’t work: +Filename: src/main.rs ``` -let guess = match guess.trim().parse() { - Ok(_) => 5, - Err(_) => "hello", -}; -``` - -The type of `guess` in this code would have to be an integer *and* a string, -and Rust requires that `guess` have only one type. So what does `continue` -return? How were we allowed to return a `u32` from one arm and have another arm -that ends with `continue` in Listing 19-26? - -As you might have guessed, `continue` has a `!` value. That is, when Rust -computes the type of `guess`, it looks at both match arms, the former with a -value of `u32` and the latter with a `!` value. Because `!` can never have a -value, Rust decides that the type of `guess` is `u32`. - -The formal way of describing this behavior is that expressions of type `!` can -be coerced into any other type. We’re allowed to end this `match` arm with -`continue` because `continue` doesn’t return a value; instead, it moves control -back to the top of the loop, so in the `Err` case, we never assign a value to -`guess`. - -The never type is useful with the `panic!` macro as well. Recall the `unwrap` -function that we call on `Option<T>` values to produce a value or panic with -this definition: +fn main() { + let p = Point { x: 0, y: 7 }; -``` -impl<T> Option<T> { - pub fn unwrap(self) -> T { - match self { - Some(val) => val, - None => panic!( - "called `Option::unwrap()` on a `None` value" - ), + match p { + Point { x, y: 0 } => println!("On the x axis at {x}"), + Point { x: 0, y } => println!("On the y axis at {y}"), + Point { x, y } => { + println!("On neither axis: ({x}, {y})"); } } } ``` -In this code, the same thing happens as in the `match` in Listing 19-26: Rust -sees that `val` has the type `T` and `panic!` has the type `!`, so the result -of the overall `match` expression is `T`. This code works because `panic!` -doesn’t produce a value; it ends the program. In the `None` case, we won’t be -returning a value from `unwrap`, so this code is valid. +Listing 18-14: Destructuring and matching literal values in one pattern -One final expression that has the type `!` is a `loop`: +The first arm will match any point that lies on the `x` axis by specifying that +the `y` field matches if its value matches the literal `0`. The pattern still +creates an `x` variable that we can use in the code for this arm. -``` -print!("forever "); +Similarly, the second arm matches any point on the `y` axis by specifying that +the `x` field matches if its value is `0` and creates a variable `y` for the +value of the `y` field. The third arm doesn’t specify any literals, so it +matches any other `Point` and creates variables for both the `x` and `y` fields. -loop { - print!("and ever "); -} -``` +In this example, the value `p` matches the second arm by virtue of `x` +containing a `0`, so this code will print `On the y axis at 7`. -Here, the loop never ends, so `!` is the value of the expression. However, this -wouldn’t be true if we included a `break`, because the loop would terminate -when it got to the `break`. - -### Dynamically Sized Types and the Sized Trait - -Rust needs to know certain details about its types, such as how much space to -allocate for a value of a particular type. This leaves one corner of its type -system a little confusing at first: the concept of *dynamically sized types*. -Sometimes referred to as *DSTs* or *unsized types*, these types let us write -code using values whose size we can know only at runtime. - -Let’s dig into the details of a dynamically sized type called `str`, which -we’ve been using throughout the book. That’s right, not `&str`, but `str` on -its own, is a DST. We can’t know how long the string is until runtime, meaning -we can’t create a variable of type `str`, nor can we take an argument of type -`str`. Consider the following code, which does not work: - -``` -let s1: str = "Hello there!"; -let s2: str = "How's it going?"; -``` - -Rust needs to know how much memory to allocate for any value of a particular -type, and all values of a type must use the same amount of memory. If Rust -allowed us to write this code, these two `str` values would need to take up the -same amount of space. But they have different lengths: `s1` needs 12 bytes of -storage and `s2` needs 15. This is why it’s not possible to create a variable -holding a dynamically sized type. - -So what do we do? In this case, you already know the answer: we make the types -of `s1` and `s2` a `&str` rather than a `str`. Recall from “String Slices” on -page XX that the slice data structure just stores the starting position and the -length of the slice. So, although a `&T` is a single value that stores the -memory address of where the `T` is located, a `&str` is *two* values: the -address of the `str` and its length. As such, we can know the size of a `&str` -value at compile time: it’s twice the length of a `usize`. That is, we always -know the size of a `&str`, no matter how long the string it refers to is. In -general, this is the way in which dynamically sized types are used in Rust: -they have an extra bit of metadata that stores the size of the dynamic -information. The golden rule of dynamically sized types is that we must always -put values of dynamically sized types behind a pointer of some kind. - -We can combine `str` with all kinds of pointers: for example, `Box<str>` or -`Rc<str>`. In fact, you’ve seen this before but with a different dynamically -sized type: traits. Every trait is a dynamically sized type we can refer to by -using the name of the trait. In “Using Trait Objects That Allow for Values of -Different Types” on page XX, we mentioned that to use traits as trait objects, -we must put them behind a pointer, such as `&dyn Trait` or `Box<dyn Trait>` -(`Rc<dyn Trait>` would work too). - -To work with DSTs, Rust provides the `Sized` trait to determine whether or not -a type’s size is known at compile time. This trait is automatically implemented -for everything whose size is known at compile time. In addition, Rust -implicitly adds a bound on `Sized` to every generic function. That is, a -generic function definition like this: - -``` -fn generic<T>(t: T) { - --snip-- -} -``` +Remember that a `match` expression stops checking arms once it has found the +first matching pattern, so even though `Point { x: 0, y: 0}` is on the `x` axis +and the `y` axis, this code would only print `On the x axis at 0`. + +#### Destructuring Enums + +We’ve destructured enums in this book (for example, Listing 6-5), but we +haven’t yet explicitly discussed that the pattern to destructure an enum +corresponds to the way the data stored within the enum is defined. As an +example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write +a `match` with patterns that will destructure each inner value. -is actually treated as though we had written this: +Filename: src/main.rs ``` -fn generic<T: Sized>(t: T) { - --snip-- +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(i32, i32, i32), } -``` -By default, generic functions will work only on types that have a known size at -compile time. However, you can use the following special syntax to relax this -restriction: +fn main() { + 1 let msg = Message::ChangeColor(0, 160, 255); -``` -fn generic<T: ?Sized>(t: &T) { - --snip-- + match msg { + 2 Message::Quit => { + println!( + "The Quit variant has no data to destructure." + ); + } + 3 Message::Move { x, y } => { + println!( + "Move in the x dir {x}, in the y dir {y}" + ); + } + 4 Message::Write(text) => { + println!("Text message: {text}"); + } + 5 Message::ChangeColor(r, g, b) => println!( + "Change color to red {r}, green {g}, and blue {b}" + ), + } } ``` -A trait bound on `?Sized` means “`T` may or may not be `Sized`” and this -notation overrides the default that generic types must have a known size at -compile time. The `?Trait` syntax with this meaning is only available for -`Sized`, not any other traits. - -Also note that we switched the type of the `t` parameter from `T` to `&T`. -Because the type might not be `Sized`, we need to use it behind some kind of -pointer. In this case, we’ve chosen a reference. +Listing 18-15: Destructuring enum variants that hold different kinds of values -Next, we’ll talk about functions and closures! +This code will print `Change color to red 0, green 160, and blue 255`. Try +changing the value of `msg` [1] to see the code from the other arms run. -## Advanced Functions and Closures +For enum variants without any data, like `Message::Quit` [2], we can’t +destructure the value any further. We can only match on the literal +`Message::Quit` value, and no variables are in that pattern. -This section explores some advanced features related to functions and closures, -including function pointers and returning closures. +For struct-like enum variants, such as `Message::Move` [3], we can use a +pattern similar to the pattern we specify to match structs. After the variant +name, we place curly brackets and then list the fields with variables so we +break apart the pieces to use in the code for this arm. Here we use the +shorthand form as we did in Listing 18-13. -### Function Pointers +For tuple-like enum variants, like `Message::Write` that holds a tuple with one +element [4] and `Message::ChangeColor` that holds a tuple with three elements +[5], the pattern is similar to the pattern we specify to match tuples. The +number of variables in the pattern must match the number of elements in the +variant we’re matching. -We’ve talked about how to pass closures to functions; you can also pass regular -functions to functions! This technique is useful when you want to pass a -function you’ve already defined rather than defining a new closure. Functions -coerce to the type `fn` (with a lowercase *f*), not to be confused with the -`Fn` closure trait. The `fn` type is called a *function pointer*. Passing -functions with function pointers will allow you to use functions as arguments -to other functions. +#### Destructuring Nested Structs and Enums -The syntax for specifying that a parameter is a function pointer is similar to -that of closures, as shown in Listing 19-27, where we’ve defined a function -`add_one` that adds 1 to its parameter. The function `do_twice` takes two -parameters: a function pointer to any function that takes an `i32` parameter -and returns an `i32`, and one `i32 value`. The `do_twice` function calls the -function `f` twice, passing it the `arg` value, then adds the two function call -results together. The `main` function calls `do_twice` with the arguments -`add_one` and `5`. +So far, our examples have all been matching structs or enums one level deep, +but matching can work on nested items too! For example, we can refactor the +code in Listing 18-15 to support RGB and HSV colors in the `ChangeColor` +message, as shown in Listing 18-16. Filename: src/main.rs ``` -fn add_one(x: i32) -> i32 { - x + 1 +enum Color { + Rgb(i32, i32, i32), + Hsv(i32, i32, i32), } -fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { - f(arg) + f(arg) +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(Color), } fn main() { - let answer = do_twice(add_one, 5); - - println!("The answer is: {answer}"); + let msg = Message::ChangeColor(Color::Hsv(0, 160, 255)); + + match msg { + Message::ChangeColor(Color::Rgb(r, g, b)) => println!( + "Change color to red {r}, green {g}, and blue {b}" + ), + Message::ChangeColor(Color::Hsv(h, s, v)) => println!( + "Change color to hue {h}, saturation {s}, value {v}" + ), + _ => (), + } } ``` -Listing 19-27: Using the `fn` type to accept a function pointer as an argument - -This code prints `The answer is: 12`. We specify that the parameter `f` in -`do_twice` is an `fn` that takes one parameter of type `i32` and returns an -`i32`. We can then call `f` in the body of `do_twice`. In `main`, we can pass -the function name `add_one` as the first argument to `do_twice`. +Listing 18-16: Matching on nested enums -Unlike closures, `fn` is a type rather than a trait, so we specify `fn` as the -parameter type directly rather than declaring a generic type parameter with one -of the `Fn` traits as a trait bound. +The pattern of the first arm in the `match` expression matches a +`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then +the pattern binds to the three inner `i32` values. The pattern of the second +arm also matches a `Message::ChangeColor` enum variant, but the inner enum +matches `Color::Hsv` instead. We can specify these complex conditions in one +`match` expression, even though two enums are involved. -Function pointers implement all three of the closure traits (`Fn`, `FnMut`, and -`FnOnce`), meaning you can always pass a function pointer as an argument for a -function that expects a closure. It’s best to write functions using a generic -type and one of the closure traits so your functions can accept either -functions or closures. +#### Destructuring Structs and Tuples -That said, one example of where you would want to only accept `fn` and not -closures is when interfacing with external code that doesn’t have closures: C -functions can accept functions as arguments, but C doesn’t have closures. - -As an example of where you could use either a closure defined inline or a named -function, let’s look at a use of the `map` method provided by the `Iterator` -trait in the standard library. To use the `map` function to turn a vector of -numbers into a vector of strings, we could use a closure, like this: +We can mix, match, and nest destructuring patterns in even more complex ways. +The following example shows a complicated destructure where we nest structs and +tuples inside a tuple and destructure all the primitive values out: ``` -let list_of_numbers = vec![1, 2, 3]; -let list_of_strings: Vec<String> = list_of_numbers - .iter() - .map(|i| i.to_string()) - .collect(); +let ((feet, inches), Point { x, y }) = + ((3, 10), Point { x: 3, y: -10 }); ``` -Or we could name a function as the argument to `map` instead of the closure, -like this: +This code lets us break complex types into their component parts so we can use +the values we’re interested in separately. -``` -let list_of_numbers = vec![1, 2, 3]; -let list_of_strings: Vec<String> = list_of_numbers - .iter() - .map(ToString::to_string) - .collect(); -``` +Destructuring with patterns is a convenient way to use pieces of values, such +as the value from each field in a struct, separately from each other. + +### Ignoring Values in a Pattern -Note that we must use the fully qualified syntax that we talked about in -“Advanced Traits” on page XX because there are multiple functions available -named `to_string`. +You’ve seen that it’s sometimes useful to ignore values in a pattern, such as +in the last arm of a `match`, to get a catchall that doesn’t actually do +anything but does account for all remaining possible values. There are a few +ways to ignore entire values or parts of values in a pattern: using the `_` +pattern (which you’ve seen), using the `_` pattern within another pattern, +using a name that starts with an underscore, or using `..` to ignore remaining +parts of a value. Let’s explore how and why to use each of these patterns. -Here, we’re using the `to_string` function defined in the `ToString` trait, -which the standard library has implemented for any type that implements -`Display`. +#### An Entire Value with _ -Recall from “Enum Values” on page XX that the name of each enum variant that we -define also becomes an initializer function. We can use these initializer -functions as function pointers that implement the closure traits, which means -we can specify the initializer functions as arguments for methods that take -closures, like so: +We’ve used the underscore as a wildcard pattern that will match any value but +not bind to the value. This is especially useful as the last arm in a `match` +expression, but we can also use it in any pattern, including function +parameters, as shown in Listing 18-17. + +Filename: src/main.rs ``` -enum Status { - Value(u32), - Stop, +fn foo(_: i32, y: i32) { + println!("This code only uses the y parameter: {y}"); } -let list_of_statuses: Vec<Status> = (0u32..20) - .map(Status::Value) - .collect(); +fn main() { + foo(3, 4); +} ``` -Here, we create `Status::Value` instances using each `u32` value in the range -that `map` is called on by using the initializer function of `Status::Value`. -Some people prefer this style and some people prefer to use closures. They -compile to the same code, so use whichever style is clearer to you. +Listing 18-17: Using `_` in a function signature -### Returning Closures +This code will completely ignore the value `3` passed as the first argument, +and will print `This code only uses the y parameter: 4`. -Closures are represented by traits, which means you can’t return closures -directly. In most cases where you might want to return a trait, you can instead -use the concrete type that implements the trait as the return value of the -function. However, you can’t do that with closures because they don’t have a -concrete type that is returnable; you’re not allowed to use the function -pointer `fn` as a return type, for example. +In most cases when you no longer need a particular function parameter, you +would change the signature so it doesn’t include the unused parameter. Ignoring +a function parameter can be especially useful in cases when, for example, +you’re implementing a trait when you need a certain type signature but the +function body in your implementation doesn’t need one of the parameters. You +then avoid getting a compiler warning about unused function parameters, as you +would if you used a name instead. -The following code tries to return a closure directly, but it won’t compile: +#### Parts of a Value with a Nested _ -``` -fn returns_closure() -> dyn Fn(i32) -> i32 { - |x| x + 1 -} -``` +We can also use `_` inside another pattern to ignore just part of a value, for +example, when we want to test for only part of a value but have no use for the +other parts in the corresponding code we want to run. Listing 18-18 shows code +responsible for managing a setting’s value. The business requirements are that +the user should not be allowed to overwrite an existing customization of a +setting but can unset the setting and give it a value if it is currently unset. -The compiler error is as follows: +Filename: src/main.rs ``` -error[E0746]: return type cannot have an unboxed trait object - --> src/lib.rs:1:25 - | -1 | fn returns_closure() -> dyn Fn(i32) -> i32 { - | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at -compile-time - | - = note: for information on `impl Trait`, see -<https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that- -implement-traits> -help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of -type `[closure@src/lib.rs:2:5: 2:14]`, which implements `Fn(i32) -> i32` - | -1 | fn returns_closure() -> impl Fn(i32) -> i32 { - | ~~~~~~~~~~~~~~~~~~~ -``` +let mut setting_value = Some(5); +let new_setting_value = Some(10); -The error references the `Sized` trait again! Rust doesn’t know how much space -it will need to store the closure. We saw a solution to this problem earlier. -We can use a trait object: - -``` -fn returns_closure() -> Box<dyn Fn(i32) -> i32> { - Box::new(|x| x + 1) +match (setting_value, new_setting_value) { + (Some(_), Some(_)) => { + println!("Can't overwrite an existing customized value"); + } + _ => { + setting_value = new_setting_value; + } } -``` - -This code will compile just fine. For more about trait objects, refer to “Using -Trait Objects That Allow for Values of Different Types” on page XX. -Next, let’s look at macros! - -## Macros +println!("setting is {:?}", setting_value); +``` -We’ve used macros like `println!` throughout this book, but we haven’t fully -explored what a macro is and how it works. The term *macro* refers to a family -of features in Rust: *declarative* macros with `macro_rules!` and three kinds -of *procedural* macros: +Listing 18-18: Using an underscore within patterns that match `Some` variants +when we don’t need to use the value inside the `Some` -* Custom `#[derive]` macros that specify code added with the `derive` attribute -used on structs and enums -* Attribute-like macros that define custom attributes usable on any item -* Function-like macros that look like function calls but operate on the tokens -specified as their argument +This code will print `Can't overwrite an existing customized value` and then +`setting is Some(5)`. In the first match arm, we don’t need to match on or use +the values inside either `Some` variant, but we do need to test for the case +when `setting_value` and `new_setting_value` are the `Some` variant. In that +case, we print the reason for not changing `setting_value`, and it doesn’t get +changed. -We’ll talk about each of these in turn, but first, let’s look at why we even -need macros when we already have functions. +In all other cases (if either `setting_value` or `new_setting_value` is `None`) +expressed by the `_` pattern in the second arm, we want to allow +`new_setting_value` to become `setting_value`. -### The Difference Between Macros and Functions +We can also use underscores in multiple places within one pattern to ignore +particular values. Listing 18-19 shows an example of ignoring the second and +fourth values in a tuple of five items. -Fundamentally, macros are a way of writing code that writes other code, which -is known as *metaprogramming*. In Appendix C, we discuss the `derive` -attribute, which generates an implementation of various traits for you. We’ve -also used the `println!` and `vec!` macros throughout the book. All of these -macros *expand* to produce more code than the code you’ve written manually. +Filename: src/main.rs -Metaprogramming is useful for reducing the amount of code you have to write and -maintain, which is also one of the roles of functions. However, macros have -some additional powers that functions don’t have. +``` +let numbers = (2, 4, 8, 16, 32); -A function signature must declare the number and type of parameters the -function has. Macros, on the other hand, can take a variable number of -parameters: we can call `println!("hello")` with one argument or -`println!("hello {}", name)` with two arguments. Also, macros are expanded -before the compiler interprets the meaning of the code, so a macro can, for -example, implement a trait on a given type. A function can’t, because it gets -called at runtime and a trait needs to be implemented at compile time. +match numbers { + (first, _, third, _, fifth) => { + println!("Some numbers: {first}, {third}, {fifth}"); + } +} +``` -The downside to implementing a macro instead of a function is that macro -definitions are more complex than function definitions because you’re writing -Rust code that writes Rust code. Due to this indirection, macro definitions are -generally more difficult to read, understand, and maintain than function -definitions. +Listing 18-19: Ignoring multiple parts of a tuple -Another important difference between macros and functions is that you must -define macros or bring them into scope *before* you call them in a file, as -opposed to functions you can define anywhere and call anywhere. +This code will print `Some numbers: 2, 8, 32`, and the values `4` and `16` will +be ignored. -### Declarative Macros with macro_rules! for General Metaprogramming +#### An Unused Variable by Starting Its Name with _ -The most widely used form of macros in Rust is the *declarative macro*. These -are also sometimes referred to as “macros by example,” “`macro_rules!` macros,” -or just plain “macros.” At their core, declarative macros allow you to write -something similar to a Rust `match` expression. As discussed in Chapter 6, -`match` expressions are control structures that take an expression, compare the -resultant value of the expression to patterns, and then run the code associated -with the matching pattern. Macros also compare a value to patterns that are -associated with particular code: in this situation, the value is the literal -Rust source code passed to the macro; the patterns are compared with the -structure of that source code; and the code associated with each pattern, when -matched, replaces the code passed to the macro. This all happens during -compilation. +If you create a variable but don’t use it anywhere, Rust will usually issue a +warning because an unused variable could be a bug. However, sometimes it’s +useful to be able to create a variable you won’t use yet, such as when you’re +prototyping or just starting a project. In this situation, you can tell Rust +not to warn you about the unused variable by starting the name of the variable +with an underscore. In Listing 18-20, we create two unused variables, but when +we compile this code, we should only get a warning about one of them. -To define a macro, you use the `macro_rules!` construct. Let’s explore how to -use `macro_rules!` by looking at how the `vec!` macro is defined. Chapter 8 -covered how we can use the `vec!` macro to create a new vector with particular -values. For example, the following macro creates a new vector containing three -integers: +Filename: src/main.rs ``` -let v: Vec<u32> = vec![1, 2, 3]; +fn main() { + let _x = 5; + let y = 10; +} ``` -We could also use the `vec!` macro to make a vector of two integers or a vector -of five string slices. We wouldn’t be able to use a function to do the same -because we wouldn’t know the number or type of values up front. +Listing 18-20: Starting a variable name with an underscore to avoid getting +unused variable warnings -Listing 19-28 shows a slightly simplified definition of the `vec!` macro. +Here, we get a warning about not using the variable `y`, but we don’t get a +warning about not using `_x`. -Filename: src/lib.rs +Note that there is a subtle difference between using only `_` and using a name +that starts with an underscore. The syntax `_x` still binds the value to the +variable, whereas `_` doesn’t bind at all. To show a case where this +distinction matters, Listing 18-21 will provide us with an error. -``` -1 #[macro_export] -2 macro_rules! vec { - 3 ( $( $x:expr ),* ) => { - { - let mut temp_vec = Vec::new(); - 4 $( - 5 temp_vec.push(6 $x); - )* - 7 temp_vec - } - }; -} -``` +Filename: src/main.rs -Listing 19-28: A simplified version of the `vec!` macro definition - -> Note: The actual definition of the `vec!` macro in the standard library -includes code to pre-allocate the correct amount of memory up front. That code -is an optimization that we don’t include here, to make the example simpler. - -The `#[macro_export]` annotation [1] indicates that this macro should be made -available whenever the crate in which the macro is defined is brought into -scope. Without this annotation, the macro can’t be brought into scope. - -We then start the macro definition with `macro_rules!` and the name of the -macro we’re defining *without* the exclamation mark [2]. The name, in this case -`vec`, is followed by curly brackets denoting the body of the macro definition. - -The structure in the `vec!` body is similar to the structure of a `match` -expression. Here we have one arm with the pattern `( $( $x:expr ),* )`, -followed by `=>` and the block of code associated with this pattern [3]. If the -pattern matches, the associated block of code will be emitted. Given that this -is the only pattern in this macro, there is only one valid way to match; any -other pattern will result in an error. More complex macros will have more than -one arm. - -Valid pattern syntax in macro definitions is different from the pattern syntax -covered in Chapter 18 because macro patterns are matched against Rust code -structure rather than values. Let’s walk through what the pattern pieces in -Listing 19-28 mean; for the full macro pattern syntax, see the Rust Reference -at *https://doc.rust-lang.org/reference/macros-by-example.html*. - -First we use a set of parentheses to encompass the whole pattern. We use a -dollar sign (`$`) to declare a variable in the macro system that will contain -the Rust code matching the pattern. The dollar sign makes it clear this is a -macro variable as opposed to a regular Rust variable. Next comes a set of -parentheses that captures values that match the pattern within the parentheses -for use in the replacement code. Within `$()` is `$x:expr`, which matches any -Rust expression and gives the expression the name `$x`. - -The comma following `$()` indicates that a literal comma separator character -could optionally appear after the code that matches the code in `$()`. The `*` -specifies that the pattern matches zero or more of whatever precedes the `*`. - -When we call this macro with `vec![1, 2, 3];`, the `$x` pattern matches three -times with the three expressions `1`, `2`, and `3`. - -Now let’s look at the pattern in the body of the code associated with this arm: -`temp_vec.push()` [5] within `$()* at [4] and [7] is generated for each part -that matches `$()` in the pattern zero or more times depending on how many -times the pattern matches. The `$x` [6] is replaced with each expression -matched. When we call this macro with `vec![1, 2, 3];`, the code generated that -replaces this macro call will be the following: - -``` -{ - let mut temp_vec = Vec::new(); - temp_vec.push(1); - temp_vec.push(2); - temp_vec.push(3); - temp_vec -} ``` +let s = Some(String::from("Hello!")); -We’ve defined a macro that can take any number of arguments of any type and can -generate code to create a vector containing the specified elements. - -To learn more about how to write macros, consult the online documentation or -other resources, such as “The Little Book of Rust Macros” at -*https://veykril.github.io/tlborm* started by Daniel Keep and continued by -Lukas Wirth. +if let Some(_s) = s { + println!("found a string"); +} -### Procedural Macros for Generating Code from Attributes +println!("{:?}", s); +``` -The second form of macros is the procedural macro, which acts more like a -function (and is a type of procedure). *Procedural macros* accept some code as -an input, operate on that code, and produce some code as an output rather than -matching against patterns and replacing the code with other code as declarative -macros do. The three kinds of procedural macros are custom `derive`, -attribute-like, and function-like, and all work in a similar fashion. +Listing 18-21: An unused variable starting with an underscore still binds the +value, which might take ownership of the value. -When creating procedural macros, the definitions must reside in their own crate -with a special crate type. This is for complex technical reasons that we hope -to eliminate in the future. In Listing 19-29, we show how to define a -procedural macro, where `some_attribute` is a placeholder for using a specific -macro variety. +We’ll receive an error because the `s` value will still be moved into `_s`, +which prevents us from using `s` again. However, using the underscore by itself +doesn’t ever bind to the value. Listing 18-22 will compile without any errors +because `s` doesn’t get moved into `_`. -Filename: src/lib.rs +Filename: src/main.rs ``` -use proc_macro::TokenStream; +let s = Some(String::from("Hello!")); -#[some_attribute] -pub fn some_name(input: TokenStream) -> TokenStream { +if let Some(_) = s { + println!("found a string"); } -``` -Listing 19-29: An example of defining a procedural macro +println!("{:?}", s); +``` -The function that defines a procedural macro takes a `TokenStream` as an input -and produces a `TokenStream` as an output. The `TokenStream` type is defined by -the `proc_macro` crate that is included with Rust and represents a sequence of -tokens. This is the core of the macro: the source code that the macro is -operating on makes up the input `TokenStream`, and the code the macro produces -is the output `TokenStream`. The function also has an attribute attached to it -that specifies which kind of procedural macro we’re creating. We can have -multiple kinds of procedural macros in the same crate. +Listing 18-22: Using an underscore does not bind the value. -Let’s look at the different kinds of procedural macros. We’ll start with a -custom `derive` macro and then explain the small dissimilarities that make the -other forms different. +This code works just fine because we never bind `s` to anything; it isn’t moved. -### How to Write a Custom derive Macro +#### Remaining Parts of a Value with .. -Let’s create a crate named `hello_macro` that defines a trait named -`HelloMacro` with one associated function named `hello_macro`. Rather than -making our users implement the `HelloMacro` trait for each of their types, -we’ll provide a procedural macro so users can annotate their type with -`#[derive(HelloMacro)]` to get a default implementation of the `hello_macro` -function. The default implementation will print `Hello, Macro! My name is` -TypeName`!` where TypeName is the name of the type on which this trait has been -defined. In other words, we’ll write a crate that enables another programmer to -write code like Listing 19-30 using our crate. +With values that have many parts, we can use the `..` syntax to use specific +parts and ignore the rest, avoiding the need to list underscores for each +ignored value. The `..` pattern ignores any parts of a value that we haven’t +explicitly matched in the rest of the pattern. In Listing 18-23, we have a +`Point` struct that holds a coordinate in three-dimensional space. In the +`match` expression, we want to operate only on the `x` coordinate and ignore +the values in the `y` and `z` fields. Filename: src/main.rs ``` -use hello_macro::HelloMacro; -use hello_macro_derive::HelloMacro; +struct Point { + x: i32, + y: i32, + z: i32, +} -#[derive(HelloMacro)] -struct Pancakes; +let origin = Point { x: 0, y: 0, z: 0 }; -fn main() { - Pancakes::hello_macro(); +match origin { + Point { x, .. } => println!("x is {x}"), } ``` -Listing 19-30: The code a user of our crate will be able to write when using -our procedural macro +Listing 18-23: Ignoring all fields of a `Point` except for `x` by using `..` -This code will print `Hello, Macro! My name is Pancakes!` when we’re done. The -first step is to make a new library crate, like this: +We list the `x` value and then just include the `..` pattern. This is quicker +than having to list `y: _` and `z: _`, particularly when we’re working with +structs that have lots of fields in situations where only one or two fields are +relevant. -``` -$ cargo new hello_macro --lib -``` +The syntax `..` will expand to as many values as it needs to be. Listing 18-24 +shows how to use `..` with a tuple. -Next, we’ll define the `HelloMacro` trait and its associated function: - -Filename: src/lib.rs +Filename: src/main.rs ``` -pub trait HelloMacro { - fn hello_macro(); +fn main() { + let numbers = (2, 4, 8, 16, 32); + + match numbers { + (first, .., last) => { + println!("Some numbers: {first}, {last}"); + } + } } ``` -We have a trait and its function. At this point, our crate user could implement -the trait to achieve the desired functionality, like so: +Listing 18-24: Matching only the first and last values in a tuple and ignoring +all other values -``` -use hello_macro::HelloMacro; +In this code, the first and last values are matched with `first` and `last`. +The `..` will match and ignore everything in the middle. -struct Pancakes; +However, using `..` must be unambiguous. If it is unclear which values are +intended for matching and which should be ignored, Rust will give us an error. +Listing 18-25 shows an example of using `..` ambiguously, so it will not +compile. -impl HelloMacro for Pancakes { - fn hello_macro() { - println!("Hello, Macro! My name is Pancakes!"); - } -} +Filename: src/main.rs +``` fn main() { - Pancakes::hello_macro(); + let numbers = (2, 4, 8, 16, 32); + + match numbers { + (.., second, ..) => { + println!("Some numbers: {second}"); + }, + } } ``` -However, they would need to write the implementation block for each type they -wanted to use with `hello_macro`; we want to spare them from having to do this -work. - -Additionally, we can’t yet provide the `hello_macro` function with default -implementation that will print the name of the type the trait is implemented -on: Rust doesn’t have reflection capabilities, so it can’t look up the type’s -name at runtime. We need a macro to generate code at compile time. +Listing 18-25: An attempt to use `..` in an ambiguous way -The next step is to define the procedural macro. At the time of this writing, -procedural macros need to be in their own crate. Eventually, this restriction -might be lifted. The convention for structuring crates and macro crates is as -follows: for a crate named foo, a custom `derive` procedural macro crate is -called foo`_derive`. Let’s start a new crate called `hello_macro_derive` inside -our `hello_macro` project: +When we compile this example, we get this error: ``` -$ cargo new hello_macro_derive --lib +error: `..` can only be used once per tuple pattern + --> src/main.rs:5:22 + | +5 | (.., second, ..) => { + | -- ^^ can only be used once per tuple pattern + | | + | previously used here ``` -Our two crates are tightly related, so we create the procedural macro crate -within the directory of our `hello_macro` crate. If we change the trait -definition in `hello_macro`, we’ll have to change the implementation of the -procedural macro in `hello_macro_derive` as well. The two crates will need to -be published separately, and programmers using these crates will need to add -both as dependencies and bring them both into scope. We could instead have the -`hello_macro` crate use `hello_macro_derive` as a dependency and re-export the -procedural macro code. However, the way we’ve structured the project makes it -possible for programmers to use `hello_macro` even if they don’t want the -`derive` functionality. +It’s impossible for Rust to determine how many values in the tuple to ignore +before matching a value with `second` and then how many further values to +ignore thereafter. This code could mean that we want to ignore `2`, bind +`second` to `4`, and then ignore `8`, `16`, and `32`; or that we want to ignore +`2` and `4`, bind `second` to `8`, and then ignore `16` and `32`; and so forth. +The variable name `second` doesn’t mean anything special to Rust, so we get a +compiler error because using `..` in two places like this is ambiguous. + +### Extra Conditionals with Match Guards + +A *match guard* is an additional `if` condition, specified after the pattern in +a `match` arm, that must also match for that arm to be chosen. Match guards are +useful for expressing more complex ideas than a pattern alone allows. -We need to declare the `hello_macro_derive` crate as a procedural macro crate. -We’ll also need functionality from the `syn` and `quote` crates, as you’ll see -in a moment, so we need to add them as dependencies. Add the following to the -*Cargo.toml* file for `hello_macro_derive`: +The condition can use variables created in the pattern. Listing 18-26 shows a +`match` where the first arm has the pattern `Some(x)` and also has a match +guard of `if x % 2 == 0` (which will be `true` if the number is even). -Filename: hello_macro_derive/Cargo.toml +Filename: src/main.rs ``` -[lib] -proc-macro = true +let num = Some(4); -[dependencies] -syn = "1.0" -quote = "1.0" +match num { + Some(x) if x % 2 == 0 => println!("The number {x} is even"), + Some(x) => println!("The number {x} is odd"), + None => (), +} ``` -To start defining the procedural macro, place the code in Listing 19-31 into -your *src/lib.rs* file for the `hello_macro_derive` crate. Note that this code -won’t compile until we add a definition for the `impl_hello_macro` function. +Listing 18-26: Adding a match guard to a pattern -Filename: hello_macro_derive/src/lib.rs +This example will print `The number 4 is even`. When `num` is compared to the +pattern in the first arm, it matches because `Some(4)` matches `Some(x)`. Then +the match guard checks whether the remainder of dividing `x` by 2 is equal to +0, and because it is, the first arm is selected. -``` -use proc_macro::TokenStream; -use quote::quote; -use syn; +If `num` had been `Some(5)` instead, the match guard in the first arm would +have been `false` because the remainder of 5 divided by 2 is 1, which is not +equal to 0. Rust would then go to the second arm, which would match because the +second arm doesn’t have a match guard and therefore matches any `Some` variant. -#[proc_macro_derive(HelloMacro)] -pub fn hello_macro_derive(input: TokenStream) -> TokenStream { - // Construct a representation of Rust code as a syntax tree - // that we can manipulate - let ast = syn::parse(input).unwrap(); +There is no way to express the `if x % 2 == 0` condition within a pattern, so +the match guard gives us the ability to express this logic. The downside of +this additional expressiveness is that the compiler doesn’t try to check for +exhaustiveness when match guard expressions are involved. - // Build the trait implementation - impl_hello_macro(&ast) -} -``` +In Listing 18-11, we mentioned that we could use match guards to solve our +pattern-shadowing problem. Recall that we created a new variable inside the +pattern in the `match` expression instead of using the variable outside the +`match`. That new variable meant we couldn’t test against the value of the +outer variable. Listing 18-27 shows how we can use a match guard to fix this +problem. -Listing 19-31: Code that most procedural macro crates will require in order to -process Rust code - -Notice that we’ve split the code into the `hello_macro_derive` function, which -is responsible for parsing the `TokenStream`, and the `impl_hello_macro` -function, which is responsible for transforming the syntax tree: this makes -writing a procedural macro more convenient. The code in the outer function -(`hello_macro_derive` in this case) will be the same for almost every -procedural macro crate you see or create. The code you specify in the body of -the inner function (`impl_hello_macro` in this case) will be different -depending on your procedural macro’s purpose. - -We’ve introduced three new crates: `proc_macro`, `syn` (available from -*https://crates.io/crates/syn*), and `quote` (available from -*https://crates.io/crates/quote*). The `proc_macro` crate comes with Rust, so -we didn’t need to add that to the dependencies in *Cargo.toml*. The -`proc_macro` crate is the compiler’s API that allows us to read and manipulate -Rust code from our code. - -The `syn` crate parses Rust code from a string into a data structure that we -can perform operations on. The `quote` crate turns `syn` data structures back -into Rust code. These crates make it much simpler to parse any sort of Rust -code we might want to handle: writing a full parser for Rust code is no simple -task. - -The `hello_macro_derive` function will be called when a user of our library -specifies `#[derive(HelloMacro)]` on a type. This is possible because we’ve -annotated the `hello_macro_derive` function here with `proc_macro_derive` and -specified the name `HelloMacro`, which matches our trait name; this is the -convention most procedural macros follow. - -The `hello_macro_derive` function first converts the `input` from a -`TokenStream` to a data structure that we can then interpret and perform -operations on. This is where `syn` comes into play. The `parse` function in -`syn` takes a `TokenStream` and returns a `DeriveInput` struct representing the -parsed Rust code. Listing 19-32 shows the relevant parts of the `DeriveInput` -struct we get from parsing the `struct Pancakes;` string. - -``` -DeriveInput { - --snip-- - - ident: Ident { - ident: "Pancakes", - span: #0 bytes(95..103) - }, - data: Struct( - DataStruct { - struct_token: Struct, - fields: Unit, - semi_token: Some( - Semi - ) - } - ) -} -``` +Filename: src/main.rs -Listing 19-32: The `DeriveInput` instance we get when parsing the code that has -the macro’s attribute in Listing 19-30 - -The fields of this struct show that the Rust code we’ve parsed is a unit struct -with the `ident` (*identifier*, meaning the name) of `Pancakes`. There are more -fields on this struct for describing all sorts of Rust code; check the `syn` -documentation for `DeriveInput` at -*https://docs.rs/syn/1.0/syn/struct.DeriveInput.html* for more information. - -Soon we’ll define the `impl_hello_macro` function, which is where we’ll build -the new Rust code we want to include. But before we do, note that the output -for our `derive` macro is also a `TokenStream`. The returned `TokenStream` is -added to the code that our crate users write, so when they compile their crate, -they’ll get the extra functionality that we provide in the modified -`TokenStream`. - -You might have noticed that we’re calling `unwrap` to cause the -`hello_macro_derive` function to panic if the call to the `syn::parse` function -fails here. It’s necessary for our procedural macro to panic on errors because -`proc_macro_derive` functions must return `TokenStream` rather than `Result` to -conform to the procedural macro API. We’ve simplified this example by using -`unwrap`; in production code, you should provide more specific error messages -about what went wrong by using `panic!` or `expect`. - -Now that we have the code to turn the annotated Rust code from a `TokenStream` -into a `DeriveInput` instance, let’s generate the code that implements the -`HelloMacro` trait on the annotated type, as shown in Listing 19-33. - -Filename: hello_macro_derive/src/lib.rs - -``` -fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { - let name = &ast.ident; - let gen = quote! { - impl HelloMacro for #name { - fn hello_macro() { - println!( - "Hello, Macro! My name is {}!", - stringify!(#name) - ); - } - } - }; - gen.into() -} ``` +fn main() { + let x = Some(5); + let y = 10; -Listing 19-33: Implementing the `HelloMacro` trait using the parsed Rust code + match x { + Some(50) => println!("Got 50"), + Some(n) if n == y => println!("Matched, n = {n}"), + _ => println!("Default case, x = {:?}", x), + } -We get an `Ident` struct instance containing the name (identifier) of the -annotated type using `ast.ident`. The struct in Listing 19-32 shows that when -we run the `impl_hello_macro` function on the code in Listing 19-30, the -`ident` we get will have the `ident` field with a value of `"Pancakes"`. Thus -the `name` variable in Listing 19-33 will contain an `Ident` struct instance -that, when printed, will be the string `"Pancakes"`, the name of the struct in -Listing 19-30. + println!("at the end: x = {:?}, y = {y}", x); +} +``` -The `quote!` macro lets us define the Rust code that we want to return. The -compiler expects something different to the direct result of the `quote!` -macro’s execution, so we need to convert it to a `TokenStream`. We do this by -calling the `into` method, which consumes this intermediate representation and -returns a value of the required `TokenStream` type. +Listing 18-27: Using a match guard to test for equality with an outer variable -The `quote!` macro also provides some very cool templating mechanics: we can -enter `#name`, and `quote!` will replace it with the value in the variable -`name`. You can even do some repetition similar to the way regular macros work. -Check out the `quote` crate’s docs at *https://docs.rs/quote* for a thorough -introduction. +This code will now print `Default case, x = Some(5)`. The pattern in the second +match arm doesn’t introduce a new variable `y` that would shadow the outer `y`, +meaning we can use the outer `y` in the match guard. Instead of specifying the +pattern as `Some(y)`, which would have shadowed the outer `y`, we specify +`Some(n)`. This creates a new variable `n` that doesn’t shadow anything because +there is no `n` variable outside the `match`. -We want our procedural macro to generate an implementation of our `HelloMacro` -trait for the type the user annotated, which we can get by using `#name`. The -trait implementation has the one function `hello_macro`, whose body contains -the functionality we want to provide: printing `Hello, Macro! My name is` and -then the name of the annotated type. +The match guard `if n == y` is not a pattern and therefore doesn’t introduce +new variables. This `y` *is* the outer `y` rather than a new shadowed `y`, and +we can look for a value that has the same value as the outer `y` by comparing +`n` to `y`. -The `stringify!` macro used here is built into Rust. It takes a Rust -expression, such as `1 + 2`, and at compile time turns the expression into a -string literal, such as `"1 + 2"`. This is different from `format!` or -`println!`, macros which evaluate the expression and then turn the result into -a `String`. There is a possibility that the `#name` input might be an -expression to print literally, so we use `stringify!`. Using `stringify!` also -saves an allocation by converting `#name` to a string literal at compile time. +You can also use the *or* operator `|` in a match guard to specify multiple +patterns; the match guard condition will apply to all the patterns. Listing +18-28 shows the precedence when combining a pattern that uses `|` with a match +guard. The important part of this example is that the `if y` match guard +applies to `4`, `5`, *and* `6`, even though it might look like `if y` only +applies to `6`. -At this point, `cargo build` should complete successfully in both `hello_macro` -and `hello_macro_derive`. Let’s hook up these crates to the code in Listing -19-30 to see the procedural macro in action! Create a new binary project in -your *projects* directory using `cargo new pancakes`. We need to add -`hello_macro` and `hello_macro_derive` as dependencies in the `pancakes` -crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` and -`hello_macro_derive` to *https://crates.io*, they would be regular -dependencies; if not, you can specify them as `path` dependencies as follows: +Filename: src/main.rs ``` -[dependencies] -hello_macro = { path = "../hello_macro" } -hello_macro_derive = { path = "../hello_macro/hello_macro_derive" } -``` +let x = 4; +let y = false; -Put the code in Listing 19-30 into *src/main.rs*, and run `cargo run`: it -should print `Hello, Macro! My name is Pancakes!` The implementation of the -`HelloMacro` trait from the procedural macro was included without the -`pancakes` crate needing to implement it; the `#[derive(HelloMacro)]` added the -trait implementation. - -Next, let’s explore how the other kinds of procedural macros differ from custom -`derive` macros. +match x { + 4 | 5 | 6 if y => println!("yes"), + _ => println!("no"), +} +``` -### Attribute-like Macros +Listing 18-28: Combining multiple patterns with a match guard -Attribute-like macros are similar to custom `derive` macros, but instead of -generating code for the `derive` attribute, they allow you to create new -attributes. They’re also more flexible: `derive` only works for structs and -enums; attributes can be applied to other items as well, such as functions. -Here’s an example of using an attribute-like macro. Say you have an attribute -named `route` that annotates functions when using a web application framework: +The match condition states that the arm only matches if the value of `x` is +equal to `4`, `5`, or `6` *and* if `y` is `true`. When this code runs, the +pattern of the first arm matches because `x` is `4`, but the match guard `if y` +is `false`, so the first arm is not chosen. The code moves on to the second +arm, which does match, and this program prints `no`. The reason is that the +`if` condition applies to the whole pattern `4 | 5 | 6`, not just to the last +value `6`. In other words, the precedence of a match guard in relation to a +pattern behaves like this: ``` -#[route(GET, "/")] -fn index() { +(4 | 5 | 6) if y => ... ``` -This `#[route]` attribute would be defined by the framework as a procedural -macro. The signature of the macro definition function would look like this: +rather than this: ``` -#[proc_macro_attribute] -pub fn route( - attr: TokenStream, - item: TokenStream -) -> TokenStream { +4 | 5 | (6 if y) => ... ``` -Here, we have two parameters of type `TokenStream`. The first is for the -contents of the attribute: the `GET, "/"` part. The second is the body of the -item the attribute is attached to: in this case, `fn index() {}` and the rest -of the function’s body. +After running the code, the precedence behavior is evident: if the match guard +were applied only to the final value in the list of values specified using the +`|` operator, the arm would have matched and the program would have printed +`yes`. -Other than that, attribute-like macros work the same way as custom `derive` -macros: you create a crate with the `proc-macro` crate type and implement a -function that generates the code you want! +### @ Bindings -### Function-like Macros +The *at* operator `@` lets us create a variable that holds a value at the same +time we’re testing that value for a pattern match. In Listing 18-29, we want to +test that a `Message::Hello` `id` field is within the range `3..=7`. We also +want to bind the value to the variable `id_variable` so we can use it in the +code associated with the arm. We could name this variable `id`, the same as the +field, but for this example we’ll use a different name. -Function-like macros define macros that look like function calls. Similarly to -`macro_rules!` macros, they’re more flexible than functions; for example, they -can take an unknown number of arguments. However, `macro_rules!` macros can -only be defined using the match-like syntax we discussed in “Declarative Macros -with macro_rules! for General Metaprogramming” on page XX. Function-like macros -take a `TokenStream` parameter, and their definition manipulates that -`TokenStream` using Rust code as the other two types of procedural macros do. -An example of a function-like macro is an `sql!` macro that might be called -like so: +Filename: src/main.rs ``` -let sql = sql!(SELECT * FROM posts WHERE id=1); -``` +enum Message { + Hello { id: i32 }, +} -This macro would parse the SQL statement inside it and check that it’s -syntactically correct, which is much more complex processing than a -`macro_rules!` macro can do. The `sql!` macro would be defined like this: +let msg = Message::Hello { id: 5 }; +match msg { + Message::Hello { + id: id_variable @ 3..=7, + } => println!("Found an id in range: {id_variable}"), + Message::Hello { id: 10..=12 } => { + println!("Found an id in another range") + } + Message::Hello { id } => println!("Some other id: {id}"), +} ``` -#[proc_macro] -pub fn sql(input: TokenStream) -> TokenStream { -``` -This definition is similar to the custom `derive` macro’s signature: we receive -the tokens that are inside the parentheses and return the code we wanted to -generate. +Listing 18-29: Using `@` to bind to a value in a pattern while also testing it + +This example will print `Found an id in range: 5`. By specifying `id_variable +@` before the range `3..=7`, we’re capturing whatever value matched the range +while also testing that the value matched the range pattern. + +In the second arm, where we only have a range specified in the pattern, the +code associated with the arm doesn’t have a variable that contains the actual +value of the `id` field. The `id` field’s value could have been 10, 11, or 12, +but the code that goes with that pattern doesn’t know which it is. The pattern +code isn’t able to use the value from the `id` field because we haven’t saved +the `id` value in a variable. + +In the last arm, where we’ve specified a variable without a range, we do have +the value available to use in the arm’s code in a variable named `id`. The +reason is that we’ve used the struct field shorthand syntax. But we haven’t +applied any test to the value in the `id` field in this arm, as we did with the +first two arms: any value would match this pattern. + +Using `@` lets us test a value and save it in a variable within one pattern. ## Summary -Whew! Now you have some Rust features in your toolbox that you likely won’t use -often, but you’ll know they’re available in very particular circumstances. -We’ve introduced several complex topics so that when you encounter them in -error message suggestions or in other people’s code, you’ll be able to -recognize these concepts and syntax. Use this chapter as a reference to guide -you to solutions. +Rust’s patterns are very useful in distinguishing between different kinds of +data. When used in `match` expressions, Rust ensures your patterns cover every +possible value, or your program won’t compile. Patterns in `let` statements and +function parameters make those constructs more useful, enabling the +destructuring of values into smaller parts at the same time as assigning to +variables. We can create simple or complex patterns to suit our needs. -Next, we’ll put everything we’ve discussed throughout the book into practice -and do one more project! +Next, for the penultimate chapter of the book, we’ll look at some advanced +aspects of a variety of Rust’s features. diff --git a/nostarch/chapter20.md b/nostarch/chapter20.md index 9d4e22cd77..410e7eb62d 100644 --- a/nostarch/chapter20.md +++ b/nostarch/chapter20.md @@ -6,1989 +6,2291 @@ directory, so all fixes need to be made in `/src/`. [TOC] -# Final Project: Building a Multithreaded Web Server +# Advanced Features + +By now, you’ve learned the most commonly used parts of the Rust programming +language. Before we do one more project, in Chapter 20, we’ll look at a few +aspects of the language you might run into every once in a while, but may not +use every day. You can use this chapter as a reference for when you encounter +any unknowns. The features covered here are useful in very specific situations. +Although you might not reach for them often, we want to make sure you have a +grasp of all the features Rust has to offer. + +In this chapter, we’ll cover: + +* Unsafe Rust: how to opt out of some of Rust’s guarantees and take +responsibility for manually upholding those guarantees +* Advanced traits: associated types, default type parameters, fully qualified +syntax, supertraits, and the newtype pattern in relation to traits +* Advanced types: more about the newtype pattern, type aliases, the never type, +and dynamically sized types +* Advanced functions and closures: function pointers and returning closures +* Macros: ways to define code that defines more code at compile time + +It’s a panoply of Rust features with something for everyone! Let’s dive in! + +## Unsafe Rust + +All the code we’ve discussed so far has had Rust’s memory safety guarantees +enforced at compile time. However, Rust has a second language hidden inside it +that doesn’t enforce these memory safety guarantees: it’s called *unsafe Rust* +and works just like regular Rust, but gives us extra superpowers. + +Unsafe Rust exists because, by nature, static analysis is conservative. When +the compiler tries to determine whether or not code upholds the guarantees, +it’s better for it to reject some valid programs than to accept some invalid +programs. Although the code *might* be okay, if the Rust compiler doesn’t have +enough information to be confident, it will reject the code. In these cases, +you can use unsafe code to tell the compiler, “Trust me, I know what I’m +doing.” Be warned, however, that you use unsafe Rust at your own risk: if you +use unsafe code incorrectly, problems can occur due to memory unsafety, such as +null pointer dereferencing. + +Another reason Rust has an unsafe alter ego is that the underlying computer +hardware is inherently unsafe. If Rust didn’t let you do unsafe operations, you +couldn’t do certain tasks. Rust needs to allow you to do low-level systems +programming, such as directly interacting with the operating system or even +writing your own operating system. Working with low-level systems programming +is one of the goals of the language. Let’s explore what we can do with unsafe +Rust and how to do it. + +### Unsafe Superpowers + +To switch to unsafe Rust, use the `unsafe` keyword and then start a new block +that holds the unsafe code. You can take five actions in unsafe Rust that you +can’t in safe Rust, which we call *unsafe superpowers*. Those superpowers +include the ability to: + +1. Dereference a raw pointer +1. Call an unsafe function or method +1. Access or modify a mutable static variable +1. Implement an unsafe trait +1. Access fields of `union`s + +It’s important to understand that `unsafe` doesn’t turn off the borrow checker +or disable any of Rust’s other safety checks: if you use a reference in unsafe +code, it will still be checked. The `unsafe` keyword only gives you access to +these five features that are then not checked by the compiler for memory +safety. You’ll still get some degree of safety inside an unsafe block. + +In addition, `unsafe` does not mean the code inside the block is necessarily +dangerous or that it will definitely have memory safety problems: the intent is +that as the programmer, you’ll ensure the code inside an `unsafe` block will +access memory in a valid way. + +People are fallible and mistakes will happen, but by requiring these five +unsafe operations to be inside blocks annotated with `unsafe`, you’ll know that +any errors related to memory safety must be within an `unsafe` block. Keep +`unsafe` blocks small; you’ll be thankful later when you investigate memory +bugs. + +To isolate unsafe code as much as possible, it’s best to enclose such code +within a safe abstraction and provide a safe API, which we’ll discuss later in +the chapter when we examine unsafe functions and methods. Parts of the standard +library are implemented as safe abstractions over unsafe code that has been +audited. Wrapping unsafe code in a safe abstraction prevents uses of `unsafe` +from leaking out into all the places that you or your users might want to use +the functionality implemented with `unsafe` code, because using a safe +abstraction is safe. + +Let’s look at each of the five unsafe superpowers in turn. We’ll also look at +some abstractions that provide a safe interface to unsafe code. + +### Dereferencing a Raw Pointer + +In “Dangling References” on page XX, we mentioned that the compiler ensures +references are always valid. Unsafe Rust has two new types called *raw +pointers* that are similar to references. As with references, raw pointers can +be immutable or mutable and are written as `*const T` and `*mut T`, +respectively. The asterisk isn’t the dereference operator; it’s part of the +type name. In the context of raw pointers, *immutable* means that the pointer +can’t be directly assigned to after being dereferenced. + +Different from references and smart pointers, raw pointers: + +* Are allowed to ignore the borrowing rules by having both immutable and +mutable pointers or multiple mutable pointers to the same location +* Aren’t guaranteed to point to valid memory +* Are allowed to be null +* Don’t implement any automatic cleanup -It’s been a long journey, but we’ve reached the end of the book. In this -chapter, we’ll build one more project together to demonstrate some of the -concepts we covered in the final chapters, as well as recap some earlier -lessons. +By opting out of having Rust enforce these guarantees, you can give up +guaranteed safety in exchange for greater performance or the ability to +interface with another language or hardware where Rust’s guarantees don’t apply. -For our final project, we’ll make a web server that says “hello” and looks like -Figure 20-1 in a web browser. - -Figure 20-1: Our final shared project - -Here is our plan for building the web server: - -1. Learn a bit about TCP and HTTP. -1. Listen for TCP connections on a socket. -1. Parse a small number of HTTP requests. -1. Create a proper HTTP response. -1. Improve the throughput of our server with a thread pool. - -Before we get started, we should mention one detail: the method we’ll use won’t -be the best way to build a web server with Rust. Community members have -published a number of production-ready crates available at *https://crates.io* -that provide more complete web server and thread pool implementations than -we’ll build. However, our intention in this chapter is to help you learn, not -to take the easy route. Because Rust is a systems programming language, we can -choose the level of abstraction we want to work with and can go to a lower -level than is possible or practical in other languages. We’ll therefore write -the basic HTTP server and thread pool manually so you can learn the general -ideas and techniques behind the crates you might use in the future. - -## Building a Single-Threaded Web Server +Listing 19-1 shows how to create an immutable and a mutable raw pointer from +references. + +``` +let mut num = 5; -We’ll start by getting a single-threaded web server working. Before we begin, -let’s look at a quick overview of the protocols involved in building web -servers. The details of these protocols are beyond the scope of this book, but -a brief overview will give you the information you need. +let r1 = &num as *const i32; +let r2 = &mut num as *mut i32; +``` -The two main protocols involved in web servers are *Hypertext Transfer -Protocol* *(HTTP)* and *Transmission Control Protocol* *(TCP)*. Both protocols -are *request-response* protocols, meaning a *client* initiates requests and a -*server* listens to the requests and provides a response to the client. The -contents of those requests and responses are defined by the protocols. +Listing 19-1: Creating raw pointers from references -TCP is the lower-level protocol that describes the details of how information -gets from one server to another but doesn’t specify what that information is. -HTTP builds on top of TCP by defining the contents of the requests and -responses. It’s technically possible to use HTTP with other protocols, but in -the vast majority of cases, HTTP sends its data over TCP. We’ll work with the -raw bytes of TCP and HTTP requests and responses. +Notice that we don’t include the `unsafe` keyword in this code. We can create +raw pointers in safe code; we just can’t dereference raw pointers outside an +unsafe block, as you’ll see in a bit. -### Listening to the TCP Connection +We’ve created raw pointers by using `as` to cast an immutable and a mutable +reference into their corresponding raw pointer types. Because we created them +directly from references guaranteed to be valid, we know these particular raw +pointers are valid, but we can’t make that assumption about just any raw +pointer. -Our web server needs to listen to a TCP connection, so that’s the first part -we’ll work on. The standard library offers a `std::net` module that lets us do -this. Let’s make a new project in the usual fashion: +To demonstrate this, next we’ll create a raw pointer whose validity we can’t be +so certain of. Listing 19-2 shows how to create a raw pointer to an arbitrary +location in memory. Trying to use arbitrary memory is undefined: there might be +data at that address or there might not, the compiler might optimize the code +so there is no memory access, or the program might terminate with a +segmentation fault. Usually, there is no good reason to write code like this, +but it is possible. ``` -$ cargo new hello - Created binary (application) `hello` project -$ cd hello +let address = 0x012345usize; +let r = address as *const i32; ``` -Now enter the code in Listing 20-1 in *src/main.rs* to start. This code will -listen at the local address `127.0.0.1:7878` for incoming TCP streams. When it -gets an incoming stream, it will print `Connection established!`. +Listing 19-2: Creating a raw pointer to an arbitrary memory address -Filename: src/main.rs +Recall that we can create raw pointers in safe code, but we can’t *dereference* +raw pointers and read the data being pointed to. In Listing 19-3, we use the +dereference operator `*` on a raw pointer that requires an `unsafe` block. ``` -use std::net::TcpListener; - -fn main() { - 1 let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); +let mut num = 5; - 2 for stream in listener.incoming() { - 3 let stream = stream.unwrap(); +let r1 = &num as *const i32; +let r2 = &mut num as *mut i32; - 4 println!("Connection established!"); - } +unsafe { + println!("r1 is: {}", *r1); + println!("r2 is: {}", *r2); } ``` -Listing 20-1: Listening for incoming streams and printing a message when we -receive a stream - -Using `TcpListener`, we can listen for TCP connections at the address -`127.0.0.1:7878` [1]. In the address, the section before the colon is an IP -address representing your computer (this is the same on every computer and -doesn’t represent the authors’ computer specifically), and `7878` is the port. -We’ve chosen this port for two reasons: HTTP isn’t normally accepted on this -port, so our server is unlikely to conflict with any other web server you might -have running on your machine, and 7878 is *rust* typed on a telephone. - -The `bind` function in this scenario works like the `new` function in that it -will return a new `TcpListener` instance. The function is called `bind` -because, in networking, connecting to a port to listen to is known as “binding -to a port.” - -The `bind` function returns a `Result<T, E>`, which indicates that it’s -possible for binding to fail. For example, connecting to port 80 requires -administrator privileges (non-administrators can listen only on ports higher -than 1023), so if we tried to connect to port 80 without being an -administrator, binding wouldn’t work. Binding also wouldn’t work, for example, -if we ran two instances of our program and so had two programs listening to the -same port. Because we’re writing a basic server just for learning purposes, we -won’t worry about handling these kinds of errors; instead, we use `unwrap` to -stop the program if errors happen. - -The `incoming` method on `TcpListener` returns an iterator that gives us a -sequence of streams [2] (more specifically, streams of type `TcpStream`). A -single *stream* represents an open connection between the client and the -server. A *connection* is the name for the full request and response process in -which a client connects to the server, the server generates a response, and the -server closes the connection. As such, we will read from the `TcpStream` to see -what the client sent and then write our response to the stream to send data -back to the client. Overall, this `for` loop will process each connection in -turn and produce a series of streams for us to handle. - -For now, our handling of the stream consists of calling `unwrap` to terminate -our program if the stream has any errors [3]; if there aren’t any errors, the -program prints a message [4]. We’ll add more functionality for the success case -in the next listing. The reason we might receive errors from the `incoming` -method when a client connects to the server is that we’re not actually -iterating over connections. Instead, we’re iterating over *connection -attempts*. The connection might not be successful for a number of reasons, many -of them operating system specific. For example, many operating systems have a -limit to the number of simultaneous open connections they can support; new -connection attempts beyond that number will produce an error until some of the -open connections are closed. - -Let’s try running this code! Invoke `cargo run` in the terminal and then load -*127.0.0.1:7878* in a web browser. The browser should show an error message -like “Connection reset” because the server isn’t currently sending back any -data. But when you look at your terminal, you should see several messages that -were printed when the browser connected to the server! - -``` - Running `target/debug/hello` -Connection established! -Connection established! -Connection established! -``` - -Sometimes you’ll see multiple messages printed for one browser request; the -reason might be that the browser is making a request for the page as well as a -request for other resources, like the *favicon.ico* icon that appears in the -browser tab. - -It could also be that the browser is trying to connect to the server multiple -times because the server isn’t responding with any data. When `stream` goes out -of scope and is dropped at the end of the loop, the connection is closed as -part of the `drop` implementation. Browsers sometimes deal with closed -connections by retrying, because the problem might be temporary. The important -factor is that we’ve successfully gotten a handle to a TCP connection! - -Remember to stop the program by pressing ctrl-C when you’re done running a -particular version of the code. Then restart the program by invoking the `cargo -run` command after you’ve made each set of code changes to make sure you’re -running the newest code. - -### Reading the Request - -Let’s implement the functionality to read the request from the browser! To -separate the concerns of first getting a connection and then taking some action -with the connection, we’ll start a new function for processing connections. In -this new `handle_connection` function, we’ll read data from the TCP stream and -print it so we can see the data being sent from the browser. Change the code to -look like Listing 20-2. +Listing 19-3: Dereferencing raw pointers within an `unsafe` block -Filename: src/main.rs +Creating a pointer does no harm; it’s only when we try to access the value that +it points at that we might end up dealing with an invalid value. -``` -1 use std::{ - io::{prelude::*, BufReader}, - net::{TcpListener, TcpStream}, -}; +Note also that in Listings 19-1 and 19-3, we created `*const i32` and `*mut +i32` raw pointers that both pointed to the same memory location, where `num` is +stored. If we instead tried to create an immutable and a mutable reference to +`num`, the code would not have compiled because Rust’s ownership rules don’t +allow a mutable reference at the same time as any immutable references. With +raw pointers, we can create a mutable pointer and an immutable pointer to the +same location and change data through the mutable pointer, potentially creating +a data race. Be careful! -fn main() { - let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); +With all of these dangers, why would you ever use raw pointers? One major use +case is when interfacing with C code, as you’ll see in “Calling an Unsafe +Function or Method” on page XX. Another case is when building up safe +abstractions that the borrow checker doesn’t understand. We’ll introduce unsafe +functions and then look at an example of a safe abstraction that uses unsafe +code. - for stream in listener.incoming() { - let stream = stream.unwrap(); +### Calling an Unsafe Function or Method - 2 handle_connection(stream); - } -} +The second type of operation you can perform in an unsafe block is calling +unsafe functions. Unsafe functions and methods look exactly like regular +functions and methods, but they have an extra `unsafe` before the rest of the +definition. The `unsafe` keyword in this context indicates the function has +requirements we need to uphold when we call this function, because Rust can’t +guarantee we’ve met these requirements. By calling an unsafe function within an +`unsafe` block, we’re saying that we’ve read this function’s documentation and +we take responsibility for upholding the function’s contracts. + +Here is an unsafe function named `dangerous` that doesn’t do anything in its +body: -fn handle_connection(mut stream: TcpStream) { - 3 let buf_reader = BufReader::new(&mut stream); - 4 let http_request: Vec<_> = buf_reader - 5 .lines() - 6 .map(|result| result.unwrap()) - 7 .take_while(|line| !line.is_empty()) - .collect(); - - 8 println!("Request: {:#?}", http_request); -} -``` - -Listing 20-2: Reading from the `TcpStream` and printing the data - -We bring `std::io::prelude` and `std::io::BufReader` into scope to get access -to traits and types that let us read from and write to the stream [1]. In the -`for` loop in the `main` function, instead of printing a message that says we -made a connection, we now call the new `handle_connection` function and pass -the `stream` to it [2]. - -In the `handle_connection` function, we create a new `BufReader` instance that -wraps a mutable reference to the `stream` [3]. `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 -lines in a vector by adding the `Vec<_>` type annotation [4]. - -`BufReader` implements the `std::io::BufRead` trait, which provides the `lines` -method [5]. The `lines` method returns an iterator of `Result<String, -std::io::Error>` by splitting the stream of data whenever it sees a newline -byte. To get each `String`, we map and `unwrap` each `Result` [6]. The `Result` -might be an error if the data isn’t valid UTF-8 or if there was a problem -reading from the stream. Again, a production program should handle these errors -more gracefully, but we’re choosing to stop the program in the error case for -simplicity. +``` +unsafe fn dangerous() {} -The browser signals the end of an HTTP request by sending two newline -characters in a row, so to get one request from the stream, we take lines until -we get a line that is the empty string [7]. Once we’ve collected the lines into -the vector, we’re printing them out using pretty debug formatting [8] so we can -take a look at the instructions the web browser is sending to our server. +unsafe { + dangerous(); +} +``` -Let’s try this code! Start the program and make a request in a web browser -again. Note that we’ll still get an error page in the browser, but our -program’s output in the terminal will now look similar to this: +We must call the `dangerous` function within a separate `unsafe` block. If we +try to call `dangerous` without the `unsafe` block, we’ll get an error: ``` -$ cargo run - Compiling hello v0.1.0 (file:///projects/hello) - Finished dev [unoptimized + debuginfo] target(s) in 0.42s - Running `target/debug/hello` -Request: [ - "GET / HTTP/1.1", - "Host: 127.0.0.1:7878", - "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) -Gecko/20100101 Firefox/99.0", - "Accept: -text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/* -;q=0.8", - "Accept-Language: en-US,en;q=0.5", - "Accept-Encoding: gzip, deflate, br", - "DNT: 1", - "Connection: keep-alive", - "Upgrade-Insecure-Requests: 1", - "Sec-Fetch-Dest: document", - "Sec-Fetch-Mode: navigate", - "Sec-Fetch-Site: none", - "Sec-Fetch-User: ?1", - "Cache-Control: max-age=0", -] +error[E0133]: call to unsafe function is unsafe and requires +unsafe function or block + --> src/main.rs:4:5 + | +4 | dangerous(); + | ^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on +how to avoid undefined behavior ``` -Depending on your browser, you might get slightly different output. Now that -we’re printing the request data, we can see why we get multiple connections -from one browser request by looking at the path after `GET` in the first line -of the request. If the repeated connections are all requesting */*, we know the -browser is trying to fetch */* repeatedly because it’s not getting a response -from our program. +With the `unsafe` block, we’re asserting to Rust that we’ve read the function’s +documentation, we understand how to use it properly, and we’ve verified that +we’re fulfilling the contract of the function. -Let’s break down this request data to understand what the browser is asking of -our program. +Bodies of unsafe functions are effectively `unsafe` blocks, so to perform other +unsafe operations within an unsafe function, we don’t need to add another +`unsafe` block. -### A Closer Look at an HTTP Request +#### Creating a Safe Abstraction over Unsafe Code -HTTP is a text-based protocol, and a request takes this format: +Just because a function contains unsafe code doesn’t mean we need to mark the +entire function as unsafe. In fact, wrapping unsafe code in a safe function is +a common abstraction. As an example, let’s study the `split_at_mut` function +from the standard library, which requires some unsafe code. We’ll explore how +we might implement it. This safe method is defined on mutable slices: it takes +one slice and makes it two by splitting the slice at the index given as an +argument. Listing 19-4 shows how to use `split_at_mut`. ``` -Method Request-URI HTTP-Version CRLF -headers CRLF -message-body -``` +let mut v = vec![1, 2, 3, 4, 5, 6]; -The first line is the *request line* that holds information about what the -client is requesting. The first part of the request line indicates the *method* -being used, such as `GET` or `POST`, which describes how the client is making -this request. Our client used a `GET` request, which means it is asking for -information. +let r = &mut v[..]; -The next part of the request line is */*, which indicates the *uniform resource -identifier* *(URI)* the client is requesting: a URI is almost, but not quite, -the same as a *uniform resource locator* *(URL)*. The difference between URIs -and URLs isn’t important for our purposes in this chapter, but the HTTP spec -uses the term *URI*, so we can just mentally substitute *URL* for *URI* here. +let (a, b) = r.split_at_mut(3); -The last part is the HTTP version the client uses, and then the request line -ends in a CRLF sequence. (CRLF stands for *carriage return* and *line feed*, -which are terms from the typewriter days!) The CRLF sequence can also be -written as `\r\n`, where `\r` is a carriage return and `\n` is a line feed. The -*CRLF sequence* separates the request line from the rest of the request data. -Note that when the CRLF is printed, we see a new line start rather than `\r\n`. +assert_eq!(a, &mut [1, 2, 3]); +assert_eq!(b, &mut [4, 5, 6]); +``` -Looking at the request line data we received from running our program so far, -we see that `GET` is the method, */* is the request URI, and `HTTP/1.1` is the -version. +Listing 19-4: Using the safe `split_at_mut` function -After the request line, the remaining lines starting from `Host:` onward are -headers. `GET` requests have no body. +We can’t implement this function using only safe Rust. An attempt might look +something like Listing 19-5, which won’t compile. For simplicity, we’ll +implement `split_at_mut` as a function rather than a method and only for slices +of `i32` values rather than for a generic type `T`. -Try making a request from a different browser or asking for a different -address, such as *127.0.0.1:7878/test*, to see how the request data changes. +``` +fn split_at_mut( + values: &mut [i32], + mid: usize, +) -> (&mut [i32], &mut [i32]) { + let len = values.len(); -Now that we know what the browser is asking for, let’s send back some data! + assert!(mid <= len); -### Writing a Response + (&mut values[..mid], &mut values[mid..]) +} +``` -We’re going to implement sending data in response to a client request. -Responses have the following format: +Listing 19-5: An attempted implementation of `split_at_mut` using only safe Rust -``` -HTTP-Version Status-Code Reason-Phrase CRLF -headers CRLF -message-body -``` +This function first gets the total length of the slice. Then it asserts that +the index given as a parameter is within the slice by checking whether it’s +less than or equal to the length. The assertion means that if we pass an index +that is greater than the length to split the slice at, the function will panic +before it attempts to use that index. -The first line is a *status line* that contains the HTTP version used in the -response, a numeric status code that summarizes the result of the request, and -a reason phrase that provides a text description of the status code. After the -CRLF sequence are any headers, another CRLF sequence, and the body of the -response. +Then we return two mutable slices in a tuple: one from the start of the +original slice to the `mid` index and another from `mid` to the end of the +slice. -Here is an example response that uses HTTP version 1.1, and has a status code -of 200, an OK reason phrase, no headers, and no body: +When we try to compile the code in Listing 19-5, we’ll get an error: ``` -HTTP/1.1 200 OK\r\n\r\n +error[E0499]: cannot borrow `*values` as mutable more than once at a time + --> src/main.rs:9:31 + | +2 | values: &mut [i32], + | - let's call the lifetime of this reference `'1` +... +9 | (&mut values[..mid], &mut values[mid..]) + | --------------------------^^^^^^-------- + | | | | + | | | second mutable borrow occurs here + | | first mutable borrow occurs here + | returning this value requires that `*values` is borrowed for `'1` ``` -The status code 200 is the standard success response. The text is a tiny -successful HTTP response. Let’s write this to the stream as our response to a -successful request! From the `handle_connection` function, remove the -`println!` that was printing the request data and replace it with the code in -Listing 20-3. +Rust’s borrow checker can’t understand that we’re borrowing different parts of +the slice; it only knows that we’re borrowing from the same slice twice. +Borrowing different parts of a slice is fundamentally okay because the two +slices aren’t overlapping, but Rust isn’t smart enough to know this. When we +know code is okay, but Rust doesn’t, it’s time to reach for unsafe code. -Filename: src/main.rs +Listing 19-6 shows how to use an `unsafe` block, a raw pointer, and some calls +to unsafe functions to make the implementation of `split_at_mut` work. ``` -fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); - let http_request: Vec<_> = buf_reader - .lines() - .map(|result| result.unwrap()) - .take_while(|line| !line.is_empty()) - .collect(); +use std::slice; + +fn split_at_mut( + values: &mut [i32], + mid: usize, +) -> (&mut [i32], &mut [i32]) { + 1 let len = values.len(); + 2 let ptr = values.as_mut_ptr(); - 1 let response = "HTTP/1.1 200 OK\r\n\r\n"; + 3 assert!(mid <= len); - 2 stream.write_all(response.3 as_bytes()).unwrap(); + 4 unsafe { + ( + 5 slice::from_raw_parts_mut(ptr, mid), + 6 slice::from_raw_parts_mut(ptr.add(mid), len - mid), + ) + } } ``` -Listing 20-3: Writing a tiny successful HTTP response to the stream +Listing 19-6: Using unsafe code in the implementation of the `split_at_mut` +function + +Recall from “The Slice Type” on page XX that a slice is a pointer to some data +and the length of the slice. We use the `len` method to get the length of a +slice [1] and the `as_mut_ptr` method to access the raw pointer of a slice [2]. +In this case, because we have a mutable slice to `i32` values, `as_mut_ptr` +returns a raw pointer with the type `*mut i32`, which we’ve stored in the +variable `ptr`. + +We keep the assertion that the `mid` index is within the slice [3]. Then we get +to the unsafe code [4]: the `slice::from_raw_parts_mut` function takes a raw +pointer and a length, and it creates a slice. We use it to create a slice that +starts from `ptr` and is `mid` items long [5]. Then we call the `add` method on +`ptr` with `mid` as an argument to get a raw pointer that starts at `mid`, and +we create a slice using that pointer and the remaining number of items after +`mid` as the length [6]. + +The function `slice::from_raw_parts_mut` is unsafe because it takes a raw +pointer and must trust that this pointer is valid. The `add` method on raw +pointers is also unsafe because it must trust that the offset location is also +a valid pointer. Therefore, we had to put an `unsafe` block around our calls to +`slice::from_raw_parts_mut` and `add` so we could call them. By looking at the +code and by adding the assertion that `mid` must be less than or equal to +`len`, we can tell that all the raw pointers used within the `unsafe` block +will be valid pointers to data within the slice. This is an acceptable and +appropriate use of `unsafe`. + +Note that we don’t need to mark the resultant `split_at_mut` function as +`unsafe`, and we can call this function from safe Rust. We’ve created a safe +abstraction to the unsafe code with an implementation of the function that uses +`unsafe` code in a safe way, because it creates only valid pointers from the +data this function has access to. + +In contrast, the use of `slice::from_raw_parts_mut` in Listing 19-7 would +likely crash when the slice is used. This code takes an arbitrary memory +location and creates a slice 10,000 items long. + +``` +use std::slice; + +let address = 0x01234usize; +let r = address as *mut i32; + +let values: &[i32] = unsafe { + slice::from_raw_parts_mut(r, 10000) +}; +``` -The first new line defines the `response` variable that holds the success -message’s data [1]. Then we call `as_bytes` on our `response` to convert the -string data to bytes [3]. The `write_all` method on `stream` takes a `&[u8]` -and sends those bytes directly down the connection [2]. Because the `write_all` -operation could fail, we use `unwrap` on any error result as before. Again, in -a real application you would add error handling here. +Listing 19-7: Creating a slice from an arbitrary memory location -With these changes, let’s run our code and make a request. We’re no longer -printing any data to the terminal, so we won’t see any output other than the -output from Cargo. When you load *127.0.0.1:7878* in a web browser, you should -get a blank page instead of an error. You’ve just handcoded receiving an HTTP -request and sending a response! +We don’t own the memory at this arbitrary location, and there is no guarantee +that the slice this code creates contains valid `i32` values. Attempting to use +`values` as though it’s a valid slice results in undefined behavior. -### Returning Real HTML +#### Using extern Functions to Call External Code -Let’s implement the functionality for returning more than a blank page. Create -the new file *hello.html* in the root of your project directory, not in the -*src* directory. You can input any HTML you want; Listing 20-4 shows one -possibility. +Sometimes your Rust code might need to interact with code written in another +language. For this, Rust has the keyword `extern` that facilitates the creation +and use of a *Foreign Function Interface* *(FFI)*, which is a way for a +programming language to define functions and enable a different (foreign) +programming language to call those functions. -Filename: hello.html +Listing 19-8 demonstrates how to set up an integration with the `abs` function +from the C standard library. Functions declared within `extern` blocks are +always unsafe to call from Rust code. The reason is that other languages don’t +enforce Rust’s rules and guarantees, and Rust can’t check them, so +responsibility falls on the programmer to ensure safety. + +Filename: src/main.rs ``` -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <title>Hello! - - -

Hello!

-

Hi from Rust

- - -``` +extern "C" { + fn abs(input: i32) -> i32; +} -Listing 20-4: A sample HTML file to return in a response +fn main() { + unsafe { + println!( + "Absolute value of -3 according to C: {}", + abs(-3) + ); + } +} +``` -This is a minimal HTML5 document with a heading and some text. To return this -from the server when a request is received, we’ll modify `handle_connection` as -shown in Listing 20-5 to read the HTML file, add it to the response as a body, -and send it. +Listing 19-8: Declaring and calling an `extern` function defined in another +language + +Within the `extern "C"` block, we list the names and signatures of external +functions from another language we want to call. The `"C"` part defines which +*application binary interface* *(ABI)* the external function uses: the ABI +defines how to call the function at the assembly level. The `"C"` ABI is the +most common and follows the C programming language’s ABI. + +> ### Calling Rust Functions from Other Languages +> +> We can also use `extern` to create an interface that allows other languages +to call Rust functions. Instead of creating a whole `extern` block, we add the +`extern` keyword and specify the ABI to use just before the `fn` keyword for +the relevant function. We also need to add a `#[no_mangle]` annotation to tell +the Rust compiler not to mangle the name of this function. *Mangling* is when a +compiler changes the name we’ve given a function to a different name that +contains more information for other parts of the compilation process to consume +but is less human readable. Every programming language compiler mangles names +slightly differently, so for a Rust function to be nameable by other languages, +we must disable the Rust compiler’s name mangling. +> +> In the following example, we make the `call_from_c` function accessible from +C code, after it’s compiled to a shared library and linked from C: +> +> ``` +> #[no_mangle] +> pub extern "C" fn call_from_c() { +> println!("Just called a Rust function from C!"); +> } +> ``` +> +> This usage of `extern` does not require `unsafe`. + +### Accessing or Modifying a Mutable Static Variable + +In this book, we’ve not yet talked about global variables, which Rust does +support but can be problematic with Rust’s ownership rules. If two threads are +accessing the same mutable global variable, it can cause a data race. + +In Rust, global variables are called *static* variables. Listing 19-9 shows an +example declaration and use of a static variable with a string slice as a value. Filename: src/main.rs ``` -use std::{ - 1 fs, - io::{prelude::*, BufReader}, - net::{TcpListener, TcpStream}, -}; ---snip-- - -fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); - let http_request: Vec<_> = buf_reader - .lines() - .map(|result| result.unwrap()) - .take_while(|line| !line.is_empty()) - .collect(); - - let status_line = "HTTP/1.1 200 OK"; - let contents = fs::read_to_string("hello.html").unwrap(); - let length = contents.len(); - - 2 let response = format!( - "{status_line}\r\n\ - Content-Length: {length}\r\n\r\n\ - {contents}" - ); +static HELLO_WORLD: &str = "Hello, world!"; - stream.write_all(response.as_bytes()).unwrap(); +fn main() { + println!("value is: {HELLO_WORLD}"); } ``` -Listing 20-5: Sending the contents of *hello.html* as the body of the response - -We’ve added `fs` to the `use` statement to bring the standard library’s -filesystem module into scope [1]. The code for reading the contents of a file -to a string should look familiar; we used it when we read the contents of a -file for our I/O project in Listing 12-4. +Listing 19-9: Defining and using an immutable static variable -Next, we use `format!` to add the file’s contents as the body of the success -response [2]. To ensure a valid HTTP response, we add the `Content-Length` -header which is set to the size of our response body, in this case the size of -`hello.html`. +Static variables are similar to constants, which we discussed in “Constants” on +page XX. The names of static variables are in `SCREAMING_SNAKE_CASE` by +convention. Static variables can only store references with the `'static` +lifetime, which means the Rust compiler can figure out the lifetime and we +aren’t required to annotate it explicitly. Accessing an immutable static +variable is safe. -Run this code with `cargo run` and load *127.0.0.1:7878* in your browser; you -should see your HTML rendered! +A subtle difference between constants and immutable static variables is that +values in a static variable have a fixed address in memory. Using the value +will always access the same data. Constants, on the other hand, are allowed to +duplicate their data whenever they’re used. Another difference is that static +variables can be mutable. Accessing and modifying mutable static variables is +*unsafe*. Listing 19-10 shows how to declare, access, and modify a mutable +static variable named `COUNTER`. -Currently, we’re ignoring the request data in `http_request` and just sending -back the contents of the HTML file unconditionally. That means if you try -requesting *127.0.0.1:7878/something-else* in your browser, you’ll still get -back this same HTML response. At the moment, our server is very limited and -does not do what most web servers do. We want to customize our responses -depending on the request and only send back the HTML file for a well-formed -request to */*. +Filename: src/main.rs -### Validating the Request and Selectively Responding +``` +static mut COUNTER: u32 = 0; -Right now, our web server will return the HTML in the file no matter what the -client requested. Let’s add functionality to check that the browser is -requesting */* before returning the HTML file, and return an error if the -browser requests anything else. For this we need to modify `handle_connection`, -as shown in Listing 20-6. This new code checks the content of the request -received against what we know a request for */* looks like and adds `if` and -`else` blocks to treat requests differently. +fn add_to_count(inc: u32) { + unsafe { + COUNTER += inc; + } +} -Filename: src/main.rs +fn main() { + add_to_count(3); + unsafe { + println!("COUNTER: {COUNTER}"); + } +} ``` ---snip-- -fn handle_connection(mut stream: TcpStream) { - let buf_reader = BufReader::new(&mut stream); - 1 let request_line = buf_reader - .lines() - .next() - .unwrap() - .unwrap(); +Listing 19-10: Reading from or writing to a mutable static variable is unsafe. - 2 if request_line == "GET / HTTP/1.1" { - let status_line = "HTTP/1.1 200 OK"; - let contents = fs::read_to_string("hello.html").unwrap(); - let length = contents.len(); +As with regular variables, we specify mutability using the `mut` keyword. Any +code that reads or writes from `COUNTER` must be within an `unsafe` block. This +code compiles and prints `COUNTER: 3` as we would expect because it’s single +threaded. Having multiple threads access `COUNTER` would likely result in data +races. - let response = format!( - "{status_line}\r\n\ - Content-Length: {length}\r\n\r\n\ - {contents}" - ); +With mutable data that is globally accessible, it’s difficult to ensure there +are no data races, which is why Rust considers mutable static variables to be +unsafe. Where possible, it’s preferable to use the concurrency techniques and +thread-safe smart pointers we discussed in Chapter 16 so the compiler checks +that data access from different threads is done safely. - stream.write_all(response.as_bytes()).unwrap(); - 3 } else { - // some other request - } +### Implementing an Unsafe Trait + +We can use `unsafe` to implement an unsafe trait. A trait is unsafe when at +least one of its methods has some invariant that the compiler can’t verify. We +declare that a trait is `unsafe` by adding the `unsafe` keyword before `trait` +and marking the implementation of the trait as `unsafe` too, as shown in +Listing 19-11. + +``` +unsafe trait Foo { + // methods go here +} + +unsafe impl Foo for i32 { + // method implementations go here } ``` -Listing 20-6: Handling requests to */* differently from other requests +Listing 19-11: Defining and implementing an unsafe trait -We’re only going to be looking at the first line of the HTTP request, so rather -than reading the entire request into a vector, we’re calling `next` to get the -first item from the iterator [1]. The first `unwrap` takes care of the `Option` -and stops the program if the iterator has no items. The second `unwrap` handles -the `Result` and has the same effect as the `unwrap` that was in the `map` -added in Listing 20-2. +By using `unsafe impl`, we’re promising that we’ll uphold the invariants that +the compiler can’t verify. -Next, we check the `request_line` to see if it equals the request line of a GET -request to the */* path [2]. If it does, the `if` block returns the contents of -our HTML file. +As an example, recall the `Send` and `Sync` marker traits we discussed in +“Extensible Concurrency with the Send and Sync Traits” on page XX: the compiler +implements these traits automatically if our types are composed entirely of +`Send` and `Sync` types. If we implement a type that contains a type that is +not `Send` or `Sync`, such as raw pointers, and we want to mark that type as +`Send` or `Sync`, we must use `unsafe`. Rust can’t verify that our type upholds +the guarantees that it can be safely sent across threads or accessed from +multiple threads; therefore, we need to do those checks manually and indicate +as such with `unsafe`. -If the `request_line` does *not* equal the GET request to the */* path, it -means we’ve received some other request. We’ll add code to the `else` block [3] -in a moment to respond to all other requests. +### Accessing Fields of a Union -Run this code now and request *127.0.0.1:7878*; you should get the HTML in -*hello.html*. If you make any other request, such as -*127.0.0.1:7878/something-else*, you’ll get a connection error like those you -saw when running the code in Listing 20-1 and Listing 20-2. +The final action that works only with `unsafe` is accessing fields of a union. +A `union` is similar to a `struct`, but only one declared field is used in a +particular instance at one time. Unions are primarily used to interface with +unions in C code. Accessing union fields is unsafe because Rust can’t guarantee +the type of the data currently being stored in the union instance. You can +learn more about unions in the Rust Reference at +*https://doc.rust-lang.org/reference/items/unions.html**.* -Now let’s add the code in Listing 20-7 to the `else` block to return a response -with the status code 404, which signals that the content for the request was -not found. We’ll also return some HTML for a page to render in the browser -indicating the response to the end user. +### When to Use Unsafe Code -Filename: src/main.rs +Using `unsafe` to use one of the five superpowers just discussed isn’t wrong or +even frowned upon, but it is trickier to get `unsafe` code correct because the +compiler can’t help uphold memory safety. When you have a reason to use +`unsafe` code, you can do so, and having the explicit `unsafe` annotation makes +it easier to track down the source of problems when they occur. -``` ---snip-- -} else { - 1 let status_line = "HTTP/1.1 404 NOT FOUND"; - 2 let contents = fs::read_to_string("404.html").unwrap(); - let length = contents.len(); +## Advanced Traits - let response = format!( - "{status_line}\r\n\ - Content-Length: {length}\r\n\r\n - {contents}" - ); +We first covered traits in “Traits: Defining Shared Behavior” on page XX, but +we didn’t discuss the more advanced details. Now that you know more about Rust, +we can get into the nitty-gritty. + +### Associated Types - stream.write_all(response.as_bytes()).unwrap(); +*Associated types* connect a type placeholder with a trait such that the trait +method definitions can use these placeholder types in their signatures. The +implementor of a trait will specify the concrete type to be used instead of the +placeholder type for the particular implementation. That way, we can define a +trait that uses some types without needing to know exactly what those types are +until the trait is implemented. + +We’ve described most of the advanced features in this chapter as being rarely +needed. Associated types are somewhere in the middle: they’re used more rarely +than features explained in the rest of the book but more commonly than many of +the other features discussed in this chapter. + +One example of a trait with an associated type is the `Iterator` trait that the +standard library provides. The associated type is named `Item` and stands in +for the type of the values the type implementing the `Iterator` trait is +iterating over. The definition of the `Iterator` trait is as shown in Listing +19-12. + +``` +pub trait Iterator { + type Item; + + fn next(&mut self) -> Option; } ``` -Listing 20-7: Responding with status code 404 and an error page if anything -other than */* was requested +Listing 19-12: The definition of the `Iterator` trait that has an associated +type `Item` -Here, our response has a status line with status code 404 and the reason phrase -`NOT FOUND` [1]. The body of the response will be the HTML in the file -*404.html* [1]. You’ll need to create a *404.html* file next to *hello.html* -for the error page; again feel free to use any HTML you want, or use the -example HTML in Listing 20-8. +The type `Item` is a placeholder, and the `next` method’s definition shows that +it will return values of type `Option`. Implementors of the +`Iterator` trait will specify the concrete type for `Item`, and the `next` +method will return an `Option` containing a value of that concrete type. -Filename: 404.html +Associated types might seem like a similar concept to generics, in that the +latter allow us to define a function without specifying what types it can +handle. To examine the difference between the two concepts, we’ll look at an +implementation of the `Iterator` trait on a type named `Counter` that specifies +the `Item` type is `u32`: + +Filename: src/lib.rs ``` - - - - - Hello! - - -

Oops!

-

Sorry, I don't know what you're asking for.

- - -``` +impl Iterator for Counter { + type Item = u32; -Listing 20-8: Sample content for the page to send back with any 404 response + fn next(&mut self) -> Option { + --snip-- +``` -With these changes, run your server again. Requesting *127.0.0.1:7878* should -return the contents of *hello.html*, and any other request, like -*127.0.0.1:7878/foo*, should return the error HTML from *404.html*. +This syntax seems comparable to that of generics. So why not just define the +`Iterator` trait with generics, as shown in Listing 19-13? -### A Touch of Refactoring +``` +pub trait Iterator { + fn next(&mut self) -> Option; +} +``` -At the moment, the `if` and `else` blocks have a lot of repetition: they’re -both reading files and writing the contents of the files to the stream. The -only differences are the status line and the filename. Let’s make the code more -concise by pulling out those differences into separate `if` and `else` lines -that will assign the values of the status line and the filename to variables; -we can then use those variables unconditionally in the code to read the file -and write the response. Listing 20-9 shows the resultant code after replacing -the large `if` and `else` blocks. +Listing 19-13: A hypothetical definition of the `Iterator` trait using generics + +The difference is that when using generics, as in Listing 19-13, we must +annotate the types in each implementation; because we can also implement +`Iterator<``String``> for Counter` or any other type, we could have multiple +implementations of `Iterator` for `Counter`. In other words, when a trait has a +generic parameter, it can be implemented for a type multiple times, changing +the concrete types of the generic type parameters each time. When we use the +`next` method on `Counter`, we would have to provide type annotations to +indicate which implementation of `Iterator` we want to use. + +With associated types, we don’t need to annotate types because we can’t +implement a trait on a type multiple times. In Listing 19-12 with the +definition that uses associated types, we can choose what the type of `Item` +will be only once because there can be only one `impl Iterator for Counter`. We +don’t have to specify that we want an iterator of `u32` values everywhere we +call `next` on `Counter`. + +Associated types also become part of the trait’s contract: implementors of the +trait must provide a type to stand in for the associated type placeholder. +Associated types often have a name that describes how the type will be used, +and documenting the associated type in the API documentation is a good practice. + +### Default Generic Type Parameters and Operator Overloading + +When we use generic type parameters, we can specify a default concrete type for +the generic type. This eliminates the need for implementors of the trait to +specify a concrete type if the default type works. You specify a default type +when declaring a generic type with the `<`PlaceholderType`=`ConcreteType`>` +syntax. + +A great example of a situation where this technique is useful is with *operator +overloading*, in which you customize the behavior of an operator (such as `+`) +in particular situations. + +Rust doesn’t allow you to create your own operators or overload arbitrary +operators. But you can overload the operations and corresponding traits listed +in `std::ops` by implementing the traits associated with the operator. For +example, in Listing 19-14 we overload the `+` operator to add two `Point` +instances together. We do this by implementing the `Add` trait on a `Point` +struct. Filename: src/main.rs ``` ---snip-- +use std::ops::Add; -fn handle_connection(mut stream: TcpStream) { - --snip-- +#[derive(Debug, Copy, Clone, PartialEq)] +struct Point { + x: i32, + y: i32, +} - let (status_line, filename) = - if request_line == "GET / HTTP/1.1" { - ("HTTP/1.1 200 OK", "hello.html") - } else { - ("HTTP/1.1 404 NOT FOUND", "404.html") - }; +impl Add for Point { + type Output = Point; - let contents = fs::read_to_string(filename).unwrap(); - let length = contents.len(); + fn add(self, other: Point) -> Point { + Point { + x: self.x + other.x, + y: self.y + other.y, + } + } +} - let response = format!( - "{status_line}\r\n\ - Content-Length: {length}\r\n\r\n\ - {contents}" +fn main() { + assert_eq!( + Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, + Point { x: 3, y: 3 } ); - - stream.write_all(response.as_bytes()).unwrap(); } ``` -Listing 20-9: Refactoring the `if` and `else` blocks to contain only the code -that differs between the two cases - -Now the `if` and `else` blocks only return the appropriate values for the -status line and filename in a tuple; we then use destructuring to assign these -two values to `status_line` and `filename` using a pattern in the `let` -statement, as discussed in Chapter 18. +Listing 19-14: Implementing the `Add` trait to overload the `+` operator for +`Point` instances -The previously duplicated code is now outside the `if` and `else` blocks and -uses the `status_line` and `filename` variables. This makes it easier to see -the difference between the two cases, and it means we have only one place to -update the code if we want to change how the file reading and response writing -work. The behavior of the code in Listing 20-9 will be the same as that in -Listing 20-8. +The `add` method adds the `x` values of two `Point` instances and the `y` +values of two `Point` instances to create a new `Point`. The `Add` trait has an +associated type named `Output` that determines the type returned from the `add` +method. -Awesome! We now have a simple web server in approximately 40 lines of Rust code -that responds to one request with a page of content and responds to all other -requests with a 404 response. +The default generic type in this code is within the `Add` trait. Here is its +definition: -Currently, our server runs in a single thread, meaning it can only serve one -request at a time. Let’s examine how that can be a problem by simulating some -slow requests. Then we’ll fix it so our server can handle multiple requests at -once. +``` +trait Add { + type Output; -## Turning Our Single-Threaded Server into a Multithreaded Server + fn add(self, rhs: Rhs) -> Self::Output; +} +``` -Right now, the server will process each request in turn, meaning it won’t -process a second connection until the first is finished processing. If the -server received more and more requests, this serial execution would be less and -less optimal. If the server receives a request that takes a long time to -process, subsequent requests will have to wait until the long request is -finished, even if the new requests can be processed quickly. We’ll need to fix -this, but first we’ll look at the problem in action. +This code should look generally familiar: a trait with one method and an +associated type. The new part is `Rhs=Self`: this syntax is called *default +type parameters*. The `Rhs` generic type parameter (short for “right-hand +side”) defines the type of the `rhs` parameter in the `add` method. If we don’t +specify a concrete type for `Rhs` when we implement the `Add` trait, the type +of `Rhs` will default to `Self`, which will be the type we’re implementing +`Add` on. -### Simulating a Slow Request +When we implemented `Add` for `Point`, we used the default for `Rhs` because we +wanted to add two `Point` instances. Let’s look at an example of implementing +the `Add` trait where we want to customize the `Rhs` type rather than using the +default. -We’ll look at how a slow-processing request can affect other requests made to -our current server implementation. Listing 20-10 implements handling a request -to */sleep* with a simulated slow response that will cause the server to sleep -for five seconds before responding. +We have two structs, `Millimeters` and `Meters`, holding values in different +units. This thin wrapping of an existing type in another struct is known as the +*newtype pattern*, which we describe in more detail in “Using the Newtype +Pattern to Implement External Traits on External Types” on page XX. We want to +add values in millimeters to values in meters and have the implementation of +`Add` do the conversion correctly. We can implement `Add` for `Millimeters` +with `Meters` as the `Rhs`, as shown in Listing 19-15. -Filename: src/main.rs +Filename: src/lib.rs ``` -use std::{ - fs, - io::{prelude::*, BufReader}, - net::{TcpListener, TcpStream}, - thread, - time::Duration, -}; ---snip-- +use std::ops::Add; -fn handle_connection(mut stream: TcpStream) { - --snip-- +struct Millimeters(u32); +struct Meters(u32); - let (status_line, filename) = 1 match &request_line[..] { - 2 "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), - 3 "GET /sleep HTTP/1.1" => { - thread::sleep(Duration::from_secs(5)); - ("HTTP/1.1 200 OK", "hello.html") - } - 4 _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), - }; +impl Add for Millimeters { + type Output = Millimeters; - --snip-- + fn add(self, other: Meters) -> Millimeters { + Millimeters(self.0 + (other.0 * 1000)) + } } ``` -Listing 20-10: Simulating a slow request by sleeping for five seconds - -We switched from `if` to `match` now that we have three cases [1]. We need to -explicitly match on a slice of `request_line` to pattern-match against the -string literal values; `match` doesn’t do automatic referencing and -dereferencing, like the equality method does. - -The first arm [2] is the same as the `if` block from Listing 20-9. The second -arm [3] matches a request to */sleep*. When that request is received, the -server will sleep for five seconds before rendering the successful HTML page. -The third arm [4] is the same as the `else` block from Listing 20-9. - -You can see how primitive our server is: real libraries would handle the -recognition of multiple requests in a much less verbose way! - -Start the server using `cargo run`. Then open two browser windows: one for -*http://127.0.0.1:7878* and the other for *http://127.0.0.1:7878/sleep*. If you -enter the */* URI a few times, as before, you’ll see it respond quickly. But if -you enter */sleep* and then load */*, you’ll see that */* waits until `sleep` -has slept for its full five seconds before loading. - -There are multiple techniques we could use to avoid requests backing up behind -a slow request; the one we’ll implement is a thread pool. - -### Improving Throughput with a Thread Pool - -A *thread pool* is a group of spawned threads that are waiting and ready to -handle a task. When the program receives a new task, it assigns one of the -threads in the pool to the task, and that thread will process the task. The -remaining threads in the pool are available to handle any other tasks that come -in while the first thread is processing. When the first thread is done -processing its task, it’s returned to the pool of idle threads, ready to handle -a new task. A thread pool allows you to process connections concurrently, -increasing the throughput of your server. - -We’ll limit the number of threads in the pool to a small number to protect us -from DoS attacks; if we had our program create a new thread for each request as -it came in, someone making 10 million requests to our server could create havoc -by using up all our server’s resources and grinding the processing of requests -to a halt. - -Rather than spawning unlimited threads, then, we’ll have a fixed number of -threads waiting in the pool. Requests that come in are sent to the pool for -processing. The pool will maintain a queue of incoming requests. Each of the -threads in the pool will pop off a request from this queue, handle the request, -and then ask the queue for another request. With this design, we can process up -to N requests concurrently, where N is the number of threads. If each thread is -responding to a long-running request, subsequent requests can still back up in -the queue, but we’ve increased the number of long-running requests we can -handle before reaching that point. - -This technique is just one of many ways to improve the throughput of a web -server. Other options you might explore are the fork/join model, the -single-threaded async I/O model, and the multithreaded async I/O model. If -you’re interested in this topic, you can read more about other solutions and -try to implement them; with a low-level language like Rust, all of these -options are possible. - -Before we begin implementing a thread pool, let’s talk about what using the -pool should look like. When you’re trying to design code, writing the client -interface first can help guide your design. Write the API of the code so it’s -structured in the way you want to call it; then implement the functionality -within that structure rather than implementing the functionality and then -designing the public API. - -Similar to how we used test-driven development in the project in Chapter 12, -we’ll use compiler-driven development here. We’ll write the code that calls the -functions we want, and then we’ll look at errors from the compiler to determine -what we should change next to get the code to work. Before we do that, however, -we’ll explore the technique we’re not going to use as a starting point. - -#### Spawning a Thread for Each Request - -First, let’s explore how our code might look if it did create a new thread for -every connection. As mentioned earlier, this isn’t our final plan due to the -problems with potentially spawning an unlimited number of threads, but it is a -starting point to get a working multithreaded server first. Then we’ll add the -thread pool as an improvement, and contrasting the two solutions will be easier. - -Listing 20-11 shows the changes to make to `main` to spawn a new thread to -handle each stream within the `for` loop. +Listing 19-15: Implementing the `Add` trait on `Millimeters` to add +`Millimeters` and `Meters` + +To add `Millimeters` and `Meters`, we specify `impl Add` to set the +value of the `Rhs` type parameter instead of using the default of `Self`. + +You’ll use default type parameters in two main ways: + +1. To extend a type without breaking existing code +1. To allow customization in specific cases most users won’t need + +The standard library’s `Add` trait is an example of the second purpose: +usually, you’ll add two like types, but the `Add` trait provides the ability to +customize beyond that. Using a default type parameter in the `Add` trait +definition means you don’t have to specify the extra parameter most of the +time. In other words, a bit of implementation boilerplate isn’t needed, making +it easier to use the trait. + +The first purpose is similar to the second but in reverse: if you want to add a +type parameter to an existing trait, you can give it a default to allow +extension of the functionality of the trait without breaking the existing +implementation code. + +### Disambiguating Between Methods with the Same Name + +Nothing in Rust prevents a trait from having a method with the same name as +another trait’s method, nor does Rust prevent you from implementing both traits +on one type. It’s also possible to implement a method directly on the type with +the same name as methods from traits. + +When calling methods with the same name, you’ll need to tell Rust which one you +want to use. Consider the code in Listing 19-16 where we’ve defined two traits, +`Pilot` and `Wizard`, that both have a method called `fly`. We then implement +both traits on a type `Human` that already has a method named `fly` implemented +on it. Each `fly` method does something different. Filename: src/main.rs ``` -fn main() { - let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); +trait Pilot { + fn fly(&self); +} - for stream in listener.incoming() { - let stream = stream.unwrap(); +trait Wizard { + fn fly(&self); +} - thread::spawn(|| { - handle_connection(stream); - }); +struct Human; + +impl Pilot for Human { + fn fly(&self) { + println!("This is your captain speaking."); } } -``` -Listing 20-11: Spawning a new thread for each stream +impl Wizard for Human { + fn fly(&self) { + println!("Up!"); + } +} -As you learned in Chapter 16, `thread::spawn` will create a new thread and then -run the code in the closure in the new thread. If you run this code and load -*/sleep* in your browser, then */* in two more browser tabs, you’ll indeed see -that the requests to */* don’t have to wait for */sleep* to finish. However, as -we mentioned, this will eventually overwhelm the system because you’d be making -new threads without any limit. +impl Human { + fn fly(&self) { + println!("*waving arms furiously*"); + } +} +``` -#### Creating a Finite Number of Threads +Listing 19-16: Two traits are defined to have a `fly` method and are +implemented on the `Human` type, and a `fly` method is implemented on `Human` +directly. -We want our thread pool to work in a similar, familiar way so that switching -from threads to a thread pool doesn’t require large changes to the code that -uses our API. Listing 20-12 shows the hypothetical interface for a `ThreadPool` -struct we want to use instead of `thread::spawn`. +When we call `fly` on an instance of `Human`, the compiler defaults to calling +the method that is directly implemented on the type, as shown in Listing 19-17. Filename: src/main.rs ``` fn main() { - let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); - 1 let pool = ThreadPool::new(4); - - for stream in listener.incoming() { - let stream = stream.unwrap(); - - 2 pool.execute(|| { - handle_connection(stream); - }); - } + let person = Human; + person.fly(); } ``` -Listing 20-12: Our ideal `ThreadPool` interface +Listing 19-17: Calling `fly` on an instance of `Human` -We use `ThreadPool::new` to create a new thread pool with a configurable number -of threads, in this case four [1]. Then, in the `for` loop, `pool.execute` has -a similar interface as `thread::spawn` in that it takes a closure the pool -should run for each stream [2]. We need to implement `pool.execute` so it takes -the closure and gives it to a thread in the pool to run. This code won’t yet -compile, but we’ll try so that the compiler can guide us in how to fix it. +Running this code will print `*waving arms furiously*`, showing that Rust +called the `fly` method implemented on `Human` directly. -#### Building ThreadPool Using Compiler-Driven Development +To call the `fly` methods from either the `Pilot` trait or the `Wizard` trait, +we need to use more explicit syntax to specify which `fly` method we mean. +Listing 19-18 demonstrates this syntax. -Make the changes in Listing 20-12 to *src/main.rs*, and then let’s use the -compiler errors from `cargo check` to drive our development. Here is the first -error we get: +Filename: src/main.rs ``` -$ cargo check - Checking hello v0.1.0 (file:///projects/hello) -error[E0433]: failed to resolve: use of undeclared type `ThreadPool` - --> src/main.rs:11:16 - | -11 | let pool = ThreadPool::new(4); - | ^^^^^^^^^^ use of undeclared type `ThreadPool` +fn main() { + let person = Human; + Pilot::fly(&person); + Wizard::fly(&person); + person.fly(); +} ``` -Great! This error tells us we need a `ThreadPool` type or module, so we’ll -build one now. Our `ThreadPool` implementation will be independent of the kind -of work our web server is doing. So let’s switch the `hello` crate from a -binary crate to a library crate to hold our `ThreadPool` implementation. After -we change to a library crate, we could also use the separate thread pool -library for any work we want to do using a thread pool, not just for serving -web requests. +Listing 19-18: Specifying which trait’s `fly` method we want to call -Create a *src/lib.rs* file that contains the following, which is the simplest -definition of a `ThreadPool` struct that we can have for now: +Specifying the trait name before the method name clarifies to Rust which +implementation of `fly` we want to call. We could also write +`Human::fly(&person)`, which is equivalent to the `person.fly()` that we used +in Listing 19-18, but this is a bit longer to write if we don’t need to +disambiguate. -Filename: src/lib.rs +Running this code prints the following: ``` -pub struct ThreadPool; +This is your captain speaking. +Up! +*waving arms furiously* ``` -Then edit the *main.rs* file to bring `ThreadPool` into scope from the library -crate by adding the following code to the top of *src/main.rs*: +Because the `fly` method takes a `self` parameter, if we had two *types* that +both implement one *trait*, Rust could figure out which implementation of a +trait to use based on the type of `self`. + +However, associated functions that are not methods don’t have a `self` +parameter. When there are multiple types or traits that define non-method +functions with the same function name, Rust doesn’t always know which type you +mean unless you use fully qualified syntax. For example, in Listing 19-19 we +create a trait for an animal shelter that wants to name all baby dogs Spot. We +make an `Animal` trait with an associated non-method function `baby_name`. The +`Animal` trait is implemented for the struct `Dog`, on which we also provide an +associated non-method function `baby_name` directly. Filename: src/main.rs ``` -use hello::ThreadPool; +trait Animal { + fn baby_name() -> String; +} + +struct Dog; + +impl Dog { + fn baby_name() -> String { + String::from("Spot") + } +} + +impl Animal for Dog { + fn baby_name() -> String { + String::from("puppy") + } +} + +fn main() { + println!("A baby dog is called a {}", Dog::baby_name()); +} ``` -This code still won’t work, but let’s check it again to get the next error that -we need to address: +Listing 19-19: A trait with an associated function and a type with an +associated function of the same name that also implements the trait + +We implement the code for naming all puppies Spot in the `baby_name` associated +function that is defined on `Dog`. The `Dog` type also implements the trait +`Animal`, which describes characteristics that all animals have. Baby dogs are +called puppies, and that is expressed in the implementation of the `Animal` +trait on `Dog` in the `baby_name` function associated with the `Animal` trait. + +In `main`, we call the `Dog::baby_name` function, which calls the associated +function defined on `Dog` directly. This code prints the following: ``` -$ cargo check - Checking hello v0.1.0 (file:///projects/hello) -error[E0599]: no function or associated item named `new` found for struct -`ThreadPool` in the current scope - --> src/main.rs:12:28 - | -12 | let pool = ThreadPool::new(4); - | ^^^ function or associated item not found in -`ThreadPool` +A baby dog is called a Spot ``` -This error indicates that next we need to create an associated function named -`new` for `ThreadPool`. We also know that `new` needs to have one parameter -that can accept `4` as an argument and should return a `ThreadPool` instance. -Let’s implement the simplest `new` function that will have those -characteristics: +This output isn’t what we wanted. We want to call the `baby_name` function that +is part of the `Animal` trait that we implemented on `Dog` so the code prints +`A baby dog is called a puppy`. The technique of specifying the trait name that +we used in Listing 19-18 doesn’t help here; if we change `main` to the code in +Listing 19-20, we’ll get a compilation error. -Filename: src/lib.rs +Filename: src/main.rs ``` -pub struct ThreadPool; - -impl ThreadPool { - pub fn new(size: usize) -> ThreadPool { - ThreadPool - } +fn main() { + println!("A baby dog is called a {}", Animal::baby_name()); } ``` -We chose `usize` as the type of the `size` parameter because we know that a -negative number of threads doesn’t make any sense. We also know we’ll use this -`4` as the number of elements in a collection of threads, which is what the -`usize` type is for, as discussed in “Integer Types” on page XX. +Listing 19-20: Attempting to call the `baby_name` function from the `Animal` +trait, but Rust doesn’t know which implementation to use -Let’s check the code again: +Because `Animal::baby_name` doesn’t have a `self` parameter, and there could be +other types that implement the `Animal` trait, Rust can’t figure out which +implementation of `Animal::baby_name` we want. We’ll get this compiler error: ``` -$ cargo check - Checking hello v0.1.0 (file:///projects/hello) -error[E0599]: no method named `execute` found for struct `ThreadPool` in the -current scope - --> src/main.rs:17:14 +error[E0283]: type annotations needed + --> src/main.rs:20:43 + | +20 | println!("A baby dog is called a {}", Animal::baby_name()); + | ^^^^^^^^^^^^^^^^^ cannot infer +type | -17 | pool.execute(|| { - | ^^^^^^^ method not found in `ThreadPool` -``` - -Now the error occurs because we don’t have an `execute` method on `ThreadPool`. -Recall from “Creating a Finite Number of Threads” on page XX that we decided -our thread pool should have an interface similar to `thread::spawn`. In -addition, we’ll implement the `execute` function so it takes the closure it’s -given and gives it to an idle thread in the pool to run. - -We’ll define the `execute` method on `ThreadPool` to take a closure as a -parameter. Recall from “Moving Captured Values Out of Closures and the Fn -Traits” on page XX that we can take closures as parameters with three different -traits: `Fn`, `FnMut`, and `FnOnce`. We need to decide which kind of closure to -use here. We know we’ll end up doing something similar to the standard library -`thread::spawn` implementation, so we can look at what bounds the signature of -`thread::spawn` has on its parameter. The documentation shows us the following: - -``` -pub fn spawn(f: F) -> JoinHandle - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, -``` - -The `F` type parameter is the one we’re concerned with here; the `T` type -parameter is related to the return value, and we’re not concerned with that. We -can see that `spawn` uses `FnOnce` as the trait bound on `F`. This is probably -what we want as well, because we’ll eventually pass the argument we get in -`execute` to `spawn`. We can be further confident that `FnOnce` is the trait we -want to use because the thread for running a request will only execute that -request’s closure one time, which matches the `Once` in `FnOnce`. - -The `F` type parameter also has the trait bound `Send` and the lifetime bound -`'static`, which are useful in our situation: we need `Send` to transfer the -closure from one thread to another and `'static` because we don’t know how long -the thread will take to execute. Let’s create an `execute` method on -`ThreadPool` that will take a generic parameter of type `F` with these bounds: + = note: cannot satisfy `_: Animal` +``` -Filename: src/lib.rs +To disambiguate and tell Rust that we want to use the implementation of +`Animal` for `Dog` as opposed to the implementation of `Animal` for some other +type, we need to use fully qualified syntax. Listing 19-21 demonstrates how to +use fully qualified syntax. + +Filename: src/main.rs ``` -impl ThreadPool { - --snip-- - pub fn execute(&self, f: F) - where - F: FnOnce() 1 + Send + 'static, - { - } +fn main() { + println!( + "A baby dog is called a {}", + ::baby_name() + ); } ``` -We still use the `()` after `FnOnce` [1] because this `FnOnce` represents a -closure that takes no parameters and returns the unit type `()`. Just like -function definitions, the return type can be omitted from the signature, but -even if we have no parameters, we still need the parentheses. +Listing 19-21: Using fully qualified syntax to specify that we want to call the +`baby_name` function from the `Animal` trait as implemented on `Dog` -Again, this is the simplest implementation of the `execute` method: it does -nothing, but we’re only trying to make our code compile. Let’s check it again: +We’re providing Rust with a type annotation within the angle brackets, which +indicates we want to call the `baby_name` method from the `Animal` trait as +implemented on `Dog` by saying that we want to treat the `Dog` type as an +`Animal` for this function call. This code will now print what we want: ``` -$ cargo check - Checking hello v0.1.0 (file:///projects/hello) - Finished dev [unoptimized + debuginfo] target(s) in 0.24s +A baby dog is called a puppy ``` -It compiles! But note that if you try `cargo run` and make a request in the -browser, you’ll see the errors in the browser that we saw at the beginning of -the chapter. Our library isn’t actually calling the closure passed to `execute` -yet! +In general, fully qualified syntax is defined as follows: -> Note: A saying you might hear about languages with strict compilers, such as -Haskell and Rust, is “if the code compiles, it works.” But this saying is not -universally true. Our project compiles, but it does absolutely nothing! If we -were building a real, complete project, this would be a good time to start -writing unit tests to check that the code compiles *and* has the behavior we -want. +``` +::function(receiver_if_method, next_arg, ...); +``` -#### Validating the Number of Threads in new +For associated functions that aren’t methods, there would not be a `receiver`: +there would only be the list of other arguments. You could use fully qualified +syntax everywhere that you call functions or methods. However, you’re allowed +to omit any part of this syntax that Rust can figure out from other information +in the program. You only need to use this more verbose syntax in cases where +there are multiple implementations that use the same name and Rust needs help +to identify which implementation you want to call. -We aren’t doing anything with the parameters to `new` and `execute`. Let’s -implement the bodies of these functions with the behavior we want. To start, -let’s think about `new`. Earlier we chose an unsigned type for the `size` -parameter because a pool with a negative number of threads makes no sense. -However, a pool with zero threads also makes no sense, yet zero is a perfectly -valid `usize`. We’ll add code to check that `size` is greater than zero before -we return a `ThreadPool` instance and have the program panic if it receives a -zero by using the `assert!` macro, as shown in Listing 20-13. +### Using Supertraits -Filename: src/lib.rs +Sometimes you might write a trait definition that depends on another trait: for +a type to implement the first trait, you want to require that type to also +implement the second trait. You would do this so that your trait definition can +make use of the associated items of the second trait. The trait your trait +definition is relying on is called a *supertrait* of your trait. +For example, let’s say we want to make an `OutlinePrint` trait with an +`outline_print` method that will print a given value formatted so that it’s +framed in asterisks. That is, given a `Point` struct that implements the +standard library trait `Display` to result in `(x, y)`, when we call +`outline_print` on a `Point` instance that has `1` for `x` and `3` for `y`, it +should print the following: + +``` +********** +* * +* (1, 3) * +* * +********** ``` -impl ThreadPool { - /// Create a new ThreadPool. - /// - /// The size is the number of threads in the pool. - /// - 1 /// # Panics - /// - /// The `new` function will panic if the size is zero. - pub fn new(size: usize) -> ThreadPool { - 2 assert!(size > 0); - ThreadPool - } +In the implementation of the `outline_print` method, we want to use the +`Display` trait’s functionality. Therefore, we need to specify that the +`OutlinePrint` trait will work only for types that also implement `Display` and +provide the functionality that `OutlinePrint` needs. We can do that in the +trait definition by specifying `OutlinePrint: Display`. This technique is +similar to adding a trait bound to the trait. Listing 19-22 shows an +implementation of the `OutlinePrint` trait. - --snip-- +Filename: src/main.rs + +``` +use std::fmt; + +trait OutlinePrint: fmt::Display { + fn outline_print(&self) { + let output = self.to_string(); + let len = output.len(); + println!("{}", "*".repeat(len + 4)); + println!("*{}*", " ".repeat(len + 2)); + println!("* {} *", output); + println!("*{}*", " ".repeat(len + 2)); + println!("{}", "*".repeat(len + 4)); + } } ``` -Listing 20-13: Implementing `ThreadPool::new` to panic if `size` is zero +Listing 19-22: Implementing the `OutlinePrint` trait that requires the +functionality from `Display` -We’ve also added some documentation for our `ThreadPool` with doc comments. -Note that we followed good documentation practices by adding a section that -calls out the situations in which our function can panic [1], as discussed in -Chapter 14. Try running `cargo doc --open` and clicking the `ThreadPool` struct -to see what the generated docs for `new` look like! +Because we’ve specified that `OutlinePrint` requires the `Display` trait, we +can use the `to_string` function that is automatically implemented for any type +that implements `Display`. If we tried to use `to_string` without adding a +colon and specifying the `Display` trait after the trait name, we’d get an +error saying that no method named `to_string` was found for the type `&Self` in +the current scope. -Instead of adding the `assert!` macro as we’ve done here [2], we could change -`new` into `build` and return a `Result` like we did with `Config::build` in -the I/O project in Listing 12-9. But we’ve decided in this case that trying to -create a thread pool without any threads should be an unrecoverable error. If -you’re feeling ambitious, try to write a function named `build` with the -following signature to compare with the `new` function: +Let’s see what happens when we try to implement `OutlinePrint` on a type that +doesn’t implement `Display`, such as the `Point` struct: + +Filename: src/main.rs ``` -pub fn build( - size: usize -) -> Result { -``` +struct Point { + x: i32, + y: i32, +} -#### Creating Space to Store the Threads +impl OutlinePrint for Point {} +``` -Now that we have a way to know we have a valid number of threads to store in -the pool, we can create those threads and store them in the `ThreadPool` struct -before returning the struct. But how do we “store” a thread? Let’s take another -look at the `thread::spawn` signature: +We get an error saying that `Display` is required but not implemented: ``` -pub fn spawn(f: F) -> JoinHandle - where - F: FnOnce() -> T, - F: Send + 'static, - T: Send + 'static, +error[E0277]: `Point` doesn't implement `std::fmt::Display` + --> src/main.rs:20:6 + | +20 | impl OutlinePrint for Point {} + | ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Point` + = note: in format strings you may be able to use `{:?}` (or {:#?} for +pretty-print) instead +note: required by a bound in `OutlinePrint` + --> src/main.rs:3:21 + | +3 | trait OutlinePrint: fmt::Display { + | ^^^^^^^^^^^^ required by this bound in `OutlinePrint` ``` -The `spawn` function returns a `JoinHandle`, where `T` is the type that the -closure returns. Let’s try using `JoinHandle` too and see what happens. In our -case, the closures we’re passing to the thread pool will handle the connection -and not return anything, so `T` will be the unit type `()`. - -The code in Listing 20-14 will compile but doesn’t create any threads yet. -We’ve changed the definition of `ThreadPool` to hold a vector of -`thread::JoinHandle<()>` instances, initialized the vector with a capacity of -`size`, set up a `for` loop that will run some code to create the threads, and -returned a `ThreadPool` instance containing them. +To fix this, we implement `Display` on `Point` and satisfy the constraint that +`OutlinePrint` requires, like so: -Filename: src/lib.rs +Filename: src/main.rs ``` -1 use std::thread; +use std::fmt; -pub struct ThreadPool { - 2 threads: Vec>, +impl fmt::Display for Point { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.x, self.y) + } } +``` -impl ThreadPool { - --snip-- - pub fn new(size: usize) -> ThreadPool { - assert!(size > 0); +Then, implementing the `OutlinePrint` trait on `Point` will compile +successfully, and we can call `outline_print` on a `Point` instance to display +it within an outline of asterisks. - 3 let mut threads = Vec::with_capacity(size); +### Using the Newtype Pattern to Implement External Traits - for _ in 0..size { - // create some threads and store them in the vector - } +In “Implementing a Trait on a Type” on page XX, we mentioned the orphan rule +that states we’re only allowed to implement a trait on a type if either the +trait or the type, or both, are local to our crate. It’s possible to get around +this restriction using the *newtype pattern*, which involves creating a new +type in a tuple struct. (We covered tuple structs in “Using Tuple Structs +Without Named Fields to Create Different Types” on page XX.) The tuple struct +will have one field and be a thin wrapper around the type for which we want to +implement a trait. Then the wrapper type is local to our crate, and we can +implement the trait on the wrapper. *Newtype* is a term that originates from +the Haskell programming language. There is no runtime performance penalty for +using this pattern, and the wrapper type is elided at compile time. + +As an example, let’s say we want to implement `Display` on `Vec`, which the +orphan rule prevents us from doing directly because the `Display` trait and the +`Vec` type are defined outside our crate. We can make a `Wrapper` struct +that holds an instance of `Vec`; then we can implement `Display` on +`Wrapper` and use the `Vec` value, as shown in Listing 19-23. + +Filename: src/main.rs - ThreadPool { threads } +``` +use std::fmt; + +struct Wrapper(Vec); + +impl fmt::Display for Wrapper { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{}]", self.0.join(", ")) } - --snip-- +} + +fn main() { + let w = Wrapper(vec![ + String::from("hello"), + String::from("world"), + ]); + println!("w = {w}"); } ``` -Listing 20-14: Creating a vector for `ThreadPool` to hold the threads +Listing 19-23: Creating a `Wrapper` type around `Vec` to implement +`Display` -We’ve brought `std::thread` into scope in the library crate [1] because we’re -using `thread::JoinHandle` as the type of the items in the vector in -`ThreadPool` [2]. +The implementation of `Display` uses `self.0` to access the inner `Vec` +because `Wrapper` is a tuple struct and `Vec` is the item at index 0 in the +tuple. Then we can use the functionality of the `Display` type on `Wrapper`. -Once a valid size is received, our `ThreadPool` creates a new vector that can -hold `size` items [3]. The `with_capacity` function performs the same task as -`Vec::new` but with an important difference: it pre-allocates space in the -vector. Because we know we need to store `size` elements in the vector, doing -this allocation up front is slightly more efficient than using `Vec::new`, -which resizes itself as elements are inserted. +The downside of using this technique is that `Wrapper` is a new type, so it +doesn’t have the methods of the value it’s holding. We would have to implement +all the methods of `Vec` directly on `Wrapper` such that the methods +delegate to `self.0`, which would allow us to treat `Wrapper` exactly like a +`Vec`. If we wanted the new type to have every method the inner type has, +implementing the `Deref` trait on the `Wrapper` to return the inner type would +be a solution (we discussed implementing the `Deref` trait in “Treating Smart +Pointers Like Regular References with Deref” on page XX). If we didn’t want the +`Wrapper` type to have all the methods of the inner type—for example, to +restrict the `Wrapper` type’s behavior—we would have to implement just the +methods we do want manually. -When you run `cargo check` again, it should succeed. +This newtype pattern is also useful even when traits are not involved. Let’s +switch focus and look at some advanced ways to interact with Rust’s type system. -#### Sending Code from the ThreadPool to a Thread +## Advanced Types -We left a comment in the `for` loop in Listing 20-14 regarding the creation of -threads. Here, we’ll look at how we actually create threads. The standard -library provides `thread::spawn` as a way to create threads, and -`thread::spawn` expects to get some code the thread should run as soon as the -thread is created. However, in our case, we want to create the threads and have -them *wait* for code that we’ll send later. The standard library’s -implementation of threads doesn’t include any way to do that; we have to -implement it manually. +The Rust type system has some features that we’ve so far mentioned but haven’t +yet discussed. We’ll start by discussing newtypes in general as we examine why +newtypes are useful as types. Then we’ll move on to type aliases, a feature +similar to newtypes but with slightly different semantics. We’ll also discuss +the `!` type and dynamically sized types. -We’ll implement this behavior by introducing a new data structure between the -`ThreadPool` and the threads that will manage this new behavior. We’ll call -this data structure *Worker*, which is a common term in pooling -implementations. The `Worker` picks up code that needs to be run and runs the -code in its thread. +### Using the Newtype Pattern for Type Safety and Abstraction -Think of people working in the kitchen at a restaurant: the workers wait until -orders come in from customers, and then they’re responsible for taking those -orders and filling them. +> Note: This section assumes you’ve read the earlier section “Using the Newtype +Pattern to Implement External Traits” on page XX. -Instead of storing a vector of `JoinHandle<()>` instances in the thread pool, -we’ll store instances of the `Worker` struct. Each `Worker` will store a single -`JoinHandle<()>` instance. Then we’ll implement a method on `Worker` that will -take a closure of code to run and send it to the already running thread for -execution. We’ll also give each `Worker` an `id` so we can distinguish between -the different instances of `Worker` in the pool when logging or debugging. +The newtype pattern is also useful for tasks beyond those we’ve discussed so +far, including statically enforcing that values are never confused and +indicating the units of a value. You saw an example of using newtypes to +indicate units in Listing 19-15: recall that the `Millimeters` and `Meters` +structs wrapped `u32` values in a newtype. If we wrote a function with a +parameter of type `Millimeters`, we wouldn’t be able to compile a program that +accidentally tried to call that function with a value of type `Meters` or a +plain `u32`. -Here is the new process that will happen when we create a `ThreadPool`. We’ll -implement the code that sends the closure to the thread after we have `Worker` -set up in this way: +We can also use the newtype pattern to abstract away some implementation +details of a type: the new type can expose a public API that is different from +the API of the private inner type. -1. Define a `Worker` struct that holds an `id` and a `JoinHandle<()>`. -1. Change `ThreadPool` to hold a vector of `Worker` instances. -1. Define a `Worker::new` function that takes an `id` number and returns a -`Worker` instance that holds the `id` and a thread spawned with an empty -closure. -1. In `ThreadPool::new`, use the `for` loop counter to generate an `id`, create -a new `Worker` with that `id`, and store the `Worker` in the vector. +Newtypes can also hide internal implementation. For example, we could provide a +`People` type to wrap a `HashMap` that stores a person’s ID +associated with their name. Code using `People` would only interact with the +public API we provide, such as a method to add a name string to the `People` +collection; that code wouldn’t need to know that we assign an `i32` ID to names +internally. The newtype pattern is a lightweight way to achieve encapsulation +to hide implementation details, which we discussed in “Encapsulation That Hides +Implementation Details” on page XX. -If you’re up for a challenge, try implementing these changes on your own before -looking at the code in Listing 20-15. +### Creating Type Synonyms with Type Aliases -Ready? Here is Listing 20-15 with one way to make the preceding modifications. +Rust provides the ability to declare a *type alias* to give an existing type +another name. For this we use the `type` keyword. For example, we can create +the alias `Kilometers` to `i32` like so: -Filename: src/lib.rs +``` +type Kilometers = i32; +``` + +Now the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters` +and `Meters` types we created in Listing 19-15, `Kilometers` is not a separate, +new type. Values that have the type `Kilometers` will be treated the same as +values of type `i32`: ``` -use std::thread; +type Kilometers = i32; -pub struct ThreadPool { - 1 workers: Vec, -} +let x: i32 = 5; +let y: Kilometers = 5; -impl ThreadPool { - --snip-- - pub fn new(size: usize) -> ThreadPool { - assert!(size > 0); +println!("x + y = {}", x + y); +``` - let mut workers = Vec::with_capacity(size); +Because `Kilometers` and `i32` are the same type, we can add values of both +types and we can pass `Kilometers` values to functions that take `i32` +parameters. However, using this method, we don’t get the type-checking benefits +that we get from the newtype pattern discussed earlier. In other words, if we +mix up `Kilometers` and `i32` values somewhere, the compiler will not give us +an error. - 2 for id in 0..size { - 3 workers.push(Worker::new(id)); - } +The main use case for type synonyms is to reduce repetition. For example, we +might have a lengthy type like this: - ThreadPool { workers } - } +``` +Box +``` + +Writing this lengthy type in function signatures and as type annotations all +over the code can be tiresome and error prone. Imagine having a project full of +code like that in Listing 19-24. + +``` +let f: Box = Box::new(|| { + println!("hi"); +}); + +fn takes_long_type(f: Box) { --snip-- } -4 struct Worker { - id: usize, - thread: thread::JoinHandle<()>, +fn returns_long_type() -> Box { + --snip-- } +``` -impl Worker { - 5 fn new(id: usize) -> Worker { - 6 let thread = thread::spawn(|| {}); +Listing 19-24: Using a long type in many places + +A type alias makes this code more manageable by reducing the repetition. In +Listing 19-25, we’ve introduced an alias named `Thunk` for the verbose type and +can replace all uses of the type with the shorter alias `Thunk`. - Worker { 7 id, 8 thread } - } -} ``` +type Thunk = Box; -Listing 20-15: Modifying `ThreadPool` to hold `Worker` instances instead of -holding threads directly +let f: Thunk = Box::new(|| println!("hi")); -We’ve changed the name of the field on `ThreadPool` from `threads` to `workers` -because it’s now holding `Worker` instances instead of `JoinHandle<()>` -instances [1]. We use the counter in the `for` loop [2] as an argument to -`Worker::new`, and we store each new `Worker` in the vector named `workers` [3]. +fn takes_long_type(f: Thunk) { + --snip-- +} -External code (like our server in *src/main.rs*) doesn’t need to know the -implementation details regarding using a `Worker` struct within `ThreadPool`, -so we make the `Worker` struct [4] and its `new` function [5] private. The -`Worker::new` function uses the `id` we give it [7] and stores a -`JoinHandle<()>` instance [8] that is created by spawning a new thread using an -empty closure [6]. +fn returns_long_type() -> Thunk { + --snip-- +} +``` -> Note: If the operating system can’t create a thread because there aren’t -enough system resources, `thread::spawn` will panic. That will cause our whole -server to panic, even though the creation of some threads might succeed. For -simplicity’s sake, this behavior is fine, but in a production thread pool -implementation, you’d likely want to use `std::thread::Builder` and its `spawn` -method that returns `Result` instead. +Listing 19-25: Introducing a type alias `Thunk` to reduce repetition -This code will compile and will store the number of `Worker` instances we -specified as an argument to `ThreadPool::new`. But we’re *still* not processing -the closure that we get in `execute`. Let’s look at how to do that next. +This code is much easier to read and write! Choosing a meaningful name for a +type alias can help communicate your intent as well (*thunk* is a word for code +to be evaluated at a later time, so it’s an appropriate name for a closure that +gets stored). -#### Sending Requests to Threads via Channels +Type aliases are also commonly used with the `Result` type for reducing +repetition. Consider the `std::io` module in the standard library. I/O +operations often return a `Result` to handle situations when operations +fail to work. This library has a `std::io::Error` struct that represents all +possible I/O errors. Many of the functions in `std::io` will be returning +`Result` where the `E` is `std::io::Error`, such as these functions in +the `Write` trait: -The next problem we’ll tackle is that the closures given to `thread::spawn` do -absolutely nothing. Currently, we get the closure we want to execute in the -`execute` method. But we need to give `thread::spawn` a closure to run when we -create each `Worker` during the creation of the `ThreadPool`. +``` +use std::fmt; +use std::io::Error; -We want the `Worker` structs that we just created to fetch the code to run from -a queue held in the `ThreadPool` and send that code to its thread to run. +pub trait Write { + fn write(&mut self, buf: &[u8]) -> Result; + fn flush(&mut self) -> Result<(), Error>; -The channels we learned about in Chapter 16—a simple way to communicate between -two threads—would be perfect for this use case. We’ll use a channel to function -as the queue of jobs, and `execute` will send a job from the `ThreadPool` to -the `Worker` instances, which will send the job to its thread. Here is the plan: + fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>; + fn write_fmt( + &mut self, + fmt: fmt::Arguments, + ) -> Result<(), Error>; +} +``` -1. The `ThreadPool` will create a channel and hold on to the sender. -1. Each `Worker` will hold on to the receiver. -1. We’ll create a new `Job` struct that will hold the closures we want to send -down the channel. -1. The `execute` method will send the job it wants to execute through the -sender. -1. In its thread, the `Worker` will loop over its receiver and execute the -closures of any jobs it receives. +The `Result<..., Error>` is repeated a lot. As such, `std::io` has this type +alias declaration: -Let’s start by creating a channel in `ThreadPool::new` and holding the sender -in the `ThreadPool` instance, as shown in Listing 20-16. The `Job` struct -doesn’t hold anything for now but will be the type of item we’re sending down -the channel. +``` +type Result = std::result::Result; +``` -Filename: src/lib.rs +Because this declaration is in the `std::io` module, we can use the fully +qualified alias `std::io::Result`; that is, a `Result` with the `E` +filled in as `std::io::Error`. The `Write` trait function signatures end up +looking like this: ``` -use std::{sync::mpsc, thread}; +pub trait Write { + fn write(&mut self, buf: &[u8]) -> Result; + fn flush(&mut self) -> Result<()>; -pub struct ThreadPool { - workers: Vec, - sender: mpsc::Sender, + fn write_all(&mut self, buf: &[u8]) -> Result<()>; + fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()>; } +``` -struct Job; - -impl ThreadPool { - --snip-- - pub fn new(size: usize) -> ThreadPool { - assert!(size > 0); - - 1 let (sender, receiver) = mpsc::channel(); +The type alias helps in two ways: it makes code easier to write *and* it gives +us a consistent interface across all of `std::io`. Because it’s an alias, it’s +just another `Result`, which means we can use any methods that work on +`Result` with it, as well as special syntax like the `?` operator. - let mut workers = Vec::with_capacity(size); +### The Never Type That Never Returns - for id in 0..size { - workers.push(Worker::new(id)); - } +Rust has a special type named `!` that’s known in type theory lingo as the +*empty type* because it has no values. We prefer to call it the *never type* +because it stands in the place of the return type when a function will never +return. Here is an example: - ThreadPool { workers, 2 sender } - } +``` +fn bar() -> ! { --snip-- } ``` -Listing 20-16: Modifying `ThreadPool` to store the sender of a channel that -transmits `Job` instances +This code is read as “the function `bar` returns never.” Functions that return +never are called *diverging functions*. We can’t create values of the type `!`, +so `bar` can never possibly return. + +But what use is a type you can never create values for? Recall the code from +Listing 2-5, part of the number-guessing game; we’ve reproduced a bit of it +here in Listing 19-26. -In `ThreadPool::new`, we create our new channel [1] and have the pool hold the -sender [2]. This will successfully compile. +``` +let guess: u32 = match guess.trim().parse() { + Ok(num) => num, + Err(_) => continue, +}; +``` -Let’s try passing a receiver of the channel into each `Worker` as the thread -pool creates the channel. We know we want to use the receiver in the thread -that the `Worker` instances spawn, so we’ll reference the `receiver` parameter -in the closure. The code in Listing 20-17 won’t quite compile yet. +Listing 19-26: A `match` with an arm that ends in `continue` -Filename: src/lib.rs +At the time, we skipped over some details in this code. In “The match Control +Flow Construct” on page XX, we discussed that `match` arms must all return the +same type. So, for example, the following code doesn’t work: ``` -impl ThreadPool { - --snip-- - pub fn new(size: usize) -> ThreadPool { - assert!(size > 0); +let guess = match guess.trim().parse() { + Ok(_) => 5, + Err(_) => "hello", +}; +``` - let (sender, receiver) = mpsc::channel(); +The type of `guess` in this code would have to be an integer *and* a string, +and Rust requires that `guess` have only one type. So what does `continue` +return? How were we allowed to return a `u32` from one arm and have another arm +that ends with `continue` in Listing 19-26? - let mut workers = Vec::with_capacity(size); +As you might have guessed, `continue` has a `!` value. That is, when Rust +computes the type of `guess`, it looks at both match arms, the former with a +value of `u32` and the latter with a `!` value. Because `!` can never have a +value, Rust decides that the type of `guess` is `u32`. - for id in 0..size { - 1 workers.push(Worker::new(id, receiver)); - } +The formal way of describing this behavior is that expressions of type `!` can +be coerced into any other type. We’re allowed to end this `match` arm with +`continue` because `continue` doesn’t return a value; instead, it moves control +back to the top of the loop, so in the `Err` case, we never assign a value to +`guess`. + +The never type is useful with the `panic!` macro as well. Recall the `unwrap` +function that we call on `Option` values to produce a value or panic with +this definition: - ThreadPool { workers, sender } +``` +impl Option { + pub fn unwrap(self) -> T { + match self { + Some(val) => val, + None => panic!( + "called `Option::unwrap()` on a `None` value" + ), + } } - --snip-- } +``` ---snip-- +In this code, the same thing happens as in the `match` in Listing 19-26: Rust +sees that `val` has the type `T` and `panic!` has the type `!`, so the result +of the overall `match` expression is `T`. This code works because `panic!` +doesn’t produce a value; it ends the program. In the `None` case, we won’t be +returning a value from `unwrap`, so this code is valid. -impl Worker { - fn new(id: usize, receiver: mpsc::Receiver) -> Worker { - let thread = thread::spawn(|| { - 2 receiver; - }); +One final expression that has the type `!` is a `loop`: - Worker { id, thread } - } -} ``` +print!("forever "); -Listing 20-17: Passing the receiver to each `Worker` +loop { + print!("and ever "); +} +``` -We’ve made some small and straightforward changes: we pass the receiver into -`Worker::new` [1], and then we use it inside the closure [2]. +Here, the loop never ends, so `!` is the value of the expression. However, this +wouldn’t be true if we included a `break`, because the loop would terminate +when it got to the `break`. + +### Dynamically Sized Types and the Sized Trait + +Rust needs to know certain details about its types, such as how much space to +allocate for a value of a particular type. This leaves one corner of its type +system a little confusing at first: the concept of *dynamically sized types*. +Sometimes referred to as *DSTs* or *unsized types*, these types let us write +code using values whose size we can know only at runtime. + +Let’s dig into the details of a dynamically sized type called `str`, which +we’ve been using throughout the book. That’s right, not `&str`, but `str` on +its own, is a DST. We can’t know how long the string is until runtime, meaning +we can’t create a variable of type `str`, nor can we take an argument of type +`str`. Consider the following code, which does not work: + +``` +let s1: str = "Hello there!"; +let s2: str = "How's it going?"; +``` + +Rust needs to know how much memory to allocate for any value of a particular +type, and all values of a type must use the same amount of memory. If Rust +allowed us to write this code, these two `str` values would need to take up the +same amount of space. But they have different lengths: `s1` needs 12 bytes of +storage and `s2` needs 15. This is why it’s not possible to create a variable +holding a dynamically sized type. + +So what do we do? In this case, you already know the answer: we make the types +of `s1` and `s2` a `&str` rather than a `str`. Recall from “String Slices” on +page XX that the slice data structure just stores the starting position and the +length of the slice. So, although a `&T` is a single value that stores the +memory address of where the `T` is located, a `&str` is *two* values: the +address of the `str` and its length. As such, we can know the size of a `&str` +value at compile time: it’s twice the length of a `usize`. That is, we always +know the size of a `&str`, no matter how long the string it refers to is. In +general, this is the way in which dynamically sized types are used in Rust: +they have an extra bit of metadata that stores the size of the dynamic +information. The golden rule of dynamically sized types is that we must always +put values of dynamically sized types behind a pointer of some kind. + +We can combine `str` with all kinds of pointers: for example, `Box` or +`Rc`. In fact, you’ve seen this before but with a different dynamically +sized type: traits. Every trait is a dynamically sized type we can refer to by +using the name of the trait. In “Using Trait Objects That Allow for Values of +Different Types” on page XX, we mentioned that to use traits as trait objects, +we must put them behind a pointer, such as `&dyn Trait` or `Box` +(`Rc` would work too). + +To work with DSTs, Rust provides the `Sized` trait to determine whether or not +a type’s size is known at compile time. This trait is automatically implemented +for everything whose size is known at compile time. In addition, Rust +implicitly adds a bound on `Sized` to every generic function. That is, a +generic function definition like this: + +``` +fn generic(t: T) { + --snip-- +} +``` -When we try to check this code, we get this error: +is actually treated as though we had written this: ``` -$ cargo check - Checking hello v0.1.0 (file:///projects/hello) -error[E0382]: use of moved value: `receiver` - --> src/lib.rs:26:42 - | -21 | let (sender, receiver) = mpsc::channel(); - | -------- move occurs because `receiver` has type -`std::sync::mpsc::Receiver`, which does not implement the `Copy` trait -... -26 | workers.push(Worker::new(id, receiver)); - | ^^^^^^^^ value moved here, in -previous iteration of loop -``` - -The code is trying to pass `receiver` to multiple `Worker` instances. This -won’t work, as you’ll recall from Chapter 16: the channel implementation that -Rust provides is multiple *producer*, single *consumer*. This means we can’t -just clone the consuming end of the channel to fix this code. We also don’t -want to send a message multiple times to multiple consumers; we want one list -of messages with multiple `Worker` instances such that each message gets -processed once. - -Additionally, taking a job off the channel queue involves mutating the -`receiver`, so the threads need a safe way to share and modify `receiver`; -otherwise, we might get race conditions (as covered in Chapter 16). - -Recall the thread-safe smart pointers discussed in Chapter 16: to share -ownership across multiple threads and allow the threads to mutate the value, we -need to use `Arc>`. The `Arc` type will let multiple `Worker` -instances own the receiver, and `Mutex` will ensure that only one `Worker` gets -a job from the receiver at a time. Listing 20-18 shows the changes we need to -make. +fn generic(t: T) { + --snip-- +} +``` -Filename: src/lib.rs +By default, generic functions will work only on types that have a known size at +compile time. However, you can use the following special syntax to relax this +restriction: ``` -use std::{ - sync::{mpsc, Arc, Mutex}, - thread, -}; ---snip-- - -impl ThreadPool { +fn generic(t: &T) { --snip-- - pub fn new(size: usize) -> ThreadPool { - assert!(size > 0); +} +``` - let (sender, receiver) = mpsc::channel(); +A trait bound on `?Sized` means “`T` may or may not be `Sized`” and this +notation overrides the default that generic types must have a known size at +compile time. The `?Trait` syntax with this meaning is only available for +`Sized`, not any other traits. - 1 let receiver = Arc::new(Mutex::new(receiver)); +Also note that we switched the type of the `t` parameter from `T` to `&T`. +Because the type might not be `Sized`, we need to use it behind some kind of +pointer. In this case, we’ve chosen a reference. - let mut workers = Vec::with_capacity(size); +Next, we’ll talk about functions and closures! - for id in 0..size { - workers.push( - Worker::new(id, Arc::clone(& 2 receiver)) - ); - } +## Advanced Functions and Closures - ThreadPool { workers, sender } - } +This section explores some advanced features related to functions and closures, +including function pointers and returning closures. - --snip-- +### Function Pointers + +We’ve talked about how to pass closures to functions; you can also pass regular +functions to functions! This technique is useful when you want to pass a +function you’ve already defined rather than defining a new closure. Functions +coerce to the type `fn` (with a lowercase *f*), not to be confused with the +`Fn` closure trait. The `fn` type is called a *function pointer*. Passing +functions with function pointers will allow you to use functions as arguments +to other functions. + +The syntax for specifying that a parameter is a function pointer is similar to +that of closures, as shown in Listing 19-27, where we’ve defined a function +`add_one` that adds 1 to its parameter. The function `do_twice` takes two +parameters: a function pointer to any function that takes an `i32` parameter +and returns an `i32`, and one `i32 value`. The `do_twice` function calls the +function `f` twice, passing it the `arg` value, then adds the two function call +results together. The `main` function calls `do_twice` with the arguments +`add_one` and `5`. + +Filename: src/main.rs + +``` +fn add_one(x: i32) -> i32 { + x + 1 } ---snip-- +fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { + f(arg) + f(arg) +} -impl Worker { - fn new( - id: usize, - receiver: Arc>>, - ) -> Worker { - --snip-- - } +fn main() { + let answer = do_twice(add_one, 5); + + println!("The answer is: {answer}"); } ``` -Listing 20-18: Sharing the receiver among the `Worker` instances using `Arc` -and `Mutex` +Listing 19-27: Using the `fn` type to accept a function pointer as an argument -In `ThreadPool::new`, we put the receiver in an `Arc` and a `Mutex` [1]. For -each new `Worker`, we clone the `Arc` to bump the reference count so the -`Worker` instances can share ownership of the receiver [2]. +This code prints `The answer is: 12`. We specify that the parameter `f` in +`do_twice` is an `fn` that takes one parameter of type `i32` and returns an +`i32`. We can then call `f` in the body of `do_twice`. In `main`, we can pass +the function name `add_one` as the first argument to `do_twice`. -With these changes, the code compiles! We’re getting there! +Unlike closures, `fn` is a type rather than a trait, so we specify `fn` as the +parameter type directly rather than declaring a generic type parameter with one +of the `Fn` traits as a trait bound. -#### Implementing the execute Method +Function pointers implement all three of the closure traits (`Fn`, `FnMut`, and +`FnOnce`), meaning you can always pass a function pointer as an argument for a +function that expects a closure. It’s best to write functions using a generic +type and one of the closure traits so your functions can accept either +functions or closures. -Let’s finally implement the `execute` method on `ThreadPool`. We’ll also change -`Job` from a struct to a type alias for a trait object that holds the type of -closure that `execute` receives. As discussed in “Creating Type Synonyms with -Type Aliases” on page XX, type aliases allow us to make long types shorter for -ease of use. Look at Listing 20-19. +That said, one example of where you would want to only accept `fn` and not +closures is when interfacing with external code that doesn’t have closures: C +functions can accept functions as arguments, but C doesn’t have closures. -Filename: src/lib.rs +As an example of where you could use either a closure defined inline or a named +function, let’s look at a use of the `map` method provided by the `Iterator` +trait in the standard library. To use the `map` function to turn a vector of +numbers into a vector of strings, we could use a closure, like this: ``` ---snip-- +let list_of_numbers = vec![1, 2, 3]; +let list_of_strings: Vec = list_of_numbers + .iter() + .map(|i| i.to_string()) + .collect(); +``` -type Job = Box; +Or we could name a function as the argument to `map` instead of the closure, +like this: -impl ThreadPool { - --snip-- +``` +let list_of_numbers = vec![1, 2, 3]; +let list_of_strings: Vec = list_of_numbers + .iter() + .map(ToString::to_string) + .collect(); +``` - pub fn execute(&self, f: F) - where - F: FnOnce() + Send + 'static, - { - 1 let job = Box::new(f); +Note that we must use the fully qualified syntax that we talked about in +“Advanced Traits” on page XX because there are multiple functions available +named `to_string`. - 2 self.sender.send(job).unwrap(); - } +Here, we’re using the `to_string` function defined in the `ToString` trait, +which the standard library has implemented for any type that implements +`Display`. + +Recall from “Enum Values” on page XX that the name of each enum variant that we +define also becomes an initializer function. We can use these initializer +functions as function pointers that implement the closure traits, which means +we can specify the initializer functions as arguments for methods that take +closures, like so: + +``` +enum Status { + Value(u32), + Stop, } ---snip-- +let list_of_statuses: Vec = (0u32..20) + .map(Status::Value) + .collect(); ``` -Listing 20-19: Creating a `Job` type alias for a `Box` that holds each closure -and then sending the job down the channel +Here, we create `Status::Value` instances using each `u32` value in the range +that `map` is called on by using the initializer function of `Status::Value`. +Some people prefer this style and some people prefer to use closures. They +compile to the same code, so use whichever style is clearer to you. -After creating a new `Job` instance using the closure we get in `execute` [1], -we send that job down the sending end of the channel [2]. We’re calling -`unwrap` on `send` for the case that sending fails. This might happen if, for -example, we stop all our threads from executing, meaning the receiving end has -stopped receiving new messages. At the moment, we can’t stop our threads from -executing: our threads continue executing as long as the pool exists. The -reason we use `unwrap` is that we know the failure case won’t happen, but the -compiler doesn’t know that. +### Returning Closures -But we’re not quite done yet! In the `Worker`, our closure being passed to -`thread::spawn` still only *references* the receiving end of the channel. -Instead, we need the closure to loop forever, asking the receiving end of the -channel for a job and running the job when it gets one. Let’s make the change -shown in Listing 20-20 to `Worker::new`. +Closures are represented by traits, which means you can’t return closures +directly. In most cases where you might want to return a trait, you can instead +use the concrete type that implements the trait as the return value of the +function. However, you can’t do that with closures because they don’t have a +concrete type that is returnable; you’re not allowed to use the function +pointer `fn` as a return type, for example. -Filename: src/lib.rs +The following code tries to return a closure directly, but it won’t compile: ``` ---snip-- +fn returns_closure() -> dyn Fn(i32) -> i32 { + |x| x + 1 +} +``` -impl Worker { - fn new( - id: usize, - receiver: Arc>>, - ) -> Worker { - let thread = thread::spawn(move || loop { - let job = receiver - 1 .lock() - 2 .unwrap() - 3 .recv() - 4 .unwrap(); +The compiler error is as follows: - println!("Worker {id} got a job; executing."); +``` +error[E0746]: return type cannot have an unboxed trait object + --> src/lib.rs:1:25 + | +1 | fn returns_closure() -> dyn Fn(i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at +compile-time + | + = note: for information on `impl Trait`, see + +help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of +type `[closure@src/lib.rs:2:5: 2:14]`, which implements `Fn(i32) -> i32` + | +1 | fn returns_closure() -> impl Fn(i32) -> i32 { + | ~~~~~~~~~~~~~~~~~~~ +``` - job(); - }); +The error references the `Sized` trait again! Rust doesn’t know how much space +it will need to store the closure. We saw a solution to this problem earlier. +We can use a trait object: - Worker { id, thread } - } +``` +fn returns_closure() -> Box i32> { + Box::new(|x| x + 1) } ``` -Listing 20-20: Receiving and executing the jobs in the `Worker` instance’s -thread +This code will compile just fine. For more about trait objects, refer to “Using +Trait Objects That Allow for Values of Different Types” on page XX. -Here, we first call `lock` on the `receiver` to acquire the mutex [1], and then -we call `unwrap` to panic on any errors [2]. Acquiring a lock might fail if the -mutex is in a *poisoned* state, which can happen if some other thread panicked -while holding the lock rather than releasing the lock. In this situation, -calling `unwrap` to have this thread panic is the correct action to take. Feel -free to change this `unwrap` to an `expect` with an error message that is -meaningful to you. +Next, let’s look at macros! -If we get the lock on the mutex, we call `recv` to receive a `Job` from the -channel [3]. A final `unwrap` moves past any errors here as well [4], which -might occur if the thread holding the sender has shut down, similar to how the -`send` method returns `Err` if the receiver shuts down. +## Macros -The call to `recv` blocks, so if there is no job yet, the current thread will -wait until a job becomes available. The `Mutex` ensures that only one -`Worker` thread at a time is trying to request a job. +We’ve used macros like `println!` throughout this book, but we haven’t fully +explored what a macro is and how it works. The term *macro* refers to a family +of features in Rust: *declarative* macros with `macro_rules!` and three kinds +of *procedural* macros: -Our thread pool is now in a working state! Give it a `cargo run` and make some -requests: +* Custom `#[derive]` macros that specify code added with the `derive` attribute +used on structs and enums +* Attribute-like macros that define custom attributes usable on any item +* Function-like macros that look like function calls but operate on the tokens +specified as their argument -``` -$ cargo run - Compiling hello v0.1.0 (file:///projects/hello) -warning: field is never read: `workers` - --> src/lib.rs:7:5 - | -7 | workers: Vec, - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default +We’ll talk about each of these in turn, but first, let’s look at why we even +need macros when we already have functions. -warning: field is never read: `id` - --> src/lib.rs:48:5 - | -48 | id: usize, - | ^^^^^^^^^ +### The Difference Between Macros and Functions -warning: field is never read: `thread` - --> src/lib.rs:49:5 - | -49 | thread: thread::JoinHandle<()>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `hello` (lib) generated 3 warnings - Finished dev [unoptimized + debuginfo] target(s) in 1.40s - Running `target/debug/hello` -Worker 0 got a job; executing. -Worker 2 got a job; executing. -Worker 1 got a job; executing. -Worker 3 got a job; executing. -Worker 0 got a job; executing. -Worker 2 got a job; executing. -Worker 1 got a job; executing. -Worker 3 got a job; executing. -Worker 0 got a job; executing. -Worker 2 got a job; executing. -``` - -Success! We now have a thread pool that executes connections asynchronously. -There are never more than four threads created, so our system won’t get -overloaded if the server receives a lot of requests. If we make a request to -*/sleep*, the server will be able to serve other requests by having another -thread run them. - -> Note: If you open */sleep* in multiple browser windows simultaneously, they -might load one at a time in five-second intervals. Some web browsers execute -multiple instances of the same request sequentially for caching reasons. This -limitation is not caused by our web server. - -After learning about the `while let` loop in Chapter 18, you might be wondering -why we didn’t write the `Worker` thread code as shown in Listing 20-21. +Fundamentally, macros are a way of writing code that writes other code, which +is known as *metaprogramming*. In Appendix C, we discuss the `derive` +attribute, which generates an implementation of various traits for you. We’ve +also used the `println!` and `vec!` macros throughout the book. All of these +macros *expand* to produce more code than the code you’ve written manually. -Filename: src/lib.rs +Metaprogramming is useful for reducing the amount of code you have to write and +maintain, which is also one of the roles of functions. However, macros have +some additional powers that functions don’t have. -``` ---snip-- +A function signature must declare the number and type of parameters the +function has. Macros, on the other hand, can take a variable number of +parameters: we can call `println!("hello")` with one argument or +`println!("hello {}", name)` with two arguments. Also, macros are expanded +before the compiler interprets the meaning of the code, so a macro can, for +example, implement a trait on a given type. A function can’t, because it gets +called at runtime and a trait needs to be implemented at compile time. -impl Worker { - fn new( - id: usize, - receiver: Arc>>, - ) -> Worker { - let thread = thread::spawn(move || { - while let Ok(job) = receiver.lock().unwrap().recv() { - println!("Worker {id} got a job; executing."); +The downside to implementing a macro instead of a function is that macro +definitions are more complex than function definitions because you’re writing +Rust code that writes Rust code. Due to this indirection, macro definitions are +generally more difficult to read, understand, and maintain than function +definitions. - job(); - } - }); +Another important difference between macros and functions is that you must +define macros or bring them into scope *before* you call them in a file, as +opposed to functions you can define anywhere and call anywhere. - Worker { id, thread } - } -} +### Declarative Macros with macro_rules! for General Metaprogramming + +The most widely used form of macros in Rust is the *declarative macro*. These +are also sometimes referred to as “macros by example,” “`macro_rules!` macros,” +or just plain “macros.” At their core, declarative macros allow you to write +something similar to a Rust `match` expression. As discussed in Chapter 6, +`match` expressions are control structures that take an expression, compare the +resultant value of the expression to patterns, and then run the code associated +with the matching pattern. Macros also compare a value to patterns that are +associated with particular code: in this situation, the value is the literal +Rust source code passed to the macro; the patterns are compared with the +structure of that source code; and the code associated with each pattern, when +matched, replaces the code passed to the macro. This all happens during +compilation. + +To define a macro, you use the `macro_rules!` construct. Let’s explore how to +use `macro_rules!` by looking at how the `vec!` macro is defined. Chapter 8 +covered how we can use the `vec!` macro to create a new vector with particular +values. For example, the following macro creates a new vector containing three +integers: + +``` +let v: Vec = vec![1, 2, 3]; ``` -Listing 20-21: An alternative implementation of `Worker::new` using `while let` +We could also use the `vec!` macro to make a vector of two integers or a vector +of five string slices. We wouldn’t be able to use a function to do the same +because we wouldn’t know the number or type of values up front. -This code compiles and runs but doesn’t result in the desired threading -behavior: a slow request will still cause other requests to wait to be -processed. The reason is somewhat subtle: the `Mutex` struct has no public -`unlock` method because the ownership of the lock is based on the lifetime of -the `MutexGuard` within the `LockResult>` that the `lock` -method returns. At compile time, the borrow checker can then enforce the rule -that a resource guarded by a `Mutex` cannot be accessed unless we hold the -lock. However, this implementation can also result in the lock being held -longer than intended if we aren’t mindful of the lifetime of the -`MutexGuard`. +Listing 19-28 shows a slightly simplified definition of the `vec!` macro. -The code in Listing 20-20 that uses `let job = -receiver.lock().unwrap().recv().unwrap();` works because with `let`, any -temporary values used in the expression on the right-hand side of the equal -sign are immediately dropped when the `let` statement ends. However, `while -let` (and `if let` and `match`) does not drop temporary values until the end of -the associated block. In Listing 20-21, the lock remains held for the duration -of the call to `job()`, meaning other `Worker` instances cannot receive jobs. +Filename: src/lib.rs -## Graceful Shutdown and Cleanup +``` +1 #[macro_export] +2 macro_rules! vec { + 3 ( $( $x:expr ),* ) => { + { + let mut temp_vec = Vec::new(); + 4 $( + 5 temp_vec.push(6 $x); + )* + 7 temp_vec + } + }; +} +``` + +Listing 19-28: A simplified version of the `vec!` macro definition + +> Note: The actual definition of the `vec!` macro in the standard library +includes code to pre-allocate the correct amount of memory up front. That code +is an optimization that we don’t include here, to make the example simpler. + +The `#[macro_export]` annotation [1] indicates that this macro should be made +available whenever the crate in which the macro is defined is brought into +scope. Without this annotation, the macro can’t be brought into scope. + +We then start the macro definition with `macro_rules!` and the name of the +macro we’re defining *without* the exclamation mark [2]. The name, in this case +`vec`, is followed by curly brackets denoting the body of the macro definition. + +The structure in the `vec!` body is similar to the structure of a `match` +expression. Here we have one arm with the pattern `( $( $x:expr ),* )`, +followed by `=>` and the block of code associated with this pattern [3]. If the +pattern matches, the associated block of code will be emitted. Given that this +is the only pattern in this macro, there is only one valid way to match; any +other pattern will result in an error. More complex macros will have more than +one arm. + +Valid pattern syntax in macro definitions is different from the pattern syntax +covered in Chapter 18 because macro patterns are matched against Rust code +structure rather than values. Let’s walk through what the pattern pieces in +Listing 19-28 mean; for the full macro pattern syntax, see the Rust Reference +at *https://doc.rust-lang.org/reference/macros-by-example.html*. + +First we use a set of parentheses to encompass the whole pattern. We use a +dollar sign (`$`) to declare a variable in the macro system that will contain +the Rust code matching the pattern. The dollar sign makes it clear this is a +macro variable as opposed to a regular Rust variable. Next comes a set of +parentheses that captures values that match the pattern within the parentheses +for use in the replacement code. Within `$()` is `$x:expr`, which matches any +Rust expression and gives the expression the name `$x`. + +The comma following `$()` indicates that a literal comma separator character +could optionally appear after the code that matches the code in `$()`. The `*` +specifies that the pattern matches zero or more of whatever precedes the `*`. + +When we call this macro with `vec![1, 2, 3];`, the `$x` pattern matches three +times with the three expressions `1`, `2`, and `3`. + +Now let’s look at the pattern in the body of the code associated with this arm: +`temp_vec.push()` [5] within `$()* at [4] and [7] is generated for each part +that matches `$()` in the pattern zero or more times depending on how many +times the pattern matches. The `$x` [6] is replaced with each expression +matched. When we call this macro with `vec![1, 2, 3];`, the code generated that +replaces this macro call will be the following: + +``` +{ + let mut temp_vec = Vec::new(); + temp_vec.push(1); + temp_vec.push(2); + temp_vec.push(3); + temp_vec +} +``` + +We’ve defined a macro that can take any number of arguments of any type and can +generate code to create a vector containing the specified elements. -The code in Listing 20-20 is responding to requests asynchronously through the -use of a thread pool, as we intended. We get some warnings about the `workers`, -`id`, and `thread` fields that we’re not using in a direct way that reminds us -we’re not cleaning up anything. When we use the less elegant ctrl-C method to -halt the main thread, all other threads are stopped immediately as well, even -if they’re in the middle of serving a request. +To learn more about how to write macros, consult the online documentation or +other resources, such as “The Little Book of Rust Macros” at +*https://veykril.github.io/tlborm* started by Daniel Keep and continued by +Lukas Wirth. -Next, then, we’ll implement the `Drop` trait to call `join` on each of the -threads in the pool so they can finish the requests they’re working on before -closing. Then we’ll implement a way to tell the threads they should stop -accepting new requests and shut down. To see this code in action, we’ll modify -our server to accept only two requests before gracefully shutting down its -thread pool. +### Procedural Macros for Generating Code from Attributes -### Implementing the Drop Trait on ThreadPool +The second form of macros is the procedural macro, which acts more like a +function (and is a type of procedure). *Procedural macros* accept some code as +an input, operate on that code, and produce some code as an output rather than +matching against patterns and replacing the code with other code as declarative +macros do. The three kinds of procedural macros are custom `derive`, +attribute-like, and function-like, and all work in a similar fashion. -Let’s start with implementing `Drop` on our thread pool. When the pool is -dropped, our threads should all join to make sure they finish their work. -Listing 20-22 shows a first attempt at a `Drop` implementation; this code won’t -quite work yet. +When creating procedural macros, the definitions must reside in their own crate +with a special crate type. This is for complex technical reasons that we hope +to eliminate in the future. In Listing 19-29, we show how to define a +procedural macro, where `some_attribute` is a placeholder for using a specific +macro variety. Filename: src/lib.rs ``` -impl Drop for ThreadPool { - fn drop(&mut self) { - 1 for worker in &mut self.workers { - 2 println!("Shutting down worker {}", worker.id); +use proc_macro::TokenStream; - 3 worker.thread.join().unwrap(); - } - } +#[some_attribute] +pub fn some_name(input: TokenStream) -> TokenStream { } ``` -Listing 20-22: Joining each thread when the thread pool goes out of scope - -First we loop through each of the thread pool `workers` [1]. We use `&mut` for -this because `self` is a mutable reference, and we also need to be able to -mutate `worker`. For each `worker`, we print a message saying that this -particular `Worker` instance is shutting down [2], and then we call `join` on -that `Worker` instance’s thread [3]. If the call to `join` fails, we use -`unwrap` to make Rust panic and go into an ungraceful shutdown. +Listing 19-29: An example of defining a procedural macro -Here is the error we get when we compile this code: +The function that defines a procedural macro takes a `TokenStream` as an input +and produces a `TokenStream` as an output. The `TokenStream` type is defined by +the `proc_macro` crate that is included with Rust and represents a sequence of +tokens. This is the core of the macro: the source code that the macro is +operating on makes up the input `TokenStream`, and the code the macro produces +is the output `TokenStream`. The function also has an attribute attached to it +that specifies which kind of procedural macro we’re creating. We can have +multiple kinds of procedural macros in the same crate. -``` -error[E0507]: cannot move out of `worker.thread` which is behind a mutable -reference - --> src/lib.rs:52:13 - | -52 | worker.thread.join().unwrap(); - | ^^^^^^^^^^^^^ ------ `worker.thread` moved due to this -method call - | | - | move occurs because `worker.thread` has type -`JoinHandle<()>`, which does not implement the `Copy` trait - | -note: this function takes ownership of the receiver `self`, which moves -`worker.thread` -``` +Let’s look at the different kinds of procedural macros. We’ll start with a +custom `derive` macro and then explain the small dissimilarities that make the +other forms different. -The error tells us we can’t call `join` because we only have a mutable borrow -of each `worker` and `join` takes ownership of its argument. To solve this -issue, we need to move the thread out of the `Worker` instance that owns -`thread` so `join` can consume the thread. We did this in Listing 17-15: if -`Worker` holds an `Option>` instead, we can call the -`take` method on the `Option` to move the value out of the `Some` variant and -leave a `None` variant in its place. In other words, a `Worker` that is running -will have a `Some` variant in `thread`, and when we want to clean up a -`Worker`, we’ll replace `Some` with `None` so the `Worker` doesn’t have a -thread to run. +### How to Write a Custom derive Macro -So we know we want to update the definition of `Worker` like this: +Let’s create a crate named `hello_macro` that defines a trait named +`HelloMacro` with one associated function named `hello_macro`. Rather than +making our users implement the `HelloMacro` trait for each of their types, +we’ll provide a procedural macro so users can annotate their type with +`#[derive(HelloMacro)]` to get a default implementation of the `hello_macro` +function. The default implementation will print `Hello, Macro! My name is` +TypeName`!` where TypeName is the name of the type on which this trait has been +defined. In other words, we’ll write a crate that enables another programmer to +write code like Listing 19-30 using our crate. -Filename: src/lib.rs +Filename: src/main.rs ``` -struct Worker { - id: usize, - thread: Option>, +use hello_macro::HelloMacro; +use hello_macro_derive::HelloMacro; + +#[derive(HelloMacro)] +struct Pancakes; + +fn main() { + Pancakes::hello_macro(); } ``` -Now let’s lean on the compiler to find the other places that need to change. -Checking this code, we get two errors: +Listing 19-30: The code a user of our crate will be able to write when using +our procedural macro -``` -error[E0599]: no method named `join` found for enum `Option` in the current -scope - --> src/lib.rs:52:27 - | -52 | worker.thread.join().unwrap(); - | ^^^^ method not found in -`Option>` +This code will print `Hello, Macro! My name is Pancakes!` when we’re done. The +first step is to make a new library crate, like this: -error[E0308]: mismatched types - --> src/lib.rs:72:22 - | -72 | Worker { id, thread } - | ^^^^^^ expected enum `Option`, found struct -`JoinHandle` - | - = note: expected enum `Option>` - found struct `JoinHandle<_>` -help: try wrapping the expression in `Some` - | -72 | Worker { id, thread: Some(thread) } - | +++++++++++++ + +``` +$ cargo new hello_macro --lib ``` -Let’s address the second error, which points to the code at the end of -`Worker::new`; we need to wrap the `thread` value in `Some` when we create a -new `Worker`. Make the following changes to fix this error: +Next, we’ll define the `HelloMacro` trait and its associated function: Filename: src/lib.rs ``` -impl Worker { - fn new( - id: usize, - receiver: Arc>>, - ) -> Worker { - --snip-- - - Worker { - id, - thread: Some(thread), - } - } +pub trait HelloMacro { + fn hello_macro(); } ``` -The first error is in our `Drop` implementation. We mentioned earlier that we -intended to call `take` on the `Option` value to move `thread` out of `worker`. -The following changes will do so: - -Filename: src/lib.rs +We have a trait and its function. At this point, our crate user could implement +the trait to achieve the desired functionality, like so: ``` -impl Drop for ThreadPool { - fn drop(&mut self) { - for worker in &mut self.workers { - println!("Shutting down worker {}", worker.id); +use hello_macro::HelloMacro; - 1 if let Some(thread) = worker.thread.take() { - 2 thread.join().unwrap(); - } - } +struct Pancakes; + +impl HelloMacro for Pancakes { + fn hello_macro() { + println!("Hello, Macro! My name is Pancakes!"); } } + +fn main() { + Pancakes::hello_macro(); +} ``` -As discussed in Chapter 17, the `take` method on `Option` takes the `Some` -variant out and leaves `None` in its place. We’re using `if let` to destructure -the `Some` and get the thread [1]; then we call `join` on the thread [2]. If a -`Worker` instance’s thread is already `None`, we know that `Worker` has already -had its thread cleaned up, so nothing happens in that case. +However, they would need to write the implementation block for each type they +wanted to use with `hello_macro`; we want to spare them from having to do this +work. -### Signaling to the Threads to Stop Listening for Jobs +Additionally, we can’t yet provide the `hello_macro` function with default +implementation that will print the name of the type the trait is implemented +on: Rust doesn’t have reflection capabilities, so it can’t look up the type’s +name at runtime. We need a macro to generate code at compile time. -With all the changes we’ve made, our code compiles without any warnings. -However, the bad news is that this code doesn’t function the way we want it to -yet. The key is the logic in the closures run by the threads of the `Worker` -instances: at the moment, we call `join`, but that won’t shut down the threads, -because they `loop` forever looking for jobs. If we try to drop our -`ThreadPool` with our current implementation of `drop`, the main thread will -block forever, waiting for the first thread to finish. +The next step is to define the procedural macro. At the time of this writing, +procedural macros need to be in their own crate. Eventually, this restriction +might be lifted. The convention for structuring crates and macro crates is as +follows: for a crate named foo, a custom `derive` procedural macro crate is +called foo`_derive`. Let’s start a new crate called `hello_macro_derive` inside +our `hello_macro` project: -To fix this problem, we’ll need a change in the `ThreadPool` `drop` -implementation and then a change in the `Worker` loop. +``` +$ cargo new hello_macro_derive --lib +``` -First we’ll change the `ThreadPool` `drop` implementation to explicitly drop -the `sender` before waiting for the threads to finish. Listing 20-23 shows the -changes to `ThreadPool` to explicitly drop `sender`. We use the same `Option` -and `take` technique as we did with the thread to be able to move `sender` out -of `ThreadPool`. +Our two crates are tightly related, so we create the procedural macro crate +within the directory of our `hello_macro` crate. If we change the trait +definition in `hello_macro`, we’ll have to change the implementation of the +procedural macro in `hello_macro_derive` as well. The two crates will need to +be published separately, and programmers using these crates will need to add +both as dependencies and bring them both into scope. We could instead have the +`hello_macro` crate use `hello_macro_derive` as a dependency and re-export the +procedural macro code. However, the way we’ve structured the project makes it +possible for programmers to use `hello_macro` even if they don’t want the +`derive` functionality. -Filename: src/lib.rs +We need to declare the `hello_macro_derive` crate as a procedural macro crate. +We’ll also need functionality from the `syn` and `quote` crates, as you’ll see +in a moment, so we need to add them as dependencies. Add the following to the +*Cargo.toml* file for `hello_macro_derive`: + +Filename: hello_macro_derive/Cargo.toml ``` -pub struct ThreadPool { - workers: Vec, - sender: Option>, -} ---snip-- -impl ThreadPool { - pub fn new(size: usize) -> ThreadPool { - --snip-- +[lib] +proc-macro = true - ThreadPool { - workers, - sender: Some(sender), - } - } +[dependencies] +syn = "1.0" +quote = "1.0" +``` - pub fn execute(&self, f: F) - where - F: FnOnce() + Send + 'static, - { - let job = Box::new(f); - - self.sender - .as_ref() - .unwrap() - .send(job) - .unwrap(); - } +To start defining the procedural macro, place the code in Listing 19-31 into +your *src/lib.rs* file for the `hello_macro_derive` crate. Note that this code +won’t compile until we add a definition for the `impl_hello_macro` function. + +Filename: hello_macro_derive/src/lib.rs + +``` +use proc_macro::TokenStream; +use quote::quote; +use syn; + +#[proc_macro_derive(HelloMacro)] +pub fn hello_macro_derive(input: TokenStream) -> TokenStream { + // Construct a representation of Rust code as a syntax tree + // that we can manipulate + let ast = syn::parse(input).unwrap(); + + // Build the trait implementation + impl_hello_macro(&ast) } +``` -impl Drop for ThreadPool { - fn drop(&mut self) { - 1 drop(self.sender.take()); +Listing 19-31: Code that most procedural macro crates will require in order to +process Rust code + +Notice that we’ve split the code into the `hello_macro_derive` function, which +is responsible for parsing the `TokenStream`, and the `impl_hello_macro` +function, which is responsible for transforming the syntax tree: this makes +writing a procedural macro more convenient. The code in the outer function +(`hello_macro_derive` in this case) will be the same for almost every +procedural macro crate you see or create. The code you specify in the body of +the inner function (`impl_hello_macro` in this case) will be different +depending on your procedural macro’s purpose. + +We’ve introduced three new crates: `proc_macro`, `syn` (available from +*https://crates.io/crates/syn*), and `quote` (available from +*https://crates.io/crates/quote*). The `proc_macro` crate comes with Rust, so +we didn’t need to add that to the dependencies in *Cargo.toml*. The +`proc_macro` crate is the compiler’s API that allows us to read and manipulate +Rust code from our code. + +The `syn` crate parses Rust code from a string into a data structure that we +can perform operations on. The `quote` crate turns `syn` data structures back +into Rust code. These crates make it much simpler to parse any sort of Rust +code we might want to handle: writing a full parser for Rust code is no simple +task. + +The `hello_macro_derive` function will be called when a user of our library +specifies `#[derive(HelloMacro)]` on a type. This is possible because we’ve +annotated the `hello_macro_derive` function here with `proc_macro_derive` and +specified the name `HelloMacro`, which matches our trait name; this is the +convention most procedural macros follow. + +The `hello_macro_derive` function first converts the `input` from a +`TokenStream` to a data structure that we can then interpret and perform +operations on. This is where `syn` comes into play. The `parse` function in +`syn` takes a `TokenStream` and returns a `DeriveInput` struct representing the +parsed Rust code. Listing 19-32 shows the relevant parts of the `DeriveInput` +struct we get from parsing the `struct Pancakes;` string. + +``` +DeriveInput { + --snip-- - for worker in &mut self.workers { - println!("Shutting down worker {}", worker.id); + ident: Ident { + ident: "Pancakes", + span: #0 bytes(95..103) + }, + data: Struct( + DataStruct { + struct_token: Struct, + fields: Unit, + semi_token: Some( + Semi + ) + } + ) +} +``` - if let Some(thread) = worker.thread.take() { - thread.join().unwrap(); +Listing 19-32: The `DeriveInput` instance we get when parsing the code that has +the macro’s attribute in Listing 19-30 + +The fields of this struct show that the Rust code we’ve parsed is a unit struct +with the `ident` (*identifier*, meaning the name) of `Pancakes`. There are more +fields on this struct for describing all sorts of Rust code; check the `syn` +documentation for `DeriveInput` at +*https://docs.rs/syn/1.0/syn/struct.DeriveInput.html* for more information. + +Soon we’ll define the `impl_hello_macro` function, which is where we’ll build +the new Rust code we want to include. But before we do, note that the output +for our `derive` macro is also a `TokenStream`. The returned `TokenStream` is +added to the code that our crate users write, so when they compile their crate, +they’ll get the extra functionality that we provide in the modified +`TokenStream`. + +You might have noticed that we’re calling `unwrap` to cause the +`hello_macro_derive` function to panic if the call to the `syn::parse` function +fails here. It’s necessary for our procedural macro to panic on errors because +`proc_macro_derive` functions must return `TokenStream` rather than `Result` to +conform to the procedural macro API. We’ve simplified this example by using +`unwrap`; in production code, you should provide more specific error messages +about what went wrong by using `panic!` or `expect`. + +Now that we have the code to turn the annotated Rust code from a `TokenStream` +into a `DeriveInput` instance, let’s generate the code that implements the +`HelloMacro` trait on the annotated type, as shown in Listing 19-33. + +Filename: hello_macro_derive/src/lib.rs + +``` +fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { + let name = &ast.ident; + let gen = quote! { + impl HelloMacro for #name { + fn hello_macro() { + println!( + "Hello, Macro! My name is {}!", + stringify!(#name) + ); } } - } + }; + gen.into() } ``` -Listing 20-23: Explicitly dropping `sender` before joining the `Worker` threads +Listing 19-33: Implementing the `HelloMacro` trait using the parsed Rust code -Dropping `sender` [1] closes the channel, which indicates no more messages will -be sent. When that happens, all the calls to `recv` that the `Worker` instances -do in the infinite loop will return an error. In Listing 20-24, we change the -`Worker` loop to gracefully exit the loop in that case, which means the threads -will finish when the `ThreadPool` `drop` implementation calls `join` on them. +We get an `Ident` struct instance containing the name (identifier) of the +annotated type using `ast.ident`. The struct in Listing 19-32 shows that when +we run the `impl_hello_macro` function on the code in Listing 19-30, the +`ident` we get will have the `ident` field with a value of `"Pancakes"`. Thus +the `name` variable in Listing 19-33 will contain an `Ident` struct instance +that, when printed, will be the string `"Pancakes"`, the name of the struct in +Listing 19-30. -Filename: src/lib.rs +The `quote!` macro lets us define the Rust code that we want to return. The +compiler expects something different to the direct result of the `quote!` +macro’s execution, so we need to convert it to a `TokenStream`. We do this by +calling the `into` method, which consumes this intermediate representation and +returns a value of the required `TokenStream` type. + +The `quote!` macro also provides some very cool templating mechanics: we can +enter `#name`, and `quote!` will replace it with the value in the variable +`name`. You can even do some repetition similar to the way regular macros work. +Check out the `quote` crate’s docs at *https://docs.rs/quote* for a thorough +introduction. + +We want our procedural macro to generate an implementation of our `HelloMacro` +trait for the type the user annotated, which we can get by using `#name`. The +trait implementation has the one function `hello_macro`, whose body contains +the functionality we want to provide: printing `Hello, Macro! My name is` and +then the name of the annotated type. + +The `stringify!` macro used here is built into Rust. It takes a Rust +expression, such as `1 + 2`, and at compile time turns the expression into a +string literal, such as `"1 + 2"`. This is different from `format!` or +`println!`, macros which evaluate the expression and then turn the result into +a `String`. There is a possibility that the `#name` input might be an +expression to print literally, so we use `stringify!`. Using `stringify!` also +saves an allocation by converting `#name` to a string literal at compile time. + +At this point, `cargo build` should complete successfully in both `hello_macro` +and `hello_macro_derive`. Let’s hook up these crates to the code in Listing +19-30 to see the procedural macro in action! Create a new binary project in +your *projects* directory using `cargo new pancakes`. We need to add +`hello_macro` and `hello_macro_derive` as dependencies in the `pancakes` +crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` and +`hello_macro_derive` to *https://crates.io*, they would be regular +dependencies; if not, you can specify them as `path` dependencies as follows: ``` -impl Worker { - fn new( - id: usize, - receiver: Arc>>, - ) -> Worker { - let thread = thread::spawn(move || loop { - let message = receiver.lock().unwrap().recv(); - - match message { - Ok(job) => { - println!( - "Worker {id} got a job; executing." - ); - - job(); - } - Err(_) => { - println!( - "Worker {id} shutting down." - ); - break; - } - } - }); +[dependencies] +hello_macro = { path = "../hello_macro" } +hello_macro_derive = { path = "../hello_macro/hello_macro_derive" } +``` - Worker { - id, - thread: Some(thread), - } - } -} +Put the code in Listing 19-30 into *src/main.rs*, and run `cargo run`: it +should print `Hello, Macro! My name is Pancakes!` The implementation of the +`HelloMacro` trait from the procedural macro was included without the +`pancakes` crate needing to implement it; the `#[derive(HelloMacro)]` added the +trait implementation. + +Next, let’s explore how the other kinds of procedural macros differ from custom +`derive` macros. + +### Attribute-like Macros + +Attribute-like macros are similar to custom `derive` macros, but instead of +generating code for the `derive` attribute, they allow you to create new +attributes. They’re also more flexible: `derive` only works for structs and +enums; attributes can be applied to other items as well, such as functions. +Here’s an example of using an attribute-like macro. Say you have an attribute +named `route` that annotates functions when using a web application framework: + +``` +#[route(GET, "/")] +fn index() { ``` -Listing 20-24: Explicitly breaking out of the loop when `recv` returns an error +This `#[route]` attribute would be defined by the framework as a procedural +macro. The signature of the macro definition function would look like this: -To see this code in action, let’s modify `main` to accept only two requests -before gracefully shutting down the server, as shown in Listing 20-25. +``` +#[proc_macro_attribute] +pub fn route( + attr: TokenStream, + item: TokenStream +) -> TokenStream { +``` -Filename: src/main.rs +Here, we have two parameters of type `TokenStream`. The first is for the +contents of the attribute: the `GET, "/"` part. The second is the body of the +item the attribute is attached to: in this case, `fn index() {}` and the rest +of the function’s body. + +Other than that, attribute-like macros work the same way as custom `derive` +macros: you create a crate with the `proc-macro` crate type and implement a +function that generates the code you want! + +### Function-like Macros + +Function-like macros define macros that look like function calls. Similarly to +`macro_rules!` macros, they’re more flexible than functions; for example, they +can take an unknown number of arguments. However, `macro_rules!` macros can +only be defined using the match-like syntax we discussed in “Declarative Macros +with macro_rules! for General Metaprogramming” on page XX. Function-like macros +take a `TokenStream` parameter, and their definition manipulates that +`TokenStream` using Rust code as the other two types of procedural macros do. +An example of a function-like macro is an `sql!` macro that might be called +like so: ``` -fn main() { - let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); - let pool = ThreadPool::new(4); +let sql = sql!(SELECT * FROM posts WHERE id=1); +``` - for stream in listener.incoming().take(2) { - let stream = stream.unwrap(); +This macro would parse the SQL statement inside it and check that it’s +syntactically correct, which is much more complex processing than a +`macro_rules!` macro can do. The `sql!` macro would be defined like this: - pool.execute(|| { - handle_connection(stream); - }); - } +``` +#[proc_macro] +pub fn sql(input: TokenStream) -> TokenStream { +``` - println!("Shutting down."); -} -``` - -Listing 20-25: Shutting down the server after serving two requests by exiting -the loop - -You wouldn’t want a real-world web server to shut down after serving only two -requests. This code just demonstrates that the graceful shutdown and cleanup is -in working order. - -The `take` method is defined in the `Iterator` trait and limits the iteration -to the first two items at most. The `ThreadPool` will go out of scope at the -end of `main`, and the `drop` implementation will run. - -Start the server with `cargo run`, and make three requests. The third request -should error, and in your terminal you should see output similar to this: - -``` -$ cargo run - Compiling hello v0.1.0 (file:///projects/hello) - Finished dev [unoptimized + debuginfo] target(s) in 1.0s - Running `target/debug/hello` -Worker 0 got a job; executing. -Shutting down. -Shutting down worker 0 -Worker 3 got a job; executing. -Worker 1 disconnected; shutting down. -Worker 2 disconnected; shutting down. -Worker 3 disconnected; shutting down. -Worker 0 disconnected; shutting down. -Shutting down worker 1 -Shutting down worker 2 -Shutting down worker 3 -``` - -You might see a different ordering of `Worker` IDs and messages printed. We can -see how this code works from the messages: `Worker` instances 0 and 3 got the -first two requests. The server stopped accepting connections after the second -connection, and the `Drop` implementation on `ThreadPool` starts executing -before `Worker` 3 even starts its job. Dropping the `sender` disconnects all -the `Worker` instances and tells them to shut down. The `Worker` instances each -print a message when they disconnect, and then the thread pool calls `join` to -wait for each `Worker` thread to finish. - -Notice one interesting aspect of this particular execution: the `ThreadPool` -dropped the `sender`, and before any `Worker` received an error, we tried to -join `Worker` 0. `Worker` 0 had not yet gotten an error from `recv`, so the -main thread blocked, waiting for `Worker` 0 to finish. In the meantime, -`Worker` 3 received a job and then all threads received an error. When `Worker` -0 finished, the main thread waited for the rest of the `Worker` instances to -finish. At that point, they had all exited their loops and stopped. - -Congrats! We’ve now completed our project; we have a basic web server that uses -a thread pool to respond asynchronously. We’re able to perform a graceful -shutdown of the server, which cleans up all the threads in the pool. See -*https://www.nostarch.com/Rust2021* to download the full code for this chapter -for reference. - -We could do more here! If you want to continue enhancing this project, here are -some ideas: - -* Add more documentation to `ThreadPool` and its public methods. -* Add tests of the library’s functionality. -* Change calls to `unwrap` to more robust error handling. -* Use `ThreadPool` to perform some task other than serving web requests. -* Find a thread pool crate on *https://crates.io* and implement a similar web -server using the crate instead. Then compare its API and robustness to the -thread pool we implemented. +This definition is similar to the custom `derive` macro’s signature: we receive +the tokens that are inside the parentheses and return the code we wanted to +generate. ## Summary -Well done! You’ve made it to the end of the book! We want to thank you for -joining us on this tour of Rust. You’re now ready to implement your own Rust -projects and help with other people’s projects. Keep in mind that there is a -welcoming community of other Rustaceans who would love to help you with any -challenges you encounter on your Rust journey. +Whew! Now you have some Rust features in your toolbox that you likely won’t use +often, but you’ll know they’re available in very particular circumstances. +We’ve introduced several complex topics so that when you encounter them in +error message suggestions or in other people’s code, you’ll be able to +recognize these concepts and syntax. Use this chapter as a reference to guide +you to solutions. + +Next, we’ll put everything we’ve discussed throughout the book into practice +and do one more project! diff --git a/nostarch/chapter21.md b/nostarch/chapter21.md new file mode 100644 index 0000000000..9d4e22cd77 --- /dev/null +++ b/nostarch/chapter21.md @@ -0,0 +1,1994 @@ + + +[TOC] + +# Final Project: Building a Multithreaded Web Server + +It’s been a long journey, but we’ve reached the end of the book. In this +chapter, we’ll build one more project together to demonstrate some of the +concepts we covered in the final chapters, as well as recap some earlier +lessons. + +For our final project, we’ll make a web server that says “hello” and looks like +Figure 20-1 in a web browser. + +Figure 20-1: Our final shared project + +Here is our plan for building the web server: + +1. Learn a bit about TCP and HTTP. +1. Listen for TCP connections on a socket. +1. Parse a small number of HTTP requests. +1. Create a proper HTTP response. +1. Improve the throughput of our server with a thread pool. + +Before we get started, we should mention one detail: the method we’ll use won’t +be the best way to build a web server with Rust. Community members have +published a number of production-ready crates available at *https://crates.io* +that provide more complete web server and thread pool implementations than +we’ll build. However, our intention in this chapter is to help you learn, not +to take the easy route. Because Rust is a systems programming language, we can +choose the level of abstraction we want to work with and can go to a lower +level than is possible or practical in other languages. We’ll therefore write +the basic HTTP server and thread pool manually so you can learn the general +ideas and techniques behind the crates you might use in the future. + +## Building a Single-Threaded Web Server + +We’ll start by getting a single-threaded web server working. Before we begin, +let’s look at a quick overview of the protocols involved in building web +servers. The details of these protocols are beyond the scope of this book, but +a brief overview will give you the information you need. + +The two main protocols involved in web servers are *Hypertext Transfer +Protocol* *(HTTP)* and *Transmission Control Protocol* *(TCP)*. Both protocols +are *request-response* protocols, meaning a *client* initiates requests and a +*server* listens to the requests and provides a response to the client. The +contents of those requests and responses are defined by the protocols. + +TCP is the lower-level protocol that describes the details of how information +gets from one server to another but doesn’t specify what that information is. +HTTP builds on top of TCP by defining the contents of the requests and +responses. It’s technically possible to use HTTP with other protocols, but in +the vast majority of cases, HTTP sends its data over TCP. We’ll work with the +raw bytes of TCP and HTTP requests and responses. + +### Listening to the TCP Connection + +Our web server needs to listen to a TCP connection, so that’s the first part +we’ll work on. The standard library offers a `std::net` module that lets us do +this. Let’s make a new project in the usual fashion: + +``` +$ cargo new hello + Created binary (application) `hello` project +$ cd hello +``` + +Now enter the code in Listing 20-1 in *src/main.rs* to start. This code will +listen at the local address `127.0.0.1:7878` for incoming TCP streams. When it +gets an incoming stream, it will print `Connection established!`. + +Filename: src/main.rs + +``` +use std::net::TcpListener; + +fn main() { + 1 let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + + 2 for stream in listener.incoming() { + 3 let stream = stream.unwrap(); + + 4 println!("Connection established!"); + } +} +``` + +Listing 20-1: Listening for incoming streams and printing a message when we +receive a stream + +Using `TcpListener`, we can listen for TCP connections at the address +`127.0.0.1:7878` [1]. In the address, the section before the colon is an IP +address representing your computer (this is the same on every computer and +doesn’t represent the authors’ computer specifically), and `7878` is the port. +We’ve chosen this port for two reasons: HTTP isn’t normally accepted on this +port, so our server is unlikely to conflict with any other web server you might +have running on your machine, and 7878 is *rust* typed on a telephone. + +The `bind` function in this scenario works like the `new` function in that it +will return a new `TcpListener` instance. The function is called `bind` +because, in networking, connecting to a port to listen to is known as “binding +to a port.” + +The `bind` function returns a `Result`, which indicates that it’s +possible for binding to fail. For example, connecting to port 80 requires +administrator privileges (non-administrators can listen only on ports higher +than 1023), so if we tried to connect to port 80 without being an +administrator, binding wouldn’t work. Binding also wouldn’t work, for example, +if we ran two instances of our program and so had two programs listening to the +same port. Because we’re writing a basic server just for learning purposes, we +won’t worry about handling these kinds of errors; instead, we use `unwrap` to +stop the program if errors happen. + +The `incoming` method on `TcpListener` returns an iterator that gives us a +sequence of streams [2] (more specifically, streams of type `TcpStream`). A +single *stream* represents an open connection between the client and the +server. A *connection* is the name for the full request and response process in +which a client connects to the server, the server generates a response, and the +server closes the connection. As such, we will read from the `TcpStream` to see +what the client sent and then write our response to the stream to send data +back to the client. Overall, this `for` loop will process each connection in +turn and produce a series of streams for us to handle. + +For now, our handling of the stream consists of calling `unwrap` to terminate +our program if the stream has any errors [3]; if there aren’t any errors, the +program prints a message [4]. We’ll add more functionality for the success case +in the next listing. The reason we might receive errors from the `incoming` +method when a client connects to the server is that we’re not actually +iterating over connections. Instead, we’re iterating over *connection +attempts*. The connection might not be successful for a number of reasons, many +of them operating system specific. For example, many operating systems have a +limit to the number of simultaneous open connections they can support; new +connection attempts beyond that number will produce an error until some of the +open connections are closed. + +Let’s try running this code! Invoke `cargo run` in the terminal and then load +*127.0.0.1:7878* in a web browser. The browser should show an error message +like “Connection reset” because the server isn’t currently sending back any +data. But when you look at your terminal, you should see several messages that +were printed when the browser connected to the server! + +``` + Running `target/debug/hello` +Connection established! +Connection established! +Connection established! +``` + +Sometimes you’ll see multiple messages printed for one browser request; the +reason might be that the browser is making a request for the page as well as a +request for other resources, like the *favicon.ico* icon that appears in the +browser tab. + +It could also be that the browser is trying to connect to the server multiple +times because the server isn’t responding with any data. When `stream` goes out +of scope and is dropped at the end of the loop, the connection is closed as +part of the `drop` implementation. Browsers sometimes deal with closed +connections by retrying, because the problem might be temporary. The important +factor is that we’ve successfully gotten a handle to a TCP connection! + +Remember to stop the program by pressing ctrl-C when you’re done running a +particular version of the code. Then restart the program by invoking the `cargo +run` command after you’ve made each set of code changes to make sure you’re +running the newest code. + +### Reading the Request + +Let’s implement the functionality to read the request from the browser! To +separate the concerns of first getting a connection and then taking some action +with the connection, we’ll start a new function for processing connections. In +this new `handle_connection` function, we’ll read data from the TCP stream and +print it so we can see the data being sent from the browser. Change the code to +look like Listing 20-2. + +Filename: src/main.rs + +``` +1 use std::{ + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + 2 handle_connection(stream); + } +} + +fn handle_connection(mut stream: TcpStream) { + 3 let buf_reader = BufReader::new(&mut stream); + 4 let http_request: Vec<_> = buf_reader + 5 .lines() + 6 .map(|result| result.unwrap()) + 7 .take_while(|line| !line.is_empty()) + .collect(); + + 8 println!("Request: {:#?}", http_request); +} +``` + +Listing 20-2: Reading from the `TcpStream` and printing the data + +We bring `std::io::prelude` and `std::io::BufReader` into scope to get access +to traits and types that let us read from and write to the stream [1]. In the +`for` loop in the `main` function, instead of printing a message that says we +made a connection, we now call the new `handle_connection` function and pass +the `stream` to it [2]. + +In the `handle_connection` function, we create a new `BufReader` instance that +wraps a mutable reference to the `stream` [3]. `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 +lines in a vector by adding the `Vec<_>` type annotation [4]. + +`BufReader` implements the `std::io::BufRead` trait, which provides the `lines` +method [5]. The `lines` method returns an iterator of `Result` by splitting the stream of data whenever it sees a newline +byte. To get each `String`, we map and `unwrap` each `Result` [6]. The `Result` +might be an error if the data isn’t valid UTF-8 or if there was a problem +reading from the stream. Again, a production program should handle these errors +more gracefully, but we’re choosing to stop the program in the error case for +simplicity. + +The browser signals the end of an HTTP request by sending two newline +characters in a row, so to get one request from the stream, we take lines until +we get a line that is the empty string [7]. Once we’ve collected the lines into +the vector, we’re printing them out using pretty debug formatting [8] so we can +take a look at the instructions the web browser is sending to our server. + +Let’s try this code! Start the program and make a request in a web browser +again. Note that we’ll still get an error page in the browser, but our +program’s output in the terminal will now look similar to this: + +``` +$ cargo run + Compiling hello v0.1.0 (file:///projects/hello) + Finished dev [unoptimized + debuginfo] target(s) in 0.42s + Running `target/debug/hello` +Request: [ + "GET / HTTP/1.1", + "Host: 127.0.0.1:7878", + "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) +Gecko/20100101 Firefox/99.0", + "Accept: +text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/* +;q=0.8", + "Accept-Language: en-US,en;q=0.5", + "Accept-Encoding: gzip, deflate, br", + "DNT: 1", + "Connection: keep-alive", + "Upgrade-Insecure-Requests: 1", + "Sec-Fetch-Dest: document", + "Sec-Fetch-Mode: navigate", + "Sec-Fetch-Site: none", + "Sec-Fetch-User: ?1", + "Cache-Control: max-age=0", +] +``` + +Depending on your browser, you might get slightly different output. Now that +we’re printing the request data, we can see why we get multiple connections +from one browser request by looking at the path after `GET` in the first line +of the request. If the repeated connections are all requesting */*, we know the +browser is trying to fetch */* repeatedly because it’s not getting a response +from our program. + +Let’s break down this request data to understand what the browser is asking of +our program. + +### A Closer Look at an HTTP Request + +HTTP is a text-based protocol, and a request takes this format: + +``` +Method Request-URI HTTP-Version CRLF +headers CRLF +message-body +``` + +The first line is the *request line* that holds information about what the +client is requesting. The first part of the request line indicates the *method* +being used, such as `GET` or `POST`, which describes how the client is making +this request. Our client used a `GET` request, which means it is asking for +information. + +The next part of the request line is */*, which indicates the *uniform resource +identifier* *(URI)* the client is requesting: a URI is almost, but not quite, +the same as a *uniform resource locator* *(URL)*. The difference between URIs +and URLs isn’t important for our purposes in this chapter, but the HTTP spec +uses the term *URI*, so we can just mentally substitute *URL* for *URI* here. + +The last part is the HTTP version the client uses, and then the request line +ends in a CRLF sequence. (CRLF stands for *carriage return* and *line feed*, +which are terms from the typewriter days!) The CRLF sequence can also be +written as `\r\n`, where `\r` is a carriage return and `\n` is a line feed. The +*CRLF sequence* separates the request line from the rest of the request data. +Note that when the CRLF is printed, we see a new line start rather than `\r\n`. + +Looking at the request line data we received from running our program so far, +we see that `GET` is the method, */* is the request URI, and `HTTP/1.1` is the +version. + +After the request line, the remaining lines starting from `Host:` onward are +headers. `GET` requests have no body. + +Try making a request from a different browser or asking for a different +address, such as *127.0.0.1:7878/test*, to see how the request data changes. + +Now that we know what the browser is asking for, let’s send back some data! + +### Writing a Response + +We’re going to implement sending data in response to a client request. +Responses have the following format: + +``` +HTTP-Version Status-Code Reason-Phrase CRLF +headers CRLF +message-body +``` + +The first line is a *status line* that contains the HTTP version used in the +response, a numeric status code that summarizes the result of the request, and +a reason phrase that provides a text description of the status code. After the +CRLF sequence are any headers, another CRLF sequence, and the body of the +response. + +Here is an example response that uses HTTP version 1.1, and has a status code +of 200, an OK reason phrase, no headers, and no body: + +``` +HTTP/1.1 200 OK\r\n\r\n +``` + +The status code 200 is the standard success response. The text is a tiny +successful HTTP response. Let’s write this to the stream as our response to a +successful request! From the `handle_connection` function, remove the +`println!` that was printing the request data and replace it with the code in +Listing 20-3. + +Filename: src/main.rs + +``` +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let http_request: Vec<_> = buf_reader + .lines() + .map(|result| result.unwrap()) + .take_while(|line| !line.is_empty()) + .collect(); + + 1 let response = "HTTP/1.1 200 OK\r\n\r\n"; + + 2 stream.write_all(response.3 as_bytes()).unwrap(); +} +``` + +Listing 20-3: Writing a tiny successful HTTP response to the stream + +The first new line defines the `response` variable that holds the success +message’s data [1]. Then we call `as_bytes` on our `response` to convert the +string data to bytes [3]. The `write_all` method on `stream` takes a `&[u8]` +and sends those bytes directly down the connection [2]. Because the `write_all` +operation could fail, we use `unwrap` on any error result as before. Again, in +a real application you would add error handling here. + +With these changes, let’s run our code and make a request. We’re no longer +printing any data to the terminal, so we won’t see any output other than the +output from Cargo. When you load *127.0.0.1:7878* in a web browser, you should +get a blank page instead of an error. You’ve just handcoded receiving an HTTP +request and sending a response! + +### Returning Real HTML + +Let’s implement the functionality for returning more than a blank page. Create +the new file *hello.html* in the root of your project directory, not in the +*src* directory. You can input any HTML you want; Listing 20-4 shows one +possibility. + +Filename: hello.html + +``` + + + + + Hello! + + +

Hello!

+

Hi from Rust

+ + +``` + +Listing 20-4: A sample HTML file to return in a response + +This is a minimal HTML5 document with a heading and some text. To return this +from the server when a request is received, we’ll modify `handle_connection` as +shown in Listing 20-5 to read the HTML file, add it to the response as a body, +and send it. + +Filename: src/main.rs + +``` +use std::{ + 1 fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; +--snip-- + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let http_request: Vec<_> = buf_reader + .lines() + .map(|result| result.unwrap()) + .take_while(|line| !line.is_empty()) + .collect(); + + let status_line = "HTTP/1.1 200 OK"; + let contents = fs::read_to_string("hello.html").unwrap(); + let length = contents.len(); + + 2 let response = format!( + "{status_line}\r\n\ + Content-Length: {length}\r\n\r\n\ + {contents}" + ); + + stream.write_all(response.as_bytes()).unwrap(); +} +``` + +Listing 20-5: Sending the contents of *hello.html* as the body of the response + +We’ve added `fs` to the `use` statement to bring the standard library’s +filesystem module into scope [1]. The code for reading the contents of a file +to a string should look familiar; we used it when we read the contents of a +file for our I/O project in Listing 12-4. + +Next, we use `format!` to add the file’s contents as the body of the success +response [2]. To ensure a valid HTTP response, we add the `Content-Length` +header which is set to the size of our response body, in this case the size of +`hello.html`. + +Run this code with `cargo run` and load *127.0.0.1:7878* in your browser; you +should see your HTML rendered! + +Currently, we’re ignoring the request data in `http_request` and just sending +back the contents of the HTML file unconditionally. That means if you try +requesting *127.0.0.1:7878/something-else* in your browser, you’ll still get +back this same HTML response. At the moment, our server is very limited and +does not do what most web servers do. We want to customize our responses +depending on the request and only send back the HTML file for a well-formed +request to */*. + +### Validating the Request and Selectively Responding + +Right now, our web server will return the HTML in the file no matter what the +client requested. Let’s add functionality to check that the browser is +requesting */* before returning the HTML file, and return an error if the +browser requests anything else. For this we need to modify `handle_connection`, +as shown in Listing 20-6. This new code checks the content of the request +received against what we know a request for */* looks like and adds `if` and +`else` blocks to treat requests differently. + +Filename: src/main.rs + +``` +--snip-- + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + 1 let request_line = buf_reader + .lines() + .next() + .unwrap() + .unwrap(); + + 2 if request_line == "GET / HTTP/1.1" { + let status_line = "HTTP/1.1 200 OK"; + let contents = fs::read_to_string("hello.html").unwrap(); + let length = contents.len(); + + let response = format!( + "{status_line}\r\n\ + Content-Length: {length}\r\n\r\n\ + {contents}" + ); + + stream.write_all(response.as_bytes()).unwrap(); + 3 } else { + // some other request + } +} +``` + +Listing 20-6: Handling requests to */* differently from other requests + +We’re only going to be looking at the first line of the HTTP request, so rather +than reading the entire request into a vector, we’re calling `next` to get the +first item from the iterator [1]. The first `unwrap` takes care of the `Option` +and stops the program if the iterator has no items. The second `unwrap` handles +the `Result` and has the same effect as the `unwrap` that was in the `map` +added in Listing 20-2. + +Next, we check the `request_line` to see if it equals the request line of a GET +request to the */* path [2]. If it does, the `if` block returns the contents of +our HTML file. + +If the `request_line` does *not* equal the GET request to the */* path, it +means we’ve received some other request. We’ll add code to the `else` block [3] +in a moment to respond to all other requests. + +Run this code now and request *127.0.0.1:7878*; you should get the HTML in +*hello.html*. If you make any other request, such as +*127.0.0.1:7878/something-else*, you’ll get a connection error like those you +saw when running the code in Listing 20-1 and Listing 20-2. + +Now let’s add the code in Listing 20-7 to the `else` block to return a response +with the status code 404, which signals that the content for the request was +not found. We’ll also return some HTML for a page to render in the browser +indicating the response to the end user. + +Filename: src/main.rs + +``` +--snip-- +} else { + 1 let status_line = "HTTP/1.1 404 NOT FOUND"; + 2 let contents = fs::read_to_string("404.html").unwrap(); + let length = contents.len(); + + let response = format!( + "{status_line}\r\n\ + Content-Length: {length}\r\n\r\n + {contents}" + ); + + stream.write_all(response.as_bytes()).unwrap(); +} +``` + +Listing 20-7: Responding with status code 404 and an error page if anything +other than */* was requested + +Here, our response has a status line with status code 404 and the reason phrase +`NOT FOUND` [1]. The body of the response will be the HTML in the file +*404.html* [1]. You’ll need to create a *404.html* file next to *hello.html* +for the error page; again feel free to use any HTML you want, or use the +example HTML in Listing 20-8. + +Filename: 404.html + +``` + + + + + Hello! + + +

Oops!

+

Sorry, I don't know what you're asking for.

+ + +``` + +Listing 20-8: Sample content for the page to send back with any 404 response + +With these changes, run your server again. Requesting *127.0.0.1:7878* should +return the contents of *hello.html*, and any other request, like +*127.0.0.1:7878/foo*, should return the error HTML from *404.html*. + +### A Touch of Refactoring + +At the moment, the `if` and `else` blocks have a lot of repetition: they’re +both reading files and writing the contents of the files to the stream. The +only differences are the status line and the filename. Let’s make the code more +concise by pulling out those differences into separate `if` and `else` lines +that will assign the values of the status line and the filename to variables; +we can then use those variables unconditionally in the code to read the file +and write the response. Listing 20-9 shows the resultant code after replacing +the large `if` and `else` blocks. + +Filename: src/main.rs + +``` +--snip-- + +fn handle_connection(mut stream: TcpStream) { + --snip-- + + let (status_line, filename) = + if request_line == "GET / HTTP/1.1" { + ("HTTP/1.1 200 OK", "hello.html") + } else { + ("HTTP/1.1 404 NOT FOUND", "404.html") + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = format!( + "{status_line}\r\n\ + Content-Length: {length}\r\n\r\n\ + {contents}" + ); + + stream.write_all(response.as_bytes()).unwrap(); +} +``` + +Listing 20-9: Refactoring the `if` and `else` blocks to contain only the code +that differs between the two cases + +Now the `if` and `else` blocks only return the appropriate values for the +status line and filename in a tuple; we then use destructuring to assign these +two values to `status_line` and `filename` using a pattern in the `let` +statement, as discussed in Chapter 18. + +The previously duplicated code is now outside the `if` and `else` blocks and +uses the `status_line` and `filename` variables. This makes it easier to see +the difference between the two cases, and it means we have only one place to +update the code if we want to change how the file reading and response writing +work. The behavior of the code in Listing 20-9 will be the same as that in +Listing 20-8. + +Awesome! We now have a simple web server in approximately 40 lines of Rust code +that responds to one request with a page of content and responds to all other +requests with a 404 response. + +Currently, our server runs in a single thread, meaning it can only serve one +request at a time. Let’s examine how that can be a problem by simulating some +slow requests. Then we’ll fix it so our server can handle multiple requests at +once. + +## Turning Our Single-Threaded Server into a Multithreaded Server + +Right now, the server will process each request in turn, meaning it won’t +process a second connection until the first is finished processing. If the +server received more and more requests, this serial execution would be less and +less optimal. If the server receives a request that takes a long time to +process, subsequent requests will have to wait until the long request is +finished, even if the new requests can be processed quickly. We’ll need to fix +this, but first we’ll look at the problem in action. + +### Simulating a Slow Request + +We’ll look at how a slow-processing request can affect other requests made to +our current server implementation. Listing 20-10 implements handling a request +to */sleep* with a simulated slow response that will cause the server to sleep +for five seconds before responding. + +Filename: src/main.rs + +``` +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; +--snip-- + +fn handle_connection(mut stream: TcpStream) { + --snip-- + + let (status_line, filename) = 1 match &request_line[..] { + 2 "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + 3 "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + 4 _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + --snip-- +} +``` + +Listing 20-10: Simulating a slow request by sleeping for five seconds + +We switched from `if` to `match` now that we have three cases [1]. We need to +explicitly match on a slice of `request_line` to pattern-match against the +string literal values; `match` doesn’t do automatic referencing and +dereferencing, like the equality method does. + +The first arm [2] is the same as the `if` block from Listing 20-9. The second +arm [3] matches a request to */sleep*. When that request is received, the +server will sleep for five seconds before rendering the successful HTML page. +The third arm [4] is the same as the `else` block from Listing 20-9. + +You can see how primitive our server is: real libraries would handle the +recognition of multiple requests in a much less verbose way! + +Start the server using `cargo run`. Then open two browser windows: one for +*http://127.0.0.1:7878* and the other for *http://127.0.0.1:7878/sleep*. If you +enter the */* URI a few times, as before, you’ll see it respond quickly. But if +you enter */sleep* and then load */*, you’ll see that */* waits until `sleep` +has slept for its full five seconds before loading. + +There are multiple techniques we could use to avoid requests backing up behind +a slow request; the one we’ll implement is a thread pool. + +### Improving Throughput with a Thread Pool + +A *thread pool* is a group of spawned threads that are waiting and ready to +handle a task. When the program receives a new task, it assigns one of the +threads in the pool to the task, and that thread will process the task. The +remaining threads in the pool are available to handle any other tasks that come +in while the first thread is processing. When the first thread is done +processing its task, it’s returned to the pool of idle threads, ready to handle +a new task. A thread pool allows you to process connections concurrently, +increasing the throughput of your server. + +We’ll limit the number of threads in the pool to a small number to protect us +from DoS attacks; if we had our program create a new thread for each request as +it came in, someone making 10 million requests to our server could create havoc +by using up all our server’s resources and grinding the processing of requests +to a halt. + +Rather than spawning unlimited threads, then, we’ll have a fixed number of +threads waiting in the pool. Requests that come in are sent to the pool for +processing. The pool will maintain a queue of incoming requests. Each of the +threads in the pool will pop off a request from this queue, handle the request, +and then ask the queue for another request. With this design, we can process up +to N requests concurrently, where N is the number of threads. If each thread is +responding to a long-running request, subsequent requests can still back up in +the queue, but we’ve increased the number of long-running requests we can +handle before reaching that point. + +This technique is just one of many ways to improve the throughput of a web +server. Other options you might explore are the fork/join model, the +single-threaded async I/O model, and the multithreaded async I/O model. If +you’re interested in this topic, you can read more about other solutions and +try to implement them; with a low-level language like Rust, all of these +options are possible. + +Before we begin implementing a thread pool, let’s talk about what using the +pool should look like. When you’re trying to design code, writing the client +interface first can help guide your design. Write the API of the code so it’s +structured in the way you want to call it; then implement the functionality +within that structure rather than implementing the functionality and then +designing the public API. + +Similar to how we used test-driven development in the project in Chapter 12, +we’ll use compiler-driven development here. We’ll write the code that calls the +functions we want, and then we’ll look at errors from the compiler to determine +what we should change next to get the code to work. Before we do that, however, +we’ll explore the technique we’re not going to use as a starting point. + +#### Spawning a Thread for Each Request + +First, let’s explore how our code might look if it did create a new thread for +every connection. As mentioned earlier, this isn’t our final plan due to the +problems with potentially spawning an unlimited number of threads, but it is a +starting point to get a working multithreaded server first. Then we’ll add the +thread pool as an improvement, and contrasting the two solutions will be easier. + +Listing 20-11 shows the changes to make to `main` to spawn a new thread to +handle each stream within the `for` loop. + +Filename: src/main.rs + +``` +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + thread::spawn(|| { + handle_connection(stream); + }); + } +} +``` + +Listing 20-11: Spawning a new thread for each stream + +As you learned in Chapter 16, `thread::spawn` will create a new thread and then +run the code in the closure in the new thread. If you run this code and load +*/sleep* in your browser, then */* in two more browser tabs, you’ll indeed see +that the requests to */* don’t have to wait for */sleep* to finish. However, as +we mentioned, this will eventually overwhelm the system because you’d be making +new threads without any limit. + +#### Creating a Finite Number of Threads + +We want our thread pool to work in a similar, familiar way so that switching +from threads to a thread pool doesn’t require large changes to the code that +uses our API. Listing 20-12 shows the hypothetical interface for a `ThreadPool` +struct we want to use instead of `thread::spawn`. + +Filename: src/main.rs + +``` +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + 1 let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + 2 pool.execute(|| { + handle_connection(stream); + }); + } +} +``` + +Listing 20-12: Our ideal `ThreadPool` interface + +We use `ThreadPool::new` to create a new thread pool with a configurable number +of threads, in this case four [1]. Then, in the `for` loop, `pool.execute` has +a similar interface as `thread::spawn` in that it takes a closure the pool +should run for each stream [2]. We need to implement `pool.execute` so it takes +the closure and gives it to a thread in the pool to run. This code won’t yet +compile, but we’ll try so that the compiler can guide us in how to fix it. + +#### Building ThreadPool Using Compiler-Driven Development + +Make the changes in Listing 20-12 to *src/main.rs*, and then let’s use the +compiler errors from `cargo check` to drive our development. Here is the first +error we get: + +``` +$ cargo check + Checking hello v0.1.0 (file:///projects/hello) +error[E0433]: failed to resolve: use of undeclared type `ThreadPool` + --> src/main.rs:11:16 + | +11 | let pool = ThreadPool::new(4); + | ^^^^^^^^^^ use of undeclared type `ThreadPool` +``` + +Great! This error tells us we need a `ThreadPool` type or module, so we’ll +build one now. Our `ThreadPool` implementation will be independent of the kind +of work our web server is doing. So let’s switch the `hello` crate from a +binary crate to a library crate to hold our `ThreadPool` implementation. After +we change to a library crate, we could also use the separate thread pool +library for any work we want to do using a thread pool, not just for serving +web requests. + +Create a *src/lib.rs* file that contains the following, which is the simplest +definition of a `ThreadPool` struct that we can have for now: + +Filename: src/lib.rs + +``` +pub struct ThreadPool; +``` + +Then edit the *main.rs* file to bring `ThreadPool` into scope from the library +crate by adding the following code to the top of *src/main.rs*: + +Filename: src/main.rs + +``` +use hello::ThreadPool; +``` + +This code still won’t work, but let’s check it again to get the next error that +we need to address: + +``` +$ cargo check + Checking hello v0.1.0 (file:///projects/hello) +error[E0599]: no function or associated item named `new` found for struct +`ThreadPool` in the current scope + --> src/main.rs:12:28 + | +12 | let pool = ThreadPool::new(4); + | ^^^ function or associated item not found in +`ThreadPool` +``` + +This error indicates that next we need to create an associated function named +`new` for `ThreadPool`. We also know that `new` needs to have one parameter +that can accept `4` as an argument and should return a `ThreadPool` instance. +Let’s implement the simplest `new` function that will have those +characteristics: + +Filename: src/lib.rs + +``` +pub struct ThreadPool; + +impl ThreadPool { + pub fn new(size: usize) -> ThreadPool { + ThreadPool + } +} +``` + +We chose `usize` as the type of the `size` parameter because we know that a +negative number of threads doesn’t make any sense. We also know we’ll use this +`4` as the number of elements in a collection of threads, which is what the +`usize` type is for, as discussed in “Integer Types” on page XX. + +Let’s check the code again: + +``` +$ cargo check + Checking hello v0.1.0 (file:///projects/hello) +error[E0599]: no method named `execute` found for struct `ThreadPool` in the +current scope + --> src/main.rs:17:14 + | +17 | pool.execute(|| { + | ^^^^^^^ method not found in `ThreadPool` +``` + +Now the error occurs because we don’t have an `execute` method on `ThreadPool`. +Recall from “Creating a Finite Number of Threads” on page XX that we decided +our thread pool should have an interface similar to `thread::spawn`. In +addition, we’ll implement the `execute` function so it takes the closure it’s +given and gives it to an idle thread in the pool to run. + +We’ll define the `execute` method on `ThreadPool` to take a closure as a +parameter. Recall from “Moving Captured Values Out of Closures and the Fn +Traits” on page XX that we can take closures as parameters with three different +traits: `Fn`, `FnMut`, and `FnOnce`. We need to decide which kind of closure to +use here. We know we’ll end up doing something similar to the standard library +`thread::spawn` implementation, so we can look at what bounds the signature of +`thread::spawn` has on its parameter. The documentation shows us the following: + +``` +pub fn spawn(f: F) -> JoinHandle + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +``` + +The `F` type parameter is the one we’re concerned with here; the `T` type +parameter is related to the return value, and we’re not concerned with that. We +can see that `spawn` uses `FnOnce` as the trait bound on `F`. This is probably +what we want as well, because we’ll eventually pass the argument we get in +`execute` to `spawn`. We can be further confident that `FnOnce` is the trait we +want to use because the thread for running a request will only execute that +request’s closure one time, which matches the `Once` in `FnOnce`. + +The `F` type parameter also has the trait bound `Send` and the lifetime bound +`'static`, which are useful in our situation: we need `Send` to transfer the +closure from one thread to another and `'static` because we don’t know how long +the thread will take to execute. Let’s create an `execute` method on +`ThreadPool` that will take a generic parameter of type `F` with these bounds: + +Filename: src/lib.rs + +``` +impl ThreadPool { + --snip-- + pub fn execute(&self, f: F) + where + F: FnOnce() 1 + Send + 'static, + { + } +} +``` + +We still use the `()` after `FnOnce` [1] because this `FnOnce` represents a +closure that takes no parameters and returns the unit type `()`. Just like +function definitions, the return type can be omitted from the signature, but +even if we have no parameters, we still need the parentheses. + +Again, this is the simplest implementation of the `execute` method: it does +nothing, but we’re only trying to make our code compile. Let’s check it again: + +``` +$ cargo check + Checking hello v0.1.0 (file:///projects/hello) + Finished dev [unoptimized + debuginfo] target(s) in 0.24s +``` + +It compiles! But note that if you try `cargo run` and make a request in the +browser, you’ll see the errors in the browser that we saw at the beginning of +the chapter. Our library isn’t actually calling the closure passed to `execute` +yet! + +> Note: A saying you might hear about languages with strict compilers, such as +Haskell and Rust, is “if the code compiles, it works.” But this saying is not +universally true. Our project compiles, but it does absolutely nothing! If we +were building a real, complete project, this would be a good time to start +writing unit tests to check that the code compiles *and* has the behavior we +want. + +#### Validating the Number of Threads in new + +We aren’t doing anything with the parameters to `new` and `execute`. Let’s +implement the bodies of these functions with the behavior we want. To start, +let’s think about `new`. Earlier we chose an unsigned type for the `size` +parameter because a pool with a negative number of threads makes no sense. +However, a pool with zero threads also makes no sense, yet zero is a perfectly +valid `usize`. We’ll add code to check that `size` is greater than zero before +we return a `ThreadPool` instance and have the program panic if it receives a +zero by using the `assert!` macro, as shown in Listing 20-13. + +Filename: src/lib.rs + +``` +impl ThreadPool { + /// Create a new ThreadPool. + /// + /// The size is the number of threads in the pool. + /// + 1 /// # Panics + /// + /// The `new` function will panic if the size is zero. + pub fn new(size: usize) -> ThreadPool { + 2 assert!(size > 0); + + ThreadPool + } + + --snip-- +} +``` + +Listing 20-13: Implementing `ThreadPool::new` to panic if `size` is zero + +We’ve also added some documentation for our `ThreadPool` with doc comments. +Note that we followed good documentation practices by adding a section that +calls out the situations in which our function can panic [1], as discussed in +Chapter 14. Try running `cargo doc --open` and clicking the `ThreadPool` struct +to see what the generated docs for `new` look like! + +Instead of adding the `assert!` macro as we’ve done here [2], we could change +`new` into `build` and return a `Result` like we did with `Config::build` in +the I/O project in Listing 12-9. But we’ve decided in this case that trying to +create a thread pool without any threads should be an unrecoverable error. If +you’re feeling ambitious, try to write a function named `build` with the +following signature to compare with the `new` function: + +``` +pub fn build( + size: usize +) -> Result { +``` + +#### Creating Space to Store the Threads + +Now that we have a way to know we have a valid number of threads to store in +the pool, we can create those threads and store them in the `ThreadPool` struct +before returning the struct. But how do we “store” a thread? Let’s take another +look at the `thread::spawn` signature: + +``` +pub fn spawn(f: F) -> JoinHandle + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, +``` + +The `spawn` function returns a `JoinHandle`, where `T` is the type that the +closure returns. Let’s try using `JoinHandle` too and see what happens. In our +case, the closures we’re passing to the thread pool will handle the connection +and not return anything, so `T` will be the unit type `()`. + +The code in Listing 20-14 will compile but doesn’t create any threads yet. +We’ve changed the definition of `ThreadPool` to hold a vector of +`thread::JoinHandle<()>` instances, initialized the vector with a capacity of +`size`, set up a `for` loop that will run some code to create the threads, and +returned a `ThreadPool` instance containing them. + +Filename: src/lib.rs + +``` +1 use std::thread; + +pub struct ThreadPool { + 2 threads: Vec>, +} + +impl ThreadPool { + --snip-- + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + + 3 let mut threads = Vec::with_capacity(size); + + for _ in 0..size { + // create some threads and store them in the vector + } + + ThreadPool { threads } + } + --snip-- +} +``` + +Listing 20-14: Creating a vector for `ThreadPool` to hold the threads + +We’ve brought `std::thread` into scope in the library crate [1] because we’re +using `thread::JoinHandle` as the type of the items in the vector in +`ThreadPool` [2]. + +Once a valid size is received, our `ThreadPool` creates a new vector that can +hold `size` items [3]. The `with_capacity` function performs the same task as +`Vec::new` but with an important difference: it pre-allocates space in the +vector. Because we know we need to store `size` elements in the vector, doing +this allocation up front is slightly more efficient than using `Vec::new`, +which resizes itself as elements are inserted. + +When you run `cargo check` again, it should succeed. + +#### Sending Code from the ThreadPool to a Thread + +We left a comment in the `for` loop in Listing 20-14 regarding the creation of +threads. Here, we’ll look at how we actually create threads. The standard +library provides `thread::spawn` as a way to create threads, and +`thread::spawn` expects to get some code the thread should run as soon as the +thread is created. However, in our case, we want to create the threads and have +them *wait* for code that we’ll send later. The standard library’s +implementation of threads doesn’t include any way to do that; we have to +implement it manually. + +We’ll implement this behavior by introducing a new data structure between the +`ThreadPool` and the threads that will manage this new behavior. We’ll call +this data structure *Worker*, which is a common term in pooling +implementations. The `Worker` picks up code that needs to be run and runs the +code in its thread. + +Think of people working in the kitchen at a restaurant: the workers wait until +orders come in from customers, and then they’re responsible for taking those +orders and filling them. + +Instead of storing a vector of `JoinHandle<()>` instances in the thread pool, +we’ll store instances of the `Worker` struct. Each `Worker` will store a single +`JoinHandle<()>` instance. Then we’ll implement a method on `Worker` that will +take a closure of code to run and send it to the already running thread for +execution. We’ll also give each `Worker` an `id` so we can distinguish between +the different instances of `Worker` in the pool when logging or debugging. + +Here is the new process that will happen when we create a `ThreadPool`. We’ll +implement the code that sends the closure to the thread after we have `Worker` +set up in this way: + +1. Define a `Worker` struct that holds an `id` and a `JoinHandle<()>`. +1. Change `ThreadPool` to hold a vector of `Worker` instances. +1. Define a `Worker::new` function that takes an `id` number and returns a +`Worker` instance that holds the `id` and a thread spawned with an empty +closure. +1. In `ThreadPool::new`, use the `for` loop counter to generate an `id`, create +a new `Worker` with that `id`, and store the `Worker` in the vector. + +If you’re up for a challenge, try implementing these changes on your own before +looking at the code in Listing 20-15. + +Ready? Here is Listing 20-15 with one way to make the preceding modifications. + +Filename: src/lib.rs + +``` +use std::thread; + +pub struct ThreadPool { + 1 workers: Vec, +} + +impl ThreadPool { + --snip-- + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + + let mut workers = Vec::with_capacity(size); + + 2 for id in 0..size { + 3 workers.push(Worker::new(id)); + } + + ThreadPool { workers } + } + --snip-- +} + +4 struct Worker { + id: usize, + thread: thread::JoinHandle<()>, +} + +impl Worker { + 5 fn new(id: usize) -> Worker { + 6 let thread = thread::spawn(|| {}); + + Worker { 7 id, 8 thread } + } +} +``` + +Listing 20-15: Modifying `ThreadPool` to hold `Worker` instances instead of +holding threads directly + +We’ve changed the name of the field on `ThreadPool` from `threads` to `workers` +because it’s now holding `Worker` instances instead of `JoinHandle<()>` +instances [1]. We use the counter in the `for` loop [2] as an argument to +`Worker::new`, and we store each new `Worker` in the vector named `workers` [3]. + +External code (like our server in *src/main.rs*) doesn’t need to know the +implementation details regarding using a `Worker` struct within `ThreadPool`, +so we make the `Worker` struct [4] and its `new` function [5] private. The +`Worker::new` function uses the `id` we give it [7] and stores a +`JoinHandle<()>` instance [8] that is created by spawning a new thread using an +empty closure [6]. + +> Note: If the operating system can’t create a thread because there aren’t +enough system resources, `thread::spawn` will panic. That will cause our whole +server to panic, even though the creation of some threads might succeed. For +simplicity’s sake, this behavior is fine, but in a production thread pool +implementation, you’d likely want to use `std::thread::Builder` and its `spawn` +method that returns `Result` instead. + +This code will compile and will store the number of `Worker` instances we +specified as an argument to `ThreadPool::new`. But we’re *still* not processing +the closure that we get in `execute`. Let’s look at how to do that next. + +#### Sending Requests to Threads via Channels + +The next problem we’ll tackle is that the closures given to `thread::spawn` do +absolutely nothing. Currently, we get the closure we want to execute in the +`execute` method. But we need to give `thread::spawn` a closure to run when we +create each `Worker` during the creation of the `ThreadPool`. + +We want the `Worker` structs that we just created to fetch the code to run from +a queue held in the `ThreadPool` and send that code to its thread to run. + +The channels we learned about in Chapter 16—a simple way to communicate between +two threads—would be perfect for this use case. We’ll use a channel to function +as the queue of jobs, and `execute` will send a job from the `ThreadPool` to +the `Worker` instances, which will send the job to its thread. Here is the plan: + +1. The `ThreadPool` will create a channel and hold on to the sender. +1. Each `Worker` will hold on to the receiver. +1. We’ll create a new `Job` struct that will hold the closures we want to send +down the channel. +1. The `execute` method will send the job it wants to execute through the +sender. +1. In its thread, the `Worker` will loop over its receiver and execute the +closures of any jobs it receives. + +Let’s start by creating a channel in `ThreadPool::new` and holding the sender +in the `ThreadPool` instance, as shown in Listing 20-16. The `Job` struct +doesn’t hold anything for now but will be the type of item we’re sending down +the channel. + +Filename: src/lib.rs + +``` +use std::{sync::mpsc, thread}; + +pub struct ThreadPool { + workers: Vec, + sender: mpsc::Sender, +} + +struct Job; + +impl ThreadPool { + --snip-- + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + + 1 let (sender, receiver) = mpsc::channel(); + + let mut workers = Vec::with_capacity(size); + + for id in 0..size { + workers.push(Worker::new(id)); + } + + ThreadPool { workers, 2 sender } + } + --snip-- +} +``` + +Listing 20-16: Modifying `ThreadPool` to store the sender of a channel that +transmits `Job` instances + +In `ThreadPool::new`, we create our new channel [1] and have the pool hold the +sender [2]. This will successfully compile. + +Let’s try passing a receiver of the channel into each `Worker` as the thread +pool creates the channel. We know we want to use the receiver in the thread +that the `Worker` instances spawn, so we’ll reference the `receiver` parameter +in the closure. The code in Listing 20-17 won’t quite compile yet. + +Filename: src/lib.rs + +``` +impl ThreadPool { + --snip-- + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + + let (sender, receiver) = mpsc::channel(); + + let mut workers = Vec::with_capacity(size); + + for id in 0..size { + 1 workers.push(Worker::new(id, receiver)); + } + + ThreadPool { workers, sender } + } + --snip-- +} + +--snip-- + +impl Worker { + fn new(id: usize, receiver: mpsc::Receiver) -> Worker { + let thread = thread::spawn(|| { + 2 receiver; + }); + + Worker { id, thread } + } +} +``` + +Listing 20-17: Passing the receiver to each `Worker` + +We’ve made some small and straightforward changes: we pass the receiver into +`Worker::new` [1], and then we use it inside the closure [2]. + +When we try to check this code, we get this error: + +``` +$ cargo check + Checking hello v0.1.0 (file:///projects/hello) +error[E0382]: use of moved value: `receiver` + --> src/lib.rs:26:42 + | +21 | let (sender, receiver) = mpsc::channel(); + | -------- move occurs because `receiver` has type +`std::sync::mpsc::Receiver`, which does not implement the `Copy` trait +... +26 | workers.push(Worker::new(id, receiver)); + | ^^^^^^^^ value moved here, in +previous iteration of loop +``` + +The code is trying to pass `receiver` to multiple `Worker` instances. This +won’t work, as you’ll recall from Chapter 16: the channel implementation that +Rust provides is multiple *producer*, single *consumer*. This means we can’t +just clone the consuming end of the channel to fix this code. We also don’t +want to send a message multiple times to multiple consumers; we want one list +of messages with multiple `Worker` instances such that each message gets +processed once. + +Additionally, taking a job off the channel queue involves mutating the +`receiver`, so the threads need a safe way to share and modify `receiver`; +otherwise, we might get race conditions (as covered in Chapter 16). + +Recall the thread-safe smart pointers discussed in Chapter 16: to share +ownership across multiple threads and allow the threads to mutate the value, we +need to use `Arc>`. The `Arc` type will let multiple `Worker` +instances own the receiver, and `Mutex` will ensure that only one `Worker` gets +a job from the receiver at a time. Listing 20-18 shows the changes we need to +make. + +Filename: src/lib.rs + +``` +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; +--snip-- + +impl ThreadPool { + --snip-- + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + + let (sender, receiver) = mpsc::channel(); + + 1 let receiver = Arc::new(Mutex::new(receiver)); + + let mut workers = Vec::with_capacity(size); + + for id in 0..size { + workers.push( + Worker::new(id, Arc::clone(& 2 receiver)) + ); + } + + ThreadPool { workers, sender } + } + + --snip-- +} + +--snip-- + +impl Worker { + fn new( + id: usize, + receiver: Arc>>, + ) -> Worker { + --snip-- + } +} +``` + +Listing 20-18: Sharing the receiver among the `Worker` instances using `Arc` +and `Mutex` + +In `ThreadPool::new`, we put the receiver in an `Arc` and a `Mutex` [1]. For +each new `Worker`, we clone the `Arc` to bump the reference count so the +`Worker` instances can share ownership of the receiver [2]. + +With these changes, the code compiles! We’re getting there! + +#### Implementing the execute Method + +Let’s finally implement the `execute` method on `ThreadPool`. We’ll also change +`Job` from a struct to a type alias for a trait object that holds the type of +closure that `execute` receives. As discussed in “Creating Type Synonyms with +Type Aliases” on page XX, type aliases allow us to make long types shorter for +ease of use. Look at Listing 20-19. + +Filename: src/lib.rs + +``` +--snip-- + +type Job = Box; + +impl ThreadPool { + --snip-- + + pub fn execute(&self, f: F) + where + F: FnOnce() + Send + 'static, + { + 1 let job = Box::new(f); + + 2 self.sender.send(job).unwrap(); + } +} + +--snip-- +``` + +Listing 20-19: Creating a `Job` type alias for a `Box` that holds each closure +and then sending the job down the channel + +After creating a new `Job` instance using the closure we get in `execute` [1], +we send that job down the sending end of the channel [2]. We’re calling +`unwrap` on `send` for the case that sending fails. This might happen if, for +example, we stop all our threads from executing, meaning the receiving end has +stopped receiving new messages. At the moment, we can’t stop our threads from +executing: our threads continue executing as long as the pool exists. The +reason we use `unwrap` is that we know the failure case won’t happen, but the +compiler doesn’t know that. + +But we’re not quite done yet! In the `Worker`, our closure being passed to +`thread::spawn` still only *references* the receiving end of the channel. +Instead, we need the closure to loop forever, asking the receiving end of the +channel for a job and running the job when it gets one. Let’s make the change +shown in Listing 20-20 to `Worker::new`. + +Filename: src/lib.rs + +``` +--snip-- + +impl Worker { + fn new( + id: usize, + receiver: Arc>>, + ) -> Worker { + let thread = thread::spawn(move || loop { + let job = receiver + 1 .lock() + 2 .unwrap() + 3 .recv() + 4 .unwrap(); + + println!("Worker {id} got a job; executing."); + + job(); + }); + + Worker { id, thread } + } +} +``` + +Listing 20-20: Receiving and executing the jobs in the `Worker` instance’s +thread + +Here, we first call `lock` on the `receiver` to acquire the mutex [1], and then +we call `unwrap` to panic on any errors [2]. Acquiring a lock might fail if the +mutex is in a *poisoned* state, which can happen if some other thread panicked +while holding the lock rather than releasing the lock. In this situation, +calling `unwrap` to have this thread panic is the correct action to take. Feel +free to change this `unwrap` to an `expect` with an error message that is +meaningful to you. + +If we get the lock on the mutex, we call `recv` to receive a `Job` from the +channel [3]. A final `unwrap` moves past any errors here as well [4], which +might occur if the thread holding the sender has shut down, similar to how the +`send` method returns `Err` if the receiver shuts down. + +The call to `recv` blocks, so if there is no job yet, the current thread will +wait until a job becomes available. The `Mutex` ensures that only one +`Worker` thread at a time is trying to request a job. + +Our thread pool is now in a working state! Give it a `cargo run` and make some +requests: + +``` +$ cargo run + Compiling hello v0.1.0 (file:///projects/hello) +warning: field is never read: `workers` + --> src/lib.rs:7:5 + | +7 | workers: Vec, + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: field is never read: `id` + --> src/lib.rs:48:5 + | +48 | id: usize, + | ^^^^^^^^^ + +warning: field is never read: `thread` + --> src/lib.rs:49:5 + | +49 | thread: thread::JoinHandle<()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `hello` (lib) generated 3 warnings + Finished dev [unoptimized + debuginfo] target(s) in 1.40s + Running `target/debug/hello` +Worker 0 got a job; executing. +Worker 2 got a job; executing. +Worker 1 got a job; executing. +Worker 3 got a job; executing. +Worker 0 got a job; executing. +Worker 2 got a job; executing. +Worker 1 got a job; executing. +Worker 3 got a job; executing. +Worker 0 got a job; executing. +Worker 2 got a job; executing. +``` + +Success! We now have a thread pool that executes connections asynchronously. +There are never more than four threads created, so our system won’t get +overloaded if the server receives a lot of requests. If we make a request to +*/sleep*, the server will be able to serve other requests by having another +thread run them. + +> Note: If you open */sleep* in multiple browser windows simultaneously, they +might load one at a time in five-second intervals. Some web browsers execute +multiple instances of the same request sequentially for caching reasons. This +limitation is not caused by our web server. + +After learning about the `while let` loop in Chapter 18, you might be wondering +why we didn’t write the `Worker` thread code as shown in Listing 20-21. + +Filename: src/lib.rs + +``` +--snip-- + +impl Worker { + fn new( + id: usize, + receiver: Arc>>, + ) -> Worker { + let thread = thread::spawn(move || { + while let Ok(job) = receiver.lock().unwrap().recv() { + println!("Worker {id} got a job; executing."); + + job(); + } + }); + + Worker { id, thread } + } +} +``` + +Listing 20-21: An alternative implementation of `Worker::new` using `while let` + +This code compiles and runs but doesn’t result in the desired threading +behavior: a slow request will still cause other requests to wait to be +processed. The reason is somewhat subtle: the `Mutex` struct has no public +`unlock` method because the ownership of the lock is based on the lifetime of +the `MutexGuard` within the `LockResult>` that the `lock` +method returns. At compile time, the borrow checker can then enforce the rule +that a resource guarded by a `Mutex` cannot be accessed unless we hold the +lock. However, this implementation can also result in the lock being held +longer than intended if we aren’t mindful of the lifetime of the +`MutexGuard`. + +The code in Listing 20-20 that uses `let job = +receiver.lock().unwrap().recv().unwrap();` works because with `let`, any +temporary values used in the expression on the right-hand side of the equal +sign are immediately dropped when the `let` statement ends. However, `while +let` (and `if let` and `match`) does not drop temporary values until the end of +the associated block. In Listing 20-21, the lock remains held for the duration +of the call to `job()`, meaning other `Worker` instances cannot receive jobs. + +## Graceful Shutdown and Cleanup + +The code in Listing 20-20 is responding to requests asynchronously through the +use of a thread pool, as we intended. We get some warnings about the `workers`, +`id`, and `thread` fields that we’re not using in a direct way that reminds us +we’re not cleaning up anything. When we use the less elegant ctrl-C method to +halt the main thread, all other threads are stopped immediately as well, even +if they’re in the middle of serving a request. + +Next, then, we’ll implement the `Drop` trait to call `join` on each of the +threads in the pool so they can finish the requests they’re working on before +closing. Then we’ll implement a way to tell the threads they should stop +accepting new requests and shut down. To see this code in action, we’ll modify +our server to accept only two requests before gracefully shutting down its +thread pool. + +### Implementing the Drop Trait on ThreadPool + +Let’s start with implementing `Drop` on our thread pool. When the pool is +dropped, our threads should all join to make sure they finish their work. +Listing 20-22 shows a first attempt at a `Drop` implementation; this code won’t +quite work yet. + +Filename: src/lib.rs + +``` +impl Drop for ThreadPool { + fn drop(&mut self) { + 1 for worker in &mut self.workers { + 2 println!("Shutting down worker {}", worker.id); + + 3 worker.thread.join().unwrap(); + } + } +} +``` + +Listing 20-22: Joining each thread when the thread pool goes out of scope + +First we loop through each of the thread pool `workers` [1]. We use `&mut` for +this because `self` is a mutable reference, and we also need to be able to +mutate `worker`. For each `worker`, we print a message saying that this +particular `Worker` instance is shutting down [2], and then we call `join` on +that `Worker` instance’s thread [3]. If the call to `join` fails, we use +`unwrap` to make Rust panic and go into an ungraceful shutdown. + +Here is the error we get when we compile this code: + +``` +error[E0507]: cannot move out of `worker.thread` which is behind a mutable +reference + --> src/lib.rs:52:13 + | +52 | worker.thread.join().unwrap(); + | ^^^^^^^^^^^^^ ------ `worker.thread` moved due to this +method call + | | + | move occurs because `worker.thread` has type +`JoinHandle<()>`, which does not implement the `Copy` trait + | +note: this function takes ownership of the receiver `self`, which moves +`worker.thread` +``` + +The error tells us we can’t call `join` because we only have a mutable borrow +of each `worker` and `join` takes ownership of its argument. To solve this +issue, we need to move the thread out of the `Worker` instance that owns +`thread` so `join` can consume the thread. We did this in Listing 17-15: if +`Worker` holds an `Option>` instead, we can call the +`take` method on the `Option` to move the value out of the `Some` variant and +leave a `None` variant in its place. In other words, a `Worker` that is running +will have a `Some` variant in `thread`, and when we want to clean up a +`Worker`, we’ll replace `Some` with `None` so the `Worker` doesn’t have a +thread to run. + +So we know we want to update the definition of `Worker` like this: + +Filename: src/lib.rs + +``` +struct Worker { + id: usize, + thread: Option>, +} +``` + +Now let’s lean on the compiler to find the other places that need to change. +Checking this code, we get two errors: + +``` +error[E0599]: no method named `join` found for enum `Option` in the current +scope + --> src/lib.rs:52:27 + | +52 | worker.thread.join().unwrap(); + | ^^^^ method not found in +`Option>` + +error[E0308]: mismatched types + --> src/lib.rs:72:22 + | +72 | Worker { id, thread } + | ^^^^^^ expected enum `Option`, found struct +`JoinHandle` + | + = note: expected enum `Option>` + found struct `JoinHandle<_>` +help: try wrapping the expression in `Some` + | +72 | Worker { id, thread: Some(thread) } + | +++++++++++++ + +``` + +Let’s address the second error, which points to the code at the end of +`Worker::new`; we need to wrap the `thread` value in `Some` when we create a +new `Worker`. Make the following changes to fix this error: + +Filename: src/lib.rs + +``` +impl Worker { + fn new( + id: usize, + receiver: Arc>>, + ) -> Worker { + --snip-- + + Worker { + id, + thread: Some(thread), + } + } +} +``` + +The first error is in our `Drop` implementation. We mentioned earlier that we +intended to call `take` on the `Option` value to move `thread` out of `worker`. +The following changes will do so: + +Filename: src/lib.rs + +``` +impl Drop for ThreadPool { + fn drop(&mut self) { + for worker in &mut self.workers { + println!("Shutting down worker {}", worker.id); + + 1 if let Some(thread) = worker.thread.take() { + 2 thread.join().unwrap(); + } + } + } +} +``` + +As discussed in Chapter 17, the `take` method on `Option` takes the `Some` +variant out and leaves `None` in its place. We’re using `if let` to destructure +the `Some` and get the thread [1]; then we call `join` on the thread [2]. If a +`Worker` instance’s thread is already `None`, we know that `Worker` has already +had its thread cleaned up, so nothing happens in that case. + +### Signaling to the Threads to Stop Listening for Jobs + +With all the changes we’ve made, our code compiles without any warnings. +However, the bad news is that this code doesn’t function the way we want it to +yet. The key is the logic in the closures run by the threads of the `Worker` +instances: at the moment, we call `join`, but that won’t shut down the threads, +because they `loop` forever looking for jobs. If we try to drop our +`ThreadPool` with our current implementation of `drop`, the main thread will +block forever, waiting for the first thread to finish. + +To fix this problem, we’ll need a change in the `ThreadPool` `drop` +implementation and then a change in the `Worker` loop. + +First we’ll change the `ThreadPool` `drop` implementation to explicitly drop +the `sender` before waiting for the threads to finish. Listing 20-23 shows the +changes to `ThreadPool` to explicitly drop `sender`. We use the same `Option` +and `take` technique as we did with the thread to be able to move `sender` out +of `ThreadPool`. + +Filename: src/lib.rs + +``` +pub struct ThreadPool { + workers: Vec, + sender: Option>, +} +--snip-- +impl ThreadPool { + pub fn new(size: usize) -> ThreadPool { + --snip-- + + ThreadPool { + workers, + sender: Some(sender), + } + } + + pub fn execute(&self, f: F) + where + F: FnOnce() + Send + 'static, + { + let job = Box::new(f); + + self.sender + .as_ref() + .unwrap() + .send(job) + .unwrap(); + } +} + +impl Drop for ThreadPool { + fn drop(&mut self) { + 1 drop(self.sender.take()); + + for worker in &mut self.workers { + println!("Shutting down worker {}", worker.id); + + if let Some(thread) = worker.thread.take() { + thread.join().unwrap(); + } + } + } +} +``` + +Listing 20-23: Explicitly dropping `sender` before joining the `Worker` threads + +Dropping `sender` [1] closes the channel, which indicates no more messages will +be sent. When that happens, all the calls to `recv` that the `Worker` instances +do in the infinite loop will return an error. In Listing 20-24, we change the +`Worker` loop to gracefully exit the loop in that case, which means the threads +will finish when the `ThreadPool` `drop` implementation calls `join` on them. + +Filename: src/lib.rs + +``` +impl Worker { + fn new( + id: usize, + receiver: Arc>>, + ) -> Worker { + let thread = thread::spawn(move || loop { + let message = receiver.lock().unwrap().recv(); + + match message { + Ok(job) => { + println!( + "Worker {id} got a job; executing." + ); + + job(); + } + Err(_) => { + println!( + "Worker {id} shutting down." + ); + break; + } + } + }); + + Worker { + id, + thread: Some(thread), + } + } +} +``` + +Listing 20-24: Explicitly breaking out of the loop when `recv` returns an error + +To see this code in action, let’s modify `main` to accept only two requests +before gracefully shutting down the server, as shown in Listing 20-25. + +Filename: src/main.rs + +``` +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming().take(2) { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } + + println!("Shutting down."); +} +``` + +Listing 20-25: Shutting down the server after serving two requests by exiting +the loop + +You wouldn’t want a real-world web server to shut down after serving only two +requests. This code just demonstrates that the graceful shutdown and cleanup is +in working order. + +The `take` method is defined in the `Iterator` trait and limits the iteration +to the first two items at most. The `ThreadPool` will go out of scope at the +end of `main`, and the `drop` implementation will run. + +Start the server with `cargo run`, and make three requests. The third request +should error, and in your terminal you should see output similar to this: + +``` +$ cargo run + Compiling hello v0.1.0 (file:///projects/hello) + Finished dev [unoptimized + debuginfo] target(s) in 1.0s + Running `target/debug/hello` +Worker 0 got a job; executing. +Shutting down. +Shutting down worker 0 +Worker 3 got a job; executing. +Worker 1 disconnected; shutting down. +Worker 2 disconnected; shutting down. +Worker 3 disconnected; shutting down. +Worker 0 disconnected; shutting down. +Shutting down worker 1 +Shutting down worker 2 +Shutting down worker 3 +``` + +You might see a different ordering of `Worker` IDs and messages printed. We can +see how this code works from the messages: `Worker` instances 0 and 3 got the +first two requests. The server stopped accepting connections after the second +connection, and the `Drop` implementation on `ThreadPool` starts executing +before `Worker` 3 even starts its job. Dropping the `sender` disconnects all +the `Worker` instances and tells them to shut down. The `Worker` instances each +print a message when they disconnect, and then the thread pool calls `join` to +wait for each `Worker` thread to finish. + +Notice one interesting aspect of this particular execution: the `ThreadPool` +dropped the `sender`, and before any `Worker` received an error, we tried to +join `Worker` 0. `Worker` 0 had not yet gotten an error from `recv`, so the +main thread blocked, waiting for `Worker` 0 to finish. In the meantime, +`Worker` 3 received a job and then all threads received an error. When `Worker` +0 finished, the main thread waited for the rest of the `Worker` instances to +finish. At that point, they had all exited their loops and stopped. + +Congrats! We’ve now completed our project; we have a basic web server that uses +a thread pool to respond asynchronously. We’re able to perform a graceful +shutdown of the server, which cleans up all the threads in the pool. See +*https://www.nostarch.com/Rust2021* to download the full code for this chapter +for reference. + +We could do more here! If you want to continue enhancing this project, here are +some ideas: + +* Add more documentation to `ThreadPool` and its public methods. +* Add tests of the library’s functionality. +* Change calls to `unwrap` to more robust error handling. +* Use `ThreadPool` to perform some task other than serving web requests. +* Find a thread pool crate on *https://crates.io* and implement a similar web +server using the crate instead. Then compare its API and robustness to the +thread pool we implemented. + +## Summary + +Well done! You’ve made it to the end of the book! We want to thank you for +joining us on this tour of Rust. You’re now ready to implement your own Rust +projects and help with other people’s projects. Keep in mind that there is a +welcoming community of other Rustaceans who would love to help you with any +challenges you encounter on your Rust journey. + From 3b8d132adf52c624118e72b6cdd7fc32aee5d001 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Thu, 3 Oct 2024 21:24:28 -0400 Subject: [PATCH 229/249] Generated nostarch snapshot for the new async chapter --- nostarch/chapter17.md | 3157 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3157 insertions(+) create mode 100644 nostarch/chapter17.md diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md new file mode 100644 index 0000000000..57e90e6704 --- /dev/null +++ b/nostarch/chapter17.md @@ -0,0 +1,3157 @@ + + +[TOC] + +## Async and Await + +Many operations we ask the computer to do can take a while to finish. For +example, if you used a video editor to create a video of a family celebration, +exporting it could take anywhere from minutes to hours. Similarly, downloading a +video shared by someone in your family might take a long time. It would be nice +if we could do something else while we are waiting for those long-running +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 couldn’t do anything else on your computer while it was running. +That would be a pretty frustrating experience, though. Instead, your computer’s +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 +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’s 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 + > “CPU-bound” or “compute-bound”. It’s limited by the speed of the computer’s + > ability to process data within the *CPU* or *GPU*, and how much of that speed + > it can use. The video download is the kind of operation which is often + > described as “IO-bound,” because it’s limited by the speed of the computer’s + > *input and output*. It can only go as fast as the data can be sent across the + > network. + +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, because 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. + +For example, if we’re building a tool to manage file downloads, we should be +able to write our program in such a way that starting one download does not lock +up the UI, and users should be able to start multiple downloads at the same +time. Many operating system APIs for interacting with the network are +*blocking*, though. That is, these APIs block the program’s progress until the +data that they are processing is completely ready. + + > + > Note: This is how *most* function calls work, if you think about it! However, + > we normally reserve the term “blocking” for function calls which interact with + > files, the network, or other resources on the computer, because those are the + > places where an individual program would benefit from the operation being + > *non*-blocking. + +We could avoid blocking our main thread by spawning a dedicated thread to +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 similar to this: + +``` +let data = fetch_data_from(url).await; +println!("{data}"); +``` + +That is exactly what Rust’s async abstraction gives us. Before we see how this +works in practice, though, we need to take a short detour into the differences +between parallelism and concurrency. + +### Parallelism and Concurrency + +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. + +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’re just one person, so you can’t make progress on both tasks +at the exact same time—but you can multi-task, making progress on multiple +tasks by switching between them. + +
+ +Concurrent work flow + +
Figure 17-1: A concurrent workflow, switching between Task A and Task B
+ +
+ +When you agree to split up a group of tasks between the people on the team, with +each person taking one task and working on it alone, this is *parallelism*. Each +person on the team can make progress at the exact same time. + +
+ +Concurrent work flow + +
Figure 17-2: A parallel workflow, where work happens on Task A and Task B independently
+ +
+ +With both of these situations, you might have to coordinate between different +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 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. If you learn +that a colleague is stuck until you finish one of your tasks, you’ll 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’re 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 +still work concurrently. Using tools such as threads, processes, and async, the +computer can pause one activity and switch to others before eventually cycling +back to that first activity again. On a machine with multiple CPU cores, it can +also do work in parallel. One core can be doing one thing while another core +does something completely unrelated, and those actually happen at the same +time. + +When working with async in Rust, we’re 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 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: + +* see how to use Rust’s `async` and `await` syntax +* explore how to use the async model to solve some of the same challenges we + looked at in Chapter 16 +* look at how multithreading and async provide complementary solutions, which + you can even use together in many cases + +## Futures and the Async Syntax + +The key elements of asynchronous programming in Rust are *futures* and Rust’s +`async` and `await` keywords. + +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 such as “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. The process of +checking with a future to see if its value is available yet is called *polling*. + +Some other languages also use `async` and `await` keywords for async +programming. If you’re familiar with those languages, you may notice some +significant differences in how Rust does things, including how it handles the +syntax. That’s for good reason, as we’ll 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 +as 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’ll see +throughout this chapter return types with their own implementations of `Future`. +We’ll 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. We’ll 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’ll 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’ll need, primarily from the `futures` at *https://crates.io/crates/futures* and `tokio` at *https://tokio.rs* +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’s well-tested and widely used. + +In some cases, `trpl` also renames or wraps the original APIs to let us stay +focused on the details relevant to this chapter. If you want to understand what +the crate does, we encourage you to check out its source code at *https://github.com/rust-lang/book/tree/main/packages/trpl*. +You’ll be able to see what crate each re-export comes from, and we’ve left +extensive comments explaining what the crate does. + +Create a new binary project named `hello-async` and add the `trpl` crate as a +dependency: + +``` +$ cargo new hello-async +$ cd hello-async +$ cargo add trpl +``` + +Now we can use the various pieces provided by `trpl` to write our first async +program. We’ll 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. + +Let’s start by writing a function that takes one page URL as a parameter, makes +a request to it, and returns the text of the title element: + + +Filename: src/main.rs + +``` +use trpl::Html; + +async fn page_title(url: &str) -> Option<String> { + 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()) +} +``` + +Listing 17-1: Defining an async function to get the title element from an HTML page + +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 don’t use a future.) This should +remind you of our discussion of iterators back in Chapter 13 at *ch13-02-iterators.html*. +Iterators do nothing unless you call their `next` method—whether directly, or +using `for` loops or methods such as `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’s +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’s also different from how many other languages + > approach async! But it’s important for Rust. We’ll see why that is later. + +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’ll get the first `<title>` +element in the document, if there is one. Because 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’s +present, and do nothing if it isn’t. (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’re awaiting, +not before it. That is, it’s 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: + + +Filename: src/main.rs + +``` + let response_text = trpl::get(url).await.text().await; +``` + +Listing 17-2: Chaining with the <code>await</code> keyword + +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’ve +written and what it means. + +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. + +Thus, writing `async fn` is equivalent to writing a function which returns a +*future* of the return type. When the compiler sees a function definition such +as the `async fn page_title` in Listing 17-1, it’s equivalent to a non-async +function defined like this: + +``` +use std::future::Future; +use trpl::Html; + +fn page_title(url: &str) -> impl Future<Output = Option<String>> + '_ { + async move { + let text = trpl::get(url).await.text().await; + Html::parse(&text) + .select_first("title") + .map(|title| title.inner_html()) + } +} +``` + +Let’s walk through each part of the transformed version: + +* It uses the `impl Trait` syntax we discussed back in the “Traits as + Parameters” at *ch10-02-traits.html#traits-as-parameters* section in Chapter 10. +* The returned trait is a `Future`, with an associated type of `Output`. Notice + 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 + `url` parameter. (We’ll talk about `async` vs. `async move` much more later + in the chapter.) +* The new version of the function has a kind of lifetime we haven’t 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 don’t 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’ll 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. Because 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>`. + + +Filename: src/main.rs + +``` +async fn main() { + let args: Vec<String> = 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"), + } +} +``` + +Listing 17-3: Calling the <code>page_title</code> function from <code>main</code> with a user-supplied argument + +Unfortunately, this doesn’t compile. The only place we can use the `await` +keyword is in async functions or blocks, and Rust won’t let us mark the +special `main` function as `async`. + +<!-- manual-regeneration +cd listings/ch17-async-await/listing-17-03 +cargo build +copy just the compiler error +--> + +``` +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` +``` + +The reason `main` can’t be marked `async` 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’s not a runtime +*itself*. (We’ll see more about why this is a bit later.) Every Rust program +that executes async code 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. The crates which +provide those runtimes also often supply async versions of common functionality +such as file or network I/O. + +Here, and throughout the rest of this chapter, we’ll 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. + +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’ll be doing more than just one +async function call, so instead we’ll pass an `async` block and explicitly +await the result of calling `page_title`, as in Listing 17-4. + + +Filename: src/main.rs + +<!-- should_panic,noplayground because mdbook does not pass args --> + +``` + trpl::run(async { + let url = &args[1]; + match page_title(url).await { + Some(title) => println!("The title for {url} was {title}"), + None => println!("{url} had no title"), + } + }) +``` + +Listing 17-4: Awaiting an async block with <code>trpl::run</code> + +When we run this, we get the behavior we might have expected initially: + +``` +$ cargo run "http://www.rust-lang.org" +The title for http://www.rust-lang.org was + Rust Programming Language +``` + +Phew: we finally have some working async code! This now compiles, and we can run +it. Before we add code to race two sites against each other, let’s briefly turn +our attention back to how futures work. + +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’s ready to try advancing this one again. This is an invisible state machine, +as if you wrote an enum in this way to save the current state at each `await` +point: + +``` +enum PageTitleFuture<'a> { + Initial { url: &'a str }, + GetAwaitPoint { url: &'a str }, + TextAwaitPoint { response: trpl::Response }, +} +``` + +Writing the code to transition between each state by hand would be tedious and +error-prone, especially when adding more functionality and more states to the +code later. Instead, the Rust compiler creates and manages the 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’ll 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 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 call the +`trpl::run` function in `main`, which sets up a runtime and runs the future +returned by the `async` block 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-5: call a + > function which runs a future to completion the way `trpl::run` does. + +Let’s put these pieces together and see how we can write concurrent code, by +calling `page_title` with two different URLs passed in from the command line +and racing them. + + +Filename: src/main.rs + +<!-- should_panic,noplayground because mdbook does not pass args --> + +``` +use trpl::{Either, Html}; + +fn main() { + let args: Vec<String> = std::env::args().collect(); + + trpl::run(async { + 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, + }; + + 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<String>) { + let text = trpl::get(url).await.text().await; + let title = Html::parse(&text) + .select_first("title") + .map(|title| title.inner_html()); + (url, title) +} +``` + +Listing 17-5: + +In Listing 17-5, we begin by calling `page_title` for each 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 haven’t yet awaited them. Then we pass the futures to `trpl::race`, +which returns a value to indicate which of the futures passed to it finishes +first. + + > + > 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 can’t, but it also + > has some additional complexity that we can skip over for now. + +Either future can legitimately “win,” so it doesn’t make sense to return a +`Result`. Instead, `race` returns a type we haven’t seen before, +`trpl::Either`. The `Either` type is somewhat similar to 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”. + +``` +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` 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! 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. More +importantly, you’ve learned the basics of working with futures, so we can now +dig into even more of the things we can *do* with async. + +<!-- TODO: map source link version to version of Rust? --> + +## Concurrency With Async + +In this section, we’ll apply async to some of the same concurrency challenges +we tackled with threads in chapter 16. Because we already talked about a lot of +the key ideas there, in this section we’ll focus on what’s different between +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 +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 + +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-6. + + +Filename: src/main.rs + +``` +use std::time::Duration; + +fn main() { + 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; + } + }); + + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(500)).await; + } + }); +} +``` + +Listing 17-6: Using <code>spawn_task</code> to count with two + +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::run` in `main`, so we’ll often skip it + > just as 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 +message. We put one loop in the body of a `trpl::spawn_task` and the other in a +top-level `for` loop. We also add an `await` after the `sleep` calls. + +This does something similar to the thread-based implementation—including the +fact that you may see the messages appear in a different order in your own +terminal when you run it. + +<!-- Not extracting output because changes to this output aren't significant; +the changes are likely to be due to the threads running differently rather than +changes in the compiler --> + +``` +hi number 1 from the second task! +hi number 1 from the first task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +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. With +threads, we used the `join` method to “block” until the thread was done running. +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. + + +Filename: src/main.rs + +``` + 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; + } + }); + + for i in 1..5 { + println!("hi number {i} from the second task!"); + trpl::sleep(Duration::from_millis(500)).await; + } + + handle.await.unwrap(); +``` + +Listing 17-7: Using <code>await</code> with a join handle to run a task to completion + +This updated version runs till *both* loops finish. + +<!-- Not extracting output because changes to this output aren't significant; +the changes are likely to be due to the threads running differently rather than +changes in the compiler --> + +``` +hi number 1 from the second task! +hi number 1 from the first task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +hi number 6 from the first task! +hi number 7 from the first task! +hi number 8 from the first task! +hi number 9 from the first task! +``` + +So far, it looks like async and threads give us the same basic outcomes, just +with different syntax: using `await` instead of calling `join` on the join +handle, and awaiting the `sleep` calls. + +The bigger difference is that we didn’t need to spawn another operating system +thread to do this. In fact, we don’t 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-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’s just a tuple with two unit values in it. + + +Filename: src/main.rs + +``` + let fut1 = 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; + } + }; + + trpl::join(fut1, fut2).await; +``` + +Listing 17-8: Using <code>trpl::join</code> to await two anonymous futures + +When we run this, we see both futures run to completion: + +<!-- Not extracting output because changes to this output aren't significant; +the changes are likely to be due to the threads running differently rather than +changes in the compiler --> + +``` +hi number 1 from the first task! +hi number 1 from the second task! +hi number 2 from the first task! +hi number 2 from the second task! +hi number 3 from the first task! +hi number 3 from the second task! +hi number 4 from the first task! +hi number 4 from the second task! +hi number 5 from the first task! +hi number 6 from the first task! +hi number 7 from the first task! +hi number 8 from the first task! +hi number 9 from the first task! +``` + +Here, you’ll see the exact same order every time, which is very different from +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 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’s still possible!) Runtimes don’t have to guarantee +fairness for any given operation, and runtimes often offer different APIs to let +you choose whether you want fairness or not. + +Try some of these different variations on awaiting the futures and see what they +do: + +* Remove the async block from around either or both of the loops. +* Await each async block immediately after defining it. +* Wrap only the first loop in an async block, and await the resulting future + after the body of second loop. + +For an extra challenge, see if you can figure out what the output will be in +each case *before* running the code! + +### Message Passing + +Sharing data between futures will also be familiar: we’ll use message passing +again, but this with async versions of the types and functions. We’ll 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-9, +we’ll begin with just a single async block—*not* spawning a separate task as +we spawned a separate thread. + + +Filename: src/main.rs + +``` + let (tx, mut rx) = trpl::channel(); + + let val = String::from("hi"); + tx.send(val).unwrap(); + + let received = rx.recv().await.unwrap(); + println!("Got: {received}"); +``` + +Listing 17-9: Creating an async channel and assigning the two halves to <code>tx</code> and <code>rx</code> + +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 +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 don’t have +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 +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 +don’t await the `send` call, because it doesn’t block. It doesn’t need to, +because the channel we’re sending it into is unbounded. + + > + > Note: Because all of this async code runs in an async block in a `trpl::run` + > call, everything within it can avoid blocking. However, the code *outside* it + > will block on the `run` function returning. That is the whole point of the + > `trpl::run` function: it lets you *choose* where to block on some set of async + > 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. + +Notice two things about this example: First, the message will arrive right away! +Second, although we use a future here, there’s 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-10: + +<!-- We cannot test this one because it never stops! --> + + +Filename: src/main.rs + +``` + 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; + } + + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } +``` + +Listing 17-10: Sending and receiving multiple messages over the async channel and sleeping with an <code>await</code> between each message + +In addition to sending the messages, we need to receive them. In this case, we +could do that manually, by just doing `rx.recv().await` four times, because we +know how many messages are coming in. In the real world, though, we’ll +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 Listing 16-10, we used a `for` loop to process all the items received from a +synchronous channel. However, Rust doesn’t 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. + +<!-- TODO: update text in ch. 19 to account for our having introduced this. --> + +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 +use it in the loop body, just as we could with `if let`. If the result is +`None`, the loop ends. Every time the loop completes, it hits the await point +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 exits! Instead, +it waits forever for new messages. You will need to shut it down using <span +class="keystroke">ctrl-c</span>. + +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 +async block, the order that `await` keywords appear in the code is also the +order they happen when running the program. + +There’s only one async block in Listing 17-10, so everything in it runs +linearly. There’s 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 +blocks. Then the runtime can execute each of them separately using `trpl::join`, +just as 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’re +trying *not* to do. + +<!-- We cannot test this one because it never stops! --> + + +Filename: src/main.rs + +``` + let tx_fut = async { + 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 rx_fut = async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; +``` + +Listing 17-11: Separating <code>send</code> and <code>recv</code> into their own <code>async</code> blocks and awaiting the futures for those blocks + +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 +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 won’t complete until the `while let` loop ends. +* The `while let` loop won’t 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 don’t call `rx.close` anywhere, and `tx` won’t be dropped until the + outermost async block passed to `trpl::run` ends. +* The block can’t 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 doesn’t +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` because +sending a message doesn’t require ownership, but if we could move `tx` into +that async block, it would be dropped once that block ends. In Chapter 13, we +learned how to use the `move` keyword with closures, and in Chapter 16, we saw +that we often need to 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 as it does with closures. + +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. + + +Filename: src/main.rs + +``` + let (tx, mut rx) = trpl::channel(); + + let tx_fut = async move { + 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 rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } + }; + + trpl::join(tx_fut, rx_fut).await; +``` + +Listing 17-12: A working example of sending and receiving messages between futures which correctly shuts down when complete + +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-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 +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. The 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’ll +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. + + +Filename: src/main.rs + +``` + let (tx, mut rx) = trpl::channel(); + + let tx1 = tx.clone(); + let tx1_fut = async move { + 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_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; + } + }; + + trpl::join3(tx1_fut, tx_fut, rx_fut).await; +``` + +Listing 17-13: Using multiple producers with async blocks + +Now we see all the messages from both sending futures. Because the sending +futures use slightly different delays after sending, the messages are also +received at those different intervals. + +<!-- Not extracting output because changes to this output aren't significant; +the changes are likely to be due to the threads running differently rather than +changes in the compiler --> + +``` +received 'hi' +received 'more' +received 'from' +received 'the' +received 'messages' +received 'future' +received 'for' +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. + +## 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 +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-13 to use `join!` instead of +`join3`, as in Listing 17-14: + + +Filename: src/main.rs + +``` + trpl::join!(tx1_fut, tx_fut, rx_fut); +``` + +Listing 17-14: Using <code>join!</code> to wait for multiple futures + +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 common pattern. + +To check all the futures in some collection, we’ll need to iterate over and +join on *all* of them. The `trpl::join_all` function accepts any type which +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`. + + +``` + let futures = vec![tx1_fut, rx_fut, tx_fut]; + + trpl::join_all(futures).await; +``` + +Listing 17-15: Storing anonymous futures in a vector and calling <code>join_all</code> + +Unfortunately, this doesn’t compile. Instead, we get this error: + +<!-- manual-regeneration +cd listings/ch17-async-await/listing-17-16/ +cargo build +copy just the compiler error +--> + +``` +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 +``` + +This might be surprising. After all, none of them return anything, so each +block produces a `Future<Output = ()>`. However, `Future` is a trait, not a +concrete type. The concrete types are the individual data structures generated +by the compiler for async blocks. You can’t put two different hand-written +structs in a `Vec`, and the same thing applies to the different structs +generated by the compiler. + +To make this work, we need to use *trait objects*, just as we did in “Returning +Errors from the run function” at *ch12-03-improving-error-handling-and-modularity.html* in Chapter 12. (We’ll cover trait objects +in detail in Chapter 18.) Using trait objects lets us treat each of the +anonymous futures produced by these types as the same type, because all of them +implement the `Future` trait. + + > + > Note: In Chapter 8, we discussed another way to include multiple types in a + > `Vec`: using an enum to represent each of the different types which can + > appear in the vector. We can’t do that here, though. For one thing, we have + > no way to name the different types, because they are anonymous. For another, + > the reason we reached for a vector and `join_all` in the first place was to be + > able to work with a dynamic collection of futures where we don’t 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-16. + + +Filename: src/main.rs + +``` + let futures = + vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; + + trpl::join_all(futures).await; +``` + +Listing 17-16: Trying to use <code>Box::new</code> to align the types of the futures in a <code>Vec</code> + +Unfortunately, this still doesn’t compile. In fact, we have the same basic +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 annotating the type of the `futures` variable: + + +Filename: src/main.rs + +``` + let futures: Vec<Box<dyn Future<Output = ()>>> = + vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; +``` + +Listing 17-17: Fixing the rest of the type mismatch errors by using an explicit type declaration + +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 the output of + the future is the unit type `()` by writing `Future<Output = ()>`. +* Then we annotate the trait with `dyn` to mark it as dynamic. +* 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 +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-17 +cargo build +copy *only* the errors +--> + +``` +error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned + --> src/main.rs:46:24 + | +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` + | | + | 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<{async block@src/main.rs:8:23: 20:10}>` 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<I>(iter: I) -> JoinAll<I::Item> + | -------- required by a bound in this function +... +105 | I::Item: Future, + | ^^^^^^ required by this bound in `join_all` + +error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned + --> src/main.rs:46:9 + | +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<F> + | ------- required by a bound in this struct +28 | where +29 | F: Future, + | ^^^^^^ required by this bound in `JoinAll` + +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<F> + | ------- 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`. +``` + +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. Later in the chapter, we’ll 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-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. + + +Filename: src/main.rs + +``` + let futures: Vec<Pin<Box<dyn Future<Output = ()>>>> = + vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; +``` + +Listing 17-18: Using <code>Pin</code> and <code>Box::pin</code> to make the <code>Vec</code> type check + +If we compile and run this, we finally get the output we hoped for: + +<!-- Not extracting output because changes to this output aren't significant; +the changes are likely to be due to the threads running differently rather than +changes in the compiler --> + +``` +received 'hi' +received 'more' +received 'from' +received 'messages' +received 'the' +received 'for' +received 'future' +received 'you' +``` + +Phew! + +There’s a bit more we can explore here. For one thing, using `Pin<Box<T>>` +comes with a small amount of extra overhead from putting these futures on the +heap with `Box`—and we’re 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 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. + +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-19. + + +Filename: src/main.rs + +``` + let tx1_fut = pin!(async move { + // --snip-- + }); + + let rx_fut = pin!(async { + // --snip-- + }); + + let tx_fut = pin!(async move { + // --snip-- + }); + + let futures: Vec<Pin<&mut dyn Future<Output = ()>>> = + vec![tx1_fut, rx_fut, tx_fut]; +``` + +Listing 17-19: Using <code>Pin</code> directly with the <code>pin!</code> macro to avoid unnecessary heap allocations + +We got this far by ignoring the fact that we might have different `Output` +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>`. + + +Filename: src/main.rs + +``` + let a = async { 1u32 }; + let b = async { "Hello!" }; + let c = async { true }; + + let (a_result, b_result, c_result) = trpl::join!(a, b, c); + println!("{a_result}, {b_result}, {c_result}"); +``` + +Listing 17-20: Three futures with distinct types + +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`! + +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 +with a set number of futures with the `join` functions or the `join!` macro, +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. + +### 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 similar to +racing one future against another. + +In Listing 17-21, we once again 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!) +Unlike when we used `race` back in Our First Async Program at *ch17-01-futures-and-syntax.html#our-first-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. + + +Filename: src/main.rs + +``` + 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."); + }; + + trpl::race(slow, fast).await; +``` + +Listing 17-21: Using <code>race</code> to get the result of whichever future finishes first + +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’s because the implementation of this particular `race` function is +not fair. It always runs the futures passed as arguments in the order they’re +passed. Other implementations *are* fair, and will randomly choose which future +to poll first. Regardless of whether the implementation of race we’re 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 Our First Async Program at *ch17-01-futures-and-syntax.html#our-first-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 isn’t 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. 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’ll 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 + +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. + + +Filename: src/main.rs + +``` +fn slow(name: &str, ms: u64) { + thread::sleep(Duration::from_millis(ms)); + println!("'{name}' ran for {ms}ms"); +} +``` + +Listing 17-22: Using <code>thread::sleep</code> to simulate slow operations + +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. + + +Filename: src/main.rs + +``` + 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; +``` + +Listing 17-23: Using <code>thread::sleep</code> to simulate slow operations + +If you run this, you will see this output: + +<!-- manual-regeneration +cd listings/ch17-async-await/listing-17-24/ +cargo run +copy just the output +--> + +``` +'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’s 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-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? + + +Filename: src/main.rs + +``` + let one_ms = Duration::from_millis(1); + + 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; + 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; + println!("'b' finished."); + }; +``` + +Listing 17-24: Using <code>sleep</code> to let operations switch off making progress + +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-24 +cargo run +copy just the output +--> + +``` +'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 don’t 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-25, we replace all those +`sleep` calls with `yield_now`. + + +Filename: src/main.rs + +``` + 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 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."); + }; +``` + +Listing 17-25: Using <code>yield_now</code> to let operations switch off making progress + +This is both clearer about the actual intent and can be significantly faster +than using `sleep`, because timers such as 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, such as the one +in Listing 17-26. (This isn’t 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`. + + +Filename: src/main.rs + +``` + 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() + ); + + 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() + ); +``` + +Listing 17-26: Comparing the performance of <code>sleep</code> and <code>yield_now</code> + +The version with `yield_now` is *way* faster! + +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 won’t usually be alternating function calls with await +points on every single line, of course. While yielding control in this way is +relatively inexpensive, it’s not free! In many cases, trying to break up a +compute-bound task might make it significantly slower, so sometimes it’s 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 + +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’re done, the result will be another building block we could use to build up +yet further async abstractions. + +Listing 17-27 shows how we would expect this `timeout` to work with a slow +future. + + +Filename: src/main.rs + +``` + let slow = async { + trpl::sleep(Duration::from_millis(100)).await; + "I finished!" + }; + + match timeout(slow, Duration::from_millis(10)).await { + Ok(message) => println!("Succeeded with '{message}'"), + Err(duration) => { + println!("Failed after {} seconds", duration.as_secs()) + } + } +``` + +Listing 17-27: Using our imagined <code>timeout</code> to run a slow operation with a time limit + +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-28 shows this declaration. + +<!-- This is not tested because it intentionally does not compile. --> + + +Filename: src/main.rs + +``` +async fn timeout<F: Future>( + future_to_try: F, + max_time: Duration, +) -> Result<F::Output, Duration> { + // Here is where our implementation will go! +} +``` + +Listing 17-28: Defining the signature of <code>timeout</code> + +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. + +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` +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-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. + + +Filename: src/main.rs + +``` +use trpl::Either; + +// --snip-- + +fn main() { + trpl::run(async { + let slow = async { + trpl::sleep(Duration::from_secs(5)).await; + "Finally finished" + }; + + match timeout(slow, Duration::from_secs(2)).await { + Ok(message) => println!("Succeeded with '{message}'"), + Err(duration) => { + println!("Failed after {} seconds", duration.as_secs()) + } + } + }); +} + +async fn timeout<F: Future>( + future_to_try: F, + max_time: Duration, +) -> Result<F::Output, Duration> { + match trpl::race(future_to_try, trpl::sleep(max_time)).await { + Either::Left(output) => Ok(output), + Either::Right(_) => Err(max_time), + } +``` + +Listing 17-29: Defining <code>timeout</code> with <code>race</code> and <code>sleep</code> + +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: + +``` +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 +such as network calls—one of the examples from the beginning of the chapter! + +In practice, you will usually work directly with `async` and `await`, and +secondarily with functions and macros such as `join`, `join_all`, `race`, and +so on. You’ll only need to reach for `pin` now and again to use them with those +APIs. + +We’ve now seen a number of ways to work with multiple futures at the same +time. Up next, we’ll 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.) + +## Streams + +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” at *ch17-02-concurrency-with-async.html#message-passing* 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’ve 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. When working directly with an `Iterator`, we call +its synchronous `next` method. With the `trpl::Receiver` stream in particular, +we called an asynchronous `recv` method instead, but these APIs otherwise feel +very similar. + +That similarity isn’t a coincidence. A stream is similar to an asynchronous +form of iteration. Whereas the `trpl::Receiver` specifically waits to receive +messages, though, the general-purpose stream API is much more general: it +provides the next item the way `Iterator` does, but asynchronously. The +similarity between iterators and streams in Rust means 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-30. + + +Filename: src/main.rs + +``` + 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); + + while let Some(value) = stream.next().await { + println!("The value was: {value}"); + } +``` + +Listing 17-30: Creating a stream from an iterator and printing its values + +We start with an array of numbers, which we convert to an iterator and then call +`map` on to double all the values. Then we convert the iterator into a stream +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, when we try to run the code, it doesn’t compile. Instead, as we +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-30 +cargo build +copy only the error output +--> + +``` +error[E0599]: no method named `next` found for struct `Iter` in the current scope + --> src/main.rs:8:40 + | +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-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 + | +1 + use futures_util::stream::stream::StreamExt; + | +1 + use std::iter::Iterator; + | +1 + use std::str::pattern::Searcher; + | +1 + use trpl::StreamExt; + | +help: there is a method `try_next` with a similar name + | +8 | while let Some(value) = stream.try_next().await { + | ~~~~~~~~ + +For more information about this error, try `rustc --explain E0599`. +``` + +As the output suggests, the problem is that we need the right trait in scope to +be able to use the `next` method. Given our discussion so far, you might +reasonably expect that to be `Stream`, but the trait we need *here* is actually +`StreamExt`. The `Ext` there is for “extension”: this is a common pattern in +the Rust community for extending one trait with another. + +You might be wondering why `StreamExt` instead of `Stream`, and for that matter +whether there is a `Stream` trait at all. Briefly, the answer is that throughout +the Rust ecosystem, the `Stream` trait defines a low-level interface which +effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait +supplies a higher-level set of APIs on top of `Stream`, including the `next` +method as well as other utility methods similar to those provided by the +`Iterator` trait. We’ll 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. + +The fix to the compiler error is to add a `use` statement for `trpl::StreamExt`, +as in Listing 17-31. + + +Filename: src/main.rs + +``` +use trpl::StreamExt; + +fn main() { + 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); + + while let Some(value) = stream.next().await { + println!("The value was: {value}"); + } + }); +} +``` + +Listing 17-31: Successfully using an iterator as the basis for a stream + +With all those pieces put together, this code works the way we want! What’s +more, now that we have `StreamExt` in scope, we can use all of its utility +methods, just as with iterators. For example, in Listing 17-32, we use the +`filter` method to filter out everything but multiples of three and five. + + +Filename: src/main.rs + +``` +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 mut filtered = + stream.filter(|value| value % 3 == 0 || value % 5 == 0); + + while let Some(value) = filtered.next().await { + println!("The value was: {value}"); + } + }); +} +``` + +Listing 17-32: Filtering a <code>Stream</code> with the <code>StreamExt::filter</code> method + +Of course, this isn’t 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 + +Many concepts are naturally represented as streams: items becoming available in +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 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. + +Let’s start by building a little stream of messages, as a stand-in for a stream +of data we might see from a WebSocket or another real-time communication +protocol. In Listing 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. + +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. + + +Filename: src/main.rs + +``` +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::run(async { + let mut messages = get_messages(); + + while let Some(message) = messages.next().await { + println!("{message}"); + } + }); +} + +fn get_messages() -> impl Stream<Item = String> { + 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) +} +``` + +Listing 17-33: Using the <code>rx</code> receiver as a <code>ReceiverStream</code> + +When we run this code, we get exactly the results we would expect: + +<!-- Not extracting output because changes to this output aren't significant; +the changes are likely to be due to the threads running differently rather than +changes in the compiler --> + +``` +Message: 'a' +Message: 'b' +Message: 'c' +Message: 'd' +Message: 'e' +Message: 'f' +Message: 'g' +Message: 'h' +Message: 'i' +Message: 'j' +``` + +We could do this with the regular `Receiver` API, or even the regular `Iterator` +API, though. Let’s add something that requires streams: adding a timeout +which applies to every item in the stream, and a delay on the items we emit. + +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 +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. + + +Filename: src/main.rs + +``` +use std::{pin::pin, time::Duration}; +use trpl::{ReceiverStream, Stream, StreamExt}; + +fn main() { + trpl::run(async { + let mut messages = + pin!(get_messages().timeout(Duration::from_millis(200))); + + while let Some(result) = messages.next().await { + match result { + Ok(message) => println!("{message}"), + Err(reason) => eprintln!("Problem: {reason:?}"), + } + } + }) +} +``` + +Listing 17-34: Using the <code>StreamExt::timeout</code> method to set a time limit on the items in a stream + +However, because 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 +`messages` array so that we can get the index of each item we are sending along +with the item itself. Then we apply a 100 millisecond delay to even-index items +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. + + +Filename: src/main.rs + +``` +fn get_messages() -> impl Stream<Item = String> { + 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(); + } + }); + + ReceiverStream::new(rx) +} +``` + +Listing 17-35: Sending messages through <code>tx</code> with an async delay without making <code>get_messages</code> an async function + +To sleep between messages in the `get_messages` function without blocking, we +need to use async. However, we can’t make `get_messages` itself into an async +function, because then we’d return a `Future<Output = Stream<Item = String>>` instead of just a `Stream<Item = String>>`. 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, +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. + + > + > Note: calling `spawn_task` in this way works because we already set up our + > runtime. Calling this particular implementation of `spawn_task` *without* + > first setting up a runtime will cause a panic. Other implementations choose + > different tradeoffs: they might spawn a new runtime and so avoid the panic but + > end up with a bit of extra overhead, or simply not provide a standalone way to + > spawn tasks without reference to a runtime. You should make sure you know what + > tradeoff your runtime has chosen and write your code accordingly! + +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-35 +cargo run +copy only the program output, *not* the compiler output +--> + +``` +Message: 'a' +Problem: Elapsed(()) +Message: 'b' +Message: 'c' +Problem: Elapsed(()) +Message: 'd' +Message: 'e' +Problem: Elapsed(()) +Message: 'f' +Message: 'g' +Problem: Elapsed(()) +Message: 'h' +Message: 'i' +Problem: Elapsed(()) +Message: 'j' +``` + +The timeout doesn’t prevent the messages from arriving in the end—we still get +all of the original messages. This is because our channel is unbounded: it can +hold as many messages as we can fit in memory. If the message doesn’t arrive +before the timeout, our stream handler will account for that, but when it polls +the stream again, the message may now have arrived. + +You can get different behavior if needed by using other kinds of channels, or +other kinds of streams more generally. Let’s see one of those in practice in our +final example for this section, by combining a stream of time intervals with +this stream of messages. + +### Merging Streams + +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’re 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-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 an infinite loop. Each iteration of the loop +asynchronously sleeps for one millisecond, increments the count, and then sends +it over the channel. Because 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. + + +Filename: src/main.rs + +``` +fn get_intervals() -> impl Stream<Item = u32> { + 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) +} +``` + +Listing 17-36: Creating a stream with a counter that will be emitted once every millisecond + +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 doesn’t 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, +which combines multiple streams into one stream that produces items from any of +the source streams as soon as the items are available, without imposing any +particular ordering. Finally, we loop over that combined stream instead of over +`messages` (Listing 17-37). + + +Filename: src/main.rs + +``` + let messages = get_messages().timeout(Duration::from_millis(200)); + let intervals = get_intervals(); + let merged = messages.merge(intervals); +``` + +Listing 17-37: Attempting to merge streams of messages and intervals + +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 compile! (Neither does the `next` call in the `while let` loop, but we’ll come back to that after fixing this.) The two streams +have different types. The `messages` stream has the type `Timeout<impl Stream<Item = String>>`, where `Timeout` is the type which implements `Stream` +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-38, we rework the `intervals` stream, because `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`. Because we don’t +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 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 pin it so that it’s safe to do so. + +<!-- We cannot directly test this one, because it never stops. --> + + +Filename: src/main.rs + +``` + let messages = get_messages().timeout(Duration::from_millis(200)); + let intervals = get_intervals() + .map(|count| format!("Interval: {count}")) + .timeout(Duration::from_secs(10)); + let merged = messages.merge(intervals); + let mut stream = pin!(merged); +``` + +Listing 17-38: Aligning the types of the the <code>intervals</code> stream with the type of the <code>messages</code> stream + +That gets us *almost* to where we need to be. Everything type checks. If you run +this, though, there will be two problems. First, it will never stop! You’ll +need to stop it with <span class="keystroke">ctrl-c</span>. Second, the +messages from the English alphabet will be buried in the midst of all the +interval counter messages: + +<!-- Not extracting output because changes to this output aren't significant; +the changes are likely to be due to the tasks running differently rather than +changes in the compiler --> + +``` +--snip-- +Interval: 38 +Interval: 39 +Interval: 40 +Message: 'a' +Interval: 41 +Interval: 42 +Interval: 43 +--snip-- +``` + +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 doesn’t 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 +hundred milliseconds should do, because that is in the same ballpark as how +often our messages arrive. + +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. + + +Filename: src/main.rs + +``` + let messages = get_messages().timeout(Duration::from_millis(200)); + let intervals = get_intervals() + .map(|count| format!("Interval: {count}")) + .throttle(Duration::from_millis(100)) + .timeout(Duration::from_secs(10)); + let merged = messages.merge(intervals).take(20); + let mut stream = pin!(merged); +``` + +Listing 17-39: Using <code>throttle</code> and <code>take</code> to manage the merged streams + +Now when we run the program, it stops after pulling twenty items from the +stream, and the intervals don’t overwhelm the messages. We also don’t get +`Interval: 100` or `Interval: 200` or so on, but instead get `Interval: 1`, +`Interval: 2`, and so on—even though we have a source stream which *can* +produce an event every millisecond. That’s because the `throttle` call +produces a new stream, wrapping the original stream, so that the original +stream only gets polled at the throttle rate, not its own “native” rate. We +don’t have a bunch of unhandled interval messages we’re choosing to +ignore. Instead, we never produce those interval messages in the first place! +This is the inherent “laziness” of Rust’s futures at work again, allowing us to +choose our performance characteristics. + +<!-- manual-regeneration +cd listings/listing-17-39 +cargo run +copy and paste only the program output +--> + +``` +Interval: 1 +Message: 'a' +Interval: 2 +Interval: 3 +Problem: Elapsed(()) +Interval: 4 +Message: 'b' +Interval: 5 +Message: 'c' +Interval: 6 +Interval: 7 +Problem: Elapsed(()) +Interval: 8 +Message: 'd' +Interval: 9 +Message: 'e' +Interval: 10 +Interval: 11 +Problem: Elapsed(()) +Interval: 12 +``` + +There’s one last thing we need to handle: errors! With both of these +channel-based streams, the `send` calls could fail when the other side of the +channel closes—and that’s just a matter of how the runtime executes the futures +which make up the stream. Up until 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 don’t 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. + + +``` +fn get_messages() -> impl Stream<Item = String> { + 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) +} + +fn get_intervals() -> impl Stream<Item = u32> { + let (tx, rx) = trpl::channel(); + + trpl::spawn_task(async move { + let mut count = 0; + 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; + }; + } + }); + + ReceiverStream::new(rx) +} +``` + +Listing 17-40: Handling errors and shutting down the loops + +Now that we’ve seen a bunch of async in practice, let’s take a step back and +dig into a few of the details of how `Future`, `Stream`, and the other key +traits which Rust uses to make async work. + +## Digging Into the Traits for Async + +Throughout the chapter, we’ve used the `Future`, `Pin`, `Unpin`, `Stream`, and +`StreamExt` traits in various ways. So far, though, we’ve 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’ll hit +situations where understanding a few more of these details matters. In this +section, we’ll dig down *enough* further to help with those situations—while +still leaving the *really* deep dive for other documentation! + +### Future + +Back in Futures and the Async Syntax at *ch17-01-futures-and-syntax.html*, 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`: + +``` +use std::pin::Pin; +use std::task::{Context, Poll}; + +pub trait Future { + type Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; +} +``` + +That trait definition includes a bunch of new types and also some syntax we +haven’t 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<Self::Output>`. We’ll 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: + +``` +enum Poll<T> { + Ready(T), + Pending, +} +``` + +This `Poll` type is similar to 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. This is similar to how `Iterator::next` behaves! + +Under the hood, when you see code which uses `await`, Rust compiles that to code +which calls `poll`. If you look back at Listing 17-4, where we printed out the +page title for a single URL once it resolved, Rust compiles it into something +kind of (although not exactly) like this: + +``` +match page_title(url).poll() { + Ready(page_title) => match page_title { + Some(title) => println!("The title for {url} was {title}"), + None => println!("{url} had no title"), + } + 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: + +``` +let mut page_title_fut = page_title(url); +loop { + match page_title_fut.poll() { + Ready(value) => match page_title { + Some(title) => println!("The title for {url} was {title}"), + None => println!("{url} had no title"), + } + 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 (in the Counting at *ch17-02-concurrency-with-async.html* 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’s +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 isn’t 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)`. + +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 + +<!-- TODO: get a *very* careful technical review of this section! --> + +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-17 +cargo build +copy *only* the final `error` block from the errors +--> + +``` +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<F> + | ------- 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 tells 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`: + +``` +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<Self::Output>; +} +``` + +The `cx` parameter and its `Context` type is interesting, but is beyond the +scope of this chapter: you generally only need to worry about it when writing a +custom `Future` implementation. + +Instead, we’ll focus on the type for `self`. This is the first time we’ve seen +a method where `self` has a type annotation. A type annotation for `self` is +similar to type annotations for other function parameters, with two key +differences. First, when we specify the type of `self` in this way, we’re +telling Rust what type `self` must be to call this method. Second, a type +annotation on `self` can’t be just any type. It’s only allowed to be the type +on which the method is implemented, a reference or smart pointer to that type, +or a `Pin` wrapping a reference to that type. We’ll see more on this syntax in +Chapter 18. For now, it’s 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’s similar to 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 *pointer types* such as references +(`&` 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, because implementing `Deref` or `DerefMut` +means your type behaves similarly to a pointer type. `Pin` is also not a +pointer itself, and it doesn’t have any behavior of its own as the ref counting +of `Rc` or `Arc` does. It’s 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`? + +In Our First Async Program at *ch17-01-futures-and-syntax.html#our-first-async-program*, 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`, the way we did back in—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, as in Figure 17-3 (a simplified +illustration to help you get a feel for the idea, rather than digging into what +are often fairly complicated details). + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-03.svg" class="center" /> + +<figcaption>Figure 17-3: A self-referential data type.</figcaption> + +</figure> + +By default, though, any object which has a reference to itself is unsafe to +move, because references always point to the actual memory address of the thing +they refer to. If you move the data structure itself, those internal references +will be left pointing to the old location. However, that memory location is now +invalid. For one thing, its value will not be updated when you make changes to +the data structure. For another—and more importantly!—the computer is now free +to reuse that memory for other things! You could end up reading completely +unrelated data later. + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-04.svg" class="center" /> + +<figcaption>Figure 17-4: The unsafe result of moving a self-referential data type.</figcaption> + +</figure> + +In principle, the Rust compiler could 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 *doesn’t move in memory*, we don’t have to update any references. +This is exactly what Rust’s borrow checker requires: you can’t 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 that value in `Pin`, it can no longer move. Thus, +if you have `Pin<Box<SomeType>>`, you actually pin the `SomeType` value, *not* +the `Box` pointer. Figure 17-5 illustrates this: + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-05.svg" class="center" /> + +<figcaption>Figure 17-5: Pinning a `Box` which points to a self-referential future type.</figcaption> + +</figure> + +In fact, the `Box` pointer can still 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, as in +Figure 17-6, there’s no potential problem. (How you would do this with a `Pin` +wrapping a `Box` is more than we’ll get into in this particular discussion, +but it would make for a good exercise! If you look at the docs for the types as +well as the `std::pin` module, you might be able to work out how you would do +that.) The key is that the self-referential type itself cannot move, because it +is still pinned. + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-06.svg" class="center" /> + +<figcaption>Figure 17-6: Moving a `Box` which points to a self-referential future type.</figcaption> + +</figure> + +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 such as numbers and booleans don’t have +any internal references, so they’re obviously safe. Neither do most types you +normally work with in Rust. A `Vec`, for example, doesn’t 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<Vec<String>>`, you’d have to do everything +via the safe but restrictive APIs provided by `Pin`, even though a +`Vec<String>` is always safe to move if there are no other references to it. We +need a way to tell the compiler that it’s actually just fine to move items +around in cases such as these. For that, we have `Unpin`. + +`Unpin` is a marker trait, as `Send` and `Sync` are, 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’s 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 as with `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! + +To make that concrete, think about a `String`: it has a length and the Unicode +characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure +17-7. However + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-07.svg" class="center" /> + +<figcaption>Figure 17-7: Pinning a String, with a dotted line indicating that the String implements the `Unpin` trait, so it is not pinned.</figcaption> + +</figure> + +This means that we can do things such as replace one string with another at the +exact same location in memory as in Figure 17-8. This doesn’t violate the `Pin` +contract because `String`—like most other types in Rust—implements `Unpin`, +because it has no internal references that make it unsafe to move around! + +<figure> + +<img alt="Concurrent work flow" src="img/trpl17-08.svg" class="center" /> + +<figcaption>Figure 17-8: Replacing the String with an entirely different String in memory.</figcaption> + +</figure> + +Now we know enough to understand the errors reported for that `join_all` call +from back in Listing 17-17. We originally tried to move the futures produced by +async blocks into a `Vec<Box<dyn Future<Output = ()>>>`, but as we’ve seen, +those futures may have internal references, so they don’t 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’re building a runtime itself, rather than for day to day Rust code. +When you see these traits in error messages, though, now you’ll have a better +idea of how to fix the code! + + > + > 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’re 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 specifics of how `Pin` and `Unpin` work, and the rules they’re required + > to uphold, are covered extensively in the API documentation for `std::pin`, so + > if you’d like to understand them more deeply, that’s 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* at *https://rust-lang.github.io/async-book/* book has + > you covered: + > + > * Chapter 2: Under the Hood: Executing Futures and Tasks at *https://rust-lang.github.io/async-book/02_execution/01_chapter.html* + > * Chapter 4: Pinning at *https://rust-lang.github.io/async-book/04_pinning/01_chapter.html* + +### The Stream Trait + +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 similar to asynchronous iterators. Unlike +`Iterator` and `Future`, there is no definition of a `Stream` trait in the +standard library as of the time of writing,<!-- TODO: verify before press time! +--> but there *is* a very common definition from the `futures` crate 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<Self::Item>`. From `Future`, we have the idea of readiness over time: +its `poll` method provides a `Poll<Self::Output>`. To represent a sequence of +items which become ready over time, we define a `Stream` trait which puts those +features together: + +``` +use std::pin::Pin; +use std::task::{Context, Poll}; + +trait Stream { + type Item; + + fn poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_> + ) -> Poll<Option<Self::Item>>; +} +``` + +The `Stream` trait defines an associated type `Item` for the type of the items +produced by the stream. This is similar to `Iterator`: there may be zero to +many of these, and unlike `Future`, where there is always a single `Output` +(even if it’s the unit type `()`). + +`Stream` also defines a method to get those items. We call it `poll_next`, to +make it clear that it polls in the same way `Future::poll` does and produces a +sequence of items in the same way `Iterator::next` does. Its return type +combines `Poll` with `Option`. The outer type is `Poll`, because it has to be +checked for readiness, just as a future does. The inner type is `Option`, +because it needs to signal whether there are more messages, just as an iterator +does. + +Something very similar to this will likely end up standardized as part of Rust’s +standard library. In the meantime, it’s 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 in the section on streaming, though, we didn’t 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. + +``` +trait StreamExt: Stream { + async fn next(&mut self) -> Option<Self::Item> + where + Self: Unpin; + + // other methods... +} +``` + +<!-- +TODO: update this if/when tokio/etc. update their MSRV and switch to using async functions +in traits, since the lack thereof is the reason they do not yet have this. +--> + + > + > Note: The actual definition we used earlier in the chapter 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 a `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 method! + +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 these traits are defined separately 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. + +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! + +## Futures, Tasks, and Threads + +As we saw in the previous chapter, threads provide one approach to concurrency. +We’ve seen another approach to concurrency in this chapter, using async with +futures and streams. You might be wondering why you would choose one or the +other. The answer is: it depends! And in many cases, the choice isn’t threads +*or* async but rather threads *and* async. + +Many operating systems have supplied threading-based concurrency models for +decades now, and many programming languages have support for them as a result. +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 +computers, some embedded systems don’t have an OS at all, so they also don’t +have threads! + +The async model provides a different—and ultimately complementary—set of +tradeoffs. In the async model, concurrent operations don’t require their own +threads. Instead, they can run on tasks, as when we used `trpl::spawn_task` to +kick off work from a synchronous function throughout the streams section. A +*task* is similar to a thread—but instead of being managed by the operating +system, it’s 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-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. + + +Filename: src/main.rs + +``` +fn get_intervals() -> impl Stream<Item = u32> { + 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) +} +``` + +Listing 17-41: Using the <code>std::thread</code> APIs instead of the async <code>trpl</code> APIs for the <code>get_intervals</code> function + +If you run this, the output is identical. And notice how little changes here +from the perspective of the calling code! What’s more, even though one of our +functions spawned an async task on the runtime and the other spawned an +OS thread, the resulting streams were unaffected by the differences. + +However, there’s a significant difference between how these two approaches +behave, although we might have a hard time measuring it in this very simple +example. We could spawn hundreds of thousands or even millions of async tasks +on any modern personal computer. If we tried to do that with threads, we would +literally run out of memory! + +However, there’s a reason these APIs are so similar. Threads act as a boundary +for sets of synchronous operations; concurrency is possible *between* threads. +Tasks act as a boundary for sets of *asynchronous* operations; concurrency is +possible both *between* and *within* tasks. In that regard, tasks are similar to +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. That is, the runtime—specifically, its executor—manages tasks, +and tasks manage futures. + +However, this doesn’t 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,” +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* as futures can. Threads in Rust also have no +mechanisms for cancellation—a subject we haven’t 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’s much more +difficult, for example, to build something similar to the `timeout` we built in +“Building Our Own Async Abstractions” at *ch17-03-more-futures.html#building-our-own-async-abstractions*, or the `throttle` +method we used with streams in “Composing Streams” at *ch17-04-streams.html#composing-streams*. The fact that +futures are richer data structures means they *can* be composed together more +naturally, as we have seen. + +Tasks then give *additional* control over futures, allowing you to choose where +and how to group the futures. 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 haven’t mentioned it up until now, but under the +hood the `Runtime` we have been using, including the `spawn_blocking` and +`spawn_task` 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: + +* If the task is *very parallelizable*, such as processing a bunch of data where + each part can be processed separately, threads are a better choice. +* If the task is *very concurrent*, such as handling messages from a bunch of + different sources which may come in a different intervals or different rates, + async is a better choice. + +And if you need some mix of parallelism and concurrency, you don’t have to +choose between threads and async. You can use them together freely, letting each +one serve the part it is best at. For example, Listing 17-42 shows a fairly +common example of this kind of mix in real-world Rust code. + + +Filename: src/main.rs + +``` +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}"); + } + }); +} +``` + +Listing 17-42: Sending messages with blocking code in a thread and awaiting the messages in an async block + +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 as we have +throughout the chapter. In that future, we await those messages, just as 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, because 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 + +This isn’t the last you’ll see of concurrency in this book: the project in +Chapter 21 will use the concepts in this chapter in a more realistic situation +than the smaller examples discussed here—and compare more directly what it looks +like to solve these kinds of problems with threading vs. with tasks and futures. + +Whether with threads, with futures and tasks, or with the combination of them +all, Rust gives you the tools you need to write safe, fast, concurrent +code—whether for a high-throughput web server or an embedded operating system. + +Next, we’ll talk about idiomatic ways to model problems and structure solutions +as your Rust programs get bigger. In addition, we’ll discuss how Rust’s idioms +relate to those you might be familiar with from object-oriented programming. From daccf5eca3cdc8b19c01bb15ad14ac196fc529a7 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <carol.nichols@gmail.com> Date: Thu, 3 Oct 2024 21:22:49 -0400 Subject: [PATCH 230/249] Manual changes to the async chapter snapshot Some of these could be scripted but I'm just trying to get this done right now. --- nostarch/chapter17.md | 1316 ++++++++++++++++++----------------------- 1 file changed, 579 insertions(+), 737 deletions(-) diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index 57e90e6704..97d8b7ce39 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -1,9 +1,3 @@ -<!-- DO NOT EDIT THIS FILE. - -This file is periodically generated from the content in the `/src/` -directory, so all fixes need to be made in `/src/`. ---> - [TOC] ## Async and Await @@ -33,14 +27,13 @@ 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 - > “CPU-bound” or “compute-bound”. It’s limited by the speed of the computer’s - > ability to process data within the *CPU* or *GPU*, and how much of that speed - > it can use. The video download is the kind of operation which is often - > described as “IO-bound,” because it’s limited by the speed of the computer’s - > *input and output*. It can only go as fast as the data can be sent across the - > network. +> Note: The video export is the kind of operation which is often described as +> “CPU-bound” or “compute-bound”. It’s limited by the speed of the computer’s +> ability to process data within the *CPU* or *GPU*, and how much of that speed +> it can use. The video download is the kind of operation which is often +> described as “IO-bound,” because it’s limited by the speed of the computer’s +> *input and output*. It can only go as fast as the data can be sent across the +> network. 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 @@ -56,12 +49,11 @@ time. Many operating system APIs for interacting with the network are *blocking*, though. That is, these APIs block the program’s progress until the data that they are processing is completely ready. - > - > Note: This is how *most* function calls work, if you think about it! However, - > we normally reserve the term “blocking” for function calls which interact with - > files, the network, or other resources on the computer, because those are the - > places where an individual program would benefit from the operation being - > *non*-blocking. +> Note: This is how *most* function calls work, if you think about it! However, +> we normally reserve the term “blocking” for function calls which interact with +> files, the network, or other resources on the computer, because those are the +> places where an individual program would benefit from the operation being +> *non*-blocking. We could avoid blocking our main thread by spawning a dedicated thread to download each file. However, we would eventually find that the overhead of those @@ -80,9 +72,9 @@ between parallelism and concurrency. ### Parallelism and Concurrency -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. +In the “Fearless Concurrency” chapter on page XX, 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. 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 @@ -95,25 +87,18 @@ to the other. You’re just one person, so you can’t make progress on both tas at the exact same time—but you can multi-task, making progress on multiple tasks by switching between them. -<figure> - -<img alt="Concurrent work flow" src="img/trpl17-01.svg" class="center" /> +<img alt="Concurrent work flow" src="img/trpl17-01.svg" /> -<figcaption>Figure 17-1: A concurrent workflow, switching between Task A and Task B</figcaption> - -</figure> +Figure 17-1: A concurrent workflow, switching between Task A and Task B When you agree to split up a group of tasks between the people on the team, with each person taking one task and working on it alone, this is *parallelism*. Each person on the team can make progress at the exact same time. -<figure> - -<img alt="Concurrent work flow" src="img/trpl17-02.svg" class="center" /> - -<figcaption>Figure 17-2: A parallel workflow, where work happens on Task A and Task B independently</figcaption> +<img alt="Concurrent work flow" src="img/trpl17-02.svg" /> -</figure> +Figure 17-2: A parallel workflow, where work happens on Task A and Task B +independently With both of these situations, you might have to coordinate between different tasks. Maybe you *thought* the task that one person was working on was totally @@ -198,8 +183,8 @@ everything you need to know as we go. 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’ll need, primarily from the `futures` at *https://crates.io/crates/futures* and `tokio` at *https://tokio.rs* -crates. +you’ll need, primarily from the `futures` and `tokio` crates, available on +*https://crates.io*. * The `futures` crate is an official home for Rust experimentation for async code, and is actually where the `Future` type was originally designed. @@ -211,7 +196,8 @@ crates. In some cases, `trpl` also renames or wraps the original APIs to let us stay focused on the details relevant to this chapter. If you want to understand what -the crate does, we encourage you to check out its source code at *https://github.com/rust-lang/book/tree/main/packages/trpl*. +the crate does, we encourage you to check out its source code at +*https://github.com/rust-lang/book/tree/main/packages/trpl*. You’ll be able to see what crate each re-export comes from, and we’ve left extensive comments explaining what the crate does. @@ -232,7 +218,6 @@ finishes that whole process first. Let’s start by writing a function that takes one page URL as a parameter, makes a request to it, and returns the text of the title element: - Filename: src/main.rs ``` @@ -264,18 +249,18 @@ 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 don’t use a future.) This should -remind you of our discussion of iterators back in Chapter 13 at *ch13-02-iterators.html*. -Iterators do nothing unless you call their `next` method—whether directly, or -using `for` loops or methods such as `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’s -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’s also different from how many other languages - > approach async! But it’s important for Rust. We’ll see why that is later. +remind you of our discussion of iterators back in the “Processing a Series of +Items with Iterators” section of Chapter 13 on page XX. Iterators do nothing +unless you call their `next` method—whether directly, or using `for` loops or +methods such as `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’s actually needed. + +> Note: This is different from the behavior we saw when using `thread::spawn` in +> the “Creating a New Thread with `spawn`” section of Chapter 16 on page XX, +> where the closure we passed to another thread started running immediately. +> It’s also different from how many other languages approach async! But it’s +> important for Rust. We’ll see why that is later. 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 @@ -297,14 +282,13 @@ 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: - Filename: src/main.rs ``` let response_text = trpl::get(url).await.text().await; ``` -Listing 17-2: Chaining with the <code>await</code> keyword +Listing 17-2: Chaining with the `await` keyword 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’ve @@ -338,7 +322,7 @@ fn page_title(url: &str) -> impl Future<Output = Option<String>> + '_ { Let’s walk through each part of the transformed version: * It uses the `impl Trait` syntax we discussed back in the “Traits as - Parameters” at *ch10-02-traits.html#traits-as-parameters* section in Chapter 10. + Parameters” section in Chapter 10 on page XX. * The returned trait is a `Future`, with an associated type of `Output`. Notice 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`. @@ -359,13 +343,13 @@ Let’s walk through each part of the transformed version: 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’ll 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. Because 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>`. - +Now we can call `page_title` in `main`. To start, we’ll 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 the “Accepting Command Line Arguments” section +of Chapter 12 on page XX. Then we pass the first URL `page_title`, and await +the result. Because 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>`. Filename: src/main.rs @@ -380,18 +364,13 @@ async fn main() { } ``` -Listing 17-3: Calling the <code>page_title</code> function from <code>main</code> with a user-supplied argument +Listing 17-3: Calling the `page_title` function from `main` with a +user-supplied argument Unfortunately, this doesn’t compile. The only place we can use the `await` keyword is in async functions or blocks, and Rust won’t let us mark the special `main` function as `async`. -<!-- manual-regeneration -cd listings/ch17-async-await/listing-17-03 -cargo build -copy just the compiler error ---> - ``` error[E0752]: `main` function is not allowed to be `async` --> src/main.rs:6:1 @@ -429,11 +408,8 @@ we tried to do in Listing 17-3. However, for most of the examples in the chapter async function call, so instead we’ll pass an `async` block and explicitly await the result of calling `page_title`, as in Listing 17-4. - Filename: src/main.rs -<!-- should_panic,noplayground because mdbook does not pass args --> - ``` trpl::run(async { let url = &args[1]; @@ -444,7 +420,7 @@ Filename: src/main.rs }) ``` -Listing 17-4: Awaiting an async block with <code>trpl::run</code> +Listing 17-4: Awaiting an async block with `trpl::run` When we run this, we get the behavior we might have expected initially: @@ -494,20 +470,17 @@ but `main` is the starting point for the program! Instead, we call the `trpl::run` function in `main`, which sets up a runtime and runs the future returned by the `async` block 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-5: call a - > function which runs a future to completion the way `trpl::run` does. +> 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-5: call a +> function which runs a future to completion the way `trpl::run` does. Let’s put these pieces together and see how we can write concurrent code, by calling `page_title` with two different URLs passed in from the command line and racing them. - Filename: src/main.rs -<!-- should_panic,noplayground because mdbook does not pass args --> - ``` use trpl::{Either, Html}; @@ -541,7 +514,7 @@ async fn page_title(url: &str) -> (&str, Option<String>) { } ``` -Listing 17-5: +Listing 17-5: Calling `page_title` for two URLs to see which returns first In Listing 17-5, we begin by calling `page_title` for each of the user-supplied URLs. We save the futures produced by calling `page_title` as `title_fut_1` and @@ -550,11 +523,10 @@ and we haven’t yet awaited them. Then we pass the futures to `trpl::race`, which returns a value to indicate which of the futures passed to it finishes first. - > - > 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 can’t, but it also - > has some additional complexity that we can skip over for now. +> 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 can’t, but it also +> has some additional complexity that we can skip over for now. Either future can legitimately “win,” so it doesn’t make sense to return a `Result`. Instead, `race` returns a type we haven’t seen before, @@ -587,12 +559,10 @@ others, while in other cases which site “wins” varies from run to run. More importantly, you’ve learned the basics of working with futures, so we can now dig into even more of the things we can *do* with async. -<!-- TODO: map source link version to version of Rust? --> - ## Concurrency With Async In this section, we’ll apply async to some of the same concurrency challenges -we tackled with threads in chapter 16. Because we already talked about a lot of +we tackled with threads in Chapter 16. Because we already talked about a lot of the key ideas there, in this section we’ll focus on what’s different between threads and futures. @@ -604,12 +574,12 @@ performance characteristics. ### Counting -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-6. - +The first task we tackled in the “Creating a New Thread with spawn” section of +Chapter 16 on page XX 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-6. Filename: src/main.rs @@ -633,15 +603,14 @@ fn main() { } ``` -Listing 17-6: Using <code>spawn_task</code> to count with two +Listing 17-6: Using `spawn_task` to count with two 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::run` in `main`, so we’ll often skip it - > just as we do with `main`. Don’t forget to include it in your code! +> Note: From this point forward in the chapter, every example will include this +> exact same wrapping code with `trpl::run` in `main`, so we’ll often skip it +> just as 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 @@ -652,10 +621,6 @@ This does something similar to the thread-based implementation—including the fact that you may see the messages appear in a different order in your own terminal when you run it. -<!-- Not extracting output because changes to this output aren't significant; -the changes are likely to be due to the threads running differently rather than -changes in the compiler --> - ``` hi number 1 from the second task! hi number 1 from the first task! @@ -677,33 +642,28 @@ 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. - Filename: src/main.rs ``` - 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 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; + } +}); - 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; +} - handle.await.unwrap(); +handle.await.unwrap(); ``` -Listing 17-7: Using <code>await</code> with a join handle to run a task to completion +Listing 17-7: Using `await` with a join handle to run a task to completion This updated version runs till *both* loops finish. -<!-- Not extracting output because changes to this output aren't significant; -the changes are likely to be due to the threads running differently rather than -changes in the compiler --> - ``` hi number 1 from the second task! hi number 1 from the first task! @@ -730,44 +690,40 @@ 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-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’s just a tuple with two unit values in it. - +In the “Waiting for All Threads to Finish Using `join` Handles” section of +Chapter 16 on page XX, 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-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’s just a tuple with two unit values in it. Filename: src/main.rs ``` - let fut1 = async { - for i in 1..10 { - println!("hi number {i} from the first task!"); - trpl::sleep(Duration::from_millis(500)).await; - } - }; +let fut1 = 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; - } - }; +let fut2 = async { + 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; +trpl::join(fut1, fut2).await; ``` -Listing 17-8: Using <code>trpl::join</code> to await two anonymous futures +Listing 17-8: Using `trpl::join` to await two anonymous futures When we run this, we see both futures run to completion: -<!-- Not extracting output because changes to this output aren't significant; -the changes are likely to be due to the threads running differently rather than -changes in the compiler --> - ``` hi number 1 from the first task! hi number 1 from the second task! @@ -811,34 +767,36 @@ each case *before* running the code! Sharing data between futures will also be familiar: we’ll use message passing again, but this with async versions of the types and functions. We’ll 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-9, -we’ll begin with just a single async block—*not* spawning a separate task as -we spawned a separate thread. - +slightly different path than we did in the “Using Message Passing to Transfer +Data Between Threads” section of Chapter 16 on page XX, to illustrate some of +the key differences between thread-based and futures-based concurrency. In +Listing 17-9, we’ll begin with just a single async block—*not* spawning a +separate task as we spawned a separate thread. Filename: src/main.rs ``` - let (tx, mut rx) = trpl::channel(); +let (tx, mut rx) = trpl::channel(); - let val = String::from("hi"); - tx.send(val).unwrap(); +let val = String::from("hi"); +tx.send(val).unwrap(); - let received = rx.recv().await.unwrap(); - println!("Got: {received}"); +let received = rx.recv().await.unwrap(); +println!("Got: {received}"); ``` -Listing 17-9: Creating an async channel and assigning the two halves to <code>tx</code> and <code>rx</code> +Listing 17-9: Creating an async channel and assigning the two halves to `tx` +and `rx` 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 -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 don’t have -to spawn a separate thread or even a task; we merely need to await the `rx.recv` -call. +single-consumer channel API we used with threads back in the “Using Message +Passing to Transfer Data Between Threads” section of Chapter 16 on page XX. 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 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 don’t have 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 @@ -847,13 +805,12 @@ a message is received or the send side of the channel closes. By contrast, we don’t await the `send` call, because it doesn’t block. It doesn’t need to, because the channel we’re sending it into is unbounded. - > - > Note: Because all of this async code runs in an async block in a `trpl::run` - > call, everything within it can avoid blocking. However, the code *outside* it - > will block on the `run` function returning. That is the whole point of the - > `trpl::run` function: it lets you *choose* where to block on some set of async - > 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. +> Note: Because all of this async code runs in an async block in a `trpl::run` +> call, everything within it can avoid blocking. However, the code *outside* it +> will block on the `run` function returning. That is the whole point of the +> `trpl::run` function: it lets you *choose* where to block on some set of async +> 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. Notice two things about this example: First, the message will arrive right away! Second, although we use a future here, there’s no concurrency yet. Everything @@ -863,32 +820,30 @@ involved. Let’s address the first part by sending a series of messages, and sleep in between them, as shown in Listing 17-10: -<!-- We cannot test this one because it never stops! --> - - Filename: src/main.rs ``` - let (tx, mut rx) = trpl::channel(); +let (tx, mut rx) = trpl::channel(); - 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; +} - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } +while let Some(value) = rx.recv().await { + println!("received '{value}'"); +} ``` -Listing 17-10: Sending and receiving multiple messages over the async channel and sleeping with an <code>await</code> between each message +Listing 17-10: Sending and receiving multiple messages over the async channel +and sleeping with an `await` between each message In addition to sending the messages, we need to receive them. In this case, we could do that manually, by just doing `rx.recv().await` four times, because we @@ -900,11 +855,10 @@ In Listing 16-10, we used a `for` loop to process all the items received from a synchronous channel. However, Rust doesn’t 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. - -<!-- TODO: update text in ch. 19 to account for our having introduced this. --> +loop is the loop version of the `if let` construct we saw back in the “Concise +Control Flow with `if let`” section in Chapter 6 on page XX. 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 `Future` until it is ready. Once a message arrives, the future will resolve @@ -945,36 +899,34 @@ just as in the counting example. Once again, we await the result of calling in sequence, we would just end up back in a sequential flow—exactly what we’re trying *not* to do. -<!-- We cannot test this one because it never stops! --> - - Filename: src/main.rs ``` - let tx_fut = async { - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; +let tx_fut = async { + 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 { - while let Some(value) = rx.recv().await { - println!("received '{value}'"); - } - }; +let rx_fut = async { + while let Some(value) = rx.recv().await { + println!("received '{value}'"); + } +}; - trpl::join(tx_fut, rx_fut).await; +trpl::join(tx_fut, rx_fut).await; ``` -Listing 17-11: Separating <code>send</code> and <code>recv</code> into their own <code>async</code> blocks and awaiting the futures for those blocks +Listing 17-11: Separating `send` and `recv` into their own `async` blocks and +awaiting the futures for those blocks 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. @@ -1004,46 +956,48 @@ 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` because sending a message doesn’t require ownership, but if we could move `tx` into -that async block, it would be dropped once that block ends. In Chapter 13, we -learned how to use the `move` keyword with closures, and in Chapter 16, we saw -that we often need to 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 as it does with closures. +that async block, it would be dropped once that block ends. In the “Capturing +References or Moving Ownership” section of Chapter 13 on page XX, we learned +how to use the `move` keyword with closures, and in the “Using `move` Closures +with Threads” section of Chapter 16 on page XX, we saw that we often need to +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 as it +does with closures. 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. - Filename: src/main.rs ``` - let (tx, mut rx) = trpl::channel(); +let (tx, mut rx) = trpl::channel(); - let tx_fut = async move { - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; +let tx_fut = async move { + 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 { - while let Some(value) = rx.recv().await { - eprintln!("received '{value}'"); - } - }; +let rx_fut = async { + while let Some(value) = rx.recv().await { + eprintln!("received '{value}'"); + } +}; - trpl::join(tx_fut, rx_fut).await; +trpl::join(tx_fut, rx_fut).await; ``` -Listing 17-12: A working example of sending and receiving messages between futures which correctly shuts down when complete +Listing 17-12: A working example of sending and receiving messages between +futures which correctly shuts down when complete 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-13, we @@ -1059,48 +1013,47 @@ that both `tx` and `tx1` get dropped when those blocks finish. Otherwise we’ll 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. - Filename: src/main.rs ``` - let (tx, mut rx) = trpl::channel(); +let (tx, mut rx) = trpl::channel(); - let tx1 = tx.clone(); - let tx1_fut = async move { - let vals = vec![ - String::from("hi"), - String::from("from"), - String::from("the"), - String::from("future"), - ]; +let tx1 = tx.clone(); +let tx1_fut = async move { + 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_millis(500)).await; - } - }; + for val in vals { + tx1.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 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; - } - }; +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; + } +}; - trpl::join3(tx1_fut, tx_fut, rx_fut).await; +trpl::join3(tx1_fut, tx_fut, rx_fut).await; ``` Listing 17-13: Using multiple producers with async blocks @@ -1109,10 +1062,6 @@ Now we see all the messages from both sending futures. Because the sending futures use slightly different delays after sending, the messages are also received at those different intervals. -<!-- Not extracting output because changes to this output aren't significant; -the changes are likely to be due to the threads running differently rather than -changes in the compiler --> - ``` received 'hi' received 'more' @@ -1137,14 +1086,13 @@ arbitrary number of arguments. It also handles awaiting the futures itself. Thus, we could rewrite the code from Listing 17-13 to use `join!` instead of `join3`, as in Listing 17-14: - Filename: src/main.rs ``` - trpl::join!(tx1_fut, tx_fut, rx_fut); +trpl::join!(tx1_fut, tx_fut, rx_fut); ``` -Listing 17-14: Using <code>join!</code> to wait for multiple futures +Listing 17-14: Using `join!` to wait for multiple futures 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 @@ -1154,27 +1102,21 @@ collection to complete is a common pattern. To check all the futures in some collection, we’ll need to iterate over and join on *all* of them. The `trpl::join_all` function accepts any type which -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`. - +implements the `Iterator` trait, which we learned about back in “The Iterator +Trait and the next Method” section of Chapter 13 on page XX, so it seems like +just the ticket. Let’s try putting our futures in a vector, and replace `join!` +with `join_all`. ``` - let futures = vec![tx1_fut, rx_fut, tx_fut]; +let futures = vec![tx1_fut, rx_fut, tx_fut]; - trpl::join_all(futures).await; +trpl::join_all(futures).await; ``` -Listing 17-15: Storing anonymous futures in a vector and calling <code>join_all</code> +Listing 17-15: Storing anonymous futures in a vector and calling `join_all` Unfortunately, this doesn’t compile. Instead, we get this error: -<!-- manual-regeneration -cd listings/ch17-async-await/listing-17-16/ -cargo build -copy just the compiler error ---> - ``` error[E0308]: mismatched types --> src/main.rs:43:37 @@ -1213,35 +1155,35 @@ by the compiler for async blocks. You can’t put two different hand-written structs in a `Vec`, and the same thing applies to the different structs generated by the compiler. -To make this work, we need to use *trait objects*, just as we did in “Returning -Errors from the run function” at *ch12-03-improving-error-handling-and-modularity.html* in Chapter 12. (We’ll cover trait objects -in detail in Chapter 18.) Using trait objects lets us treat each of the -anonymous futures produced by these types as the same type, because all of them -implement the `Future` trait. - - > - > Note: In Chapter 8, we discussed another way to include multiple types in a - > `Vec`: using an enum to represent each of the different types which can - > appear in the vector. We can’t do that here, though. For one thing, we have - > no way to name the different types, because they are anonymous. For another, - > the reason we reached for a vector and `join_all` in the first place was to be - > able to work with a dynamic collection of futures where we don’t know what - > they will all be until runtime. +To make this work, we need to use *trait objects*, just as we did in the +“Returning Errors from the run function” section in Chapter 12 on page XX. +(We’ll cover trait objects in detail in Chapter 18.) Using trait objects lets +us treat each of the anonymous futures produced by these types as the same +type, because all of them implement the `Future` trait. + +> Note: In the “Using an Enum to Store Multiple Types” section of Chapter 8 on +> page XX, we discussed another way to include multiple types in a `Vec`: using +> an enum to represent each of the different types which can appear in the +> vector. We can’t do that here, though. For one thing, we have no way to name +> the different types, because they are anonymous. For another, the reason we +> reached for a vector and `join_all` in the first place was to be able to work +> with a dynamic collection of futures where we don’t 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-16. - Filename: src/main.rs ``` - let futures = - vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; +let futures = + vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; - trpl::join_all(futures).await; +trpl::join_all(futures).await; ``` -Listing 17-16: Trying to use <code>Box::new</code> to align the types of the futures in a <code>Vec</code> +Listing 17-16: Trying to use `Box::new` to align the types of the futures in a +`Vec` Unfortunately, this still doesn’t compile. In fact, we have the same basic error we did before, but we get one for both the second and third `Box::new` @@ -1249,15 +1191,15 @@ 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 annotating the type of the `futures` variable: - Filename: src/main.rs ``` - let futures: Vec<Box<dyn Future<Output = ()>>> = - vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; +let futures: Vec<Box<dyn Future<Output = ()>>> = + vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)]; ``` -Listing 17-17: Fixing the rest of the type mismatch errors by using an explicit type declaration +Listing 17-17: Fixing the rest of the type mismatch errors by using an explicit +type declaration The type we had to write here is a little involved, so let’s walk through it: @@ -1271,12 +1213,6 @@ That already made a big difference. Now when we run the compiler, we only have 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-17 -cargo build -copy *only* the errors ---> - ``` error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned --> src/main.rs:46:24 @@ -1290,7 +1226,7 @@ error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned 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 `join_all` - --> /Users/chris/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:105:14 + --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:105:14 | 102 | pub fn join_all<I>(iter: I) -> JoinAll<I::Item> | -------- required by a bound in this function @@ -1308,7 +1244,7 @@ error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned 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 + --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:29:8 | 27 | pub struct JoinAll<F> | ------- required by a bound in this struct @@ -1326,7 +1262,7 @@ error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned 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 + --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:29:8 | 27 | pub struct JoinAll<F> | ------- required by a bound in this struct @@ -1347,22 +1283,17 @@ 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. - Filename: src/main.rs ``` - let futures: Vec<Pin<Box<dyn Future<Output = ()>>>> = - vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; +let futures: Vec<Pin<Box<dyn Future<Output = ()>>>> = + vec![Box::pin(tx1_fut), Box::pin(rx_fut), Box::pin(tx_fut)]; ``` -Listing 17-18: Using <code>Pin</code> and <code>Box::pin</code> to make the <code>Vec</code> type check +Listing 17-18: Using `Pin` and `Box::pin` to make the `Vec` type check If we compile and run this, we finally get the output we hoped for: -<!-- Not extracting output because changes to this output aren't significant; -the changes are likely to be due to the threads running differently rather than -changes in the compiler --> - ``` received 'hi' received 'more' @@ -1391,32 +1322,33 @@ 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-19. - Filename: src/main.rs ``` - let tx1_fut = pin!(async move { - // --snip-- - }); +let tx1_fut = pin!(async move { + // --snip-- +}); - let rx_fut = pin!(async { - // --snip-- - }); +let rx_fut = pin!(async { + // --snip-- +}); - let tx_fut = pin!(async move { - // --snip-- - }); +let tx_fut = pin!(async move { + // --snip-- +}); - let futures: Vec<Pin<&mut dyn Future<Output = ()>>> = - vec![tx1_fut, rx_fut, tx_fut]; +let futures: Vec<Pin<&mut dyn Future<Output = ()>>> = + vec![tx1_fut, rx_fut, tx_fut]; ``` -Listing 17-19: Using <code>Pin</code> directly with the <code>pin!</code> macro to avoid unnecessary heap allocations +Listing 17-19: Using `Pin` directly with the `pin!` macro to avoid unnecessary +heap allocations We got this far by ignoring the fact that we might have different `Output` 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>`. - +`Future<Output = u32>`, the anonymous future for `b` implements +`Future<Output = &str>`, and the anonymous future for `c` implements +`Future<Output = bool>`. Filename: src/main.rs @@ -1455,30 +1387,29 @@ In Listing 17-21, we once again use `trpl::race` to run two futures, `slow` and 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!) -Unlike when we used `race` back in Our First Async Program at *ch17-01-futures-and-syntax.html#our-first-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. - +Unlike when we used `race` back in the “Our First Async Program” section of this +chapter on page XX, we just ignore the `Either` instance it returns here, +because all of the interesting behavior happens in the body of the async blocks. Filename: src/main.rs ``` - let slow = async { - println!("'slow' started."); - trpl::sleep(Duration::from_millis(100)).await; - println!("'slow' finished."); - }; +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 fast = async { + println!("'fast' started."); + trpl::sleep(Duration::from_millis(50)).await; + println!("'fast' finished."); +}; - trpl::race(slow, fast).await; +trpl::race(slow, fast).await; ``` -Listing 17-21: Using <code>race</code> to get the result of whichever future finishes first +Listing 17-21: Using `race` to get the result of whichever future finishes first 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 @@ -1489,11 +1420,11 @@ to poll first. Regardless of whether the implementation of race we’re 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 Our First Async Program at *ch17-01-futures-and-syntax.html#our-first-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 isn’t 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 the “Our First Async Program” section of this chapter on page XX +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 isn’t 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 @@ -1517,7 +1448,6 @@ function. It uses `std::thread::sleep` instead of `trpl::sleep` so that calling `slow` to stand in for real-world operations which are both long-running and blocking. - Filename: src/main.rs ``` @@ -1527,48 +1457,41 @@ fn slow(name: &str, ms: u64) { } ``` -Listing 17-22: Using <code>thread::sleep</code> to simulate slow operations +Listing 17-22: Using `thread::sleep` to simulate slow operations 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. - Filename: src/main.rs ``` - 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 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."); - }; +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; +trpl::race(a, b).await; ``` -Listing 17-23: Using <code>thread::sleep</code> to simulate slow operations +Listing 17-23: Using `thread::sleep` to simulate slow operations If you run this, you will see this output: -<!-- manual-regeneration -cd listings/ch17-async-await/listing-17-24/ -cargo run -copy just the output ---> - ``` 'a' started. 'a' ran for 30ms @@ -1595,48 +1518,41 @@ 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? - Filename: src/main.rs ``` - let one_ms = Duration::from_millis(1); +let one_ms = Duration::from_millis(1); - 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; - println!("'a' finished."); - }; +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; + 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; - println!("'b' 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; + println!("'b' finished."); +}; ``` -Listing 17-24: Using <code>sleep</code> to let operations switch off making progress +Listing 17-24: Using `sleep` to let operations switch off making progress 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-24 -cargo run -copy just the output ---> - ``` 'a' started. 'a' ran for 30ms @@ -1660,36 +1576,35 @@ 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-25, we replace all those `sleep` calls with `yield_now`. - Filename: src/main.rs ``` - 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 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."); - }; -``` - -Listing 17-25: Using <code>yield_now</code> to let operations switch off making progress +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 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."); +}; +``` + +Listing 17-25: Using `yield_now` to let operations switch off making progress This is both clearer about the actual intent and can be significantly faster than using `sleep`, because timers such as the one used by `sleep` often have @@ -1706,39 +1621,38 @@ 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`. - Filename: src/main.rs ``` - 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() - ); - - 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() - ); +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() +); + +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() +); ``` -Listing 17-26: Comparing the performance of <code>sleep</code> and <code>yield_now</code> +Listing 17-26: Comparing the performance of `sleep` and `yield_now` The version with `yield_now` is *way* faster! @@ -1770,24 +1684,24 @@ yet further async abstractions. Listing 17-27 shows how we would expect this `timeout` to work with a slow future. - Filename: src/main.rs ``` - let slow = async { - trpl::sleep(Duration::from_millis(100)).await; - "I finished!" - }; +let slow = async { + trpl::sleep(Duration::from_millis(100)).await; + "I finished!" +}; - match timeout(slow, Duration::from_millis(10)).await { - Ok(message) => println!("Succeeded with '{message}'"), - Err(duration) => { - println!("Failed after {} seconds", duration.as_secs()) - } - } +match timeout(slow, Duration::from_millis(10)).await { + Ok(message) => println!("Succeeded with '{message}'"), + Err(duration) => { + println!("Failed after {} seconds", duration.as_secs()) + } +} ``` -Listing 17-27: Using our imagined <code>timeout</code> to run a slow operation with a time limit +Listing 17-27: Using our imagined `timeout` to run a slow operation with a time +limit Let’s implement this! To begin, let’s think about the API for `timeout`: @@ -1803,9 +1717,6 @@ Let’s implement this! To begin, let’s think about the API for `timeout`: Listing 17-28 shows this declaration. -<!-- This is not tested because it intentionally does not compile. --> - - Filename: src/main.rs ``` @@ -1817,7 +1728,7 @@ async fn timeout<F: Future>( } ``` -Listing 17-28: Defining the signature of <code>timeout</code> +Listing 17-28: Defining the signature of `timeout` 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 @@ -1836,7 +1747,6 @@ In Listing 17-29, we match on the result of awaiting `trpl::race`. If the If the sleep timer elapsed instead and we get a `Right(())`, we ignore the `()` with `_` and return `Err(max_time)` instead. - Filename: src/main.rs ``` @@ -1870,7 +1780,7 @@ async fn timeout<F: Future>( } ``` -Listing 17-29: Defining <code>timeout</code> with <code>race</code> and <code>sleep</code> +Listing 17-29: Defining `timeout` with `race` and `sleep` 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: @@ -1906,18 +1816,19 @@ to consider first, though: ## Streams 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” at *ch17-02-concurrency-with-async.html#message-passing* earlier in the chapter. +exception was the async channel we used. Recall how we used the receiver for +our async channel in the “Message Passing” section of this chapter on page XX. 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’ve 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. When working directly with an `Iterator`, we call -its synchronous `next` method. With the `trpl::Receiver` stream in particular, -we called an asynchronous `recv` method instead, but these APIs otherwise feel +`Iterator` trait in “The `Iterator` Trait and the `next` Method” section of +Chapter 13 on page XX, 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. When working directly with an `Iterator`, we call its +synchronous `next` method. With the `trpl::Receiver` stream in particular, we +called an asynchronous `recv` method instead, but these APIs otherwise feel very similar. That similarity isn’t a coincidence. A stream is similar to an asynchronous @@ -1928,17 +1839,16 @@ similarity between iterators and streams in Rust means 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-30. - Filename: src/main.rs ``` - 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 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); - while let Some(value) = stream.next().await { - println!("The value was: {value}"); - } +while let Some(value) = stream.next().await { + println!("The value was: {value}"); +} ``` Listing 17-30: Creating a stream from an iterator and printing its values @@ -1951,14 +1861,6 @@ stream as they arrive with the `while let` loop. Unfortunately, when we try to run the code, it doesn’t compile. Instead, as we 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-30 -cargo build -copy only the error output ---> - ``` error[E0599]: no method named `next` found for struct `Iter` in the current scope --> src/main.rs:8:40 @@ -1966,7 +1868,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-30/target/debug/deps/async_await-bbd5bb8f6851cb5f.long-type-18426562901668632191.txt' + = note: the full type name has been written to '~/projects/hello-async/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 @@ -2006,7 +1908,6 @@ keep moving. The fix to the compiler error is to add a `use` statement for `trpl::StreamExt`, as in Listing 17-31. - Filename: src/main.rs ``` @@ -2032,7 +1933,6 @@ more, now that we have `StreamExt` in scope, we can use all of its utility methods, just as with iterators. For example, in Listing 17-32, we use the `filter` method to filter out everything but multiples of three and five. - Filename: src/main.rs ``` @@ -2054,7 +1954,7 @@ fn main() { } ``` -Listing 17-32: Filtering a <code>Stream</code> with the <code>StreamExt::filter</code> method +Listing 17-32: Filtering a `Stream` with the `StreamExt::filter` method Of course, this isn’t 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 @@ -2082,7 +1982,6 @@ 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. - Filename: src/main.rs ``` @@ -2110,14 +2009,10 @@ fn get_messages() -> impl Stream<Item = String> { } ``` -Listing 17-33: Using the <code>rx</code> receiver as a <code>ReceiverStream</code> +Listing 17-33: Using the `rx` receiver as a `ReceiverStream` When we run this code, we get exactly the results we would expect: -<!-- Not extracting output because changes to this output aren't significant; -the changes are likely to be due to the threads running differently rather than -changes in the compiler --> - ``` Message: 'a' Message: 'b' @@ -2145,7 +2040,6 @@ 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. - Filename: src/main.rs ``` @@ -2167,7 +2061,8 @@ fn main() { } ``` -Listing 17-34: Using the <code>StreamExt::timeout</code> method to set a time limit on the items in a stream +Listing 17-34: Using the `StreamExt::timeout` method to set a time limit on the +items in a stream However, because 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 @@ -2178,7 +2073,6 @@ 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. - Filename: src/main.rs ``` @@ -2199,40 +2093,34 @@ fn get_messages() -> impl Stream<Item = String> { } ``` -Listing 17-35: Sending messages through <code>tx</code> with an async delay without making <code>get_messages</code> an async function +Listing 17-35: Sending messages through `tx` with an async delay without making +`get_messages` an async function To sleep between messages in the `get_messages` function without blocking, we need to use async. However, we can’t make `get_messages` itself into an async -function, because then we’d return a `Future<Output = Stream<Item = String>>` instead of just a `Stream<Item = String>>`. 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, -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. +function, because then we’d return a `Future<Output = Stream<Item = String>>` +instead of just a `Stream<Item = String>>`. 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, 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. - > - > Note: calling `spawn_task` in this way works because we already set up our - > runtime. Calling this particular implementation of `spawn_task` *without* - > first setting up a runtime will cause a panic. Other implementations choose - > different tradeoffs: they might spawn a new runtime and so avoid the panic but - > end up with a bit of extra overhead, or simply not provide a standalone way to - > spawn tasks without reference to a runtime. You should make sure you know what - > tradeoff your runtime has chosen and write your code accordingly! +> Note: calling `spawn_task` in this way works because we already set up our +> runtime. Calling this particular implementation of `spawn_task` *without* +> first setting up a runtime will cause a panic. Other implementations choose +> different tradeoffs: they might spawn a new runtime and so avoid the panic but +> end up with a bit of extra overhead, or simply not provide a standalone way to +> spawn tasks without reference to a runtime. You should make sure you know what +> tradeoff your runtime has chosen and write your code accordingly! 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-35 -cargo run -copy only the program output, *not* the compiler output ---> - ``` Message: 'a' Problem: Elapsed(()) @@ -2280,7 +2168,6 @@ it over the channel. Because 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. - Filename: src/main.rs ``` @@ -2300,7 +2187,8 @@ fn get_intervals() -> impl Stream<Item = u32> { } ``` -Listing 17-36: Creating a stream with a counter that will be emitted once every millisecond +Listing 17-36: Creating a stream with a counter that will be emitted once every +millisecond 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 @@ -2314,23 +2202,25 @@ the source streams as soon as the items are available, without imposing any particular ordering. Finally, we loop over that combined stream instead of over `messages` (Listing 17-37). - Filename: src/main.rs ``` - let messages = get_messages().timeout(Duration::from_millis(200)); - let intervals = get_intervals(); - let merged = messages.merge(intervals); +let messages = get_messages().timeout(Duration::from_millis(200)); +let intervals = get_intervals(); +let merged = messages.merge(intervals); ``` Listing 17-37: Attempting to merge streams of messages and intervals -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 compile! (Neither does the `next` call in the `while let` loop, but we’ll come back to that after fixing this.) The two streams -have different types. The `messages` stream has the type `Timeout<impl Stream<Item = String>>`, where `Timeout` is the type which implements `Stream` -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. +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 compile! (Neither does the `next` call +in the `while let` loop, but we’ll come back to that after fixing this.) The +two streams have different types. The `messages` stream has the type +`Timeout<impl Stream<Item = String>>`, where `Timeout` is the type which +implements `Stream` 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-38, we rework the `intervals` stream, because `messages` is already in the basic format we want and has to handle timeout errors. First, we @@ -2342,21 +2232,19 @@ which is longer than the other durations we are using. Here, we create a `stream` mutable, so that the `while let` loop’s `next` calls can iterate through the stream, and pin it so that it’s safe to do so. -<!-- We cannot directly test this one, because it never stops. --> - - Filename: src/main.rs ``` - let messages = get_messages().timeout(Duration::from_millis(200)); - let intervals = get_intervals() - .map(|count| format!("Interval: {count}")) - .timeout(Duration::from_secs(10)); - let merged = messages.merge(intervals); - let mut stream = pin!(merged); +let messages = get_messages().timeout(Duration::from_millis(200)); +let intervals = get_intervals() + .map(|count| format!("Interval: {count}")) + .timeout(Duration::from_secs(10)); +let merged = messages.merge(intervals); +let mut stream = pin!(merged); ``` -Listing 17-38: Aligning the types of the the <code>intervals</code> stream with the type of the <code>messages</code> stream +Listing 17-38: Aligning the types of the the `intervals` stream with the type +of the `messages` stream That gets us *almost* to where we need to be. Everything type checks. If you run this, though, there will be two problems. First, it will never stop! You’ll @@ -2364,10 +2252,6 @@ need to stop it with <span class="keystroke">ctrl-c</span>. Second, the messages from the English alphabet will be buried in the midst of all the interval counter messages: -<!-- Not extracting output because changes to this output aren't significant; -the changes are likely to be due to the tasks running differently rather than -changes in the compiler --> - ``` --snip-- Interval: 38 @@ -2391,20 +2275,19 @@ 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. - Filename: src/main.rs ``` - let messages = get_messages().timeout(Duration::from_millis(200)); - let intervals = get_intervals() - .map(|count| format!("Interval: {count}")) - .throttle(Duration::from_millis(100)) - .timeout(Duration::from_secs(10)); - let merged = messages.merge(intervals).take(20); - let mut stream = pin!(merged); +let messages = get_messages().timeout(Duration::from_millis(200)); +let intervals = get_intervals() + .map(|count| format!("Interval: {count}")) + .throttle(Duration::from_millis(100)) + .timeout(Duration::from_secs(10)); +let merged = messages.merge(intervals).take(20); +let mut stream = pin!(merged); ``` -Listing 17-39: Using <code>throttle</code> and <code>take</code> to manage the merged streams +Listing 17-39: Using `throttle` and `take` to manage the merged streams Now when we run the program, it stops after pulling twenty items from the stream, and the intervals don’t overwhelm the messages. We also don’t get @@ -2418,12 +2301,6 @@ ignore. Instead, we never produce those interval messages in the first place! This is the inherent “laziness” of Rust’s futures at work again, allowing us to choose our performance characteristics. -<!-- manual-regeneration -cd listings/listing-17-39 -cargo run -copy and paste only the program output ---> - ``` Interval: 1 Message: 'a' @@ -2457,7 +2334,6 @@ 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. - ``` fn get_messages() -> impl Stream<Item = String> { let (tx, rx) = trpl::channel(); @@ -2517,9 +2393,9 @@ still leaving the *really* deep dive for other documentation! ### Future -Back in Futures and the Async Syntax at *ch17-01-futures-and-syntax.html*, 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 the “Futures and the Async Syntax” section of this chapter on page XX, +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`: ``` use std::pin::Pin; @@ -2557,11 +2433,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 - > 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. This is similar to how `Iterator::next` behaves! +> 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. This is similar to how `Iterator::next` behaves! Under the hood, when you see code which uses `await`, Rust compiles that to code which calls `poll`. If you look back at Listing 17-4, where we printed out the @@ -2606,14 +2481,14 @@ 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 (in the Counting at *ch17-02-concurrency-with-async.html* 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’s -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 isn’t 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 +Recall our description (in the “Counting” section of this chapter on page XX) +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’s 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 isn’t +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)`. The exact details of how a runtime does that are more than we will cover in even @@ -2623,17 +2498,9 @@ it is not yet ready. ### Pinning and the Pin and Unpin Traits -<!-- TODO: get a *very* careful technical review of this section! --> - 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-17 -cargo build -copy *only* the final `error` block from the errors ---> - ``` error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned --> src/main.rs:46:33 @@ -2645,7 +2512,7 @@ error[E0277]: `{async block@src/main.rs:8:23: 20:10}` cannot be unpinned 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 + --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/future/join_all.rs:29:8 | 27 | pub struct JoinAll<F> | ------- required by a bound in this struct @@ -2701,27 +2568,30 @@ other smart pointer types we saw in Chapter 15, which also wrap other types. Unlike those, however, `Pin` only works with *pointer types* such as references (`&` 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, because implementing `Deref` or `DerefMut` -means your type behaves similarly to a pointer type. `Pin` is also not a -pointer itself, and it doesn’t have any behavior of its own as the ref counting -of `Rc` or `Arc` does. It’s purely a tool the compiler can use to uphold the -relevant guarantees, by wrapping pointers in the type. +we covered in the “Treating Smart Pointers Like Regular References with the +Deref Trait” section of Chapter 15 on page XX. You can think of this +restriction as equivalent to only working with pointers, though, because +implementing `Deref` or `DerefMut` means your type behaves similarly to a +pointer type. `Pin` is also not a pointer itself, and it doesn’t have any +behavior of its own as the ref counting of `Rc` or `Arc` does. It’s 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`? -In Our First Async Program at *ch17-01-futures-and-syntax.html#our-first-async-program*, 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. +In the “”ur First Async Program” section of this chapter on page XX, 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 @@ -2736,13 +2606,9 @@ themselves in the fields of any given variant, as in Figure 17-3 (a simplified illustration to help you get a feel for the idea, rather than digging into what are often fairly complicated details). -<figure> - -<img alt="Concurrent work flow" src="img/trpl17-03.svg" class="center" /> +<img alt="Concurrent work flow" src="img/trpl17-03.svg" /> -<figcaption>Figure 17-3: A self-referential data type.</figcaption> - -</figure> +Figure 17-3: A self-referential data type. By default, though, any object which has a reference to itself is unsafe to move, because references always point to the actual memory address of the thing @@ -2753,13 +2619,9 @@ the data structure. For another—and more importantly!—the computer is now fr to reuse that memory for other things! You could end up reading completely unrelated data later. -<figure> - -<img alt="Concurrent work flow" src="img/trpl17-04.svg" class="center" /> +<img alt="Concurrent work flow" src="img/trpl17-04.svg" /> -<figcaption>Figure 17-4: The unsafe result of moving a self-referential data type.</figcaption> - -</figure> +Figure 17-4: The unsafe result of moving a self-referential data type. In principle, the Rust compiler could try to update every reference to an object every time it gets moved. That would potentially be a lot of performance @@ -2774,13 +2636,9 @@ value by wrapping a pointer to that value in `Pin`, it can no longer move. Thus, if you have `Pin<Box<SomeType>>`, you actually pin the `SomeType` value, *not* the `Box` pointer. Figure 17-5 illustrates this: -<figure> - -<img alt="Concurrent work flow" src="img/trpl17-05.svg" class="center" /> - -<figcaption>Figure 17-5: Pinning a `Box` which points to a self-referential future type.</figcaption> +<img alt="Concurrent work flow" src="img/trpl17-05.svg" /> -</figure> +Figure 17-5: Pinning a `Box` which points to a self-referential future type. In fact, the `Box` pointer can still move around freely. Remember: we care about making sure the data ultimately being referenced stays in its place. If a @@ -2792,13 +2650,9 @@ well as the `std::pin` module, you might be able to work out how you would do that.) The key is that the self-referential type itself cannot move, because it is still pinned. -<figure> +<img alt="Concurrent work flow" src="img/trpl17-06.svg" /> -<img alt="Concurrent work flow" src="img/trpl17-06.svg" class="center" /> - -<figcaption>Figure 17-6: Moving a `Box` which points to a self-referential future type.</figcaption> - -</figure> +Figure 17-6: Moving a `Box` which points to a self-referential future type. 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 @@ -2812,12 +2666,13 @@ via the safe but restrictive APIs provided by `Pin`, even though a need a way to tell the compiler that it’s actually just fine to move items around in cases such as these. For that, we have `Unpin`. -`Unpin` is a marker trait, as `Send` and `Sync` are, 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’s 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. +`Unpin` is a marker trait, as `Send` and `Sync` are, which we saw in the +“Extensible Concurrency with the `Sync` and `Send` Traits” section of Chapter +16 on page XX. Recall that marker traits have no functionality of their own. +They exist only to tell the compiler that it’s 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 as with `Send` and `Sync`, the compiler implements `Unpin` automatically for all types where it can prove it is safe. Implementing `Unpin` manually is @@ -2829,26 +2684,19 @@ To make that concrete, think about a `String`: it has a length and the Unicode characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure 17-7. However -<figure> - -<img alt="Concurrent work flow" src="img/trpl17-07.svg" class="center" /> +<img alt="Concurrent work flow" src="img/trpl17-07.svg" /> -<figcaption>Figure 17-7: Pinning a String, with a dotted line indicating that the String implements the `Unpin` trait, so it is not pinned.</figcaption> - -</figure> +Figure 17-7: Pinning a String, with a dotted line indicating that the String +implements the `Unpin` trait, so it is not pinned. This means that we can do things such as replace one string with another at the exact same location in memory as in Figure 17-8. This doesn’t violate the `Pin` contract because `String`—like most other types in Rust—implements `Unpin`, because it has no internal references that make it unsafe to move around! -<figure> - -<img alt="Concurrent work flow" src="img/trpl17-08.svg" class="center" /> - -<figcaption>Figure 17-8: Replacing the String with an entirely different String in memory.</figcaption> +<img alt="Concurrent work flow" src="img/trpl17-08.svg" /> -</figure> +Figure 17-8: Replacing the String with an entirely different String in memory. Now we know enough to understand the errors reported for that `join_all` call from back in Listing 17-17. We originally tried to move the futures produced by @@ -2862,22 +2710,21 @@ when you’re building a runtime itself, rather than for day to day Rust code. When you see these traits in error messages, though, now you’ll have a better idea of how to fix the code! - > - > 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’re 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 specifics of how `Pin` and `Unpin` work, and the rules they’re required - > to uphold, are covered extensively in the API documentation for `std::pin`, so - > if you’d like to understand them more deeply, that’s 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* at *https://rust-lang.github.io/async-book/* book has - > you covered: - > - > * Chapter 2: Under the Hood: Executing Futures and Tasks at *https://rust-lang.github.io/async-book/02_execution/01_chapter.html* - > * Chapter 4: Pinning at *https://rust-lang.github.io/async-book/04_pinning/01_chapter.html* +> 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’re 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 specifics of how `Pin` and `Unpin` work, and the rules they’re required +> to uphold, are covered extensively in the API documentation for `std::pin`, so +> if you’d like to understand them more deeply, that’s 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* book available at +> *https://rust-lang.github.io/async-book/* has you covered: +> +> * Chapter 2: Under the Hood: Executing Futures and Tasks +> * Chapter 4: Pinning ### The Stream Trait @@ -2885,9 +2732,8 @@ 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 similar to asynchronous iterators. Unlike `Iterator` and `Future`, there is no definition of a `Stream` trait in the -standard library as of the time of writing,<!-- TODO: verify before press time! ---> but there *is* a very common definition from the `futures` crate used -throughout the ecosystem. +standard library as of the time of writing, but there *is* a very common +definition from the `futures` crate 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 @@ -2945,23 +2791,17 @@ trait StreamExt: Stream { } ``` -<!-- -TODO: update this if/when tokio/etc. update their MSRV and switch to using async functions -in traits, since the lack thereof is the reason they do not yet have this. ---> - - > - > Note: The actual definition we used earlier in the chapter 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 a `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 method! +> Note: The actual definition we used earlier in the chapter 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: +> +> ``` +> fn next(&mut self) -> Next<'_, Self> where Self: Unpin; +> ``` +> +> That `Next` type is a `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 method! The `StreamExt` trait is also the home of all the interesting methods available to use with streams. `StreamExt` is automatically implemented for every type @@ -2982,11 +2822,12 @@ fit together! ## Futures, Tasks, and Threads -As we saw in the previous chapter, threads provide one approach to concurrency. -We’ve seen another approach to concurrency in this chapter, using async with -futures and streams. You might be wondering why you would choose one or the -other. The answer is: it depends! And in many cases, the choice isn’t threads -*or* async but rather threads *and* async. +As we saw in the “Using Threads to Run Code Simultaneously” section of Chapter +16 on page XX, threads provide one approach to concurrency. We’ve seen another +approach to concurrency in this chapter, using async with futures and streams. +You might be wondering why you would choose one or the other. The answer is: it +depends! And in many cases, the choice isn’t threads *or* async but rather +threads *and* async. Many operating systems have supplied threading-based concurrency models for decades now, and many programming languages have support for them as a result. @@ -3011,7 +2852,6 @@ could do the exact same thing with a thread! In Listing 17-40, we used the `thread::spawn` and `thread::sleep` APIs from the standard library in the `get_intervals` function. - Filename: src/main.rs ``` @@ -3037,7 +2877,8 @@ fn get_intervals() -> impl Stream<Item = u32> { } ``` -Listing 17-41: Using the <code>std::thread</code> APIs instead of the async <code>trpl</code> APIs for the <code>get_intervals</code> function +Listing 17-41: Using the `std::thread` APIs instead of the async `trpl` APIs +for the `get_intervals` function If you run this, the output is identical. And notice how little changes here from the perspective of the calling code! What’s more, even though one of our @@ -3074,10 +2915,11 @@ state got cleaned up correctly. These limitations make threads harder to compose than futures. It’s much more difficult, for example, to build something similar to the `timeout` we built in -“Building Our Own Async Abstractions” at *ch17-03-more-futures.html#building-our-own-async-abstractions*, or the `throttle` -method we used with streams in “Composing Streams” at *ch17-04-streams.html#composing-streams*. The fact that -futures are richer data structures means they *can* be composed together more -naturally, as we have seen. +the “Building Our Own Async Abstractions” section of this chapter on page XX, +or the `throttle` method we used with streams in the “Composing Streams” +section of this chapter on page XX. The fact that futures are richer data +structures means they *can* be composed together more naturally, as we have +seen. Tasks then give *additional* control over futures, allowing you to choose where and how to group the futures. And it turns out that threads and tasks often @@ -3103,7 +2945,6 @@ choose between threads and async. You can use them together freely, letting each one serve the part it is best at. For example, Listing 17-42 shows a fairly common example of this kind of mix in real-world Rust code. - Filename: src/main.rs ``` @@ -3127,7 +2968,8 @@ fn main() { } ``` -Listing 17-42: Sending messages with blocking code in a thread and awaiting the messages in an async block +Listing 17-42: Sending messages with blocking code in a thread and awaiting the +messages in an async block 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 From db949d6a96fd0d8bd444c7f6786feabb1362662b Mon Sep 17 00:00:00 2001 From: Chris Krycho <hello@chriskrycho.com> Date: Mon, 7 Oct 2024 07:59:07 -0600 Subject: [PATCH 231/249] Ch. 17: Remove TODO about `Stream` stabilization Per the [async working group][wg], the _status quo_ for this is unlikely to change before we go to print. We can of course update the online copy as soon as it *does* change, and if it happens to change such that we can sneak it in before going to press, great. [wg]: https://rust-lang.zulipchat.com/#narrow/stream/187312-wg-async/topic/Rename.20AsyncIterator.20back.20to.20Stream.2C.20introduce.20an.20AFIT-based/near/475300446 --- src/ch17-05-traits-for-async.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 7cc3825886..94494b7171 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -376,9 +376,8 @@ 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 similar to asynchronous iterators. Unlike `Iterator` and `Future`, there is no definition of a `Stream` trait in the -standard library as of the time of writing,<!-- TODO: verify before press time! ---> but there *is* a very common definition from the `futures` crate used -throughout the ecosystem. +standard library as of the time of writing, but there *is* a very common +definition from the `futures` crate 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 c1d60d0696402152b9859e13f4f041d5ba0b8189 Mon Sep 17 00:00:00 2001 From: Chris Krycho <hello@chriskrycho.com> Date: Mon, 7 Oct 2024 08:31:33 -0600 Subject: [PATCH 232/249] =?UTF-8?q?Ch.=2017:=20some=20alternative=20wordin?= =?UTF-8?q?gs=20for=20=E2=80=9Clike=E2=80=9D=20substitutions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nostarch/chapter17.md | 15 +++++++-------- src/ch17-05-traits-for-async.md | 6 +++--- src/ch17-06-futures-tasks-threads.md | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index 97d8b7ce39..45757777d4 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -2569,13 +2569,12 @@ Unlike those, however, `Pin` only works with *pointer types* such as references (`&` 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 the “Treating Smart Pointers Like Regular References with the -Deref Trait” section of Chapter 15 on page XX. You can think of this -restriction as equivalent to only working with pointers, though, because -implementing `Deref` or `DerefMut` means your type behaves similarly to a -pointer type. `Pin` is also not a pointer itself, and it doesn’t have any -behavior of its own as the ref counting of `Rc` or `Arc` does. It’s purely a -tool the compiler can use to uphold the relevant guarantees, by wrapping -pointers in the type. +Deref Trait” section of Chapter 15 on page XX. You can think of this restriction +as equivalent to only working with pointers, though, because implementing +`Deref` or `DerefMut` means your type behaves similarly to a pointer type. `Pin` +is also not a pointer itself, and it doesn’t have any behavior of its own the +way `Rc` and `Arc` do with ref counting. It’s 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 @@ -2908,7 +2907,7 @@ 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,” 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* as futures can. Threads in Rust also have no +no *intra-task concurrency* the way futures can. Threads in Rust also have no mechanisms for cancellation—a subject we haven’t 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. diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 94494b7171..a7c5feee50 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -195,9 +195,9 @@ Unlike those, however, `Pin` only works with *pointer types* such as references `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, because implementing `Deref` or `DerefMut` -means your type behaves similarly to a pointer type. `Pin` is also not a -pointer itself, and it doesn’t have any behavior of its own as the ref counting -of `Rc` or `Arc` does. It’s purely a tool the compiler can use to uphold the +means your type behaves similarly to a pointer type. `Pin` is also not a pointer +itself, and it doesn’t have any behavior of its own the way `Rc` and `Arc` do +with ref counting. It’s 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 diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 428eb61c9c..21556b658c 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -65,7 +65,7 @@ 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,” 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* as futures can. Threads in Rust also have no +no *intra-task concurrency* the way futures can. Threads in Rust also have no mechanisms for cancellation—a subject we haven’t 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. From 8f63245b5c8cef562453aaef579cd9d6b850549f Mon Sep 17 00:00:00 2001 From: Chris Krycho <hello@chriskrycho.com> Date: Mon, 7 Oct 2024 12:47:44 -0600 Subject: [PATCH 233/249] Ch. 17: fix task names in Figure 17-2 --- dot/trpl17-02.dot | 18 +++++++++--------- src/img/trpl17-02.svg | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dot/trpl17-02.dot b/dot/trpl17-02.dot index 07d66a3e4b..3e4116a7de 100644 --- a/dot/trpl17-02.dot +++ b/dot/trpl17-02.dot @@ -1,25 +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"; + label = "Task B"; B1 -> B2 -> B3; - + B0 [style = invis;]; - B3 -> B0 [style = invis;] + B3 -> B0 [style = invis;]; } - + subgraph cluster_ColleagueA { newrank = true; - label = "Task 1"; + label = "Task A"; A1 -> A2 -> A3 -> A4; } -} +} \ No newline at end of file diff --git a/src/img/trpl17-02.svg b/src/img/trpl17-02.svg index b2df090c23..5c32a1a262 100644 --- a/src/img/trpl17-02.svg +++ b/src/img/trpl17-02.svg @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<!-- Generated by graphviz version 12.1.0 (20240811.2233) +<!-- Generated by graphviz version 12.1.2 (20240928.0832) --> <!-- Pages: 1 --> <svg @@ -11,12 +11,12 @@ <g id="clust1" class="cluster"> <title>cluster_ColleagueB -Task 2 +Task B cluster_ColleagueA -Task 1 +Task A From 3111eda07a4a4692bf69e3aaad999d840ac9c138 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 7 Oct 2024 13:25:41 -0600 Subject: [PATCH 234/249] Ch. 17: create a diagram showing blocked parallelism --- dot/trpl17-03.dot | 35 +++++++--- dot/trpl17-04.dot | 31 +++------ dot/trpl17-05.dot | 52 ++++++-------- dot/trpl17-06.dot | 58 +++++---------- dot/trpl17-07.dot | 73 ++++++++++++------- dot/trpl17-08.dot | 41 +++-------- dot/trpl17-09.dot | 62 +++++++++++++++++ nostarch/chapter17.md | 46 ++++++------ src/ch17-00-async-await.md | 18 +++-- src/ch17-05-traits-for-async.md | 32 ++++----- src/img/trpl17-03.svg | 120 ++++++++++++++++++++++++++------ 11 files changed, 348 insertions(+), 220 deletions(-) create mode 100644 dot/trpl17-09.dot diff --git a/dot/trpl17-03.dot b/dot/trpl17-03.dot index 6c63b7bde4..7d5a4971cf 100644 --- a/dot/trpl17-03.dot +++ b/dot/trpl17-03.dot @@ -1,19 +1,32 @@ digraph { - rankdir = RL; - overlap = false; dpi = 300.0; + + rankdir = "LR"; splines = false; cluster = true; - node [shape = "plaintext";]; + 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 A"; + A1; + A2; + A0_1 [style = invis;]; + A3; + + A1 -> A2; + A2 -> A0_1 [arrowhead = "tee"; headport = "A0_1:c"; headclip = false;]; + A0_1; + A0_1 -> A3 [dir = both; arrowtail = "tee"; tailclip = false;]; + } - fut1 [label = < - - - - -
fut1
0
1
>;]; + subgraph cluster_ColleagueA { + newrank = true; + label = "Task B"; + B1 -> B2 -> B3 -> B4; + } - edge [tailclip = "false";]; - fut1:source:c -> fut1:target [dir = forward;]; + B3 -> A3; } \ No newline at end of file diff --git a/dot/trpl17-04.dot b/dot/trpl17-04.dot index afcf8e77a1..6c63b7bde4 100644 --- a/dot/trpl17-04.dot +++ b/dot/trpl17-04.dot @@ -7,26 +7,13 @@ digraph { node [shape = "plaintext";]; - // Group the two together, which results in the desired alignment. - subgraph { - // But don't show the frame! - style = "invis"; - - fut1 [label = < - - - - -
fut1
?
?
?
>;]; - - fut2 [label = < - - - - -
fut2
0
1
>;]; - - edge [tailclip = "false"; dir = forward]; - fut2:source:c -> fut1:target:e; - } + fut1 [label = < + + + + +
fut1
0
1
>;]; + + edge [tailclip = "false";]; + fut1:source:c -> fut1:target [dir = forward;]; } \ No newline at end of file diff --git a/dot/trpl17-05.dot b/dot/trpl17-05.dot index e036a385c3..afcf8e77a1 100644 --- a/dot/trpl17-05.dot +++ b/dot/trpl17-05.dot @@ -1,42 +1,32 @@ digraph { - rankdir = LR; + rankdir = RL; + overlap = false; dpi = 300.0; + splines = false; + cluster = true; node [shape = "plaintext";]; - pinned_box [label = < - - -
Pin
>;]; - - subgraph cluster_box { - label = ""; - peripheries = 0; + // Group the two together, which results in the desired alignment. + subgraph { + // But don't show the frame! + style = "invis"; - subgraph cluster_box_internal { - peripheries = 1; - label = "b1"; - shape = box; - style = solid; - pin [shape = "point";]; - } - } - - subgraph cluster_deref { - style = bold; - label = "pinned"; + fut1 [label = < + + + + +
fut1
?
?
?
>;]; - box [label = < - - + fut2 [label = <
fut
0
+ + + - -
fut2
0
1
...
1
>;]; + + edge [tailclip = "false"; dir = forward]; + fut2:source:c -> fut1:target:e; } - - edge [tailclip = false;]; - pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; - pin -> box [headport = "target";]; - box -> box [tailport = "source:c"; headport = "internal";]; } \ No newline at end of file diff --git a/dot/trpl17-06.dot b/dot/trpl17-06.dot index 11b79574c4..e036a385c3 100644 --- a/dot/trpl17-06.dot +++ b/dot/trpl17-06.dot @@ -1,50 +1,32 @@ digraph { rankdir = LR; - newrank = true; dpi = 300.0; node [shape = "plaintext";]; + pinned_box [label = < + + +
Pin
>;]; - subgraph cluster_not_fut { + subgraph cluster_box { + label = ""; peripheries = 0; - pin [label = < - - -
Pin
>;]; - - subgraph cluster_boxes { - peripheries = 0; - rank = same; - - subgraph cluster_box_1 { - subgraph cluster_box_2_internal { - label = "b1"; - shape = box; - style = solid; - style = filled; - peripheries = 1; - box1 [shape = "point";style = "invis";]; - } - } - - subgraph cluster_box_2 { - subgraph cluster_box_2_internal { - label = "b2"; - shape = box; - style = solid; - peripheries = 1; - box2 [shape = "point";]; - } - } + subgraph cluster_box_internal { + peripheries = 1; + label = "b1"; + shape = box; + style = solid; + pin [shape = "point";]; } } - subgraph cluster_target { + + subgraph cluster_deref { style = bold; label = "pinned"; - fut [label = < + box [label = <
@@ -53,12 +35,8 @@ digraph {
fut
0
>;]; } - - box1 -> box2 [rankdir = TB; style = invis;]; - edge [tailclip = false;]; - pin -> box1 [style = "invis";]; - pin -> box2 [tailport = "source:c"; arrowhead = "none";]; - box2 -> fut [headport = "target";]; - fut -> fut [tailport = "source:c"; headport = "internal";]; + pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; + pin -> box [headport = "target";]; + box -> box [tailport = "source:c"; headport = "internal";]; } \ No newline at end of file diff --git a/dot/trpl17-07.dot b/dot/trpl17-07.dot index 8e9897f46d..11b79574c4 100644 --- a/dot/trpl17-07.dot +++ b/dot/trpl17-07.dot @@ -1,39 +1,64 @@ digraph { rankdir = LR; - overlap = false; - dpi = 300.0; - splines = false; - cluster = true; newrank = true; - outputorder = in; - compound = true; - labelloc = "c"; + dpi = 300.0; node [shape = "plaintext";]; - pinned_box [label = < - - -
Pin
>;]; - - subgraph cluster_deref { - style = dashed; - label = "String"; + subgraph cluster_not_fut { + peripheries = 0; + + pin [label = < + + +
Pin
>;]; - pin [shape = "point";]; + subgraph cluster_boxes { + peripheries = 0; + rank = same; + + subgraph cluster_box_1 { + subgraph cluster_box_2_internal { + label = "b1"; + shape = box; + style = solid; + style = filled; + peripheries = 1; + box1 [shape = "point";style = "invis";]; + } + } + + subgraph cluster_box_2 { + subgraph cluster_box_2_internal { + label = "b2"; + shape = box; + style = solid; + peripheries = 1; + box2 [shape = "point";]; + } + } + } + } + subgraph cluster_target { + style = bold; + label = "pinned"; fut [label = < - - - - - - + + + + +
5usizehello
fut
0
...
1
>;]; } + + box1 -> box2 [rankdir = TB; style = invis;]; + edge [tailclip = false;]; - pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; - pin -> fut [headport = "target";]; + pin -> box1 [style = "invis";]; + pin -> box2 [tailport = "source:c"; arrowhead = "none";]; + box2 -> fut [headport = "target";]; + fut -> fut [tailport = "source:c"; headport = "internal";]; } \ No newline at end of file diff --git a/dot/trpl17-08.dot b/dot/trpl17-08.dot index de73007511..8e9897f46d 100644 --- a/dot/trpl17-08.dot +++ b/dot/trpl17-08.dot @@ -16,47 +16,24 @@ digraph { >;]; - subgraph cluster_both { - peripheries = 0; - + + subgraph cluster_deref { + style = dashed; + label = "String"; + pin [shape = "point";]; - string1 [label = < - - - + fut [label = <
s1
5usize
+ - - +
5usize h e l lo
o
>;]; - - subgraph cluster_deref { - style = dashed; - label = "String"; - peripheries = 1; - - pin [shape = "point";]; - - string2 [label = < - - - - - - - - - - - -
s2
7usizegoodbye
>;]; - } } edge [tailclip = false;]; pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; - pin -> string2 [headport = "target";]; + pin -> fut [headport = "target";]; } \ No newline at end of file diff --git a/dot/trpl17-09.dot b/dot/trpl17-09.dot new file mode 100644 index 0000000000..de73007511 --- /dev/null +++ b/dot/trpl17-09.dot @@ -0,0 +1,62 @@ +digraph { + rankdir = LR; + overlap = false; + dpi = 300.0; + splines = false; + cluster = true; + newrank = true; + outputorder = in; + compound = true; + labelloc = "c"; + + node [shape = "plaintext";]; + + pinned_box [label = < + + +
Pin
>;]; + + subgraph cluster_both { + peripheries = 0; + + + + string1 [label = < + + + + + + + + + +
s1
5usizehello
>;]; + + subgraph cluster_deref { + style = dashed; + label = "String"; + peripheries = 1; + + pin [shape = "point";]; + + string2 [label = < + + + + + + + + + + + +
s2
7usizegoodbye
>;]; + } + } + + edge [tailclip = false;]; + pinned_box -> pin [tailport = "source:c"; arrowhead = "none";]; + pin -> string2 [headport = "target";]; +} \ No newline at end of file diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index 45757777d4..a8149cf5c6 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -89,7 +89,7 @@ tasks by switching between them. Concurrent work flow -Figure 17-1: A concurrent workflow, switching between Task A and Task B +Figure 17-1: A concurrent workflow, switching between Task A and Task B. When you agree to split up a group of tasks between the people on the team, with each person taking one task and working on it alone, this is *parallelism*. Each @@ -98,15 +98,21 @@ person on the team can make progress at the exact same time. Concurrent work flow Figure 17-2: A parallel workflow, where work happens on Task A and Task B -independently +independently. With both of these situations, you might have to coordinate between different 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 your own tasks depends -on another of your tasks. Now your concurrent work has also become serial. +after the other, as in Figure 17-3. + +Concurrent work flow + +Figure 17-3: A partially parallel workflow, where work happens on Task A and Task B independently until task A3 is blocked on the results of task B3. + +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. If you learn that a colleague is stuck until you finish one of your tasks, you’ll probably @@ -2601,13 +2607,13 @@ 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, as in Figure 17-3 (a simplified +themselves in the fields of any given variant, as in Figure 17-4 (a simplified illustration to help you get a feel for the idea, rather than digging into what are often fairly complicated details). -Concurrent work flow +Concurrent work flow -Figure 17-3: A self-referential data type. +Figure 17-4: A self-referential data type. By default, though, any object which has a reference to itself is unsafe to move, because references always point to the actual memory address of the thing @@ -2618,9 +2624,9 @@ the data structure. For another—and more importantly!—the computer is now fr to reuse that memory for other things! You could end up reading completely unrelated data later. -Concurrent work flow +Concurrent work flow -Figure 17-4: The unsafe result of moving a self-referential data type. +Figure 17-5: The unsafe result of moving a self-referential data type. In principle, the Rust compiler could try to update every reference to an object every time it gets moved. That would potentially be a lot of performance @@ -2633,25 +2639,25 @@ 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 that value in `Pin`, it can no longer move. Thus, if you have `Pin>`, you actually pin the `SomeType` value, *not* -the `Box` pointer. Figure 17-5 illustrates this: +the `Box` pointer. Figure 17-6 illustrates this: -Concurrent work flow +Concurrent work flow -Figure 17-5: Pinning a `Box` which points to a self-referential future type. +Figure 17-6: Pinning a `Box` which points to a self-referential future type. In fact, the `Box` pointer can still 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, as in -Figure 17-6, there’s no potential problem. (How you would do this with a `Pin` +Figure 17-7, there’s no potential problem. (How you would do this with a `Pin` wrapping a `Box` is more than we’ll get into in this particular discussion, but it would make for a good exercise! If you look at the docs for the types as well as the `std::pin` module, you might be able to work out how you would do that.) The key is that the self-referential type itself cannot move, because it is still pinned. -Concurrent work flow +Concurrent work flow -Figure 17-6: Moving a `Box` which points to a self-referential future type. +Figure 17-7: Moving a `Box` which points to a self-referential future type. 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 @@ -2683,19 +2689,19 @@ To make that concrete, think about a `String`: it has a length and the Unicode characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure 17-7. However -Concurrent work flow +Concurrent work flow -Figure 17-7: Pinning a String, with a dotted line indicating that the String +Figure 17-8: Pinning a String, with a dotted line indicating that the String implements the `Unpin` trait, so it is not pinned. This means that we can do things such as replace one string with another at the -exact same location in memory as in Figure 17-8. This doesn’t violate the `Pin` +exact same location in memory as in Figure 17-9. This doesn’t violate the `Pin` contract because `String`—like most other types in Rust—implements `Unpin`, because it has no internal references that make it unsafe to move around! -Concurrent work flow +Concurrent work flow -Figure 17-8: Replacing the String with an entirely different String in memory. +Figure 17-9: Replacing the String with an entirely different String in memory. Now we know enough to understand the errors reported for that `join_all` call from back in Listing 17-17. We originally tried to move the futures produced by diff --git a/src/ch17-00-async-await.md b/src/ch17-00-async-await.md index 920486d333..5fe7020224 100644 --- a/src/ch17-00-async-await.md +++ b/src/ch17-00-async-await.md @@ -89,7 +89,7 @@ tasks by switching between them. Concurrent work flow -
Figure 17-1: A concurrent workflow, switching between Task A and Task B
+
Figure 17-1: A concurrent workflow, switching between Task A and Task B.
@@ -101,7 +101,7 @@ person on the team can make progress at the exact same time. Concurrent work flow -
Figure 17-2: A parallel workflow, where work happens on Task A and Task B independently
+
Figure 17-2: A parallel workflow, where work happens on Task A and Task B independently.
@@ -110,8 +110,18 @@ 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 your own tasks depends -on another of your tasks. Now your concurrent work has also become serial. +after the other, as in Figure 17-3. + +
+ +Concurrent work flow + +
Figure 17-3: A partially parallel workflow, where work happens on Task A and Task B independently until task A3 is blocked on the results of task B3.
+ +
+ +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. If you learn that a colleague is stuck until you finish one of your tasks, you’ll probably diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index a7c5feee50..746264d861 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -224,15 +224,15 @@ 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, as in Figure 17-3 (a simplified +themselves in the fields of any given variant, as in Figure 17-4 (a simplified illustration to help you get a feel for the idea, rather than digging into what are often fairly complicated details).
-Concurrent work flow +Concurrent work flow -
Figure 17-3: A self-referential data type.
+
Figure 17-4: A self-referential data type.
@@ -247,9 +247,9 @@ unrelated data later.
-Concurrent work flow +Concurrent work flow -
Figure 17-4: The unsafe result of moving a self-referential data type.
+
Figure 17-5: The unsafe result of moving a self-referential data type.
@@ -264,20 +264,20 @@ 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 that value in `Pin`, it can no longer move. Thus, if you have `Pin>`, you actually pin the `SomeType` value, *not* -the `Box` pointer. Figure 17-5 illustrates this: +the `Box` pointer. Figure 17-6 illustrates this:
-Concurrent work flow +Concurrent work flow -
Figure 17-5: Pinning a `Box` which points to a self-referential future type.
+
Figure 17-6: Pinning a `Box` which points to a self-referential future type.
In fact, the `Box` pointer can still 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, as in -Figure 17-6, there’s no potential problem. (How you would do this with a `Pin` +Figure 17-7, there’s no potential problem. (How you would do this with a `Pin` wrapping a `Box` is more than we’ll get into in this particular discussion, but it would make for a good exercise! If you look at the docs for the types as well as the `std::pin` module, you might be able to work out how you would do @@ -286,9 +286,9 @@ is still pinned.
-Concurrent work flow +Concurrent work flow -
Figure 17-6: Moving a `Box` which points to a self-referential future type.
+
Figure 17-7: Moving a `Box` which points to a self-referential future type.
@@ -323,22 +323,22 @@ characters which make it up. We can wrap a `String` in `Pin`, as seen in Figure
-Concurrent work flow +Concurrent work flow -
Figure 17-7: Pinning a String, with a dotted line indicating that the String implements the `Unpin` trait, so it is not pinned.
+
Figure 17-8: Pinning a String, with a dotted line indicating that the String implements the `Unpin` trait, so it is not pinned.
This means that we can do things such as replace one string with another at the -exact same location in memory as in Figure 17-8. This doesn’t violate the `Pin` +exact same location in memory as in Figure 17-9. This doesn’t violate the `Pin` contract because `String`—like most other types in Rust—implements `Unpin`, because it has no internal references that make it unsafe to move around!
-Concurrent work flow +Concurrent work flow -
Figure 17-8: Replacing the String with an entirely different String in memory.
+
Figure 17-9: Replacing the String with an entirely different String in memory.
diff --git a/src/img/trpl17-03.svg b/src/img/trpl17-03.svg index fed6c36040..ad105a5830 100644 --- a/src/img/trpl17-03.svg +++ b/src/img/trpl17-03.svg @@ -1,30 +1,110 @@ - - - - - + + + + +cluster_ColleagueB + +Task A + + +cluster_ColleagueA + +Task B + + -fut1 - -fut1 - -0 - -1 - -   - - +A1 + +A1 + + + +A2 + +A2 + + -fut1:c->fut1:target - - +A1->A2 + + + + + + +A2->A0_1:c + + + + + + +A3 + +A3 + + + +A0_1->A3 + + + + + + + +B1 + +B1 + + + +B2 + +B2 + + + +B1->B2 + + + + + +B3 + +B3 + + + +B2->B3 + + + + + +B3->A3 + + + + + +B4 + +B4 + + + +B3->B4 + + From a64884fb8b8011840c291168d1ab26c0b0886749 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 7 Oct 2024 13:57:33 -0600 Subject: [PATCH 235/249] =?UTF-8?q?Ch.=2017:=20kill=20a=20double-=E2=80=9C?= =?UTF-8?q?thus=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nostarch/chapter17.md | 8 ++++---- src/ch17-01-futures-and-syntax.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index a8149cf5c6..ad633688d1 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -301,10 +301,10 @@ some code in `main` to call it, let’s talk a little more about what we’ve written and what it means. 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. +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. An async function’s return type is the type of the of +the anonymous data type the compiler creates for that async block. Thus, writing `async fn` is equivalent to writing a function which returns a *future* of the return type. When the compiler sees a function definition such diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 2799ff3276..6edade4551 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -146,10 +146,10 @@ some code in `main` to call it, let’s talk a little more about what we’ve written and what it means. 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. +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. An async function’s return type is the type of the +anonymous data type the compiler creates for that async block. Thus, writing `async fn` is equivalent to writing a function which returns a *future* of the return type. When the compiler sees a function definition such From 8aee93d82d18477e8c0290eda2f4b00852c88d7a Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 7 Oct 2024 13:57:33 -0600 Subject: [PATCH 236/249] Ch. 17: include `main` when first showing `trpl::run` This gives people a better chance of understanding how the pieces fit together. --- listings/ch17-async-await/listing-17-04/src/main.rs | 4 ++-- nostarch/chapter17.md | 4 ++++ 2 files changed, 6 insertions(+), 2 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 dbc0d4c6e1..23b2ea99f0 100644 --- a/listings/ch17-async-await/listing-17-04/src/main.rs +++ b/listings/ch17-async-await/listing-17-04/src/main.rs @@ -2,10 +2,10 @@ extern crate trpl; // required for mdbook test use trpl::Html; +// ANCHOR: run fn main() { let args: Vec = std::env::args().collect(); - // ANCHOR: run trpl::run(async { let url = &args[1]; match page_title(url).await { @@ -13,8 +13,8 @@ fn main() { None => println!("{url} had no title"), } }) - // ANCHOR_END: run } +// ANCHOR_END: run async fn page_title(url: &str) -> Option { let response_text = trpl::get(url).await.text().await; diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index ad633688d1..35ca15f610 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -417,6 +417,9 @@ await the result of calling `page_title`, as in Listing 17-4. Filename: src/main.rs ``` +fn main() { + let args: Vec = std::env::args().collect(); + trpl::run(async { let url = &args[1]; match page_title(url).await { @@ -424,6 +427,7 @@ Filename: src/main.rs None => println!("{url} had no title"), } }) +} ``` Listing 17-4: Awaiting an async block with `trpl::run` From f45980afda19546ea29879ec9bd9aac84d6aeeb8 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 7 Oct 2024 14:24:34 -0600 Subject: [PATCH 237/249] Ch. 17: get rid of some extra italics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These made more sense when this section was all about big ideas and the runtimes; now it’s needless since we actually spent the section building something non-trivial. --- nostarch/chapter17.md | 2 +- src/ch17-01-futures-and-syntax.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index 35ca15f610..8055982cb9 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -567,7 +567,7 @@ You have built a small working web scraper now! 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. More importantly, you’ve learned the basics of working with futures, so we can now -dig into even more of the things we can *do* with async. +dig into even more of the things we can do with async. ## Concurrency With Async diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md index 6edade4551..a82366f7f3 100644 --- a/src/ch17-01-futures-and-syntax.md +++ b/src/ch17-01-futures-and-syntax.md @@ -369,7 +369,7 @@ You have built a small working web scraper now! 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. More importantly, you’ve learned the basics of working with futures, so we can now -dig into even more of the things we can *do* with async. +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 From 7076be0692052f578dfb3e819c42b644202cd403 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 8 Oct 2024 08:09:29 -0600 Subject: [PATCH 238/249] Ch. 17: improve the discussion of streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - One example compiles that I used to think didn’t. Probably the result of some renumbering. Need to check *all* of those. - Don’t repeat the same basic “you ” form so much. --- nostarch/chapter17.md | 50 +++++++++++++++++++++--------------------- src/ch17-04-streams.md | 48 +++++++++++++++++++--------------------- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index 8055982cb9..dbb4296914 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -1899,21 +1899,20 @@ help: there is a method `try_next` with a similar name For more information about this error, try `rustc --explain E0599`. ``` -As the output suggests, the problem is that we need the right trait in scope to -be able to use the `next` method. Given our discussion so far, you might -reasonably expect that to be `Stream`, but the trait we need *here* is actually -`StreamExt`. The `Ext` there is for “extension”: this is a common pattern in -the Rust community for extending one trait with another. - -You might be wondering why `StreamExt` instead of `Stream`, and for that matter -whether there is a `Stream` trait at all. Briefly, the answer is that throughout -the Rust ecosystem, the `Stream` trait defines a low-level interface which -effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait -supplies a higher-level set of APIs on top of `Stream`, including the `next` -method as well as other utility methods similar to those provided by the -`Iterator` trait. We’ll 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. +As the output suggests, the reason for the compiler error is that we need the +right trait in scope to be able to use the `next` method. Given our discussion +so far, you might reasonably expect that to be `Stream`, but the trait we need +here is actually `StreamExt`. The `Ext` there is for “extension”: this is a +common pattern in the Rust community for extending one trait with another. + +Why do we need `StreamExt` instead of `Stream`, and what does the `Stream` trait +itself do? Briefly, the answer is that throughout the Rust ecosystem, the +`Stream` trait defines a low-level interface which effectively combines the +`Iterator` and `Future` traits. The `StreamExt` trait supplies a higher-level +set of APIs on top of `Stream`, including the `next` method as well as other +utility methods similar to those provided by the `Iterator` trait. We’ll 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. The fix to the compiler error is to add a `use` statement for `trpl::StreamExt`, as in Listing 17-31. @@ -2109,13 +2108,13 @@ Listing 17-35: Sending messages through `tx` with an async delay without making To sleep between messages in the `get_messages` function without blocking, we need to use async. However, we can’t make `get_messages` itself into an async function, because then we’d 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, 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 of 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, 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. @@ -2557,9 +2556,10 @@ pub trait Future { } ``` -The `cx` parameter and its `Context` type is interesting, but is beyond the -scope of this chapter: you generally only need to worry about it when writing a -custom `Future` implementation. +The `cx` parameter and its `Context` type is the key to how a runtime actually +knows when to check any given future, while still being lazy. The details of how +that works are beyond the scope of this chapter, though: you generally only need +to worry about it when writing a custom `Future` implementation. Instead, we’ll focus on the type for `self`. This is the first time we’ve seen a method where `self` has a type annotation. A type annotation for `self` is diff --git a/src/ch17-04-streams.md b/src/ch17-04-streams.md index 7bcc24ee4e..a3085aa62a 100644 --- a/src/ch17-04-streams.md +++ b/src/ch17-04-streams.md @@ -74,28 +74,27 @@ help: there is a method `try_next` with a similar name For more information about this error, try `rustc --explain E0599`. ``` -As the output suggests, the problem is that we need the right trait in scope to -be able to use the `next` method. Given our discussion so far, you might -reasonably expect that to be `Stream`, but the trait we need *here* is actually -`StreamExt`. The `Ext` there is for “extension”: this is a common pattern in -the Rust community for extending one trait with another. - -You might be wondering why `StreamExt` instead of `Stream`, and for that matter -whether there is a `Stream` trait at all. Briefly, the answer is that throughout -the Rust ecosystem, the `Stream` trait defines a low-level interface which -effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait -supplies a higher-level set of APIs on top of `Stream`, including the `next` -method as well as other utility methods similar to those provided by the -`Iterator` trait. We’ll 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. +As the output suggests, the reason for the compiler error is that we need the +right trait in scope to be able to use the `next` method. Given our discussion +so far, you might reasonably expect that to be `Stream`, but the trait we need +here is actually `StreamExt`. The `Ext` there is for “extension”: this is a +common pattern in the Rust community for extending one trait with another. + +Why do we need `StreamExt` instead of `Stream`, and what does the `Stream` trait +itself do? Briefly, the answer is that throughout the Rust ecosystem, the +`Stream` trait defines a low-level interface which effectively combines the +`Iterator` and `Future` traits. The `StreamExt` trait supplies a higher-level +set of APIs on top of `Stream`, including the `next` method as well as other +utility methods similar to those provided by the `Iterator` trait. We’ll 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. The fix to the compiler error is to add a `use` statement for `trpl::StreamExt`, as in Listing 17-31. -```rust,ignore,does_not_compile +```rust {{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs:all}} ``` @@ -208,15 +207,14 @@ for 200 milliseconds, this should affect half of the messages. To sleep between messages in the `get_messages` function without blocking, we need to use async. However, we can’t make `get_messages` itself into an async -function, because then we’d 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, -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. +function, because then we’d return a `Future>` +instead of 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, 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. From 3b920cdf3bceec5868b05467467423765de79753 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 8 Oct 2024 08:09:29 -0600 Subject: [PATCH 239/249] Ch. 17: tweaks and fixes for discussion of the traits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix the numbers on the SVG files so they match up again after having added a new 17-3 earlier in the chapter. - Actually explain what `Context` is *for*, even though we don’t get into the details of using it. --- nostarch/chapter17.md | 2 +- src/ch17-05-traits-for-async.md | 19 +++--- src/img/trpl17-04.svg | 48 +++++--------- src/img/trpl17-05.svg | 85 +++++++++--------------- src/img/trpl17-06.svg | 111 ++++++++++++++------------------ src/img/trpl17-07.svg | 107 +++++++++++++++++++----------- src/img/trpl17-08.svg | 94 ++++++++++----------------- src/img/trpl17-09.svg | 85 ++++++++++++++++++++++++ 8 files changed, 291 insertions(+), 260 deletions(-) create mode 100644 src/img/trpl17-09.svg diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index dbb4296914..612740c2cb 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -2675,7 +2675,7 @@ via the safe but restrictive APIs provided by `Pin`, even though a need a way to tell the compiler that it’s actually just fine to move items around in cases such as these. For that, we have `Unpin`. -`Unpin` is a marker trait, as `Send` and `Sync` are, which we saw in the +`Unpin` is a marker trait, similar to the `Send` and `Sync` traits we saw in the “Extensible Concurrency with the `Sync` and `Send` Traits” section of Chapter 16 on page XX. Recall that marker traits have no functionality of their own. They exist only to tell the compiler that it’s safe to use the type which diff --git a/src/ch17-05-traits-for-async.md b/src/ch17-05-traits-for-async.md index 746264d861..c7c82d8711 100644 --- a/src/ch17-05-traits-for-async.md +++ b/src/ch17-05-traits-for-async.md @@ -172,9 +172,10 @@ pub trait Future { } ``` -The `cx` parameter and its `Context` type is interesting, but is beyond the -scope of this chapter: you generally only need to worry about it when writing a -custom `Future` implementation. +The `cx` parameter and its `Context` type is the key to how a runtime actually +knows when to check any given future, while still being lazy. The details of how +that works are beyond the scope of this chapter, though: you generally only need +to worry about it when writing a custom `Future` implementation. Instead, we’ll focus on the type for `self`. This is the first time we’ve seen a method where `self` has a type annotation. A type annotation for `self` is @@ -304,12 +305,12 @@ via the safe but restrictive APIs provided by `Pin`, even though a need a way to tell the compiler that it’s actually just fine to move items around in cases such as these. For that, we have `Unpin`. -`Unpin` is a marker trait, as `Send` and `Sync` are, 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’s 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. +`Unpin` is a marker trait, similar to the `Send` and `Sync` traits we saw in +Chapter 16. Recall that marker traits have no functionality of their own. They +exist only to tell the compiler that it’s 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 as with `Send` and `Sync`, the compiler implements `Unpin` automatically for all types where it can prove it is safe. Implementing `Unpin` manually is diff --git a/src/img/trpl17-04.svg b/src/img/trpl17-04.svg index e3472baa7c..fed6c36040 100644 --- a/src/img/trpl17-04.svg +++ b/src/img/trpl17-04.svg @@ -4,43 +4,27 @@ - - - - -%3 - + + + fut1 - - -fut1 - -? - -? - -? - - - -fut2 - -fut2 - -0 - -1 - - + +fut1 + +0 + +1 + +   - + -fut2:c->fut1:c - - +fut1:c->fut1:target + + diff --git a/src/img/trpl17-05.svg b/src/img/trpl17-05.svg index 443bb568dc..e3472baa7c 100644 --- a/src/img/trpl17-05.svg +++ b/src/img/trpl17-05.svg @@ -5,65 +5,42 @@ --> - - + viewBox="0.00 0.00 767.00 575.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + + -cluster_box +%3 - -cluster_box_internal - -b1 - - -cluster_deref - -pinned - - + -pinned_box - -Pin - - - - +fut1 + + +fut1 + +? + +? + +? + + -pin - - - +fut2 + +fut2 + +0 + +1 + + + + -pinned_box:c->pin - - - - -box - -fut - -0 - - - -... - -1 - - - -pin->box:target - - - - - -box:c->box:internal - - +fut2:c->fut1:c + + diff --git a/src/img/trpl17-06.svg b/src/img/trpl17-06.svg index 712e3006f6..443bb568dc 100644 --- a/src/img/trpl17-06.svg +++ b/src/img/trpl17-06.svg @@ -4,83 +4,66 @@ - - - + + + -cluster_not_fut +cluster_box -cluster_boxes +cluster_box_internal + +b1 -cluster_box_1 +cluster_deref + +pinned - -cluster_box_2_internal - -b1 - - -cluster_box_2 - - -cluster_box_2_internal - -b2 - - -cluster_target - -pinned + + +pinned_box + +Pin + + - + pin - -Pin - - + - - - - -box2 - - - - -pin:c->box2 - + + +pinned_box:c->pin + - - - -fut - -fut - -0 - - - -... - -1 + + +box + +fut + +0 + + + +... + +1 - - -box2->fut:target - - + + +pin->box:target + + - - -fut:c->fut:internal - - + + +box:c->box:internal + + diff --git a/src/img/trpl17-07.svg b/src/img/trpl17-07.svg index b2275ac19f..712e3006f6 100644 --- a/src/img/trpl17-07.svg +++ b/src/img/trpl17-07.svg @@ -4,54 +4,83 @@ - - - + + + -cluster_deref - -String +cluster_not_fut - - -pinned_box - -Pin - - + +cluster_boxes + + +cluster_box_1 + + +cluster_box_2_internal + +b1 + + +cluster_box_2 + + +cluster_box_2_internal + +b2 + + +cluster_target + +pinned - + pin - + +Pin + + + + + + + +box2 + - - -pinned_box:c->pin - + + +pin:c->box2 + + - + fut - -5usize - -h - -e - -l - -l - -o - - - -pin->fut:target - - + +fut + +0 + + + +... + +1 + + + +box2->fut:target + + + + + +fut:c->fut:internal + + diff --git a/src/img/trpl17-08.svg b/src/img/trpl17-08.svg index 997d9b82e1..b2275ac19f 100644 --- a/src/img/trpl17-08.svg +++ b/src/img/trpl17-08.svg @@ -4,82 +4,54 @@ - - - + + + -cluster_both - - cluster_deref - -String + +String pinned_box - -Pin - - + +Pin + + - + pin - + pinned_box:c->pin - + - - -string1 - - -s1 - -5usize - -h - -e - -l - -l - -o - - - -string2 - -s2 - -7usize - -g - -o - -o - -d - -b - -y - -e - - + + +fut + +5usize + +h + +e + +l + +l + +o + + -pin->string2:target - - +pin->fut:target + + diff --git a/src/img/trpl17-09.svg b/src/img/trpl17-09.svg new file mode 100644 index 0000000000..997d9b82e1 --- /dev/null +++ b/src/img/trpl17-09.svg @@ -0,0 +1,85 @@ + + + + + + + + +cluster_both + + +cluster_deref + +String + + + +pinned_box + +Pin + + + + + +pin + + + + +pinned_box:c->pin + + + + +string1 + + +s1 + +5usize + +h + +e + +l + +l + +o + + + +string2 + +s2 + +7usize + +g + +o + +o + +d + +b + +y + +e + + + +pin->string2:target + + + + + From 1af831aa5e80534d82a13998038630598d85ee2e Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 8 Oct 2024 08:09:29 -0600 Subject: [PATCH 240/249] Ch. 17: Fix a lot of wording issues in the conclusion section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So many “however” sections! Etc. --- nostarch/chapter17.md | 72 ++++++++++++++-------------- src/ch17-06-futures-tasks-threads.md | 70 +++++++++++++-------------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/nostarch/chapter17.md b/nostarch/chapter17.md index 612740c2cb..af8698283c 100644 --- a/nostarch/chapter17.md +++ b/nostarch/chapter17.md @@ -2850,9 +2850,9 @@ have threads! The async model provides a different—and ultimately complementary—set of tradeoffs. In the async model, concurrent operations don’t require their own threads. Instead, they can run on tasks, as when we used `trpl::spawn_task` to -kick off work from a synchronous function throughout the streams section. A -*task* is similar to a thread—but instead of being managed by the operating -system, it’s managed by library-level code: the runtime. +kick off work from a synchronous function throughout the streams section. A task +is similar to a thread, but instead of being managed by the operating system, +it’s 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 @@ -2894,41 +2894,41 @@ from the perspective of the calling code! What’s more, even though one of our functions spawned an async task on the runtime and the other spawned an OS thread, the resulting streams were unaffected by the differences. -However, there’s a significant difference between how these two approaches -behave, although we might have a hard time measuring it in this very simple -example. We could spawn hundreds of thousands or even millions of async tasks -on any modern personal computer. If we tried to do that with threads, we would -literally run out of memory! +Despite the similarities, these two approaches behave very differently, although +we might have a hard time measuring it in this very simple example. We could +spawn millions of async tasks on any modern personal computer. If we tried to do +that with threads, we would literally run out of memory! However, there’s a reason these APIs are so similar. Threads act as a boundary for sets of synchronous operations; concurrency is possible *between* threads. Tasks act as a boundary for sets of *asynchronous* operations; concurrency is -possible both *between* and *within* tasks. In that regard, tasks are similar to -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. That is, the runtime—specifically, its executor—manages tasks, -and tasks manage futures. - -However, this doesn’t 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,” -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* the way futures can. Threads in Rust also have no -mechanisms for cancellation—a subject we haven’t 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’s much more -difficult, for example, to build something similar to the `timeout` we built in -the “Building Our Own Async Abstractions” section of this chapter on page XX, -or the `throttle` method we used with streams in the “Composing Streams” -section of this chapter on page XX. The fact that futures are richer data -structures means they *can* be composed together more naturally, as we have -seen. +possible both *between* and *within* tasks, because a task can switch between +futures in its body. Finally, futures are Rust’s most granular unit of +concurrency, and each future may represent a tree of other futures. The +runtime—specifically, its executor—manages tasks, and tasks manage futures. In +that regard, tasks are similar to lightweight, runtime-managed threads with +added capabilities that come from being managed by a runtime instead of by the +operating system. + +This doesn’t mean that async tasks are always better than threads, any more than +that threads are always better than tasks. + +Concurrency with threads is in some ways a simpler programming model than +concurrency with `async`. That can be a strength or a weakness. 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 built-in support for *intra-task concurrency* the +way futures do. Threads in Rust also have no mechanisms for cancellation—a +subject we haven’t 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 also make threads harder to compose than futures. It’s much +more difficult, for example, to use threads to build helpers such as the +`timeout` we built in the “Building Our Own Async Abstractions” section of this +chapter on page XX or the `throttle` method we used with streams in the +“Composing Streams” section of this chapter on page XX. The fact that futures +are richer data structures means they can be composed together more naturally, +as we have seen. Tasks then give *additional* control over futures, allowing you to choose where and how to group the futures. And it turns out that threads and tasks often @@ -2938,8 +2938,8 @@ hood the `Runtime` we have been using, including the `spawn_blocking` and `spawn_task` 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. +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: diff --git a/src/ch17-06-futures-tasks-threads.md b/src/ch17-06-futures-tasks-threads.md index 21556b658c..bda6177385 100644 --- a/src/ch17-06-futures-tasks-threads.md +++ b/src/ch17-06-futures-tasks-threads.md @@ -18,9 +18,9 @@ have threads! The async model provides a different—and ultimately complementary—set of tradeoffs. In the async model, concurrent operations don’t require their own threads. Instead, they can run on tasks, as when we used `trpl::spawn_task` to -kick off work from a synchronous function throughout the streams section. A -*task* is similar to a thread—but instead of being managed by the operating -system, it’s managed by library-level code: the runtime. +kick off work from a synchronous function throughout the streams section. A task +is similar to a thread, but instead of being managed by the operating system, +it’s 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 @@ -42,40 +42,40 @@ from the perspective of the calling code! What’s more, even though one of our functions spawned an async task on the runtime and the other spawned an OS thread, the resulting streams were unaffected by the differences. -However, there’s a significant difference between how these two approaches -behave, although we might have a hard time measuring it in this very simple -example. We could spawn hundreds of thousands or even millions of async tasks -on any modern personal computer. If we tried to do that with threads, we would -literally run out of memory! +Despite the similarities, these two approaches behave very differently, although +we might have a hard time measuring it in this very simple example. We could +spawn millions of async tasks on any modern personal computer. If we tried to do +that with threads, we would literally run out of memory! However, there’s a reason these APIs are so similar. Threads act as a boundary for sets of synchronous operations; concurrency is possible *between* threads. Tasks act as a boundary for sets of *asynchronous* operations; concurrency is -possible both *between* and *within* tasks. In that regard, tasks are similar to -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. That is, the runtime—specifically, its executor—manages tasks, -and tasks manage futures. - -However, this doesn’t 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,” -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* the way futures can. Threads in Rust also have no -mechanisms for cancellation—a subject we haven’t 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’s much more -difficult, for example, to build something similar to the `timeout` we built in -[“Building Our Own Async Abstractions”][combining-futures], or the `throttle` -method we used with streams in [“Composing Streams”][streams]. The fact that -futures are richer data structures means they *can* be composed together more -naturally, as we have seen. +possible both *between* and *within* tasks, because a task can switch between +futures in its body. Finally, futures are Rust’s most granular unit of +concurrency, and each future may represent a tree of other futures. The +runtime—specifically, its executor—manages tasks, and tasks manage futures. In +that regard, tasks are similar to lightweight, runtime-managed threads with +added capabilities that come from being managed by a runtime instead of by the +operating system. + +This doesn’t mean that async tasks are always better than threads, any more than +that threads are always better than tasks. + +Concurrency with threads is in some ways a simpler programming model than +concurrency with `async`. That can be a strength or a weakness. 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 built-in support for *intra-task concurrency* the +way futures do. Threads in Rust also have no mechanisms for cancellation—a +subject we haven’t 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 also make threads harder to compose than futures. It’s much +more difficult, for example, to use threads to build helpers such as the +`timeout` we built in [“Building Our Own Async Abstractions”][combining-futures] +or the `throttle` method we used with streams in [“Composing Streams”][streams]. +The fact that futures are richer data structures means they can be composed +together more naturally, as we have seen. Tasks then give *additional* control over futures, allowing you to choose where and how to group the futures. And it turns out that threads and tasks often @@ -85,8 +85,8 @@ hood the `Runtime` we have been using, including the `spawn_blocking` and `spawn_task` 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. +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: From 887694bfde68cb685eefb74cfc5722097b8b6880 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 8 Oct 2024 08:09:29 -0600 Subject: [PATCH 241/249] Ch. 17: update all the listing lock files --- .../ch17-async-await/listing-17-01/Cargo.lock | 2 +- .../ch17-async-await/listing-17-02/Cargo.lock | 2 +- .../ch17-async-await/listing-17-03/Cargo.lock | 16 +- .../ch17-async-await/listing-17-04/Cargo.lock | 16 +- .../ch17-async-await/listing-17-05/Cargo.lock | 16 +- .../ch17-async-await/listing-17-06/Cargo.lock | 2 +- .../ch17-async-await/listing-17-07/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-08/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-09/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-10/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-11/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-12/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-13/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-14/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-15/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-16/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-17/Cargo.lock | 1653 +++++++++++++++- .../ch17-async-await/listing-17-18/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-19/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-20/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-21/Cargo.lock | 1625 ++++++++++++++-- .../ch17-async-await/listing-17-22/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-23/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-24/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-25/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-26/Cargo.lock | 1625 ++++++++++++++-- .../ch17-async-await/listing-17-27/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-28/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-29/Cargo.lock | 2 +- .../ch17-async-await/listing-17-30/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-31/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-32/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-33/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-34/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-35/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-36/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-37/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-38/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-39/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-40/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-41/Cargo.lock | 1663 ++++++++++++++++- .../ch17-async-await/listing-17-42/Cargo.lock | 2 +- .../no-listing-state-machine/Cargo.lock | 2 +- 43 files changed, 53941 insertions(+), 2575 deletions(-) diff --git a/listings/ch17-async-await/listing-17-01/Cargo.lock b/listings/ch17-async-await/listing-17-01/Cargo.lock index 1109eb84f5..4ee6b7a268 100644 --- a/listings/ch17-async-await/listing-17-01/Cargo.lock +++ b/listings/ch17-async-await/listing-17-01/Cargo.lock @@ -1484,7 +1484,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/listing-17-02/Cargo.lock b/listings/ch17-async-await/listing-17-02/Cargo.lock index 1bd5f08c34..9a37f621b1 100644 --- a/listings/ch17-async-await/listing-17-02/Cargo.lock +++ b/listings/ch17-async-await/listing-17-02/Cargo.lock @@ -1484,7 +1484,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/listing-17-03/Cargo.lock b/listings/ch17-async-await/listing-17-03/Cargo.lock index cb7d407618..9a37f621b1 100644 --- a/listings/ch17-async-await/listing-17-03/Cargo.lock +++ b/listings/ch17-async-await/listing-17-03/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" @@ -1484,7 +1484,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/listing-17-04/Cargo.lock b/listings/ch17-async-await/listing-17-04/Cargo.lock index cb7d407618..9a37f621b1 100644 --- a/listings/ch17-async-await/listing-17-04/Cargo.lock +++ b/listings/ch17-async-await/listing-17-04/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" @@ -1484,7 +1484,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/listing-17-05/Cargo.lock b/listings/ch17-async-await/listing-17-05/Cargo.lock index cb7d407618..9a37f621b1 100644 --- a/listings/ch17-async-await/listing-17-05/Cargo.lock +++ b/listings/ch17-async-await/listing-17-05/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" @@ -1484,7 +1484,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/listing-17-06/Cargo.lock b/listings/ch17-async-await/listing-17-06/Cargo.lock index a55aeb1e1c..0be7d2c88b 100644 --- a/listings/ch17-async-await/listing-17-06/Cargo.lock +++ b/listings/ch17-async-await/listing-17-06/Cargo.lock @@ -1485,7 +1485,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/listing-17-07/Cargo.lock b/listings/ch17-async-await/listing-17-07/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-07/Cargo.lock +++ b/listings/ch17-async-await/listing-17-07/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-08/Cargo.lock b/listings/ch17-async-await/listing-17-08/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-08/Cargo.lock +++ b/listings/ch17-async-await/listing-17-08/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-09/Cargo.lock b/listings/ch17-async-await/listing-17-09/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-09/Cargo.lock +++ b/listings/ch17-async-await/listing-17-09/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-10/Cargo.lock b/listings/ch17-async-await/listing-17-10/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-10/Cargo.lock +++ b/listings/ch17-async-await/listing-17-10/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-11/Cargo.lock b/listings/ch17-async-await/listing-17-11/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-11/Cargo.lock +++ b/listings/ch17-async-await/listing-17-11/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-12/Cargo.lock b/listings/ch17-async-await/listing-17-12/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-12/Cargo.lock +++ b/listings/ch17-async-await/listing-17-12/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-13/Cargo.lock b/listings/ch17-async-await/listing-17-13/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-13/Cargo.lock +++ b/listings/ch17-async-await/listing-17-13/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-14/Cargo.lock b/listings/ch17-async-await/listing-17-14/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-14/Cargo.lock +++ b/listings/ch17-async-await/listing-17-14/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-15/Cargo.lock b/listings/ch17-async-await/listing-17-15/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-15/Cargo.lock +++ b/listings/ch17-async-await/listing-17-15/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-16/Cargo.lock b/listings/ch17-async-await/listing-17-16/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-16/Cargo.lock +++ b/listings/ch17-async-await/listing-17-16/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-17/Cargo.lock b/listings/ch17-async-await/listing-17-17/Cargo.lock index c0e8bb2b3f..973206db69 100644 --- a/listings/ch17-async-await/listing-17-17/Cargo.lock +++ b/listings/ch17-async-await/listing-17-17/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,12 +337,66 @@ 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" 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.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -159,122 +404,1414 @@ 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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[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.82" +name = "hyper-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "unicode-ident", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] [[package]] -name = "slab" -version = "0.4.9" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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 = [ - "autocfg", + "wasm-bindgen", ] [[package]] -name = "syn" -version = "2.0.63" +name = "libc" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +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 = [ - "proc-macro2", - "quote", - "unicode-ident", + "autocfg", + "scopeguard", ] [[package]] -name = "tokio" -version = "1.37.0" +name = "log" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +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 = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", ] [[package]] -name = "trpl" -version = "0.1.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 = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ - "futures", - "tokio", + "adler", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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.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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-18/Cargo.lock b/listings/ch17-async-await/listing-17-18/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-18/Cargo.lock +++ b/listings/ch17-async-await/listing-17-18/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-19/Cargo.lock b/listings/ch17-async-await/listing-17-19/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-19/Cargo.lock +++ b/listings/ch17-async-await/listing-17-19/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-20/Cargo.lock b/listings/ch17-async-await/listing-17-20/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-20/Cargo.lock +++ b/listings/ch17-async-await/listing-17-20/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-21/Cargo.lock b/listings/ch17-async-await/listing-17-21/Cargo.lock index 3be4eaaa53..34598194f8 100644 --- a/listings/ch17-async-await/listing-17-21/Cargo.lock +++ b/listings/ch17-async-await/listing-17-21/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,17 +64,35 @@ 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.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.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" @@ -69,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" @@ -112,293 +291,1355 @@ dependencies = [ ] [[package]] -name = "futures-io" -version = "0.3.30" +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.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.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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 = "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 = "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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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.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.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-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.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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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", + "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 = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] [[package]] -name = "futures-macro" -version = "0.3.30" +name = "string_cache_codegen" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro2", "quote", - "syn", ] [[package]] -name = "futures-sink" -version = "0.3.30" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] -name = "futures-task" -version = "0.3.30" +name = "syn" +version = "2.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] -name = "futures-util" -version = "0.3.30" +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" 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.28.1" +name = "system-configuration" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "system-configuration-sys" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] -name = "libc" -version = "0.2.154" +name = "tempfile" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] [[package]] -name = "lock_api" -version = "0.4.12" +name = "tendril" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" dependencies = [ - "autocfg", - "scopeguard", + "futf", + "mac", + "utf-8", ] [[package]] -name = "memchr" -version = "2.7.2" +name = "tinyvec" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] [[package]] -name = "miniz_oxide" -version = "0.7.2" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", -] +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "mio" -version = "0.8.11" +name = "tokio" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ + "backtrace", + "bytes", "libc", - "wasi", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", "windows-sys 0.48.0", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "hermit-abi", - "libc", + "native-tls", + "tokio", ] [[package]] -name = "object" -version = "0.32.2" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "memchr", + "rustls", + "rustls-pki-types", + "tokio", ] [[package]] -name = "parking_lot" -version = "0.12.2" +name = "tokio-stream" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ - "lock_api", - "parking_lot_core", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] -name = "parking_lot_core" -version = "0.9.10" +name = "tokio-util" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.5", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "tower-service" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] -name = "pin-utils" -version = "0.1.0" +name = "tracing" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] [[package]] -name = "proc-macro2" -version = "1.0.82" +name = "tracing-core" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "unicode-ident", + "once_cell", ] [[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +name = "trpl" +version = "0.2.0" dependencies = [ - "proc-macro2", + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", ] [[package]] -name = "redox_syscall" -version = "0.5.1" +name = "try-lock" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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 = [ - "bitflags", + "tinyvec", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "unicode-width" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] -name = "scopeguard" -version = "1.2.0" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "signal-hook-registry" -version = "1.4.2" +name = "url" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ - "libc", + "form_urlencoded", + "idna", + "percent-encoding", ] [[package]] -name = "slab" -version = "0.4.9" +name = "utf-8" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +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 = [ - "autocfg", + "try-lock", ] [[package]] -name = "smallvec" -version = "1.13.2" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "socket2" -version = "0.5.7" +name = "wasm-bindgen" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ - "libc", - "windows-sys 0.52.0", + "cfg-if", + "once_cell", + "wasm-bindgen-macro", ] [[package]] -name = "syn" -version = "2.0.63" +name = "wasm-bindgen-backend" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ + "bumpalo", + "log", + "once_cell", "proc-macro2", "quote", - "unicode-ident", + "syn", + "wasm-bindgen-shared", ] [[package]] -name = "tokio" -version = "1.37.0" +name = "wasm-bindgen-futures" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "tokio-macros" -version = "2.2.0" +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 = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] -name = "trpl" -version = "0.1.0" +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 = [ - "futures", - "tokio", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "windows-registry" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "windows-result" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +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" @@ -415,7 +1656,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "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]] @@ -435,18 +1685,18 @@ dependencies = [ [[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 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "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.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "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]] @@ -457,9 +1707,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[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" @@ -469,9 +1719,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[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" @@ -481,15 +1731,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[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" @@ -499,9 +1749,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[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" @@ -511,9 +1761,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[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" @@ -523,9 +1773,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[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" @@ -535,6 +1785,33 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[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 = "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 = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-22/Cargo.lock b/listings/ch17-async-await/listing-17-22/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-22/Cargo.lock +++ b/listings/ch17-async-await/listing-17-22/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-23/Cargo.lock b/listings/ch17-async-await/listing-17-23/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-23/Cargo.lock +++ b/listings/ch17-async-await/listing-17-23/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-24/Cargo.lock b/listings/ch17-async-await/listing-17-24/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-24/Cargo.lock +++ b/listings/ch17-async-await/listing-17-24/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-25/Cargo.lock b/listings/ch17-async-await/listing-17-25/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-25/Cargo.lock +++ b/listings/ch17-async-await/listing-17-25/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-26/Cargo.lock b/listings/ch17-async-await/listing-17-26/Cargo.lock index 3be4eaaa53..34598194f8 100644 --- a/listings/ch17-async-await/listing-17-26/Cargo.lock +++ b/listings/ch17-async-await/listing-17-26/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,17 +64,35 @@ 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.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.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" @@ -69,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" @@ -112,293 +291,1355 @@ dependencies = [ ] [[package]] -name = "futures-io" -version = "0.3.30" +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.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.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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 = "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 = "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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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.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.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-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.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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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", + "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 = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] [[package]] -name = "futures-macro" -version = "0.3.30" +name = "string_cache_codegen" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro2", "quote", - "syn", ] [[package]] -name = "futures-sink" -version = "0.3.30" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] -name = "futures-task" -version = "0.3.30" +name = "syn" +version = "2.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] -name = "futures-util" -version = "0.3.30" +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" 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.28.1" +name = "system-configuration" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "system-configuration-sys" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] -name = "libc" -version = "0.2.154" +name = "tempfile" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] [[package]] -name = "lock_api" -version = "0.4.12" +name = "tendril" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" dependencies = [ - "autocfg", - "scopeguard", + "futf", + "mac", + "utf-8", ] [[package]] -name = "memchr" -version = "2.7.2" +name = "tinyvec" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] [[package]] -name = "miniz_oxide" -version = "0.7.2" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", -] +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "mio" -version = "0.8.11" +name = "tokio" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ + "backtrace", + "bytes", "libc", - "wasi", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", "windows-sys 0.48.0", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "hermit-abi", - "libc", + "native-tls", + "tokio", ] [[package]] -name = "object" -version = "0.32.2" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "memchr", + "rustls", + "rustls-pki-types", + "tokio", ] [[package]] -name = "parking_lot" -version = "0.12.2" +name = "tokio-stream" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ - "lock_api", - "parking_lot_core", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] -name = "parking_lot_core" -version = "0.9.10" +name = "tokio-util" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.5", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "tower-service" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] -name = "pin-utils" -version = "0.1.0" +name = "tracing" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] [[package]] -name = "proc-macro2" -version = "1.0.82" +name = "tracing-core" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "unicode-ident", + "once_cell", ] [[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +name = "trpl" +version = "0.2.0" dependencies = [ - "proc-macro2", + "futures", + "reqwest", + "scraper", + "tokio", + "tokio-stream", ] [[package]] -name = "redox_syscall" -version = "0.5.1" +name = "try-lock" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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 = [ - "bitflags", + "tinyvec", ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "unicode-width" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] -name = "scopeguard" -version = "1.2.0" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "signal-hook-registry" -version = "1.4.2" +name = "url" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ - "libc", + "form_urlencoded", + "idna", + "percent-encoding", ] [[package]] -name = "slab" -version = "0.4.9" +name = "utf-8" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +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 = [ - "autocfg", + "try-lock", ] [[package]] -name = "smallvec" -version = "1.13.2" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "socket2" -version = "0.5.7" +name = "wasm-bindgen" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ - "libc", - "windows-sys 0.52.0", + "cfg-if", + "once_cell", + "wasm-bindgen-macro", ] [[package]] -name = "syn" -version = "2.0.63" +name = "wasm-bindgen-backend" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ + "bumpalo", + "log", + "once_cell", "proc-macro2", "quote", - "unicode-ident", + "syn", + "wasm-bindgen-shared", ] [[package]] -name = "tokio" -version = "1.37.0" +name = "wasm-bindgen-futures" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "tokio-macros" -version = "2.2.0" +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 = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] -name = "trpl" -version = "0.1.0" +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 = [ - "futures", - "tokio", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "windows-registry" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "windows-result" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +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" @@ -415,7 +1656,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "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]] @@ -435,18 +1685,18 @@ dependencies = [ [[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 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "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.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "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]] @@ -457,9 +1707,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[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" @@ -469,9 +1719,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[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" @@ -481,15 +1731,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[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" @@ -499,9 +1749,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[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" @@ -511,9 +1761,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[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" @@ -523,9 +1773,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[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" @@ -535,6 +1785,33 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[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 = "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 = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/listings/ch17-async-await/listing-17-27/Cargo.lock b/listings/ch17-async-await/listing-17-27/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-27/Cargo.lock +++ b/listings/ch17-async-await/listing-17-27/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-28/Cargo.lock b/listings/ch17-async-await/listing-17-28/Cargo.lock index 2e0f3ebedb..f09d29189b 100644 --- a/listings/ch17-async-await/listing-17-28/Cargo.lock +++ b/listings/ch17-async-await/listing-17-28/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,1445 @@ 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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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.lock b/listings/ch17-async-await/listing-17-29/Cargo.lock index a55aeb1e1c..0be7d2c88b 100644 --- a/listings/ch17-async-await/listing-17-29/Cargo.lock +++ b/listings/ch17-async-await/listing-17-29/Cargo.lock @@ -1485,7 +1485,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/listing-17-30/Cargo.lock b/listings/ch17-async-await/listing-17-30/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-30/Cargo.lock +++ b/listings/ch17-async-await/listing-17-30/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-31/Cargo.lock b/listings/ch17-async-await/listing-17-31/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-31/Cargo.lock +++ b/listings/ch17-async-await/listing-17-31/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-32/Cargo.lock b/listings/ch17-async-await/listing-17-32/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-32/Cargo.lock +++ b/listings/ch17-async-await/listing-17-32/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-33/Cargo.lock b/listings/ch17-async-await/listing-17-33/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-33/Cargo.lock +++ b/listings/ch17-async-await/listing-17-33/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-34/Cargo.lock b/listings/ch17-async-await/listing-17-34/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-34/Cargo.lock +++ b/listings/ch17-async-await/listing-17-34/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-35/Cargo.lock b/listings/ch17-async-await/listing-17-35/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-35/Cargo.lock +++ b/listings/ch17-async-await/listing-17-35/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-36/Cargo.lock b/listings/ch17-async-await/listing-17-36/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-36/Cargo.lock +++ b/listings/ch17-async-await/listing-17-36/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-37/Cargo.lock b/listings/ch17-async-await/listing-17-37/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-37/Cargo.lock +++ b/listings/ch17-async-await/listing-17-37/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-38/Cargo.lock b/listings/ch17-async-await/listing-17-38/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-38/Cargo.lock +++ b/listings/ch17-async-await/listing-17-38/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-39/Cargo.lock b/listings/ch17-async-await/listing-17-39/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-39/Cargo.lock +++ b/listings/ch17-async-await/listing-17-39/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-40/Cargo.lock b/listings/ch17-async-await/listing-17-40/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-40/Cargo.lock +++ b/listings/ch17-async-await/listing-17-40/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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-41/Cargo.lock b/listings/ch17-async-await/listing-17-41/Cargo.lock index 36905af42a..72e870c80c 100644 --- a/listings/ch17-async-await/listing-17-41/Cargo.lock +++ b/listings/ch17-async-await/listing-17-41/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.99" @@ -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.29.0" @@ -153,140 +373,1445 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[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.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "memchr" -version = "2.7.4" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "html5ever" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +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.36.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +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.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] -name = "proc-macro2" -version = "1.0.85" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +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.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "autocfg", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "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.38.0" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "equivalent", + "hashbrown", ] [[package]] -name = "tokio-stream" -version = "0.1.15" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.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.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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-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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +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-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.2.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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[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.lock b/listings/ch17-async-await/listing-17-42/Cargo.lock index 35391aee48..071a0943b4 100644 --- a/listings/ch17-async-await/listing-17-42/Cargo.lock +++ b/listings/ch17-async-await/listing-17-42/Cargo.lock @@ -1485,7 +1485,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", diff --git a/listings/ch17-async-await/no-listing-state-machine/Cargo.lock b/listings/ch17-async-await/no-listing-state-machine/Cargo.lock index 5e72795fea..7b6b110bc2 100644 --- a/listings/ch17-async-await/no-listing-state-machine/Cargo.lock +++ b/listings/ch17-async-await/no-listing-state-machine/Cargo.lock @@ -1484,7 +1484,7 @@ dependencies = [ [[package]] name = "trpl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "futures", "reqwest", From fb0215d9107b4609c3f24d702c96daa1caf0540b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 26 Sep 2024 11:09:39 -0600 Subject: [PATCH 242/249] Ch. 17: Listings for Ch. 20 -> Ch. 21 --- .../listing-21-01}/Cargo.lock | 0 .../listing-21-01}/Cargo.toml | 0 .../listing-21-01}/src/main.rs | 0 .../listing-21-02}/Cargo.lock | 0 .../listing-21-02}/Cargo.toml | 0 .../listing-21-02}/src/main.rs | 0 .../listing-21-03}/Cargo.lock | 0 .../listing-21-03}/Cargo.toml | 0 .../listing-21-03}/src/main.rs | 0 .../listing-21-05}/Cargo.lock | 0 .../listing-21-05}/Cargo.toml | 0 .../listing-21-05}/hello.html | 0 .../listing-21-05}/src/main.rs | 0 .../listing-21-06}/Cargo.lock | 0 .../listing-21-06}/Cargo.toml | 0 .../listing-21-06}/hello.html | 0 .../listing-21-06}/src/main.rs | 0 .../listing-21-07}/404.html | 0 .../listing-21-07}/Cargo.lock | 0 .../listing-21-07}/Cargo.toml | 0 .../listing-21-07}/hello.html | 0 .../listing-21-07}/src/main.rs | 0 .../listing-21-09}/404.html | 0 .../listing-21-09}/Cargo.lock | 0 .../listing-21-09}/Cargo.toml | 0 .../listing-21-09}/hello.html | 0 .../listing-21-09}/src/main.rs | 0 .../listing-21-10}/404.html | 0 .../listing-21-10}/Cargo.lock | 0 .../listing-21-10}/Cargo.toml | 0 .../listing-21-10}/hello.html | 0 .../listing-21-10}/src/main.rs | 0 .../listing-21-11}/404.html | 0 .../listing-21-11}/Cargo.lock | 0 .../listing-21-11}/Cargo.toml | 0 .../listing-21-11}/hello.html | 0 .../listing-21-11}/src/main.rs | 0 .../listing-21-12}/404.html | 0 .../listing-21-12}/Cargo.lock | 0 .../listing-21-12}/Cargo.toml | 0 .../listing-21-12}/hello.html | 0 .../listing-21-12}/output.txt | 0 .../listing-21-12}/src/main.rs | 0 .../listing-21-13}/404.html | 0 .../listing-21-13}/Cargo.lock | 0 .../listing-21-13}/Cargo.toml | 0 .../listing-21-13}/hello.html | 0 .../listing-21-13}/src/lib.rs | 0 .../listing-21-13}/src/main.rs | 0 .../listing-21-14}/404.html | 0 .../listing-21-14}/Cargo.lock | 0 .../listing-21-14}/Cargo.toml | 0 .../listing-21-14}/hello.html | 0 .../listing-21-14}/src/lib.rs | 0 .../listing-21-14}/src/main.rs | 0 .../listing-21-15}/404.html | 0 .../listing-21-15}/Cargo.lock | 0 .../listing-21-15}/Cargo.toml | 0 .../listing-21-15}/hello.html | 0 .../listing-21-15}/src/lib.rs | 0 .../listing-21-15}/src/main.rs | 0 .../listing-21-16}/404.html | 0 .../listing-21-16}/Cargo.lock | 0 .../listing-21-16}/Cargo.toml | 0 .../listing-21-16}/hello.html | 0 .../listing-21-16}/src/lib.rs | 0 .../listing-21-16}/src/main.rs | 0 .../listing-21-17}/404.html | 0 .../listing-21-17}/Cargo.lock | 0 .../listing-21-17}/Cargo.toml | 0 .../listing-21-17}/hello.html | 0 .../listing-21-17}/output.txt | 0 .../listing-21-17}/src/lib.rs | 0 .../listing-21-17}/src/main.rs | 0 .../listing-21-18}/404.html | 0 .../listing-21-18}/Cargo.lock | 0 .../listing-21-18}/Cargo.toml | 0 .../listing-21-18}/hello.html | 0 .../listing-21-18}/src/lib.rs | 0 .../listing-21-18}/src/main.rs | 0 .../listing-21-19}/404.html | 0 .../listing-21-19}/Cargo.lock | 0 .../listing-21-19}/Cargo.toml | 0 .../listing-21-19}/hello.html | 0 .../listing-21-19}/src/lib.rs | 0 .../listing-21-19}/src/main.rs | 0 .../listing-21-20}/404.html | 0 .../listing-21-20}/Cargo.lock | 0 .../listing-21-20}/Cargo.toml | 0 .../listing-21-20}/hello.html | 0 .../listing-21-20}/src/lib.rs | 0 .../listing-21-20}/src/main.rs | 0 .../listing-21-21}/404.html | 0 .../listing-21-21}/Cargo.lock | 0 .../listing-21-21}/Cargo.toml | 0 .../listing-21-21}/hello.html | 0 .../listing-21-21}/src/lib.rs | 0 .../listing-21-21}/src/main.rs | 0 .../listing-21-22}/404.html | 0 .../listing-21-22}/Cargo.lock | 0 .../listing-21-22}/Cargo.toml | 0 .../listing-21-22}/hello.html | 0 .../listing-21-22}/output.txt | 0 .../listing-21-22}/src/lib.rs | 0 .../listing-21-22}/src/main.rs | 0 .../listing-21-23}/404.html | 0 .../listing-21-23}/Cargo.lock | 0 .../listing-21-23}/Cargo.toml | 0 .../listing-21-23}/hello.html | 0 .../listing-21-23}/src/lib.rs | 0 .../listing-21-23}/src/main.rs | 0 .../listing-21-24}/404.html | 0 .../listing-21-24}/Cargo.lock | 0 .../listing-21-24}/Cargo.toml | 0 .../listing-21-24}/hello.html | 0 .../listing-21-24}/src/lib.rs | 0 .../listing-21-24}/src/main.rs | 0 .../listing-21-25}/404.html | 0 .../listing-21-25}/Cargo.lock | 0 .../listing-21-25}/Cargo.toml | 0 .../listing-21-25}/hello.html | 0 .../listing-21-25}/src/lib.rs | 0 .../listing-21-25}/src/main.rs | 0 .../404.html | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../hello.html | 0 .../output.txt | 0 .../src/lib.rs | 0 .../src/main.rs | 0 .../404.html | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../hello.html | 0 .../output.txt | 0 .../src/lib.rs | 0 .../src/main.rs | 0 .../no-listing-03-define-execute/404.html | 0 .../no-listing-03-define-execute/Cargo.lock | 0 .../no-listing-03-define-execute/Cargo.toml | 0 .../no-listing-03-define-execute/hello.html | 0 .../no-listing-03-define-execute/output.txt | 0 .../no-listing-03-define-execute/src/lib.rs | 0 .../no-listing-03-define-execute/src/main.rs | 0 .../404.html | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../hello.html | 0 .../output.txt | 0 .../src/lib.rs | 0 .../src/main.rs | 0 .../no-listing-05-fix-worker-new/404.html | 0 .../no-listing-05-fix-worker-new/Cargo.lock | 0 .../no-listing-05-fix-worker-new/Cargo.toml | 0 .../no-listing-05-fix-worker-new/hello.html | 0 .../no-listing-05-fix-worker-new/src/lib.rs | 0 .../no-listing-05-fix-worker-new/src/main.rs | 0 .../404.html | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../hello.html | 0 .../src/lib.rs | 0 .../src/main.rs | 0 .../no-listing-07-final-code/404.html | 0 .../no-listing-07-final-code/Cargo.lock | 0 .../no-listing-07-final-code/Cargo.toml | 0 .../no-listing-07-final-code/hello.html | 0 .../no-listing-07-final-code/src/lib.rs | 0 .../no-listing-07-final-code/src/main.rs | 0 src/ch21-01-single-threaded.md | 62 +++++----- src/ch21-02-multithreaded.md | 106 +++++++++--------- src/ch21-03-graceful-shutdown-and-cleanup.md | 42 +++---- 172 files changed, 105 insertions(+), 105 deletions(-) rename listings/{ch20-web-server/listing-20-01 => ch21-web-server/listing-21-01}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-01 => ch21-web-server/listing-21-01}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-01 => ch21-web-server/listing-21-01}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-02 => ch21-web-server/listing-21-02}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-02 => ch21-web-server/listing-21-02}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-02 => ch21-web-server/listing-21-02}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-03 => ch21-web-server/listing-21-03}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-03 => ch21-web-server/listing-21-03}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-03 => ch21-web-server/listing-21-03}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-05 => ch21-web-server/listing-21-05}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-05 => ch21-web-server/listing-21-05}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-05 => ch21-web-server/listing-21-05}/hello.html (100%) rename listings/{ch20-web-server/listing-20-05 => ch21-web-server/listing-21-05}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-06 => ch21-web-server/listing-21-06}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-06 => ch21-web-server/listing-21-06}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-06 => ch21-web-server/listing-21-06}/hello.html (100%) rename listings/{ch20-web-server/listing-20-06 => ch21-web-server/listing-21-06}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-07 => ch21-web-server/listing-21-07}/404.html (100%) rename listings/{ch20-web-server/listing-20-07 => ch21-web-server/listing-21-07}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-07 => ch21-web-server/listing-21-07}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-07 => ch21-web-server/listing-21-07}/hello.html (100%) rename listings/{ch20-web-server/listing-20-07 => ch21-web-server/listing-21-07}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-09 => ch21-web-server/listing-21-09}/404.html (100%) rename listings/{ch20-web-server/listing-20-09 => ch21-web-server/listing-21-09}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-09 => ch21-web-server/listing-21-09}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-09 => ch21-web-server/listing-21-09}/hello.html (100%) rename listings/{ch20-web-server/listing-20-09 => ch21-web-server/listing-21-09}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-10 => ch21-web-server/listing-21-10}/404.html (100%) rename listings/{ch20-web-server/listing-20-10 => ch21-web-server/listing-21-10}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-10 => ch21-web-server/listing-21-10}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-10 => ch21-web-server/listing-21-10}/hello.html (100%) rename listings/{ch20-web-server/listing-20-10 => ch21-web-server/listing-21-10}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-11 => ch21-web-server/listing-21-11}/404.html (100%) rename listings/{ch20-web-server/listing-20-11 => ch21-web-server/listing-21-11}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-11 => ch21-web-server/listing-21-11}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-11 => ch21-web-server/listing-21-11}/hello.html (100%) rename listings/{ch20-web-server/listing-20-11 => ch21-web-server/listing-21-11}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-12 => ch21-web-server/listing-21-12}/404.html (100%) rename listings/{ch20-web-server/listing-20-12 => ch21-web-server/listing-21-12}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-12 => ch21-web-server/listing-21-12}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-12 => ch21-web-server/listing-21-12}/hello.html (100%) rename listings/{ch20-web-server/listing-20-12 => ch21-web-server/listing-21-12}/output.txt (100%) rename listings/{ch20-web-server/listing-20-12 => ch21-web-server/listing-21-12}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-13 => ch21-web-server/listing-21-13}/404.html (100%) rename listings/{ch20-web-server/listing-20-13 => ch21-web-server/listing-21-13}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-13 => ch21-web-server/listing-21-13}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-13 => ch21-web-server/listing-21-13}/hello.html (100%) rename listings/{ch20-web-server/listing-20-13 => ch21-web-server/listing-21-13}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-13 => ch21-web-server/listing-21-13}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-14 => ch21-web-server/listing-21-14}/404.html (100%) rename listings/{ch20-web-server/listing-20-14 => ch21-web-server/listing-21-14}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-14 => ch21-web-server/listing-21-14}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-14 => ch21-web-server/listing-21-14}/hello.html (100%) rename listings/{ch20-web-server/listing-20-14 => ch21-web-server/listing-21-14}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-14 => ch21-web-server/listing-21-14}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-15 => ch21-web-server/listing-21-15}/404.html (100%) rename listings/{ch20-web-server/listing-20-15 => ch21-web-server/listing-21-15}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-15 => ch21-web-server/listing-21-15}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-15 => ch21-web-server/listing-21-15}/hello.html (100%) rename listings/{ch20-web-server/listing-20-15 => ch21-web-server/listing-21-15}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-15 => ch21-web-server/listing-21-15}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-16 => ch21-web-server/listing-21-16}/404.html (100%) rename listings/{ch20-web-server/listing-20-16 => ch21-web-server/listing-21-16}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-16 => ch21-web-server/listing-21-16}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-16 => ch21-web-server/listing-21-16}/hello.html (100%) rename listings/{ch20-web-server/listing-20-16 => ch21-web-server/listing-21-16}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-16 => ch21-web-server/listing-21-16}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-17 => ch21-web-server/listing-21-17}/404.html (100%) rename listings/{ch20-web-server/listing-20-17 => ch21-web-server/listing-21-17}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-17 => ch21-web-server/listing-21-17}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-17 => ch21-web-server/listing-21-17}/hello.html (100%) rename listings/{ch20-web-server/listing-20-17 => ch21-web-server/listing-21-17}/output.txt (100%) rename listings/{ch20-web-server/listing-20-17 => ch21-web-server/listing-21-17}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-17 => ch21-web-server/listing-21-17}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-18 => ch21-web-server/listing-21-18}/404.html (100%) rename listings/{ch20-web-server/listing-20-18 => ch21-web-server/listing-21-18}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-18 => ch21-web-server/listing-21-18}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-18 => ch21-web-server/listing-21-18}/hello.html (100%) rename listings/{ch20-web-server/listing-20-18 => ch21-web-server/listing-21-18}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-18 => ch21-web-server/listing-21-18}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-19 => ch21-web-server/listing-21-19}/404.html (100%) rename listings/{ch20-web-server/listing-20-19 => ch21-web-server/listing-21-19}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-19 => ch21-web-server/listing-21-19}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-19 => ch21-web-server/listing-21-19}/hello.html (100%) rename listings/{ch20-web-server/listing-20-19 => ch21-web-server/listing-21-19}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-19 => ch21-web-server/listing-21-19}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-20 => ch21-web-server/listing-21-20}/404.html (100%) rename listings/{ch20-web-server/listing-20-20 => ch21-web-server/listing-21-20}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-20 => ch21-web-server/listing-21-20}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-20 => ch21-web-server/listing-21-20}/hello.html (100%) rename listings/{ch20-web-server/listing-20-20 => ch21-web-server/listing-21-20}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-20 => ch21-web-server/listing-21-20}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-21 => ch21-web-server/listing-21-21}/404.html (100%) rename listings/{ch20-web-server/listing-20-21 => ch21-web-server/listing-21-21}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-21 => ch21-web-server/listing-21-21}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-21 => ch21-web-server/listing-21-21}/hello.html (100%) rename listings/{ch20-web-server/listing-20-21 => ch21-web-server/listing-21-21}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-21 => ch21-web-server/listing-21-21}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-22 => ch21-web-server/listing-21-22}/404.html (100%) rename listings/{ch20-web-server/listing-20-22 => ch21-web-server/listing-21-22}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-22 => ch21-web-server/listing-21-22}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-22 => ch21-web-server/listing-21-22}/hello.html (100%) rename listings/{ch20-web-server/listing-20-22 => ch21-web-server/listing-21-22}/output.txt (100%) rename listings/{ch20-web-server/listing-20-22 => ch21-web-server/listing-21-22}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-22 => ch21-web-server/listing-21-22}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-23 => ch21-web-server/listing-21-23}/404.html (100%) rename listings/{ch20-web-server/listing-20-23 => ch21-web-server/listing-21-23}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-23 => ch21-web-server/listing-21-23}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-23 => ch21-web-server/listing-21-23}/hello.html (100%) rename listings/{ch20-web-server/listing-20-23 => ch21-web-server/listing-21-23}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-23 => ch21-web-server/listing-21-23}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-24 => ch21-web-server/listing-21-24}/404.html (100%) rename listings/{ch20-web-server/listing-20-24 => ch21-web-server/listing-21-24}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-24 => ch21-web-server/listing-21-24}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-24 => ch21-web-server/listing-21-24}/hello.html (100%) rename listings/{ch20-web-server/listing-20-24 => ch21-web-server/listing-21-24}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-24 => ch21-web-server/listing-21-24}/src/main.rs (100%) rename listings/{ch20-web-server/listing-20-25 => ch21-web-server/listing-21-25}/404.html (100%) rename listings/{ch20-web-server/listing-20-25 => ch21-web-server/listing-21-25}/Cargo.lock (100%) rename listings/{ch20-web-server/listing-20-25 => ch21-web-server/listing-21-25}/Cargo.toml (100%) rename listings/{ch20-web-server/listing-20-25 => ch21-web-server/listing-21-25}/hello.html (100%) rename listings/{ch20-web-server/listing-20-25 => ch21-web-server/listing-21-25}/src/lib.rs (100%) rename listings/{ch20-web-server/listing-20-25 => ch21-web-server/listing-21-25}/src/main.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-01-define-threadpool-struct/404.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-01-define-threadpool-struct/Cargo.lock (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-01-define-threadpool-struct/Cargo.toml (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-01-define-threadpool-struct/hello.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-01-define-threadpool-struct/output.txt (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-01-define-threadpool-struct/src/lib.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-01-define-threadpool-struct/src/main.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-02-impl-threadpool-new/404.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-02-impl-threadpool-new/Cargo.lock (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-02-impl-threadpool-new/Cargo.toml (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-02-impl-threadpool-new/hello.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-02-impl-threadpool-new/output.txt (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-02-impl-threadpool-new/src/lib.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-02-impl-threadpool-new/src/main.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-03-define-execute/404.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-03-define-execute/Cargo.lock (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-03-define-execute/Cargo.toml (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-03-define-execute/hello.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-03-define-execute/output.txt (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-03-define-execute/src/lib.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-03-define-execute/src/main.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-04-update-worker-definition/404.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-04-update-worker-definition/Cargo.lock (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-04-update-worker-definition/Cargo.toml (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-04-update-worker-definition/hello.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-04-update-worker-definition/output.txt (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-04-update-worker-definition/src/lib.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-04-update-worker-definition/src/main.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-05-fix-worker-new/404.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-05-fix-worker-new/Cargo.lock (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-05-fix-worker-new/Cargo.toml (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-05-fix-worker-new/hello.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-05-fix-worker-new/src/lib.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-05-fix-worker-new/src/main.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-06-fix-threadpool-drop/404.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-06-fix-threadpool-drop/Cargo.lock (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-06-fix-threadpool-drop/Cargo.toml (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-06-fix-threadpool-drop/hello.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-06-fix-threadpool-drop/src/lib.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-06-fix-threadpool-drop/src/main.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-07-final-code/404.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-07-final-code/Cargo.lock (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-07-final-code/Cargo.toml (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-07-final-code/hello.html (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-07-final-code/src/lib.rs (100%) rename listings/{ch20-web-server => ch21-web-server}/no-listing-07-final-code/src/main.rs (100%) diff --git a/listings/ch20-web-server/listing-20-01/Cargo.lock b/listings/ch21-web-server/listing-21-01/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-01/Cargo.lock rename to listings/ch21-web-server/listing-21-01/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-01/Cargo.toml b/listings/ch21-web-server/listing-21-01/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-01/Cargo.toml rename to listings/ch21-web-server/listing-21-01/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-01/src/main.rs b/listings/ch21-web-server/listing-21-01/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-01/src/main.rs rename to listings/ch21-web-server/listing-21-01/src/main.rs diff --git a/listings/ch20-web-server/listing-20-02/Cargo.lock b/listings/ch21-web-server/listing-21-02/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-02/Cargo.lock rename to listings/ch21-web-server/listing-21-02/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-02/Cargo.toml b/listings/ch21-web-server/listing-21-02/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-02/Cargo.toml rename to listings/ch21-web-server/listing-21-02/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-02/src/main.rs b/listings/ch21-web-server/listing-21-02/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-02/src/main.rs rename to listings/ch21-web-server/listing-21-02/src/main.rs diff --git a/listings/ch20-web-server/listing-20-03/Cargo.lock b/listings/ch21-web-server/listing-21-03/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-03/Cargo.lock rename to listings/ch21-web-server/listing-21-03/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-03/Cargo.toml b/listings/ch21-web-server/listing-21-03/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-03/Cargo.toml rename to listings/ch21-web-server/listing-21-03/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-03/src/main.rs b/listings/ch21-web-server/listing-21-03/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-03/src/main.rs rename to listings/ch21-web-server/listing-21-03/src/main.rs diff --git a/listings/ch20-web-server/listing-20-05/Cargo.lock b/listings/ch21-web-server/listing-21-05/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-05/Cargo.lock rename to listings/ch21-web-server/listing-21-05/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-05/Cargo.toml b/listings/ch21-web-server/listing-21-05/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-05/Cargo.toml rename to listings/ch21-web-server/listing-21-05/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-05/hello.html b/listings/ch21-web-server/listing-21-05/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-05/hello.html rename to listings/ch21-web-server/listing-21-05/hello.html diff --git a/listings/ch20-web-server/listing-20-05/src/main.rs b/listings/ch21-web-server/listing-21-05/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-05/src/main.rs rename to listings/ch21-web-server/listing-21-05/src/main.rs diff --git a/listings/ch20-web-server/listing-20-06/Cargo.lock b/listings/ch21-web-server/listing-21-06/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-06/Cargo.lock rename to listings/ch21-web-server/listing-21-06/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-06/Cargo.toml b/listings/ch21-web-server/listing-21-06/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-06/Cargo.toml rename to listings/ch21-web-server/listing-21-06/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-06/hello.html b/listings/ch21-web-server/listing-21-06/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-06/hello.html rename to listings/ch21-web-server/listing-21-06/hello.html diff --git a/listings/ch20-web-server/listing-20-06/src/main.rs b/listings/ch21-web-server/listing-21-06/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-06/src/main.rs rename to listings/ch21-web-server/listing-21-06/src/main.rs diff --git a/listings/ch20-web-server/listing-20-07/404.html b/listings/ch21-web-server/listing-21-07/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-07/404.html rename to listings/ch21-web-server/listing-21-07/404.html diff --git a/listings/ch20-web-server/listing-20-07/Cargo.lock b/listings/ch21-web-server/listing-21-07/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-07/Cargo.lock rename to listings/ch21-web-server/listing-21-07/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-07/Cargo.toml b/listings/ch21-web-server/listing-21-07/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-07/Cargo.toml rename to listings/ch21-web-server/listing-21-07/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-07/hello.html b/listings/ch21-web-server/listing-21-07/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-07/hello.html rename to listings/ch21-web-server/listing-21-07/hello.html diff --git a/listings/ch20-web-server/listing-20-07/src/main.rs b/listings/ch21-web-server/listing-21-07/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-07/src/main.rs rename to listings/ch21-web-server/listing-21-07/src/main.rs diff --git a/listings/ch20-web-server/listing-20-09/404.html b/listings/ch21-web-server/listing-21-09/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-09/404.html rename to listings/ch21-web-server/listing-21-09/404.html diff --git a/listings/ch20-web-server/listing-20-09/Cargo.lock b/listings/ch21-web-server/listing-21-09/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-09/Cargo.lock rename to listings/ch21-web-server/listing-21-09/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-09/Cargo.toml b/listings/ch21-web-server/listing-21-09/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-09/Cargo.toml rename to listings/ch21-web-server/listing-21-09/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-09/hello.html b/listings/ch21-web-server/listing-21-09/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-09/hello.html rename to listings/ch21-web-server/listing-21-09/hello.html diff --git a/listings/ch20-web-server/listing-20-09/src/main.rs b/listings/ch21-web-server/listing-21-09/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-09/src/main.rs rename to listings/ch21-web-server/listing-21-09/src/main.rs diff --git a/listings/ch20-web-server/listing-20-10/404.html b/listings/ch21-web-server/listing-21-10/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-10/404.html rename to listings/ch21-web-server/listing-21-10/404.html diff --git a/listings/ch20-web-server/listing-20-10/Cargo.lock b/listings/ch21-web-server/listing-21-10/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-10/Cargo.lock rename to listings/ch21-web-server/listing-21-10/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-10/Cargo.toml b/listings/ch21-web-server/listing-21-10/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-10/Cargo.toml rename to listings/ch21-web-server/listing-21-10/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-10/hello.html b/listings/ch21-web-server/listing-21-10/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-10/hello.html rename to listings/ch21-web-server/listing-21-10/hello.html diff --git a/listings/ch20-web-server/listing-20-10/src/main.rs b/listings/ch21-web-server/listing-21-10/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-10/src/main.rs rename to listings/ch21-web-server/listing-21-10/src/main.rs diff --git a/listings/ch20-web-server/listing-20-11/404.html b/listings/ch21-web-server/listing-21-11/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-11/404.html rename to listings/ch21-web-server/listing-21-11/404.html diff --git a/listings/ch20-web-server/listing-20-11/Cargo.lock b/listings/ch21-web-server/listing-21-11/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-11/Cargo.lock rename to listings/ch21-web-server/listing-21-11/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-11/Cargo.toml b/listings/ch21-web-server/listing-21-11/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-11/Cargo.toml rename to listings/ch21-web-server/listing-21-11/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-11/hello.html b/listings/ch21-web-server/listing-21-11/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-11/hello.html rename to listings/ch21-web-server/listing-21-11/hello.html diff --git a/listings/ch20-web-server/listing-20-11/src/main.rs b/listings/ch21-web-server/listing-21-11/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-11/src/main.rs rename to listings/ch21-web-server/listing-21-11/src/main.rs diff --git a/listings/ch20-web-server/listing-20-12/404.html b/listings/ch21-web-server/listing-21-12/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-12/404.html rename to listings/ch21-web-server/listing-21-12/404.html diff --git a/listings/ch20-web-server/listing-20-12/Cargo.lock b/listings/ch21-web-server/listing-21-12/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-12/Cargo.lock rename to listings/ch21-web-server/listing-21-12/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-12/Cargo.toml b/listings/ch21-web-server/listing-21-12/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-12/Cargo.toml rename to listings/ch21-web-server/listing-21-12/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-12/hello.html b/listings/ch21-web-server/listing-21-12/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-12/hello.html rename to listings/ch21-web-server/listing-21-12/hello.html diff --git a/listings/ch20-web-server/listing-20-12/output.txt b/listings/ch21-web-server/listing-21-12/output.txt similarity index 100% rename from listings/ch20-web-server/listing-20-12/output.txt rename to listings/ch21-web-server/listing-21-12/output.txt diff --git a/listings/ch20-web-server/listing-20-12/src/main.rs b/listings/ch21-web-server/listing-21-12/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-12/src/main.rs rename to listings/ch21-web-server/listing-21-12/src/main.rs diff --git a/listings/ch20-web-server/listing-20-13/404.html b/listings/ch21-web-server/listing-21-13/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-13/404.html rename to listings/ch21-web-server/listing-21-13/404.html diff --git a/listings/ch20-web-server/listing-20-13/Cargo.lock b/listings/ch21-web-server/listing-21-13/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-13/Cargo.lock rename to listings/ch21-web-server/listing-21-13/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-13/Cargo.toml b/listings/ch21-web-server/listing-21-13/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-13/Cargo.toml rename to listings/ch21-web-server/listing-21-13/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-13/hello.html b/listings/ch21-web-server/listing-21-13/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-13/hello.html rename to listings/ch21-web-server/listing-21-13/hello.html diff --git a/listings/ch20-web-server/listing-20-13/src/lib.rs b/listings/ch21-web-server/listing-21-13/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-13/src/lib.rs rename to listings/ch21-web-server/listing-21-13/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-13/src/main.rs b/listings/ch21-web-server/listing-21-13/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-13/src/main.rs rename to listings/ch21-web-server/listing-21-13/src/main.rs diff --git a/listings/ch20-web-server/listing-20-14/404.html b/listings/ch21-web-server/listing-21-14/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-14/404.html rename to listings/ch21-web-server/listing-21-14/404.html diff --git a/listings/ch20-web-server/listing-20-14/Cargo.lock b/listings/ch21-web-server/listing-21-14/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-14/Cargo.lock rename to listings/ch21-web-server/listing-21-14/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-14/Cargo.toml b/listings/ch21-web-server/listing-21-14/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-14/Cargo.toml rename to listings/ch21-web-server/listing-21-14/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-14/hello.html b/listings/ch21-web-server/listing-21-14/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-14/hello.html rename to listings/ch21-web-server/listing-21-14/hello.html diff --git a/listings/ch20-web-server/listing-20-14/src/lib.rs b/listings/ch21-web-server/listing-21-14/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-14/src/lib.rs rename to listings/ch21-web-server/listing-21-14/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-14/src/main.rs b/listings/ch21-web-server/listing-21-14/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-14/src/main.rs rename to listings/ch21-web-server/listing-21-14/src/main.rs diff --git a/listings/ch20-web-server/listing-20-15/404.html b/listings/ch21-web-server/listing-21-15/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-15/404.html rename to listings/ch21-web-server/listing-21-15/404.html diff --git a/listings/ch20-web-server/listing-20-15/Cargo.lock b/listings/ch21-web-server/listing-21-15/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-15/Cargo.lock rename to listings/ch21-web-server/listing-21-15/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-15/Cargo.toml b/listings/ch21-web-server/listing-21-15/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-15/Cargo.toml rename to listings/ch21-web-server/listing-21-15/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-15/hello.html b/listings/ch21-web-server/listing-21-15/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-15/hello.html rename to listings/ch21-web-server/listing-21-15/hello.html diff --git a/listings/ch20-web-server/listing-20-15/src/lib.rs b/listings/ch21-web-server/listing-21-15/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-15/src/lib.rs rename to listings/ch21-web-server/listing-21-15/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-15/src/main.rs b/listings/ch21-web-server/listing-21-15/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-15/src/main.rs rename to listings/ch21-web-server/listing-21-15/src/main.rs diff --git a/listings/ch20-web-server/listing-20-16/404.html b/listings/ch21-web-server/listing-21-16/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-16/404.html rename to listings/ch21-web-server/listing-21-16/404.html diff --git a/listings/ch20-web-server/listing-20-16/Cargo.lock b/listings/ch21-web-server/listing-21-16/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-16/Cargo.lock rename to listings/ch21-web-server/listing-21-16/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-16/Cargo.toml b/listings/ch21-web-server/listing-21-16/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-16/Cargo.toml rename to listings/ch21-web-server/listing-21-16/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-16/hello.html b/listings/ch21-web-server/listing-21-16/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-16/hello.html rename to listings/ch21-web-server/listing-21-16/hello.html diff --git a/listings/ch20-web-server/listing-20-16/src/lib.rs b/listings/ch21-web-server/listing-21-16/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-16/src/lib.rs rename to listings/ch21-web-server/listing-21-16/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-16/src/main.rs b/listings/ch21-web-server/listing-21-16/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-16/src/main.rs rename to listings/ch21-web-server/listing-21-16/src/main.rs diff --git a/listings/ch20-web-server/listing-20-17/404.html b/listings/ch21-web-server/listing-21-17/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-17/404.html rename to listings/ch21-web-server/listing-21-17/404.html diff --git a/listings/ch20-web-server/listing-20-17/Cargo.lock b/listings/ch21-web-server/listing-21-17/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-17/Cargo.lock rename to listings/ch21-web-server/listing-21-17/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-17/Cargo.toml b/listings/ch21-web-server/listing-21-17/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-17/Cargo.toml rename to listings/ch21-web-server/listing-21-17/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-17/hello.html b/listings/ch21-web-server/listing-21-17/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-17/hello.html rename to listings/ch21-web-server/listing-21-17/hello.html diff --git a/listings/ch20-web-server/listing-20-17/output.txt b/listings/ch21-web-server/listing-21-17/output.txt similarity index 100% rename from listings/ch20-web-server/listing-20-17/output.txt rename to listings/ch21-web-server/listing-21-17/output.txt diff --git a/listings/ch20-web-server/listing-20-17/src/lib.rs b/listings/ch21-web-server/listing-21-17/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-17/src/lib.rs rename to listings/ch21-web-server/listing-21-17/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-17/src/main.rs b/listings/ch21-web-server/listing-21-17/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-17/src/main.rs rename to listings/ch21-web-server/listing-21-17/src/main.rs diff --git a/listings/ch20-web-server/listing-20-18/404.html b/listings/ch21-web-server/listing-21-18/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-18/404.html rename to listings/ch21-web-server/listing-21-18/404.html diff --git a/listings/ch20-web-server/listing-20-18/Cargo.lock b/listings/ch21-web-server/listing-21-18/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-18/Cargo.lock rename to listings/ch21-web-server/listing-21-18/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-18/Cargo.toml b/listings/ch21-web-server/listing-21-18/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-18/Cargo.toml rename to listings/ch21-web-server/listing-21-18/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-18/hello.html b/listings/ch21-web-server/listing-21-18/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-18/hello.html rename to listings/ch21-web-server/listing-21-18/hello.html diff --git a/listings/ch20-web-server/listing-20-18/src/lib.rs b/listings/ch21-web-server/listing-21-18/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-18/src/lib.rs rename to listings/ch21-web-server/listing-21-18/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-18/src/main.rs b/listings/ch21-web-server/listing-21-18/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-18/src/main.rs rename to listings/ch21-web-server/listing-21-18/src/main.rs diff --git a/listings/ch20-web-server/listing-20-19/404.html b/listings/ch21-web-server/listing-21-19/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-19/404.html rename to listings/ch21-web-server/listing-21-19/404.html diff --git a/listings/ch20-web-server/listing-20-19/Cargo.lock b/listings/ch21-web-server/listing-21-19/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-19/Cargo.lock rename to listings/ch21-web-server/listing-21-19/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-19/Cargo.toml b/listings/ch21-web-server/listing-21-19/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-19/Cargo.toml rename to listings/ch21-web-server/listing-21-19/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-19/hello.html b/listings/ch21-web-server/listing-21-19/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-19/hello.html rename to listings/ch21-web-server/listing-21-19/hello.html diff --git a/listings/ch20-web-server/listing-20-19/src/lib.rs b/listings/ch21-web-server/listing-21-19/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-19/src/lib.rs rename to listings/ch21-web-server/listing-21-19/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-19/src/main.rs b/listings/ch21-web-server/listing-21-19/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-19/src/main.rs rename to listings/ch21-web-server/listing-21-19/src/main.rs diff --git a/listings/ch20-web-server/listing-20-20/404.html b/listings/ch21-web-server/listing-21-20/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-20/404.html rename to listings/ch21-web-server/listing-21-20/404.html diff --git a/listings/ch20-web-server/listing-20-20/Cargo.lock b/listings/ch21-web-server/listing-21-20/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-20/Cargo.lock rename to listings/ch21-web-server/listing-21-20/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-20/Cargo.toml b/listings/ch21-web-server/listing-21-20/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-20/Cargo.toml rename to listings/ch21-web-server/listing-21-20/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-20/hello.html b/listings/ch21-web-server/listing-21-20/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-20/hello.html rename to listings/ch21-web-server/listing-21-20/hello.html diff --git a/listings/ch20-web-server/listing-20-20/src/lib.rs b/listings/ch21-web-server/listing-21-20/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-20/src/lib.rs rename to listings/ch21-web-server/listing-21-20/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-20/src/main.rs b/listings/ch21-web-server/listing-21-20/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-20/src/main.rs rename to listings/ch21-web-server/listing-21-20/src/main.rs diff --git a/listings/ch20-web-server/listing-20-21/404.html b/listings/ch21-web-server/listing-21-21/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-21/404.html rename to listings/ch21-web-server/listing-21-21/404.html diff --git a/listings/ch20-web-server/listing-20-21/Cargo.lock b/listings/ch21-web-server/listing-21-21/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-21/Cargo.lock rename to listings/ch21-web-server/listing-21-21/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-21/Cargo.toml b/listings/ch21-web-server/listing-21-21/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-21/Cargo.toml rename to listings/ch21-web-server/listing-21-21/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-21/hello.html b/listings/ch21-web-server/listing-21-21/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-21/hello.html rename to listings/ch21-web-server/listing-21-21/hello.html diff --git a/listings/ch20-web-server/listing-20-21/src/lib.rs b/listings/ch21-web-server/listing-21-21/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-21/src/lib.rs rename to listings/ch21-web-server/listing-21-21/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-21/src/main.rs b/listings/ch21-web-server/listing-21-21/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-21/src/main.rs rename to listings/ch21-web-server/listing-21-21/src/main.rs diff --git a/listings/ch20-web-server/listing-20-22/404.html b/listings/ch21-web-server/listing-21-22/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-22/404.html rename to listings/ch21-web-server/listing-21-22/404.html diff --git a/listings/ch20-web-server/listing-20-22/Cargo.lock b/listings/ch21-web-server/listing-21-22/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-22/Cargo.lock rename to listings/ch21-web-server/listing-21-22/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-22/Cargo.toml b/listings/ch21-web-server/listing-21-22/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-22/Cargo.toml rename to listings/ch21-web-server/listing-21-22/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-22/hello.html b/listings/ch21-web-server/listing-21-22/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-22/hello.html rename to listings/ch21-web-server/listing-21-22/hello.html diff --git a/listings/ch20-web-server/listing-20-22/output.txt b/listings/ch21-web-server/listing-21-22/output.txt similarity index 100% rename from listings/ch20-web-server/listing-20-22/output.txt rename to listings/ch21-web-server/listing-21-22/output.txt diff --git a/listings/ch20-web-server/listing-20-22/src/lib.rs b/listings/ch21-web-server/listing-21-22/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-22/src/lib.rs rename to listings/ch21-web-server/listing-21-22/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-22/src/main.rs b/listings/ch21-web-server/listing-21-22/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-22/src/main.rs rename to listings/ch21-web-server/listing-21-22/src/main.rs diff --git a/listings/ch20-web-server/listing-20-23/404.html b/listings/ch21-web-server/listing-21-23/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-23/404.html rename to listings/ch21-web-server/listing-21-23/404.html diff --git a/listings/ch20-web-server/listing-20-23/Cargo.lock b/listings/ch21-web-server/listing-21-23/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-23/Cargo.lock rename to listings/ch21-web-server/listing-21-23/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-23/Cargo.toml b/listings/ch21-web-server/listing-21-23/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-23/Cargo.toml rename to listings/ch21-web-server/listing-21-23/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-23/hello.html b/listings/ch21-web-server/listing-21-23/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-23/hello.html rename to listings/ch21-web-server/listing-21-23/hello.html diff --git a/listings/ch20-web-server/listing-20-23/src/lib.rs b/listings/ch21-web-server/listing-21-23/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-23/src/lib.rs rename to listings/ch21-web-server/listing-21-23/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-23/src/main.rs b/listings/ch21-web-server/listing-21-23/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-23/src/main.rs rename to listings/ch21-web-server/listing-21-23/src/main.rs diff --git a/listings/ch20-web-server/listing-20-24/404.html b/listings/ch21-web-server/listing-21-24/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-24/404.html rename to listings/ch21-web-server/listing-21-24/404.html diff --git a/listings/ch20-web-server/listing-20-24/Cargo.lock b/listings/ch21-web-server/listing-21-24/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-24/Cargo.lock rename to listings/ch21-web-server/listing-21-24/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-24/Cargo.toml b/listings/ch21-web-server/listing-21-24/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-24/Cargo.toml rename to listings/ch21-web-server/listing-21-24/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-24/hello.html b/listings/ch21-web-server/listing-21-24/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-24/hello.html rename to listings/ch21-web-server/listing-21-24/hello.html diff --git a/listings/ch20-web-server/listing-20-24/src/lib.rs b/listings/ch21-web-server/listing-21-24/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-24/src/lib.rs rename to listings/ch21-web-server/listing-21-24/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-24/src/main.rs b/listings/ch21-web-server/listing-21-24/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-24/src/main.rs rename to listings/ch21-web-server/listing-21-24/src/main.rs diff --git a/listings/ch20-web-server/listing-20-25/404.html b/listings/ch21-web-server/listing-21-25/404.html similarity index 100% rename from listings/ch20-web-server/listing-20-25/404.html rename to listings/ch21-web-server/listing-21-25/404.html diff --git a/listings/ch20-web-server/listing-20-25/Cargo.lock b/listings/ch21-web-server/listing-21-25/Cargo.lock similarity index 100% rename from listings/ch20-web-server/listing-20-25/Cargo.lock rename to listings/ch21-web-server/listing-21-25/Cargo.lock diff --git a/listings/ch20-web-server/listing-20-25/Cargo.toml b/listings/ch21-web-server/listing-21-25/Cargo.toml similarity index 100% rename from listings/ch20-web-server/listing-20-25/Cargo.toml rename to listings/ch21-web-server/listing-21-25/Cargo.toml diff --git a/listings/ch20-web-server/listing-20-25/hello.html b/listings/ch21-web-server/listing-21-25/hello.html similarity index 100% rename from listings/ch20-web-server/listing-20-25/hello.html rename to listings/ch21-web-server/listing-21-25/hello.html diff --git a/listings/ch20-web-server/listing-20-25/src/lib.rs b/listings/ch21-web-server/listing-21-25/src/lib.rs similarity index 100% rename from listings/ch20-web-server/listing-20-25/src/lib.rs rename to listings/ch21-web-server/listing-21-25/src/lib.rs diff --git a/listings/ch20-web-server/listing-20-25/src/main.rs b/listings/ch21-web-server/listing-21-25/src/main.rs similarity index 100% rename from listings/ch20-web-server/listing-20-25/src/main.rs rename to listings/ch21-web-server/listing-21-25/src/main.rs diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/404.html b/listings/ch21-web-server/no-listing-01-define-threadpool-struct/404.html similarity index 100% rename from listings/ch20-web-server/no-listing-01-define-threadpool-struct/404.html rename to listings/ch21-web-server/no-listing-01-define-threadpool-struct/404.html diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.lock b/listings/ch21-web-server/no-listing-01-define-threadpool-struct/Cargo.lock similarity index 100% rename from listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.lock rename to listings/ch21-web-server/no-listing-01-define-threadpool-struct/Cargo.lock diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.toml b/listings/ch21-web-server/no-listing-01-define-threadpool-struct/Cargo.toml similarity index 100% rename from listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.toml rename to listings/ch21-web-server/no-listing-01-define-threadpool-struct/Cargo.toml diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/hello.html b/listings/ch21-web-server/no-listing-01-define-threadpool-struct/hello.html similarity index 100% rename from listings/ch20-web-server/no-listing-01-define-threadpool-struct/hello.html rename to listings/ch21-web-server/no-listing-01-define-threadpool-struct/hello.html diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt b/listings/ch21-web-server/no-listing-01-define-threadpool-struct/output.txt similarity index 100% rename from listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt rename to listings/ch21-web-server/no-listing-01-define-threadpool-struct/output.txt diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/lib.rs b/listings/ch21-web-server/no-listing-01-define-threadpool-struct/src/lib.rs similarity index 100% rename from listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/lib.rs rename to listings/ch21-web-server/no-listing-01-define-threadpool-struct/src/lib.rs diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs b/listings/ch21-web-server/no-listing-01-define-threadpool-struct/src/main.rs similarity index 100% rename from listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs rename to listings/ch21-web-server/no-listing-01-define-threadpool-struct/src/main.rs diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/404.html b/listings/ch21-web-server/no-listing-02-impl-threadpool-new/404.html similarity index 100% rename from listings/ch20-web-server/no-listing-02-impl-threadpool-new/404.html rename to listings/ch21-web-server/no-listing-02-impl-threadpool-new/404.html diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.lock b/listings/ch21-web-server/no-listing-02-impl-threadpool-new/Cargo.lock similarity index 100% rename from listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.lock rename to listings/ch21-web-server/no-listing-02-impl-threadpool-new/Cargo.lock diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.toml b/listings/ch21-web-server/no-listing-02-impl-threadpool-new/Cargo.toml similarity index 100% rename from listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.toml rename to listings/ch21-web-server/no-listing-02-impl-threadpool-new/Cargo.toml diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/hello.html b/listings/ch21-web-server/no-listing-02-impl-threadpool-new/hello.html similarity index 100% rename from listings/ch20-web-server/no-listing-02-impl-threadpool-new/hello.html rename to listings/ch21-web-server/no-listing-02-impl-threadpool-new/hello.html diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt b/listings/ch21-web-server/no-listing-02-impl-threadpool-new/output.txt similarity index 100% rename from listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt rename to listings/ch21-web-server/no-listing-02-impl-threadpool-new/output.txt diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/lib.rs b/listings/ch21-web-server/no-listing-02-impl-threadpool-new/src/lib.rs similarity index 100% rename from listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/lib.rs rename to listings/ch21-web-server/no-listing-02-impl-threadpool-new/src/lib.rs diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs b/listings/ch21-web-server/no-listing-02-impl-threadpool-new/src/main.rs similarity index 100% rename from listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs rename to listings/ch21-web-server/no-listing-02-impl-threadpool-new/src/main.rs diff --git a/listings/ch20-web-server/no-listing-03-define-execute/404.html b/listings/ch21-web-server/no-listing-03-define-execute/404.html similarity index 100% rename from listings/ch20-web-server/no-listing-03-define-execute/404.html rename to listings/ch21-web-server/no-listing-03-define-execute/404.html diff --git a/listings/ch20-web-server/no-listing-03-define-execute/Cargo.lock b/listings/ch21-web-server/no-listing-03-define-execute/Cargo.lock similarity index 100% rename from listings/ch20-web-server/no-listing-03-define-execute/Cargo.lock rename to listings/ch21-web-server/no-listing-03-define-execute/Cargo.lock diff --git a/listings/ch20-web-server/no-listing-03-define-execute/Cargo.toml b/listings/ch21-web-server/no-listing-03-define-execute/Cargo.toml similarity index 100% rename from listings/ch20-web-server/no-listing-03-define-execute/Cargo.toml rename to listings/ch21-web-server/no-listing-03-define-execute/Cargo.toml diff --git a/listings/ch20-web-server/no-listing-03-define-execute/hello.html b/listings/ch21-web-server/no-listing-03-define-execute/hello.html similarity index 100% rename from listings/ch20-web-server/no-listing-03-define-execute/hello.html rename to listings/ch21-web-server/no-listing-03-define-execute/hello.html diff --git a/listings/ch20-web-server/no-listing-03-define-execute/output.txt b/listings/ch21-web-server/no-listing-03-define-execute/output.txt similarity index 100% rename from listings/ch20-web-server/no-listing-03-define-execute/output.txt rename to listings/ch21-web-server/no-listing-03-define-execute/output.txt diff --git a/listings/ch20-web-server/no-listing-03-define-execute/src/lib.rs b/listings/ch21-web-server/no-listing-03-define-execute/src/lib.rs similarity index 100% rename from listings/ch20-web-server/no-listing-03-define-execute/src/lib.rs rename to listings/ch21-web-server/no-listing-03-define-execute/src/lib.rs diff --git a/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs b/listings/ch21-web-server/no-listing-03-define-execute/src/main.rs similarity index 100% rename from listings/ch20-web-server/no-listing-03-define-execute/src/main.rs rename to listings/ch21-web-server/no-listing-03-define-execute/src/main.rs diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/404.html b/listings/ch21-web-server/no-listing-04-update-worker-definition/404.html similarity index 100% rename from listings/ch20-web-server/no-listing-04-update-worker-definition/404.html rename to listings/ch21-web-server/no-listing-04-update-worker-definition/404.html diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.lock b/listings/ch21-web-server/no-listing-04-update-worker-definition/Cargo.lock similarity index 100% rename from listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.lock rename to listings/ch21-web-server/no-listing-04-update-worker-definition/Cargo.lock diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.toml b/listings/ch21-web-server/no-listing-04-update-worker-definition/Cargo.toml similarity index 100% rename from listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.toml rename to listings/ch21-web-server/no-listing-04-update-worker-definition/Cargo.toml diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/hello.html b/listings/ch21-web-server/no-listing-04-update-worker-definition/hello.html similarity index 100% rename from listings/ch20-web-server/no-listing-04-update-worker-definition/hello.html rename to listings/ch21-web-server/no-listing-04-update-worker-definition/hello.html diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt b/listings/ch21-web-server/no-listing-04-update-worker-definition/output.txt similarity index 100% rename from listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt rename to listings/ch21-web-server/no-listing-04-update-worker-definition/output.txt diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/src/lib.rs b/listings/ch21-web-server/no-listing-04-update-worker-definition/src/lib.rs similarity index 100% rename from listings/ch20-web-server/no-listing-04-update-worker-definition/src/lib.rs rename to listings/ch21-web-server/no-listing-04-update-worker-definition/src/lib.rs diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs b/listings/ch21-web-server/no-listing-04-update-worker-definition/src/main.rs similarity index 100% rename from listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs rename to listings/ch21-web-server/no-listing-04-update-worker-definition/src/main.rs diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/404.html b/listings/ch21-web-server/no-listing-05-fix-worker-new/404.html similarity index 100% rename from listings/ch20-web-server/no-listing-05-fix-worker-new/404.html rename to listings/ch21-web-server/no-listing-05-fix-worker-new/404.html diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.lock b/listings/ch21-web-server/no-listing-05-fix-worker-new/Cargo.lock similarity index 100% rename from listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.lock rename to listings/ch21-web-server/no-listing-05-fix-worker-new/Cargo.lock diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.toml b/listings/ch21-web-server/no-listing-05-fix-worker-new/Cargo.toml similarity index 100% rename from listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.toml rename to listings/ch21-web-server/no-listing-05-fix-worker-new/Cargo.toml diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/hello.html b/listings/ch21-web-server/no-listing-05-fix-worker-new/hello.html similarity index 100% rename from listings/ch20-web-server/no-listing-05-fix-worker-new/hello.html rename to listings/ch21-web-server/no-listing-05-fix-worker-new/hello.html diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/src/lib.rs b/listings/ch21-web-server/no-listing-05-fix-worker-new/src/lib.rs similarity index 100% rename from listings/ch20-web-server/no-listing-05-fix-worker-new/src/lib.rs rename to listings/ch21-web-server/no-listing-05-fix-worker-new/src/lib.rs diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs b/listings/ch21-web-server/no-listing-05-fix-worker-new/src/main.rs similarity index 100% rename from listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs rename to listings/ch21-web-server/no-listing-05-fix-worker-new/src/main.rs diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/404.html b/listings/ch21-web-server/no-listing-06-fix-threadpool-drop/404.html similarity index 100% rename from listings/ch20-web-server/no-listing-06-fix-threadpool-drop/404.html rename to listings/ch21-web-server/no-listing-06-fix-threadpool-drop/404.html diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.lock b/listings/ch21-web-server/no-listing-06-fix-threadpool-drop/Cargo.lock similarity index 100% rename from listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.lock rename to listings/ch21-web-server/no-listing-06-fix-threadpool-drop/Cargo.lock diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml b/listings/ch21-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml similarity index 100% rename from listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml rename to listings/ch21-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/hello.html b/listings/ch21-web-server/no-listing-06-fix-threadpool-drop/hello.html similarity index 100% rename from listings/ch20-web-server/no-listing-06-fix-threadpool-drop/hello.html rename to listings/ch21-web-server/no-listing-06-fix-threadpool-drop/hello.html diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs b/listings/ch21-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs similarity index 100% rename from listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs rename to listings/ch21-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs b/listings/ch21-web-server/no-listing-06-fix-threadpool-drop/src/main.rs similarity index 100% rename from listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs rename to listings/ch21-web-server/no-listing-06-fix-threadpool-drop/src/main.rs diff --git a/listings/ch20-web-server/no-listing-07-final-code/404.html b/listings/ch21-web-server/no-listing-07-final-code/404.html similarity index 100% rename from listings/ch20-web-server/no-listing-07-final-code/404.html rename to listings/ch21-web-server/no-listing-07-final-code/404.html diff --git a/listings/ch20-web-server/no-listing-07-final-code/Cargo.lock b/listings/ch21-web-server/no-listing-07-final-code/Cargo.lock similarity index 100% rename from listings/ch20-web-server/no-listing-07-final-code/Cargo.lock rename to listings/ch21-web-server/no-listing-07-final-code/Cargo.lock diff --git a/listings/ch20-web-server/no-listing-07-final-code/Cargo.toml b/listings/ch21-web-server/no-listing-07-final-code/Cargo.toml similarity index 100% rename from listings/ch20-web-server/no-listing-07-final-code/Cargo.toml rename to listings/ch21-web-server/no-listing-07-final-code/Cargo.toml diff --git a/listings/ch20-web-server/no-listing-07-final-code/hello.html b/listings/ch21-web-server/no-listing-07-final-code/hello.html similarity index 100% rename from listings/ch20-web-server/no-listing-07-final-code/hello.html rename to listings/ch21-web-server/no-listing-07-final-code/hello.html diff --git a/listings/ch20-web-server/no-listing-07-final-code/src/lib.rs b/listings/ch21-web-server/no-listing-07-final-code/src/lib.rs similarity index 100% rename from listings/ch20-web-server/no-listing-07-final-code/src/lib.rs rename to listings/ch21-web-server/no-listing-07-final-code/src/lib.rs diff --git a/listings/ch20-web-server/no-listing-07-final-code/src/main.rs b/listings/ch21-web-server/no-listing-07-final-code/src/main.rs similarity index 100% rename from listings/ch20-web-server/no-listing-07-final-code/src/main.rs rename to listings/ch21-web-server/no-listing-07-final-code/src/main.rs diff --git a/src/ch21-01-single-threaded.md b/src/ch21-01-single-threaded.md index b474d926fe..11ae851b78 100644 --- a/src/ch21-01-single-threaded.md +++ b/src/ch21-01-single-threaded.md @@ -30,17 +30,17 @@ $ cargo new hello $ cd hello ``` -Now enter the code in Listing 20-1 in *src/main.rs* to start. This code will +Now enter the code in Listing 21-1 in *src/main.rs* to start. This code will listen at the local address `127.0.0.1:7878` for incoming TCP streams. When it gets an incoming stream, it will print `Connection established!`. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-01/src/main.rs}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-01/src/main.rs}} ``` -Listing 20-1: Listening for incoming streams and printing +Listing 21-1: Listening for incoming streams and printing a message when we receive a stream Using `TcpListener`, we can listen for TCP connections at the address @@ -125,15 +125,15 @@ separate the concerns of first getting a connection and then taking some action with the connection, we’ll start a new function for processing connections. In this new `handle_connection` function, we’ll read data from the TCP stream and print it so we can see the data being sent from the browser. Change the code to -look like Listing 20-2. +look like Listing 21-2. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-02/src/main.rs}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-02/src/main.rs}} ``` -Listing 20-2: Reading from the `TcpStream` and printing +Listing 21-2: Reading from the `TcpStream` and printing the data We bring `std::io::prelude` and `std::io::BufReader` into scope to get access @@ -271,15 +271,15 @@ The status code 200 is the standard success response. The text is a tiny successful HTTP response. Let’s write this to the stream as our response to a successful request! From the `handle_connection` function, remove the `println!` that was printing the request data and replace it with the code in -Listing 20-3. +Listing 21-3. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-03/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-03/src/main.rs:here}} ``` -Listing 20-3: Writing a tiny successful HTTP response to +Listing 21-3: Writing a tiny successful HTTP response to the stream The first new line defines the `response` variable that holds the success @@ -299,30 +299,30 @@ request and sending a response! Let’s implement the functionality for returning more than a blank page. Create the new file *hello.html* in the root of your project directory, not in the -*src* directory. You can input any HTML you want; Listing 20-4 shows one +*src* directory. You can input any HTML you want; Listing 21-4 shows one possibility. Filename: hello.html ```html -{{#include ../listings/ch20-web-server/listing-20-05/hello.html}} +{{#include ../listings/ch21-web-server/listing-21-05/hello.html}} ``` -Listing 20-4: A sample HTML file to return in a +Listing 21-4: A sample HTML file to return in a response This is a minimal HTML5 document with a heading and some text. To return this from the server when a request is received, we’ll modify `handle_connection` as -shown in Listing 20-5 to read the HTML file, add it to the response as a body, +shown in Listing 21-5 to read the HTML file, add it to the response as a body, and send it. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-05/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-05/src/main.rs:here}} ``` -Listing 20-5: Sending the contents of *hello.html* as the +Listing 21-5: Sending the contents of *hello.html* as the body of the response We’ve added `fs` to the `use` statement to bring the standard library’s @@ -352,17 +352,17 @@ Right now, our web server will return the HTML in the file no matter what the client requested. Let’s add functionality to check that the browser is requesting */* before returning the HTML file and return an error if the browser requests anything else. For this we need to modify `handle_connection`, -as shown in Listing 20-6. This new code checks the content of the request +as shown in Listing 21-6. This new code checks the content of the request received against what we know a request for */* looks like and adds `if` and `else` blocks to treat requests differently. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-06/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-06/src/main.rs:here}} ``` -Listing 20-6: Handling requests to */* differently from +Listing 21-6: Handling requests to */* differently from other requests We’re only going to be looking at the first line of the HTTP request, so rather @@ -370,7 +370,7 @@ than reading the entire request into a vector, we’re calling `next` to get the first item from the iterator. The first `unwrap` takes care of the `Option` and stops the program if the iterator has no items. The second `unwrap` handles the `Result` and has the same effect as the `unwrap` that was in the `map` added in -Listing 20-2. +Listing 21-2. Next, we check the `request_line` to see if it equals the request line of a GET request to the */* path. If it does, the `if` block returns the contents of our @@ -383,9 +383,9 @@ a moment to respond to all other requests. Run this code now and request *127.0.0.1:7878*; you should get the HTML in *hello.html*. If you make any other request, such as *127.0.0.1:7878/something-else*, you’ll get a connection error like those you -saw when running the code in Listing 20-1 and Listing 20-2. +saw when running the code in Listing 21-1 and Listing 21-2. -Now let’s add the code in Listing 20-7 to the `else` block to return a response +Now let’s add the code in Listing 21-7 to the `else` block to return a response with the status code 404, which signals that the content for the request was not found. We’ll also return some HTML for a page to render in the browser indicating the response to the end user. @@ -393,25 +393,25 @@ indicating the response to the end user. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-07/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-07/src/main.rs:here}} ``` -Listing 20-7: Responding with status code 404 and an +Listing 21-7: Responding with status code 404 and an error page if anything other than */* was requested Here, our response has a status line with status code 404 and the reason phrase `NOT FOUND`. The body of the response will be the HTML in the file *404.html*. You’ll need to create a *404.html* file next to *hello.html* for the error page; again feel free to use any HTML you want or use the example HTML in -Listing 20-8. +Listing 21-8. Filename: 404.html ```html -{{#include ../listings/ch20-web-server/listing-20-07/404.html}} +{{#include ../listings/ch21-web-server/listing-21-07/404.html}} ``` -Listing 20-8: Sample content for the page to send back +Listing 21-8: Sample content for the page to send back with any 404 response With these changes, run your server again. Requesting *127.0.0.1:7878* should @@ -426,16 +426,16 @@ differences are the status line and the filename. Let’s make the code more concise by pulling out those differences into separate `if` and `else` lines that will assign the values of the status line and the filename to variables; we can then use those variables unconditionally in the code to read the file -and write the response. Listing 20-9 shows the resulting code after replacing +and write the response. Listing 21-9 shows the resulting code after replacing the large `if` and `else` blocks. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-09/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-09/src/main.rs:here}} ``` -Listing 20-9: Refactoring the `if` and `else` blocks to +Listing 21-9: Refactoring the `if` and `else` blocks to contain only the code that differs between the two cases Now the `if` and `else` blocks only return the appropriate values for the @@ -447,8 +447,8 @@ The previously duplicated code is now outside the `if` and `else` blocks and uses the `status_line` and `filename` variables. This makes it easier to see the difference between the two cases, and it means we have only one place to update the code if we want to change how the file reading and response writing -work. The behavior of the code in Listing 20-9 will be the same as that in -Listing 20-7. +work. The behavior of the code in Listing 21-9 will be the same as that in +Listing 21-7. Awesome! We now have a simple web server in approximately 40 lines of Rust code that responds to one request with a page of content and responds to all other diff --git a/src/ch21-02-multithreaded.md b/src/ch21-02-multithreaded.md index 82d6fdf8f6..bcb0b133b0 100644 --- a/src/ch21-02-multithreaded.md +++ b/src/ch21-02-multithreaded.md @@ -11,17 +11,17 @@ this, but first, we’ll look at the problem in action. ### Simulating a Slow Request in the Current Server Implementation We’ll look at how a slow-processing request can affect other requests made to -our current server implementation. Listing 20-10 implements handling a request +our current server implementation. Listing 21-10 implements handling a request to */sleep* with a simulated slow response that will cause the server to sleep for 5 seconds before responding. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-10/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-10/src/main.rs:here}} ``` -Listing 20-10: Simulating a slow request by sleeping for +Listing 21-10: Simulating a slow request by sleeping for 5 seconds We switched from `if` to `match` now that we have three cases. We need to @@ -29,10 +29,10 @@ explicitly match on a slice of `request_line` to pattern match against the string literal values; `match` doesn’t do automatic referencing and dereferencing like the equality method does. -The first arm is the same as the `if` block from Listing 20-9. The second arm +The first arm is the same as the `if` block from Listing 21-9. The second arm matches a request to */sleep*. When that request is received, the server will sleep for 5 seconds before rendering the successful HTML page. The third arm is -the same as the `else` block from Listing 20-9. +the same as the `else` block from Listing 21-9. You can see how primitive our server is: real libraries would handle the recognition of multiple requests in a much less verbose way! @@ -103,16 +103,16 @@ every connection. As mentioned earlier, this isn’t our final plan due to the problems with potentially spawning an unlimited number of threads, but it is a starting point to get a working multithreaded server first. Then we’ll add the thread pool as an improvement, and contrasting the two solutions will be -easier. Listing 20-11 shows the changes to make to `main` to spawn a new thread +easier. Listing 21-11 shows the changes to make to `main` to spawn a new thread to handle each stream within the `for` loop. Filename: src/main.rs ```rust,no_run -{{#rustdoc_include ../listings/ch20-web-server/listing-20-11/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-11/src/main.rs:here}} ``` -Listing 20-11: Spawning a new thread for each +Listing 21-11: Spawning a new thread for each stream As you learned in Chapter 16, `thread::spawn` will create a new thread and then @@ -129,16 +129,16 @@ new threads without any limit. We want our thread pool to work in a similar, familiar way so switching from threads to a thread pool doesn’t require large changes to the code that uses -our API. Listing 20-12 shows the hypothetical interface for a `ThreadPool` +our API. Listing 21-12 shows the hypothetical interface for a `ThreadPool` struct we want to use instead of `thread::spawn`. Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch20-web-server/listing-20-12/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-12/src/main.rs:here}} ``` -Listing 20-12: Our ideal `ThreadPool` interface +Listing 21-12: Our ideal `ThreadPool` interface We use `ThreadPool::new` to create a new thread pool with a configurable number of threads, in this case four. Then, in the `for` loop, `pool.execute` has a @@ -152,12 +152,12 @@ compile, but we’ll try so the compiler can guide us in how to fix it. #### Building `ThreadPool` Using Compiler Driven Development -Make the changes in Listing 20-12 to *src/main.rs*, and then let’s use the +Make the changes in Listing 21-12 to *src/main.rs*, and then let’s use the compiler errors from `cargo check` to drive our development. Here is the first error we get: ```console -{{#include ../listings/ch20-web-server/listing-20-12/output.txt}} +{{#include ../listings/ch21-web-server/listing-21-12/output.txt}} ``` Great! This error tells us we need a `ThreadPool` type or module, so we’ll @@ -174,7 +174,7 @@ definition of a `ThreadPool` struct that we can have for now: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/lib.rs}} +{{#rustdoc_include ../listings/ch21-web-server/no-listing-01-define-threadpool-struct/src/lib.rs}} ``` Then edit *main.rs* file to bring `ThreadPool` into scope from the library @@ -183,14 +183,14 @@ crate by adding the following code to the top of *src/main.rs*: Filename: src/main.rs ```rust,ignore -{{#rustdoc_include ../listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/no-listing-01-define-threadpool-struct/src/main.rs:here}} ``` This code still won’t work, but let’s check it again to get the next error that we need to address: ```console -{{#include ../listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt}} +{{#include ../listings/ch21-web-server/no-listing-01-define-threadpool-struct/output.txt}} ``` This error indicates that next we need to create an associated function named @@ -202,7 +202,7 @@ characteristics: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/lib.rs}} +{{#rustdoc_include ../listings/ch21-web-server/no-listing-02-impl-threadpool-new/src/lib.rs}} ``` We chose `usize` as the type of the `size` parameter, because we know that a @@ -214,7 +214,7 @@ ignore --> section of Chapter 3. Let’s check the code again: ```console -{{#include ../listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt}} +{{#include ../listings/ch21-web-server/no-listing-02-impl-threadpool-new/output.txt}} ``` Now the error occurs because we don’t have an `execute` method on `ThreadPool`. @@ -258,7 +258,7 @@ the thread will take to execute. Let’s create an `execute` method on Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/no-listing-03-define-execute/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/no-listing-03-define-execute/src/lib.rs:here}} ``` We still use the `()` after `FnOnce` because this `FnOnce` represents a closure @@ -270,7 +270,7 @@ Again, this is the simplest implementation of the `execute` method: it does nothing, but we’re trying only to make our code compile. Let’s check it again: ```console -{{#include ../listings/ch20-web-server/no-listing-03-define-execute/output.txt}} +{{#include ../listings/ch21-web-server/no-listing-03-define-execute/output.txt}} ``` It compiles! But note that if you try `cargo run` and make a request in the @@ -294,15 +294,15 @@ parameter, because a pool with a negative number of threads makes no sense. However, a pool with zero threads also makes no sense, yet zero is a perfectly valid `usize`. We’ll add code to check that `size` is greater than zero before we return a `ThreadPool` instance and have the program panic if it receives a -zero by using the `assert!` macro, as shown in Listing 20-13. +zero by using the `assert!` macro, as shown in Listing 21-13. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/listing-20-13/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-13/src/lib.rs:here}} ``` -Listing 20-13: Implementing `ThreadPool::new` to panic if +Listing 21-13: Implementing `ThreadPool::new` to panic if `size` is zero We’ve also added some documentation for our `ThreadPool` with doc comments. @@ -342,7 +342,7 @@ closure returns. Let’s try using `JoinHandle` too and see what happens. In our case, the closures we’re passing to the thread pool will handle the connection and not return anything, so `T` will be the unit type `()`. -The code in Listing 20-14 will compile but doesn’t create any threads yet. +The code in Listing 21-14 will compile but doesn’t create any threads yet. We’ve changed the definition of `ThreadPool` to hold a vector of `thread::JoinHandle<()>` instances, initialized the vector with a capacity of `size`, set up a `for` loop that will run some code to create the threads, and @@ -351,10 +351,10 @@ returned a `ThreadPool` instance containing them. Filename: src/lib.rs ```rust,ignore,not_desired_behavior -{{#rustdoc_include ../listings/ch20-web-server/listing-20-14/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-14/src/lib.rs:here}} ``` -Listing 20-14: Creating a vector for `ThreadPool` to hold +Listing 21-14: Creating a vector for `ThreadPool` to hold the threads We’ve brought `std::thread` into scope in the library crate, because we’re @@ -372,7 +372,7 @@ When you run `cargo check` again, it should succeed. #### A `Worker` Struct Responsible for Sending Code from the `ThreadPool` to a Thread -We left a comment in the `for` loop in Listing 20-14 regarding the creation of +We left a comment in the `for` loop in Listing 21-14 regarding the creation of threads. Here, we’ll look at how we actually create threads. The standard library provides `thread::spawn` as a way to create threads, and `thread::spawn` expects to get some code the thread should run as soon as the @@ -409,17 +409,17 @@ set up in this way: a new `Worker` with that `id`, and store the worker in the vector. If you’re up for a challenge, try implementing these changes on your own before -looking at the code in Listing 20-15. +looking at the code in Listing 21-15. -Ready? Here is Listing 20-15 with one way to make the preceding modifications. +Ready? Here is Listing 21-15 with one way to make the preceding modifications. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/listing-20-15/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-15/src/lib.rs:here}} ``` -Listing 20-15: Modifying `ThreadPool` to hold `Worker` +Listing 21-15: Modifying `ThreadPool` to hold `Worker` instances instead of holding threads directly We’ve changed the name of the field on `ThreadPool` from `threads` to `workers` @@ -470,17 +470,17 @@ the `Worker` instances, which will send the job to its thread. Here is the plan: closures of any jobs it receives. Let’s start by creating a channel in `ThreadPool::new` and holding the sender -in the `ThreadPool` instance, as shown in Listing 20-16. The `Job` struct +in the `ThreadPool` instance, as shown in Listing 21-16. The `Job` struct doesn’t hold anything for now but will be the type of item we’re sending down the channel. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/listing-20-16/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-16/src/lib.rs:here}} ``` -Listing 20-16: Modifying `ThreadPool` to store the +Listing 21-16: Modifying `ThreadPool` to store the sender of a channel that transmits `Job` instances In `ThreadPool::new`, we create our new channel and have the pool hold the @@ -489,15 +489,15 @@ sender. This will successfully compile. Let’s try passing a receiver of the channel into each worker as the thread pool creates the channel. We know we want to use the receiver in the thread that the workers spawn, so we’ll reference the `receiver` parameter in the closure. The -code in Listing 20-17 won’t quite compile yet. +code in Listing 21-17 won’t quite compile yet. Filename: src/lib.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch20-web-server/listing-20-17/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-17/src/lib.rs:here}} ``` -Listing 20-17: Passing the receiver to the workers +Listing 21-17: Passing the receiver to the workers We’ve made some small and straightforward changes: we pass the receiver into `Worker::new`, and then we use it inside the closure. @@ -505,7 +505,7 @@ We’ve made some small and straightforward changes: we pass the receiver into When we try to check this code, we get this error: ```console -{{#include ../listings/ch20-web-server/listing-20-17/output.txt}} +{{#include ../listings/ch21-web-server/listing-21-17/output.txt}} ``` The code is trying to pass `receiver` to multiple `Worker` instances. This @@ -523,15 +523,15 @@ Recall the thread-safe smart pointers discussed in Chapter 16: to share ownership across multiple threads and allow the threads to mutate the value, we need to use `Arc>`. The `Arc` type will let multiple workers own the receiver, and `Mutex` will ensure that only one worker gets a job from the -receiver at a time. Listing 20-18 shows the changes we need to make. +receiver at a time. Listing 21-18 shows the changes we need to make. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/listing-20-18/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-18/src/lib.rs:here}} ``` -Listing 20-18: Sharing the receiver among the workers +Listing 21-18: Sharing the receiver among the workers using `Arc` and `Mutex` In `ThreadPool::new`, we put the receiver in an `Arc` and a `Mutex`. For each @@ -547,15 +547,15 @@ Let’s finally implement the `execute` method on `ThreadPool`. We’ll also cha closure that `execute` receives. As discussed in the [“Creating Type Synonyms with Type Aliases”][creating-type-synonyms-with-type-aliases] section of Chapter 19, type aliases allow us to make long types shorter for -ease of use. Look at Listing 20-19. +ease of use. Look at Listing 21-19. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/listing-20-19/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-19/src/lib.rs:here}} ``` -Listing 20-19: Creating a `Job` type alias for a `Box` +Listing 21-19: Creating a `Job` type alias for a `Box` that holds each closure and then sending the job down the channel After creating a new `Job` instance using the closure we get in `execute`, we @@ -571,15 +571,15 @@ But we’re not quite done yet! In the worker, our closure being passed to `thread::spawn` still only *references* the receiving end of the channel. Instead, we need the closure to loop forever, asking the receiving end of the channel for a job and running the job when it gets one. Let’s make the change -shown in Listing 20-20 to `Worker::new`. +shown in Listing 21-20 to `Worker::new`. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch20-web-server/listing-20-20/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch21-web-server/listing-21-20/src/lib.rs:here}} ``` -Listing 20-20: Receiving and executing the jobs in the +Listing 21-20: Receiving and executing the jobs in the worker’s thread Here, we first call `lock` on the `receiver` to acquire the mutex, and then we @@ -603,7 +603,7 @@ Our thread pool is now in a working state! Give it a `cargo run` and make some requests: section in @@ -278,15 +278,15 @@ abstraction to the unsafe code with an implementation of the function that uses `unsafe` code in a safe way, because it creates only valid pointers from the data this function has access to. -In contrast, the use of `slice::from_raw_parts_mut` in Listing 19-7 would +In contrast, the use of `slice::from_raw_parts_mut` in Listing 20-7 would likely crash when the slice is used. This code takes an arbitrary memory location and creates a slice 10,000 items long. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-07/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-07/src/main.rs:here}} ``` -Listing 19-7: Creating a slice from an arbitrary memory +Listing 20-7: Creating a slice from an arbitrary memory location We don’t own the memory at this arbitrary location, and there is no guarantee @@ -301,7 +301,7 @@ and use of a *Foreign Function Interface (FFI)*. An FFI is a way for a programming language to define functions and enable a different (foreign) programming language to call those functions. -Listing 19-8 demonstrates how to set up an integration with the `abs` function +Listing 20-8 demonstrates how to set up an integration with the `abs` function from the C standard library. Functions declared within `extern` blocks are always unsafe to call from Rust code. The reason is that other languages don’t enforce Rust’s rules and guarantees, and Rust can’t check them, so @@ -310,10 +310,10 @@ responsibility falls on the programmer to ensure safety. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-08/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-08/src/main.rs}} ``` -Listing 19-8: Declaring and calling an `extern` function +Listing 20-8: Declaring and calling an `extern` function defined in another language Within the `extern "C"` block, we list the names and signatures of external @@ -353,17 +353,17 @@ In this book, we’ve not yet talked about *global variables*, which Rust does support but can be problematic with Rust’s ownership rules. If two threads are accessing the same mutable global variable, it can cause a data race. -In Rust, global variables are called *static* variables. Listing 19-9 shows an +In Rust, global variables are called *static* variables. Listing 20-9 shows an example declaration and use of a static variable with a string slice as a value. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-09/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-09/src/main.rs}} ``` -Listing 19-9: Defining and using an immutable static +Listing 20-9: Defining and using an immutable static variable Static variables are similar to constants, which we discussed in the @@ -380,16 +380,16 @@ values in a static variable have a fixed address in memory. Using the value will always access the same data. Constants, on the other hand, are allowed to duplicate their data whenever they’re used. Another difference is that static variables can be mutable. Accessing and modifying mutable static variables is -*unsafe*. Listing 19-10 shows how to declare, access, and modify a mutable +*unsafe*. Listing 20-10 shows how to declare, access, and modify a mutable static variable named `COUNTER`. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-10/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-10/src/main.rs}} ``` -Listing 19-10: Reading from or writing to a mutable +Listing 20-10: Reading from or writing to a mutable static variable is unsafe As with regular variables, we specify mutability using the `mut` keyword. Any @@ -410,13 +410,13 @@ We can use `unsafe` to implement an unsafe trait. A trait is unsafe when at least one of its methods has some invariant that the compiler can’t verify. We declare that a trait is `unsafe` by adding the `unsafe` keyword before `trait` and marking the implementation of the trait as `unsafe` too, as shown in -Listing 19-11. +Listing 20-11. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-11/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-11/src/main.rs}} ``` -Listing 19-11: Defining and implementing an unsafe +Listing 20-11: Defining and implementing an unsafe trait By using `unsafe impl`, we’re promising that we’ll uphold the invariants that diff --git a/src/ch20-03-advanced-traits.md b/src/ch20-03-advanced-traits.md index a32b0e1da7..7dc333e782 100644 --- a/src/ch20-03-advanced-traits.md +++ b/src/ch20-03-advanced-traits.md @@ -23,13 +23,13 @@ One example of a trait with an associated type is the `Iterator` trait that the standard library provides. The associated type is named `Item` and stands in for the type of the values the type implementing the `Iterator` trait is iterating over. The definition of the `Iterator` trait is as shown in Listing -19-12. +20-12. ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-12/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-12/src/lib.rs}} ``` -Listing 19-12: The definition of the `Iterator` trait +Listing 20-12: The definition of the `Iterator` trait that has an associated type `Item` The type `Item` is a placeholder, and the `next` method’s definition shows that @@ -46,20 +46,20 @@ the `Item` type is `u32`: Filename: src/lib.rs ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs:ch19}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs:ch19}} ``` This syntax seems comparable to that of generics. So why not just define the -`Iterator` trait with generics, as shown in Listing 19-13? +`Iterator` trait with generics, as shown in Listing 20-13? ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-13/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-13/src/lib.rs}} ``` -Listing 19-13: A hypothetical definition of the +Listing 20-13: A hypothetical definition of the `Iterator` trait using generics -The difference is that when using generics, as in Listing 19-13, we must +The difference is that when using generics, as in Listing 20-13, we must annotate the types in each implementation; because we can also implement `Iterator for Counter` or any other type, we could have multiple implementations of `Iterator` for `Counter`. In other words, when a trait has a @@ -69,7 +69,7 @@ the concrete types of the generic type parameters each time. When we use the indicate which implementation of `Iterator` we want to use. With associated types, we don’t need to annotate types because we can’t -implement a trait on a type multiple times. In Listing 19-12 with the +implement a trait on a type multiple times. In Listing 20-12 with the definition that uses associated types, we can only choose what the type of `Item` will be once, because there can only be one `impl Iterator for Counter`. We don’t have to specify that we want an iterator of `u32` values everywhere @@ -94,17 +94,17 @@ in particular situations. Rust doesn’t allow you to create your own operators or overload arbitrary operators. But you can overload the operations and corresponding traits listed in `std::ops` by implementing the traits associated with the operator. For -example, in Listing 19-14 we overload the `+` operator to add two `Point` +example, in Listing 20-14 we overload the `+` operator to add two `Point` instances together. We do this by implementing the `Add` trait on a `Point` struct: Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-14/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-14/src/main.rs}} ``` -Listing 19-14: Implementing the `Add` trait to overload +Listing 20-14: Implementing the `Add` trait to overload the `+` operator for `Point` instances The `add` method adds the `x` values of two `Point` instances and the `y` @@ -142,15 +142,15 @@ units. This thin wrapping of an existing type in another struct is known as the Pattern to Implement External Traits on External Types”][newtype] section. We want to add values in millimeters to values in meters and have the implementation of `Add` do the conversion correctly. We can implement `Add` -for `Millimeters` with `Meters` as the `Rhs`, as shown in Listing 19-15. +for `Millimeters` with `Meters` as the `Rhs`, as shown in Listing 20-15. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-15/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-15/src/lib.rs}} ``` -Listing 19-15: Implementing the `Add` trait on +Listing 20-15: Implementing the `Add` trait on `Millimeters` to add `Millimeters` to `Meters` To add `Millimeters` and `Meters`, we specify `impl Add` to set the @@ -181,7 +181,7 @@ on one type. It’s also possible to implement a method directly on the type wit the same name as methods from traits. When calling methods with the same name, you’ll need to tell Rust which one you -want to use. Consider the code in Listing 19-16 where we’ve defined two traits, +want to use. Consider the code in Listing 20-16 where we’ve defined two traits, `Pilot` and `Wizard`, that both have a method called `fly`. We then implement both traits on a type `Human` that already has a method named `fly` implemented on it. Each `fly` method does something different. @@ -189,23 +189,23 @@ on it. Each `fly` method does something different. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-16/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-16/src/main.rs:here}} ``` -Listing 19-16: Two traits are defined to have a `fly` +Listing 20-16: Two traits are defined to have a `fly` method and are implemented on the `Human` type, and a `fly` method is implemented on `Human` directly When we call `fly` on an instance of `Human`, the compiler defaults to calling -the method that is directly implemented on the type, as shown in Listing 19-17. +the method that is directly implemented on the type, as shown in Listing 20-17. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-17/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-17/src/main.rs:here}} ``` -Listing 19-17: Calling `fly` on an instance of +Listing 20-17: Calling `fly` on an instance of `Human` Running this code will print `*waving arms furiously*`, showing that Rust @@ -213,27 +213,27 @@ called the `fly` method implemented on `Human` directly. To call the `fly` methods from either the `Pilot` trait or the `Wizard` trait, we need to use more explicit syntax to specify which `fly` method we mean. -Listing 19-18 demonstrates this syntax. +Listing 20-18 demonstrates this syntax. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-18/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-18/src/main.rs:here}} ``` -Listing 19-18: Specifying which trait’s `fly` method we +Listing 20-18: Specifying which trait’s `fly` method we want to call Specifying the trait name before the method name clarifies to Rust which implementation of `fly` we want to call. We could also write `Human::fly(&person)`, which is equivalent to the `person.fly()` that we used -in Listing 19-18, but this is a bit longer to write if we don’t need to +in Listing 20-18, but this is a bit longer to write if we don’t need to disambiguate. Running this code prints the following: ```console -{{#include ../listings/ch19-advanced-features/listing-19-18/output.txt}} +{{#include ../listings/ch20-advanced-features/listing-20-18/output.txt}} ``` Because the `fly` method takes a `self` parameter, if we had two *types* that @@ -243,7 +243,7 @@ trait to use based on the type of `self`. However, associated functions that are not methods don’t have a `self` parameter. When there are multiple types or traits that define non-method functions with the same function name, Rust doesn't always know which type you -mean unless you use *fully qualified syntax*. For example, in Listing 19-19 we +mean unless you use *fully qualified syntax*. For example, in Listing 20-19 we create a trait for an animal shelter that wants to name all baby dogs *Spot*. We make an `Animal` trait with an associated non-method function `baby_name`. The `Animal` trait is implemented for the struct `Dog`, on which we also @@ -252,10 +252,10 @@ provide an associated non-method function `baby_name` directly. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-19/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-19/src/main.rs}} ``` -Listing 19-19: A trait with an associated function and a +Listing 20-19: A trait with an associated function and a type with an associated function of the same name that also implements the trait @@ -269,22 +269,22 @@ In `main`, we call the `Dog::baby_name` function, which calls the associated function defined on `Dog` directly. This code prints the following: ```console -{{#include ../listings/ch19-advanced-features/listing-19-19/output.txt}} +{{#include ../listings/ch20-advanced-features/listing-20-19/output.txt}} ``` This output isn’t what we wanted. We want to call the `baby_name` function that is part of the `Animal` trait that we implemented on `Dog` so the code prints `A baby dog is called a puppy`. The technique of specifying the trait name that -we used in Listing 19-18 doesn’t help here; if we change `main` to the code in -Listing 19-20, we’ll get a compilation error. +we used in Listing 20-18 doesn’t help here; if we change `main` to the code in +Listing 20-20, we’ll get a compilation error. Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-20/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-20/src/main.rs:here}} ``` -Listing 19-20: Attempting to call the `baby_name` +Listing 20-20: Attempting to call the `baby_name` function from the `Animal` trait, but Rust doesn’t know which implementation to use @@ -293,21 +293,21 @@ other types that implement the `Animal` trait, Rust can’t figure out which implementation of `Animal::baby_name` we want. We’ll get this compiler error: ```console -{{#include ../listings/ch19-advanced-features/listing-19-20/output.txt}} +{{#include ../listings/ch20-advanced-features/listing-20-20/output.txt}} ``` To disambiguate and tell Rust that we want to use the implementation of `Animal` for `Dog` as opposed to the implementation of `Animal` for some other -type, we need to use fully qualified syntax. Listing 19-21 demonstrates how to +type, we need to use fully qualified syntax. Listing 20-21 demonstrates how to use fully qualified syntax. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-21/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-21/src/main.rs:here}} ``` -Listing 19-21: Using fully qualified syntax to specify +Listing 20-21: Using fully qualified syntax to specify that we want to call the `baby_name` function from the `Animal` trait as implemented on `Dog` @@ -317,7 +317,7 @@ implemented on `Dog` by saying that we want to treat the `Dog` type as an `Animal` for this function call. This code will now print what we want: ```console -{{#include ../listings/ch19-advanced-features/listing-19-21/output.txt}} +{{#include ../listings/ch20-advanced-features/listing-20-21/output.txt}} ``` In general, fully qualified syntax is defined as follows: @@ -362,16 +362,16 @@ In the implementation of the `outline_print` method, we want to use the `OutlinePrint` trait will work only for types that also implement `Display` and provide the functionality that `OutlinePrint` needs. We can do that in the trait definition by specifying `OutlinePrint: Display`. This technique is -similar to adding a trait bound to the trait. Listing 19-22 shows an +similar to adding a trait bound to the trait. Listing 20-22 shows an implementation of the `OutlinePrint` trait. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-22/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-22/src/main.rs:here}} ``` -Listing 19-22: Implementing the `OutlinePrint` trait that +Listing 20-22: Implementing the `OutlinePrint` trait that requires the functionality from `Display` Because we’ve specified that `OutlinePrint` requires the `Display` trait, we @@ -387,13 +387,13 @@ doesn’t implement `Display`, such as the `Point` struct: Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs:here}} ``` We get an error saying that `Display` is required but not implemented: ```console -{{#include ../listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt}} +{{#include ../listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt}} ``` To fix this, we implement `Display` on `Point` and satisfy the constraint that @@ -402,7 +402,7 @@ To fix this, we implement `Display` on `Point` and satisfy the constraint that Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-03-impl-display-for-point/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-03-impl-display-for-point/src/main.rs:here}} ``` Then implementing the `OutlinePrint` trait on `Point` will compile @@ -429,15 +429,15 @@ As an example, let’s say we want to implement `Display` on `Vec`, which the orphan rule prevents us from doing directly because the `Display` trait and the `Vec` type are defined outside our crate. We can make a `Wrapper` struct that holds an instance of `Vec`; then we can implement `Display` on -`Wrapper` and use the `Vec` value, as shown in Listing 19-23. +`Wrapper` and use the `Vec` value, as shown in Listing 20-23. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-23/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-23/src/main.rs}} ``` -Listing 19-23: Creating a `Wrapper` type around +Listing 20-23: Creating a `Wrapper` type around `Vec` to implement `Display` The implementation of `Display` uses `self.0` to access the inner `Vec`, diff --git a/src/ch20-04-advanced-types.md b/src/ch20-04-advanced-types.md index 427c108aa4..a626529842 100644 --- a/src/ch20-04-advanced-types.md +++ b/src/ch20-04-advanced-types.md @@ -15,7 +15,7 @@ the `!` type and dynamically sized types. The newtype pattern is also useful for tasks beyond those we’ve discussed so far, including statically enforcing that values are never confused and indicating the units of a value. You saw an example of using newtypes to -indicate units in Listing 19-15: recall that the `Millimeters` and `Meters` +indicate units in Listing 20-15: recall that the `Millimeters` and `Meters` structs wrapped `u32` values in a newtype. If we wrote a function with a parameter of type `Millimeters`, we couldn’t compile a program that accidentally tried to call that function with a value of type `Meters` or a @@ -43,16 +43,16 @@ another name. For this we use the `type` keyword. For example, we can create the alias `Kilometers` to `i32` like so: ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-04-kilometers-alias/src/main.rs:here}} ``` Now, the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters` -and `Meters` types we created in Listing 19-15, `Kilometers` is not a separate, +and `Meters` types we created in Listing 20-15, `Kilometers` is not a separate, new type. Values that have the type `Kilometers` will be treated the same as values of type `i32`: ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:there}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-04-kilometers-alias/src/main.rs:there}} ``` Because `Kilometers` and `i32` are the same type, we can add values of both @@ -71,23 +71,23 @@ Box Writing this lengthy type in function signatures and as type annotations all over the code can be tiresome and error prone. Imagine having a project full of -code like that in Listing 19-24. +code like that in Listing 20-24. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-24/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-24/src/main.rs:here}} ``` -Listing 19-24: Using a long type in many places +Listing 20-24: Using a long type in many places A type alias makes this code more manageable by reducing the repetition. In -Listing 19-25, we’ve introduced an alias named `Thunk` for the verbose type and +Listing 20-25, we’ve introduced an alias named `Thunk` for the verbose type and can replace all uses of the type with the shorter alias `Thunk`. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-25/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-25/src/main.rs:here}} ``` -Listing 19-25: Introducing a type alias `Thunk` to reduce +Listing 20-25: Introducing a type alias `Thunk` to reduce repetition This code is much easier to read and write! Choosing a meaningful name for a @@ -104,14 +104,14 @@ possible I/O errors. Many of the functions in `std::io` will be returning the `Write` trait: ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-05-write-trait/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-05-write-trait/src/lib.rs}} ``` The `Result<..., Error>` is repeated a lot. As such, `std::io` has this type alias declaration: ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-06-result-alias/src/lib.rs:here}} ``` Because this declaration is in the `std::io` module, we can use the fully @@ -120,7 +120,7 @@ filled in as `std::io::Error`. The `Write` trait function signatures end up looking like this: ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:there}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-06-result-alias/src/lib.rs:there}} ``` The type alias helps in two ways: it makes code easier to write *and* it gives @@ -136,7 +136,7 @@ because it stands in the place of the return type when a function will never return. Here is an example: ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-07-never-type/src/lib.rs:here}} ``` This code is read as “the function `bar` returns never.” Functions that return @@ -145,13 +145,13 @@ so `bar` can never possibly return. But what use is a type you can never create values for? Recall the code from Listing 2-5, part of the number guessing game; we’ve reproduced a bit of it -here in Listing 19-26. +here in Listing 20-26. ```rust,ignore {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs:ch19}} ``` -Listing 19-26: A `match` with an arm that ends in +Listing 20-26: A `match` with an arm that ends in `continue` At the time, we skipped over some details in this code. In Chapter 6 in [“The @@ -160,13 +160,13 @@ section, we discussed that `match` arms must all return the same type. So, for example, the following code doesn’t work: ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-08-match-arms-different-types/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-08-match-arms-different-types/src/main.rs:here}} ``` The type of `guess` in this code would have to be an integer *and* a string, and Rust requires that `guess` have only one type. So what does `continue` return? How were we allowed to return a `u32` from one arm and have another arm -that ends with `continue` in Listing 19-26? +that ends with `continue` in Listing 20-26? As you might have guessed, `continue` has a `!` value. That is, when Rust computes the type of `guess`, it looks at both match arms, the former with a @@ -184,10 +184,10 @@ function that we call on `Option` values to produce a value or panic with this definition: ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-09-unwrap-definition/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-09-unwrap-definition/src/lib.rs:here}} ``` -In this code, the same thing happens as in the `match` in Listing 19-26: Rust +In this code, the same thing happens as in the `match` in Listing 20-26: Rust sees that `val` has the type `T` and `panic!` has the type `!`, so the result of the overall `match` expression is `T`. This code works because `panic!` doesn’t produce a value; it ends the program. In the `None` case, we won’t be @@ -196,7 +196,7 @@ returning a value from `unwrap`, so this code is valid. One final expression that has the type `!` is a `loop`: ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-10-loop-returns-never/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-10-loop-returns-never/src/main.rs:here}} ``` Here, the loop never ends, so `!` is the value of the expression. However, this @@ -218,7 +218,7 @@ we can’t create a variable of type `str`, nor can we take an argument of type `str`. Consider the following code, which does not work: ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-11-cant-create-str/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-11-cant-create-str/src/main.rs:here}} ``` Rust needs to know how much memory to allocate for any value of a particular @@ -259,13 +259,13 @@ implicitly adds a bound on `Sized` to every generic function. That is, a generic function definition like this: ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs}} ``` is actually treated as though we had written this: ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs}} ``` By default, generic functions will work only on types that have a known size at @@ -273,7 +273,7 @@ compile time. However, you can use the following special syntax to relax this restriction: ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs}} ``` A trait bound on `?Sized` means “`T` may or may not be `Sized`” and this diff --git a/src/ch20-05-advanced-functions-and-closures.md b/src/ch20-05-advanced-functions-and-closures.md index d0de1dfd0a..ac8305736d 100644 --- a/src/ch20-05-advanced-functions-and-closures.md +++ b/src/ch20-05-advanced-functions-and-closures.md @@ -14,7 +14,7 @@ with function pointers will allow you to use functions as arguments to other functions. The syntax for specifying that a parameter is a function pointer is similar to -that of closures, as shown in Listing 19-27, where we’ve defined a function +that of closures, as shown in Listing 20-27, where we’ve defined a function `add_one` that adds one to its parameter. The function `do_twice` takes two parameters: a function pointer to any function that takes an `i32` parameter and returns an `i32`, and one `i32` value. The `do_twice` function calls the @@ -25,10 +25,10 @@ results together. The `main` function calls `do_twice` with the arguments Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-27/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-27/src/main.rs}} ``` -Listing 19-27: Using the `fn` type to accept a function +Listing 20-27: Using the `fn` type to accept a function pointer as an argument This code prints `The answer is: 12`. We specify that the parameter `f` in @@ -56,14 +56,14 @@ trait in the standard library. To use the `map` function to turn a vector of numbers into a vector of strings, we could use a closure, like this: ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-15-map-closure/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-15-map-closure/src/main.rs:here}} ``` Or we could name a function as the argument to `map` instead of the closure, like this: ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-16-map-function/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-16-map-function/src/main.rs:here}} ``` Note that we must use the fully qualified syntax that we talked about earlier @@ -79,7 +79,7 @@ implement the closure traits, which means we can specify the initializer functions as arguments for methods that take closures, like so: ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-17-map-initializer/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-17-map-initializer/src/main.rs:here}} ``` Here we create `Status::Value` instances using each `u32` value in the range @@ -99,13 +99,13 @@ pointer `fn` as a return type, for example. The following code tries to return a closure directly, but it won’t compile: ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-18-returns-closure/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs}} ``` The compiler error is as follows: ```console -{{#include ../listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt}} +{{#include ../listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt}} ``` The error references the `Sized` trait again! Rust doesn’t know how much space @@ -113,7 +113,7 @@ it will need to store the closure. We saw a solution to this problem earlier. We can use a trait object: ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs}} ``` This code will compile just fine. For more about trait objects, refer to the diff --git a/src/ch20-06-macros.md b/src/ch20-06-macros.md index f24a818c18..b9b97201cc 100644 --- a/src/ch20-06-macros.md +++ b/src/ch20-06-macros.md @@ -73,15 +73,15 @@ We could also use the `vec!` macro to make a vector of two integers or a vector of five string slices. We wouldn’t be able to use a function to do the same because we wouldn’t know the number or type of values up front. -Listing 19-28 shows a slightly simplified definition of the `vec!` macro. +Listing 20-28 shows a slightly simplified definition of the `vec!` macro. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-28/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-28/src/lib.rs}} ``` -Listing 19-28: A simplified version of the `vec!` macro +Listing 20-28: A simplified version of the `vec!` macro definition > Note: The actual definition of the `vec!` macro in the standard library @@ -107,7 +107,7 @@ one arm. Valid pattern syntax in macro definitions is different than the pattern syntax covered in Chapter 18 because macro patterns are matched against Rust code structure rather than values. Let’s walk through what the pattern pieces in -Listing 19-28 mean; for the full macro pattern syntax, see the [Rust +Listing 20-28 mean; for the full macro pattern syntax, see the [Rust Reference][ref]. First, we use a set of parentheses to encompass the whole pattern. We use a @@ -160,7 +160,7 @@ attribute-like, and function-like, and all work in a similar fashion. When creating procedural macros, the definitions must reside in their own crate with a special crate type. This is for complex technical reasons that we hope -to eliminate in the future. In Listing 19-29, we show how to define a +to eliminate in the future. In Listing 20-29, we show how to define a procedural macro, where `some_attribute` is a placeholder for using a specific macro variety. @@ -174,7 +174,7 @@ pub fn some_name(input: TokenStream) -> TokenStream { } ``` -Listing 19-29: An example of defining a procedural +Listing 20-29: An example of defining a procedural macro The function that defines a procedural macro takes a `TokenStream` as an input @@ -200,15 +200,15 @@ we’ll provide a procedural macro so users can annotate their type with function. The default implementation will print `Hello, Macro! My name is TypeName!` where `TypeName` is the name of the type on which this trait has been defined. In other words, we’ll write a crate that enables another -programmer to write code like Listing 19-30 using our crate. +programmer to write code like Listing 20-30 using our crate. Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-30/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-30/src/main.rs}} ``` -Listing 19-30: The code a user of our crate will be able +Listing 20-30: The code a user of our crate will be able to write when using our procedural macro This code will print `Hello, Macro! My name is Pancakes!` when we’re done. The @@ -223,14 +223,14 @@ Next, we’ll define the `HelloMacro` trait and its associated function: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/src/lib.rs}} ``` We have a trait and its function. At this point, our crate user could implement the trait to achieve the desired functionality, like so: ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/src/main.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/src/main.rs}} ``` However, they would need to write the implementation block for each type they @@ -272,20 +272,20 @@ in a moment, so we need to add them as dependencies. Add the following to the Filename: hello_macro_derive/Cargo.toml ```toml -{{#include ../listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml:6:12}} +{{#include ../listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/Cargo.toml:6:12}} ``` -To start defining the procedural macro, place the code in Listing 19-31 into +To start defining the procedural macro, place the code in Listing 20-31 into your *src/lib.rs* file for the `hello_macro_derive` crate. Note that this code won’t compile until we add a definition for the `impl_hello_macro` function. Filename: hello_macro_derive/src/lib.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/src/lib.rs}} ``` -Listing 19-31: Code that most procedural macro crates +Listing 20-31: Code that most procedural macro crates will require in order to process Rust code Notice that we’ve split the code into the `hello_macro_derive` function, which @@ -318,7 +318,7 @@ The `hello_macro_derive` function first converts the `input` from a `TokenStream` to a data structure that we can then interpret and perform operations on. This is where `syn` comes into play. The `parse` function in `syn` takes a `TokenStream` and returns a `DeriveInput` struct representing the -parsed Rust code. Listing 19-32 shows the relevant parts of the `DeriveInput` +parsed Rust code. Listing 20-32 shows the relevant parts of the `DeriveInput` struct we get from parsing the `struct Pancakes;` string: ```rust,ignore @@ -341,8 +341,8 @@ DeriveInput { } ``` -Listing 19-32: The `DeriveInput` instance we get when -parsing the code that has the macro’s attribute in Listing 19-30 +Listing 20-32: The `DeriveInput` instance we get when +parsing the code that has the macro’s attribute in Listing 20-30 The fields of this struct show that the Rust code we’ve parsed is a unit struct with the `ident` (identifier, meaning the name) of `Pancakes`. There are more @@ -366,24 +366,24 @@ about what went wrong by using `panic!` or `expect`. Now that we have the code to turn the annotated Rust code from a `TokenStream` into a `DeriveInput` instance, let’s generate the code that implements the -`HelloMacro` trait on the annotated type, as shown in Listing 19-33. +`HelloMacro` trait on the annotated type, as shown in Listing 20-33. Filename: hello_macro_derive/src/lib.rs ```rust,ignore -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-33/hello_macro/hello_macro_derive/src/lib.rs:here}} ``` -Listing 19-33: Implementing the `HelloMacro` trait using +Listing 20-33: Implementing the `HelloMacro` trait using the parsed Rust code We get an `Ident` struct instance containing the name (identifier) of the -annotated type using `ast.ident`. The struct in Listing 19-32 shows that when -we run the `impl_hello_macro` function on the code in Listing 19-30, the +annotated type using `ast.ident`. The struct in Listing 20-32 shows that when +we run the `impl_hello_macro` function on the code in Listing 20-30, the `ident` we get will have the `ident` field with a value of `"Pancakes"`. Thus, -the `name` variable in Listing 19-33 will contain an `Ident` struct instance +the `name` variable in Listing 20-33 will contain an `Ident` struct instance that, when printed, will be the string `"Pancakes"`, the name of the struct in -Listing 19-30. +Listing 20-30. The `quote!` macro lets us define the Rust code that we want to return. The compiler expects something different to the direct result of the `quote!` @@ -412,7 +412,7 @@ saves an allocation by converting `#name` to a string literal at compile time. At this point, `cargo build` should complete successfully in both `hello_macro` and `hello_macro_derive`. Let’s hook up these crates to the code in Listing -19-30 to see the procedural macro in action! Create a new binary project in +20-30 to see the procedural macro in action! Create a new binary project in your *projects* directory using `cargo new pancakes`. We need to add `hello_macro` and `hello_macro_derive` as dependencies in the `pancakes` crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` and @@ -420,10 +420,10 @@ crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` an dependencies; if not, you can specify them as `path` dependencies as follows: ```toml -{{#include ../listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml:7:9}} +{{#include ../listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml:7:9}} ``` -Put the code in Listing 19-30 into *src/main.rs*, and run `cargo run`: it +Put the code in Listing 20-30 into *src/main.rs*, and run `cargo run`: it should print `Hello, Macro! My name is Pancakes!` The implementation of the `HelloMacro` trait from the procedural macro was included without the `pancakes` crate needing to implement it; the `#[derive(HelloMacro)]` added the From 1f6ce678419e9841b34fa0bf21b75a5b6d67c1f4 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 26 Sep 2024 14:03:07 -0600 Subject: [PATCH 244/249] Ch. 17: Listings for Ch. 18 -> Ch. 19 --- .../listing-19-01}/Cargo.lock | 0 .../listing-19-01}/Cargo.toml | 0 .../listing-19-01}/src/main.rs | 0 .../listing-19-02}/Cargo.lock | 0 .../listing-19-02}/Cargo.toml | 0 .../listing-19-02}/src/main.rs | 0 .../listing-19-03}/Cargo.lock | 0 .../listing-19-03}/Cargo.toml | 0 .../listing-19-03}/output.txt | 0 .../listing-19-03}/src/main.rs | 0 .../listing-19-04}/Cargo.lock | 0 .../listing-19-04}/Cargo.toml | 0 .../listing-19-04}/src/main.rs | 0 .../listing-19-05}/Cargo.lock | 0 .../listing-19-05}/Cargo.toml | 0 .../listing-19-05}/output.txt | 0 .../listing-19-05}/src/main.rs | 0 .../listing-19-06}/Cargo.lock | 0 .../listing-19-06}/Cargo.toml | 0 .../listing-19-06}/src/main.rs | 0 .../listing-19-07}/Cargo.lock | 0 .../listing-19-07}/Cargo.toml | 0 .../listing-19-07}/src/main.rs | 0 .../listing-19-08}/Cargo.lock | 0 .../listing-19-08}/Cargo.toml | 0 .../listing-19-08}/output.txt | 0 .../listing-19-08}/src/main.rs | 0 .../listing-19-09}/Cargo.lock | 0 .../listing-19-09}/Cargo.toml | 0 .../listing-19-09}/src/main.rs | 0 .../listing-19-10}/Cargo.lock | 0 .../listing-19-10}/Cargo.toml | 0 .../listing-19-10}/output.txt | 0 .../listing-19-10}/src/main.rs | 0 .../listing-19-11}/Cargo.lock | 0 .../listing-19-11}/Cargo.toml | 0 .../listing-19-11}/src/main.rs | 0 .../listing-19-12}/Cargo.lock | 0 .../listing-19-12}/Cargo.toml | 0 .../listing-19-12}/src/main.rs | 0 .../listing-19-13}/Cargo.lock | 0 .../listing-19-13}/Cargo.toml | 0 .../listing-19-13}/src/main.rs | 0 .../listing-19-14}/Cargo.lock | 0 .../listing-19-14}/Cargo.toml | 0 .../listing-19-14}/src/main.rs | 0 .../listing-19-15}/Cargo.lock | 0 .../listing-19-15}/Cargo.toml | 0 .../listing-19-15}/src/main.rs | 0 .../listing-19-16}/Cargo.lock | 0 .../listing-19-16}/Cargo.toml | 0 .../listing-19-16}/src/main.rs | 0 .../listing-19-17}/Cargo.lock | 0 .../listing-19-17}/Cargo.toml | 0 .../listing-19-17}/src/main.rs | 0 .../listing-19-18}/Cargo.lock | 0 .../listing-19-18}/Cargo.toml | 0 .../listing-19-18}/src/main.rs | 0 .../listing-19-19}/Cargo.lock | 0 .../listing-19-19}/Cargo.toml | 0 .../listing-19-19}/src/main.rs | 0 .../listing-19-20}/Cargo.lock | 0 .../listing-19-20}/Cargo.toml | 0 .../listing-19-20}/src/main.rs | 0 .../listing-19-21}/Cargo.lock | 0 .../listing-19-21}/Cargo.toml | 0 .../listing-19-21}/src/main.rs | 0 .../listing-19-22}/Cargo.lock | 0 .../listing-19-22}/Cargo.toml | 0 .../listing-19-22}/src/main.rs | 0 .../listing-19-23}/Cargo.lock | 0 .../listing-19-23}/Cargo.toml | 0 .../listing-19-23}/src/main.rs | 0 .../listing-19-24}/Cargo.lock | 0 .../listing-19-24}/Cargo.toml | 0 .../listing-19-24}/src/main.rs | 0 .../listing-19-25}/Cargo.lock | 0 .../listing-19-25}/Cargo.toml | 0 .../listing-19-25}/output.txt | 0 .../listing-19-25}/rustfmt-ignore | 0 .../listing-19-25}/src/main.rs | 0 .../listing-19-26}/Cargo.lock | 0 .../listing-19-26}/Cargo.toml | 0 .../listing-19-26}/src/main.rs | 0 .../listing-19-27}/Cargo.lock | 0 .../listing-19-27}/Cargo.toml | 0 .../listing-19-27}/src/main.rs | 0 .../listing-19-28}/Cargo.lock | 0 .../listing-19-28}/Cargo.toml | 0 .../listing-19-28}/src/main.rs | 0 .../listing-19-29}/Cargo.lock | 0 .../listing-19-29}/Cargo.toml | 0 .../listing-19-29}/src/main.rs | 0 .../no-listing-01-literals/Cargo.lock | 0 .../no-listing-01-literals/Cargo.toml | 0 .../no-listing-01-literals/src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 .../no-listing-03-ranges/Cargo.lock | 0 .../no-listing-03-ranges/Cargo.toml | 0 .../no-listing-03-ranges/src/main.rs | 0 .../no-listing-04-ranges-of-char/Cargo.lock | 0 .../no-listing-04-ranges-of-char/Cargo.toml | 0 .../no-listing-04-ranges-of-char/src/main.rs | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../src/main.rs | 0 src/ch19-01-all-the-places-for-patterns.md | 50 +++---- src/ch19-02-refutability.md | 22 +-- src/ch19-03-pattern-syntax.md | 134 +++++++++--------- 111 files changed, 103 insertions(+), 103 deletions(-) rename listings/{ch18-patterns-and-matching/listing-18-01 => ch19-patterns-and-matching/listing-19-01}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-01 => ch19-patterns-and-matching/listing-19-01}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-01 => ch19-patterns-and-matching/listing-19-01}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-02 => ch19-patterns-and-matching/listing-19-02}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-02 => ch19-patterns-and-matching/listing-19-02}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-02 => ch19-patterns-and-matching/listing-19-02}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-03 => ch19-patterns-and-matching/listing-19-03}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-03 => ch19-patterns-and-matching/listing-19-03}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-03 => ch19-patterns-and-matching/listing-19-03}/output.txt (100%) rename listings/{ch18-patterns-and-matching/listing-18-03 => ch19-patterns-and-matching/listing-19-03}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-04 => ch19-patterns-and-matching/listing-19-04}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-04 => ch19-patterns-and-matching/listing-19-04}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-04 => ch19-patterns-and-matching/listing-19-04}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-05 => ch19-patterns-and-matching/listing-19-05}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-05 => ch19-patterns-and-matching/listing-19-05}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-05 => ch19-patterns-and-matching/listing-19-05}/output.txt (100%) rename listings/{ch18-patterns-and-matching/listing-18-05 => ch19-patterns-and-matching/listing-19-05}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-06 => ch19-patterns-and-matching/listing-19-06}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-06 => ch19-patterns-and-matching/listing-19-06}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-06 => ch19-patterns-and-matching/listing-19-06}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-07 => ch19-patterns-and-matching/listing-19-07}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-07 => ch19-patterns-and-matching/listing-19-07}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-07 => ch19-patterns-and-matching/listing-19-07}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-08 => ch19-patterns-and-matching/listing-19-08}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-08 => ch19-patterns-and-matching/listing-19-08}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-08 => ch19-patterns-and-matching/listing-19-08}/output.txt (100%) rename listings/{ch18-patterns-and-matching/listing-18-08 => ch19-patterns-and-matching/listing-19-08}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-09 => ch19-patterns-and-matching/listing-19-09}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-09 => ch19-patterns-and-matching/listing-19-09}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-09 => ch19-patterns-and-matching/listing-19-09}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-10 => ch19-patterns-and-matching/listing-19-10}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-10 => ch19-patterns-and-matching/listing-19-10}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-10 => ch19-patterns-and-matching/listing-19-10}/output.txt (100%) rename listings/{ch18-patterns-and-matching/listing-18-10 => ch19-patterns-and-matching/listing-19-10}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-11 => ch19-patterns-and-matching/listing-19-11}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-11 => ch19-patterns-and-matching/listing-19-11}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-11 => ch19-patterns-and-matching/listing-19-11}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-12 => ch19-patterns-and-matching/listing-19-12}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-12 => ch19-patterns-and-matching/listing-19-12}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-12 => ch19-patterns-and-matching/listing-19-12}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-13 => ch19-patterns-and-matching/listing-19-13}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-13 => ch19-patterns-and-matching/listing-19-13}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-13 => ch19-patterns-and-matching/listing-19-13}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-14 => ch19-patterns-and-matching/listing-19-14}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-14 => ch19-patterns-and-matching/listing-19-14}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-14 => ch19-patterns-and-matching/listing-19-14}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-15 => ch19-patterns-and-matching/listing-19-15}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-15 => ch19-patterns-and-matching/listing-19-15}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-15 => ch19-patterns-and-matching/listing-19-15}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-16 => ch19-patterns-and-matching/listing-19-16}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-16 => ch19-patterns-and-matching/listing-19-16}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-16 => ch19-patterns-and-matching/listing-19-16}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-17 => ch19-patterns-and-matching/listing-19-17}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-17 => ch19-patterns-and-matching/listing-19-17}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-17 => ch19-patterns-and-matching/listing-19-17}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-18 => ch19-patterns-and-matching/listing-19-18}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-18 => ch19-patterns-and-matching/listing-19-18}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-18 => ch19-patterns-and-matching/listing-19-18}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-19 => ch19-patterns-and-matching/listing-19-19}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-19 => ch19-patterns-and-matching/listing-19-19}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-19 => ch19-patterns-and-matching/listing-19-19}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-20 => ch19-patterns-and-matching/listing-19-20}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-20 => ch19-patterns-and-matching/listing-19-20}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-20 => ch19-patterns-and-matching/listing-19-20}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-21 => ch19-patterns-and-matching/listing-19-21}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-21 => ch19-patterns-and-matching/listing-19-21}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-21 => ch19-patterns-and-matching/listing-19-21}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-22 => ch19-patterns-and-matching/listing-19-22}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-22 => ch19-patterns-and-matching/listing-19-22}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-22 => ch19-patterns-and-matching/listing-19-22}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-23 => ch19-patterns-and-matching/listing-19-23}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-23 => ch19-patterns-and-matching/listing-19-23}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-23 => ch19-patterns-and-matching/listing-19-23}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-24 => ch19-patterns-and-matching/listing-19-24}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-24 => ch19-patterns-and-matching/listing-19-24}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-24 => ch19-patterns-and-matching/listing-19-24}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-25 => ch19-patterns-and-matching/listing-19-25}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-25 => ch19-patterns-and-matching/listing-19-25}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-25 => ch19-patterns-and-matching/listing-19-25}/output.txt (100%) rename listings/{ch18-patterns-and-matching/listing-18-25 => ch19-patterns-and-matching/listing-19-25}/rustfmt-ignore (100%) rename listings/{ch18-patterns-and-matching/listing-18-25 => ch19-patterns-and-matching/listing-19-25}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-26 => ch19-patterns-and-matching/listing-19-26}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-26 => ch19-patterns-and-matching/listing-19-26}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-26 => ch19-patterns-and-matching/listing-19-26}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-27 => ch19-patterns-and-matching/listing-19-27}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-27 => ch19-patterns-and-matching/listing-19-27}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-27 => ch19-patterns-and-matching/listing-19-27}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-28 => ch19-patterns-and-matching/listing-19-28}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-28 => ch19-patterns-and-matching/listing-19-28}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-28 => ch19-patterns-and-matching/listing-19-28}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching/listing-18-29 => ch19-patterns-and-matching/listing-19-29}/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching/listing-18-29 => ch19-patterns-and-matching/listing-19-29}/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching/listing-18-29 => ch19-patterns-and-matching/listing-19-29}/src/main.rs (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-01-literals/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-01-literals/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-01-literals/src/main.rs (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-02-multiple-patterns/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-02-multiple-patterns/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-02-multiple-patterns/src/main.rs (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-03-ranges/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-03-ranges/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-03-ranges/src/main.rs (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-04-ranges-of-char/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-04-ranges-of-char/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-04-ranges-of-char/src/main.rs (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-05-destructuring-structs-and-tuples/Cargo.lock (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-05-destructuring-structs-and-tuples/Cargo.toml (100%) rename listings/{ch18-patterns-and-matching => ch19-patterns-and-matching}/no-listing-05-destructuring-structs-and-tuples/src/main.rs (100%) diff --git a/listings/ch18-patterns-and-matching/listing-18-01/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-01/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-01/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-01/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-01/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-01/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-01/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-01/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-01/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-01/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-01/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-01/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-02/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-02/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-02/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-02/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-02/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-02/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-02/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-02/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-02/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-02/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-02/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-02/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-03/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-03/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-03/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-03/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-03/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-03/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-03/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-03/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-03/output.txt b/listings/ch19-patterns-and-matching/listing-19-03/output.txt similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-03/output.txt rename to listings/ch19-patterns-and-matching/listing-19-03/output.txt diff --git a/listings/ch18-patterns-and-matching/listing-18-03/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-03/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-03/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-03/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-04/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-04/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-04/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-04/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-04/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-04/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-04/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-04/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-04/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-04/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-04/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-04/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-05/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-05/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-05/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-05/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-05/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-05/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-05/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-05/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-05/output.txt b/listings/ch19-patterns-and-matching/listing-19-05/output.txt similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-05/output.txt rename to listings/ch19-patterns-and-matching/listing-19-05/output.txt diff --git a/listings/ch18-patterns-and-matching/listing-18-05/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-05/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-05/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-05/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-06/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-06/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-06/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-06/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-06/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-06/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-06/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-06/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-06/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-06/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-06/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-06/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-07/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-07/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-07/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-07/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-07/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-07/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-07/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-07/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-07/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-07/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-07/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-07/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-08/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-08/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-08/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-08/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-08/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-08/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-08/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-08/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-08/output.txt b/listings/ch19-patterns-and-matching/listing-19-08/output.txt similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-08/output.txt rename to listings/ch19-patterns-and-matching/listing-19-08/output.txt diff --git a/listings/ch18-patterns-and-matching/listing-18-08/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-08/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-08/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-08/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-09/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-09/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-09/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-09/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-09/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-09/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-09/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-09/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-09/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-09/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-09/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-09/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-10/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-10/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-10/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-10/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-10/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-10/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-10/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-10/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-10/output.txt b/listings/ch19-patterns-and-matching/listing-19-10/output.txt similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-10/output.txt rename to listings/ch19-patterns-and-matching/listing-19-10/output.txt diff --git a/listings/ch18-patterns-and-matching/listing-18-10/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-10/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-10/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-10/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-11/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-11/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-11/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-11/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-11/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-11/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-11/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-11/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-11/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-11/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-11/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-11/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-12/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-12/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-12/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-12/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-12/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-12/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-12/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-12/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-12/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-12/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-12/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-12/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-13/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-13/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-13/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-13/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-13/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-13/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-13/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-13/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-13/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-13/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-13/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-13/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-14/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-14/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-14/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-14/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-14/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-14/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-14/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-14/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-14/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-14/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-14/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-15/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-15/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-15/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-15/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-15/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-15/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-15/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-15/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-15/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-15/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-15/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-16/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-16/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-16/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-16/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-16/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-16/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-16/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-16/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-16/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-16/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-16/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-17/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-17/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-17/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-17/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-17/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-17/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-17/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-17/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-17/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-17/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-17/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-17/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-18/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-18/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-18/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-18/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-18/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-18/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-18/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-18/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-18/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-18/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-18/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-18/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-19/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-19/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-19/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-19/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-19/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-19/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-19/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-19/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-19/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-19/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-19/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-19/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-20/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-20/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-20/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-20/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-20/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-20/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-20/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-20/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-20/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-20/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-20/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-20/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-21/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-21/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-21/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-21/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-21/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-21/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-21/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-21/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-21/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-21/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-21/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-21/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-22/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-22/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-22/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-22/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-22/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-22/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-22/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-22/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-22/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-22/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-22/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-22/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-23/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-23/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-23/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-23/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-23/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-23/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-23/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-23/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-23/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-23/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-23/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-23/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-24/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-24/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-24/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-24/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-24/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-24/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-24/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-24/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-24/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-24/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-24/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-24/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-25/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-25/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-25/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-25/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-25/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-25/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-25/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-25/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-25/output.txt b/listings/ch19-patterns-and-matching/listing-19-25/output.txt similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-25/output.txt rename to listings/ch19-patterns-and-matching/listing-19-25/output.txt diff --git a/listings/ch18-patterns-and-matching/listing-18-25/rustfmt-ignore b/listings/ch19-patterns-and-matching/listing-19-25/rustfmt-ignore similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-25/rustfmt-ignore rename to listings/ch19-patterns-and-matching/listing-19-25/rustfmt-ignore diff --git a/listings/ch18-patterns-and-matching/listing-18-25/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-25/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-25/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-25/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-26/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-26/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-26/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-26/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-26/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-26/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-26/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-26/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-26/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-26/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-26/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-26/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-27/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-27/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-27/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-27/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-27/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-27/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-27/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-27/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-27/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-27/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-27/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-27/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-28/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-28/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-28/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-28/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-28/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-28/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-28/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-28/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-28/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-28/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-28/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-28/src/main.rs diff --git a/listings/ch18-patterns-and-matching/listing-18-29/Cargo.lock b/listings/ch19-patterns-and-matching/listing-19-29/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-29/Cargo.lock rename to listings/ch19-patterns-and-matching/listing-19-29/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/listing-18-29/Cargo.toml b/listings/ch19-patterns-and-matching/listing-19-29/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-29/Cargo.toml rename to listings/ch19-patterns-and-matching/listing-19-29/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/listing-18-29/src/main.rs b/listings/ch19-patterns-and-matching/listing-19-29/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/listing-18-29/src/main.rs rename to listings/ch19-patterns-and-matching/listing-19-29/src/main.rs diff --git a/listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.lock b/listings/ch19-patterns-and-matching/no-listing-01-literals/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.lock rename to listings/ch19-patterns-and-matching/no-listing-01-literals/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.toml b/listings/ch19-patterns-and-matching/no-listing-01-literals/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.toml rename to listings/ch19-patterns-and-matching/no-listing-01-literals/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/no-listing-01-literals/src/main.rs b/listings/ch19-patterns-and-matching/no-listing-01-literals/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-01-literals/src/main.rs rename to listings/ch19-patterns-and-matching/no-listing-01-literals/src/main.rs diff --git a/listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.lock b/listings/ch19-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.lock rename to listings/ch19-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml b/listings/ch19-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml rename to listings/ch19-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs b/listings/ch19-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs rename to listings/ch19-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs diff --git a/listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.lock b/listings/ch19-patterns-and-matching/no-listing-03-ranges/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.lock rename to listings/ch19-patterns-and-matching/no-listing-03-ranges/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.toml b/listings/ch19-patterns-and-matching/no-listing-03-ranges/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.toml rename to listings/ch19-patterns-and-matching/no-listing-03-ranges/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/no-listing-03-ranges/src/main.rs b/listings/ch19-patterns-and-matching/no-listing-03-ranges/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-03-ranges/src/main.rs rename to listings/ch19-patterns-and-matching/no-listing-03-ranges/src/main.rs diff --git a/listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.lock b/listings/ch19-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.lock rename to listings/ch19-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml b/listings/ch19-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml rename to listings/ch19-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs b/listings/ch19-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs rename to listings/ch19-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs diff --git a/listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.lock b/listings/ch19-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.lock similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.lock rename to listings/ch19-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.lock diff --git a/listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml b/listings/ch19-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml rename to listings/ch19-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml diff --git a/listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs b/listings/ch19-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs similarity index 100% rename from listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs rename to listings/ch19-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs diff --git a/src/ch19-01-all-the-places-for-patterns.md b/src/ch19-01-all-the-places-for-patterns.md index e6f9ebd2cb..92578802e5 100644 --- a/src/ch19-01-all-the-places-for-patterns.md +++ b/src/ch19-01-all-the-places-for-patterns.md @@ -52,13 +52,13 @@ way to write the equivalent of a `match` that only matches one case. Optionally, `if let` can have a corresponding `else` containing code to run if the pattern in the `if let` doesn’t match. -Listing 18-1 shows that it’s also possible to mix and match `if let`, `else +Listing 19-1 shows that it’s also possible to mix and match `if let`, `else if`, and `else if let` expressions. Doing so gives us more flexibility than a `match` expression in which we can express only one value to compare with the patterns. Also, Rust doesn't require that the conditions in a series of `if let`, `else if`, `else if let` arms relate to each other. -The code in Listing 18-1 determines what color to make your background based on +The code in Listing 19-1 determines what color to make your background based on a series of checks for several conditions. For this example, we’ve created variables with hardcoded values that a real program might receive from user input. @@ -66,10 +66,10 @@ input. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-01/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-01/src/main.rs}} ``` -Listing 18-1: Mixing `if let`, `else if`, `else if let`, +Listing 19-1: Mixing `if let`, `else if`, `else if let`, and `else` If the user specifies a favorite color, that color is used as the background. @@ -100,14 +100,14 @@ not alert us to the possible logic bug. Similar in construction to `if let`, the `while let` conditional loop allows a `while` loop to run for as long as a pattern continues to match. In Listing -18-2 we code a `while let` loop that uses a vector as a stack and prints the +19-2 we code a `while let` loop that uses a vector as a stack and prints the values in the vector in the opposite order in which they were pushed. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-02/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-02/src/main.rs:here}} ``` -Listing 18-2: Using a `while let` loop to print values +Listing 19-2: Using a `while let` loop to print values for as long as `stack.pop()` returns `Some` This example prints 3, 2, and then 1. The `pop` method takes the last element @@ -119,21 +119,21 @@ use `while let` to pop every element off our stack. ### `for` Loops In a `for` loop, the value that directly follows the keyword `for` is a -pattern. For example, in `for x in y` the `x` is the pattern. Listing 18-3 +pattern. For example, in `for x in y` the `x` is the pattern. Listing 19-3 demonstrates how to use a pattern in a `for` loop to destructure, or break apart, a tuple as part of the `for` loop. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-03/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-03/src/main.rs:here}} ``` -Listing 18-3: Using a pattern in a `for` loop to +Listing 19-3: Using a pattern in a `for` loop to destructure a tuple -The code in Listing 18-3 will print the following: +The code in Listing 19-3 will print the following: ```console -{{#include ../listings/ch18-patterns-and-matching/listing-18-03/output.txt}} +{{#include ../listings/ch19-patterns-and-matching/listing-19-03/output.txt}} ``` We adapt an iterator using the `enumerate` method so it produces a value and @@ -169,13 +169,13 @@ the variable `x`.” Because the name `x` is the whole pattern, this pattern effectively means “bind everything to the variable `x`, whatever the value is.” To see the pattern matching aspect of `let` more clearly, consider Listing -18-4, which uses a pattern with `let` to destructure a tuple. +19-4, which uses a pattern with `let` to destructure a tuple. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-04/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-04/src/main.rs:here}} ``` -Listing 18-4: Using a pattern to destructure a tuple and +Listing 19-4: Using a pattern to destructure a tuple and create three variables at once Here, we match a tuple against a pattern. Rust compares the value `(1, 2, 3)` @@ -185,20 +185,20 @@ pattern as nesting three individual variable patterns inside it. If the number of elements in the pattern doesn’t match the number of elements in the tuple, the overall type won’t match and we’ll get a compiler error. For -example, Listing 18-5 shows an attempt to destructure a tuple with three +example, Listing 19-5 shows an attempt to destructure a tuple with three elements into two variables, which won’t work. ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-05/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-05/src/main.rs:here}} ``` -Listing 18-5: Incorrectly constructing a pattern whose +Listing 19-5: Incorrectly constructing a pattern whose variables don’t match the number of elements in the tuple Attempting to compile this code results in this type error: ```console -{{#include ../listings/ch18-patterns-and-matching/listing-18-05/output.txt}} +{{#include ../listings/ch19-patterns-and-matching/listing-19-05/output.txt}} ``` To fix the error, we could ignore one or more of the values in the tuple using @@ -210,28 +210,28 @@ of elements in the tuple. ### Function Parameters -Function parameters can also be patterns. The code in Listing 18-6, which +Function parameters can also be patterns. The code in Listing 19-6, which declares a function named `foo` that takes one parameter named `x` of type `i32`, should by now look familiar. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-06/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-06/src/main.rs:here}} ``` -Listing 18-6: A function signature uses patterns in the +Listing 19-6: A function signature uses patterns in the parameters The `x` part is a pattern! As we did with `let`, we could match a tuple in a -function’s arguments to the pattern. Listing 18-7 splits the values in a tuple +function’s arguments to the pattern. Listing 19-7 splits the values in a tuple as we pass it to a function. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-07/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-07/src/main.rs}} ``` -Listing 18-7: A function with parameters that destructure +Listing 19-7: A function with parameters that destructure a tuple This code prints `Current location: (3, 5)`. The values `&(3, 5)` match the diff --git a/src/ch19-02-refutability.md b/src/ch19-02-refutability.md index c8ca8b5766..a648d46a17 100644 --- a/src/ch19-02-refutability.md +++ b/src/ch19-02-refutability.md @@ -23,15 +23,15 @@ those cases, you’ll need to change either the pattern or the construct you’r using the pattern with, depending on the intended behavior of the code. Let’s look at an example of what happens when we try to use a refutable pattern -where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a +where Rust requires an irrefutable pattern and vice versa. Listing 19-8 shows a `let` statement, but for the pattern we’ve specified `Some(x)`, a refutable pattern. As you might expect, this code will not compile. ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-08/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-08/src/main.rs:here}} ``` -Listing 18-8: Attempting to use a refutable pattern with +Listing 19-8: Attempting to use a refutable pattern with `let` If `some_option_value` was a `None` value, it would fail to match the pattern @@ -41,7 +41,7 @@ do with a `None` value. At compile time, Rust will complain that we’ve tried t use a refutable pattern where an irrefutable pattern is required: ```console -{{#include ../listings/ch18-patterns-and-matching/listing-18-08/output.txt}} +{{#include ../listings/ch19-patterns-and-matching/listing-19-08/output.txt}} ``` Because we didn’t cover (and couldn’t cover!) every valid value with the @@ -51,32 +51,32 @@ If we have a refutable pattern where an irrefutable pattern is needed, we can fix it by changing the code that uses the pattern: instead of using `let`, we can use `if let`. Then if the pattern doesn’t match, the code will just skip the code in the curly brackets, giving it a way to continue validly. Listing -18-9 shows how to fix the code in Listing 18-8. +19-9 shows how to fix the code in Listing 19-8. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-09/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-09/src/main.rs:here}} ``` -Listing 18-9: Using `if let` and a block with refutable +Listing 19-9: Using `if let` and a block with refutable patterns instead of `let` We’ve given the code an out! This code is perfectly valid now. However, if we give `if let` an irrefutable pattern (a pattern that will always -match), such as `x`, as shown in Listing 18-10, the compiler will give a +match), such as `x`, as shown in Listing 19-10, the compiler will give a warning. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-10/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-10/src/main.rs:here}} ``` -Listing 18-10: Attempting to use an irrefutable pattern +Listing 19-10: Attempting to use an irrefutable pattern with `if let` Rust complains that it doesn’t make sense to use `if let` with an irrefutable pattern: ```console -{{#include ../listings/ch18-patterns-and-matching/listing-18-10/output.txt}} +{{#include ../listings/ch19-patterns-and-matching/listing-19-10/output.txt}} ``` For this reason, match arms must use refutable patterns, except for the last diff --git a/src/ch19-03-pattern-syntax.md b/src/ch19-03-pattern-syntax.md index aeaa766ff3..afdcc4246d 100644 --- a/src/ch19-03-pattern-syntax.md +++ b/src/ch19-03-pattern-syntax.md @@ -9,7 +9,7 @@ As you saw in Chapter 6, you can match patterns against literals directly. The following code gives some examples: ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-01-literals/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/no-listing-01-literals/src/main.rs:here}} ``` This code prints `one` because the value in `x` is 1. This syntax is useful @@ -23,7 +23,7 @@ them many times in the book. However, there is a complication when you use named variables in `match` expressions. Because `match` starts a new scope, variables declared as part of a pattern inside the `match` expression will shadow those with the same name outside the `match` construct, as is the case -with all variables. In Listing 18-11, we declare a variable named `x` with the +with all variables. In Listing 19-11, we declare a variable named `x` with the value `Some(5)` and a variable `y` with the value `10`. We then create a `match` expression on the value `x`. Look at the patterns in the match arms and `println!` at the end, and try to figure out what the code will print before @@ -32,10 +32,10 @@ running this code or reading further. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-11/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-11/src/main.rs:here}} ``` -Listing 18-11: A `match` expression with an arm that +Listing 19-11: A `match` expression with an arm that introduces a shadowed variable `y` Let’s walk through what happens when the `match` expression runs. The pattern @@ -75,7 +75,7 @@ meaning if the value of `x` matches either of the values in that arm, that arm’s code will run: ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs:here}} ``` This code prints `one or two`. @@ -87,7 +87,7 @@ following code, when a pattern matches any of the values within the given range, that arm will execute: ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-03-ranges/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/no-listing-03-ranges/src/main.rs:here}} ``` If `x` is 1, 2, 3, 4, or 5, the first arm will match. This syntax is more @@ -103,7 +103,7 @@ numeric values, ranges are only allowed with numeric or `char` values. Here is an example using ranges of `char` values: ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs:here}} ``` Rust can tell that `'c'` is within the first pattern’s range and prints `early @@ -116,16 +116,16 @@ different parts of these values. Let’s walk through each value. #### Destructuring Structs -Listing 18-12 shows a `Point` struct with two fields, `x` and `y`, that we can +Listing 19-12 shows a `Point` struct with two fields, `x` and `y`, that we can break apart using a pattern with a `let` statement. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-12/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-12/src/main.rs}} ``` -Listing 18-12: Destructuring a struct’s fields into +Listing 19-12: Destructuring a struct’s fields into separate variables This code creates the variables `a` and `b` that match the values of the `x` @@ -136,17 +136,17 @@ easier to remember which variables came from which fields. Because of this common usage, and because writing `let Point { x: x, y: y } = p;` contains a lot of duplication, Rust has a shorthand for patterns that match struct fields: you only need to list the name of the struct field, and the variables created -from the pattern will have the same names. Listing 18-13 behaves in the same -way as the code in Listing 18-12, but the variables created in the `let` +from the pattern will have the same names. Listing 19-13 behaves in the same +way as the code in Listing 19-12, but the variables created in the `let` pattern are `x` and `y` instead of `a` and `b`. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-13/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-13/src/main.rs}} ``` -Listing 18-13: Destructuring struct fields using struct +Listing 19-13: Destructuring struct fields using struct field shorthand This code creates the variables `x` and `y` that match the `x` and `y` fields @@ -158,17 +158,17 @@ rather than creating variables for all the fields. Doing so allows us to test some of the fields for particular values while creating variables to destructure the other fields. -In Listing 18-14, we have a `match` expression that separates `Point` values +In Listing 19-14, we have a `match` expression that separates `Point` values into three cases: points that lie directly on the `x` axis (which is true when `y = 0`), on the `y` axis (`x = 0`), or neither. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-14/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-14/src/main.rs:here}} ``` -Listing 18-14: Destructuring and matching literal values +Listing 19-14: Destructuring and matching literal values in one pattern The first arm will match any point that lies on the `x` axis by specifying that @@ -192,16 +192,16 @@ and the `y` axis, this code would only print `On the x axis at 0`. We've destructured enums in this book (for example, Listing 6-5 in Chapter 6), but haven’t yet explicitly discussed that the pattern to destructure an enum corresponds to the way the data stored within the enum is defined. As an -example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write +example, in Listing 19-15 we use the `Message` enum from Listing 6-2 and write a `match` with patterns that will destructure each inner value. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-15/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-15/src/main.rs}} ``` -Listing 18-15: Destructuring enum variants that hold +Listing 19-15: Destructuring enum variants that hold different kinds of values This code will print `Change the color to red 0, green 160, and blue 255`. Try @@ -215,7 +215,7 @@ For struct-like enum variants, such as `Message::Move`, we can use a pattern similar to the pattern we specify to match structs. After the variant name, we place curly brackets and then list the fields with variables so we break apart the pieces to use in the code for this arm. Here we use the shorthand form as -we did in Listing 18-13. +we did in Listing 19-13. For tuple-like enum variants, like `Message::Write` that holds a tuple with one element and `Message::ChangeColor` that holds a tuple with three elements, the @@ -227,14 +227,14 @@ matching. So far, our examples have all been matching structs or enums one level deep, but matching can work on nested items too! For example, we can refactor the -code in Listing 18-15 to support RGB and HSV colors in the `ChangeColor` -message, as shown in Listing 18-16. +code in Listing 19-15 to support RGB and HSV colors in the `ChangeColor` +message, as shown in Listing 19-16. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-16/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-16/src/main.rs}} ``` -Listing 18-16: Matching on nested enums +Listing 19-16: Matching on nested enums The pattern of the first arm in the `match` expression matches a `Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then @@ -250,7 +250,7 @@ The following example shows a complicated destructure where we nest structs and tuples inside a tuple and destructure all the primitive values out: ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs:here}} ``` This code lets us break complex types into their component parts so we can use @@ -274,15 +274,15 @@ parts of a value. Let’s explore how and why to use each of these patterns. We’ve used the underscore as a wildcard pattern that will match any value but not bind to the value. This is especially useful as the last arm in a `match` expression, but we can also use it in any pattern, including function -parameters, as shown in Listing 18-17. +parameters, as shown in Listing 19-17. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-17/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-17/src/main.rs}} ``` -Listing 18-17: Using `_` in a function signature +Listing 19-17: Using `_` in a function signature This code will completely ignore the value `3` passed as the first argument, and will print `This code only uses the y parameter: 4`. @@ -299,16 +299,16 @@ would if you used a name instead. We can also use `_` inside another pattern to ignore just part of a value, for example, when we want to test for only part of a value but have no use for the -other parts in the corresponding code we want to run. Listing 18-18 shows code +other parts in the corresponding code we want to run. Listing 19-18 shows code responsible for managing a setting’s value. The business requirements are that the user should not be allowed to overwrite an existing customization of a setting but can unset the setting and give it a value if it is currently unset. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-18/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-18/src/main.rs:here}} ``` -Listing 18-18: Using an underscore within patterns that +Listing 19-18: Using an underscore within patterns that match `Some` variants when we don’t need to use the value inside the `Some` @@ -324,14 +324,14 @@ In all other cases (if either `setting_value` or `new_setting_value` are `new_setting_value` to become `setting_value`. We can also use underscores in multiple places within one pattern to ignore -particular values. Listing 18-19 shows an example of ignoring the second and +particular values. Listing 19-19 shows an example of ignoring the second and fourth values in a tuple of five items. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-19/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-19/src/main.rs:here}} ``` -Listing 18-19: Ignoring multiple parts of a tuple +Listing 19-19: Ignoring multiple parts of a tuple This code will print `Some numbers: 2, 8, 32`, and the values 4 and 16 will be ignored. @@ -343,16 +343,16 @@ warning because an unused variable could be a bug. However, sometimes it’s useful to be able to create a variable you won’t use yet, such as when you’re prototyping or just starting a project. In this situation, you can tell Rust not to warn you about the unused variable by starting the name of the variable -with an underscore. In Listing 18-20, we create two unused variables, but when +with an underscore. In Listing 19-20, we create two unused variables, but when we compile this code, we should only get a warning about one of them. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-20/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-20/src/main.rs}} ``` -Listing 18-20: Starting a variable name with an +Listing 19-20: Starting a variable name with an underscore to avoid getting unused variable warnings Here we get a warning about not using the variable `y`, but we don’t get a @@ -361,25 +361,25 @@ warning about not using `_x`. Note that there is a subtle difference between using only `_` and using a name that starts with an underscore. The syntax `_x` still binds the value to the variable, whereas `_` doesn’t bind at all. To show a case where this -distinction matters, Listing 18-21 will provide us with an error. +distinction matters, Listing 19-21 will provide us with an error. ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-21/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-21/src/main.rs:here}} ``` -Listing 18-21: An unused variable starting with an +Listing 19-21: An unused variable starting with an underscore still binds the value, which might take ownership of the value We’ll receive an error because the `s` value will still be moved into `_s`, which prevents us from using `s` again. However, using the underscore by itself -doesn’t ever bind to the value. Listing 18-22 will compile without any errors +doesn’t ever bind to the value. Listing 19-22 will compile without any errors because `s` doesn’t get moved into `_`. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-22/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-22/src/main.rs:here}} ``` -Listing 18-22: Using an underscore does not bind the +Listing 19-22: Using an underscore does not bind the value This code works just fine because we never bind `s` to anything; it isn’t moved. @@ -389,16 +389,16 @@ This code works just fine because we never bind `s` to anything; it isn’t move With values that have many parts, we can use the `..` syntax to use specific parts and ignore the rest, avoiding the need to list underscores for each ignored value. The `..` pattern ignores any parts of a value that we haven’t -explicitly matched in the rest of the pattern. In Listing 18-23, we have a +explicitly matched in the rest of the pattern. In Listing 19-23, we have a `Point` struct that holds a coordinate in three-dimensional space. In the `match` expression, we want to operate only on the `x` coordinate and ignore the values in the `y` and `z` fields. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-23/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-23/src/main.rs:here}} ``` -Listing 18-23: Ignoring all fields of a `Point` except +Listing 19-23: Ignoring all fields of a `Point` except for `x` by using `..` We list the `x` value and then just include the `..` pattern. This is quicker @@ -406,16 +406,16 @@ than having to list `y: _` and `z: _`, particularly when we’re working with structs that have lots of fields in situations where only one or two fields are relevant. -The syntax `..` will expand to as many values as it needs to be. Listing 18-24 +The syntax `..` will expand to as many values as it needs to be. Listing 19-24 shows how to use `..` with a tuple. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-24/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-24/src/main.rs}} ``` -Listing 18-24: Matching only the first and last values in +Listing 19-24: Matching only the first and last values in a tuple and ignoring all other values In this code, the first and last value are matched with `first` and `last`. The @@ -423,22 +423,22 @@ In this code, the first and last value are matched with `first` and `last`. The However, using `..` must be unambiguous. If it is unclear which values are intended for matching and which should be ignored, Rust will give us an error. -Listing 18-25 shows an example of using `..` ambiguously, so it will not +Listing 19-25 shows an example of using `..` ambiguously, so it will not compile. Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-25/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-25/src/main.rs}} ``` -Listing 18-25: An attempt to use `..` in an ambiguous +Listing 19-25: An attempt to use `..` in an ambiguous way When we compile this example, we get this error: ```console -{{#include ../listings/ch18-patterns-and-matching/listing-18-25/output.txt}} +{{#include ../listings/ch19-patterns-and-matching/listing-19-25/output.txt}} ``` It’s impossible for Rust to determine how many values in the tuple to ignore @@ -455,15 +455,15 @@ A *match guard* is an additional `if` condition, specified after the pattern in a `match` arm, that must also match for that arm to be chosen. Match guards are useful for expressing more complex ideas than a pattern alone allows. -The condition can use variables created in the pattern. Listing 18-26 shows a +The condition can use variables created in the pattern. Listing 19-26 shows a `match` where the first arm has the pattern `Some(x)` and also has a match guard of `if x % 2 == 0` (which will be true if the number is even). ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-26/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-26/src/main.rs:here}} ``` -Listing 18-26: Adding a match guard to a pattern +Listing 19-26: Adding a match guard to a pattern This example will print `The number 4 is even`. When `num` is compared to the pattern in the first arm, it matches, because `Some(4)` matches `Some(x)`. Then @@ -480,20 +480,20 @@ the match guard gives us the ability to express this logic. The downside of this additional expressiveness is that the compiler doesn't try to check for exhaustiveness when match guard expressions are involved. -In Listing 18-11, we mentioned that we could use match guards to solve our +In Listing 19-11, we mentioned that we could use match guards to solve our pattern-shadowing problem. Recall that we created a new variable inside the pattern in the `match` expression instead of using the variable outside the `match`. That new variable meant we couldn’t test against the value of the -outer variable. Listing 18-27 shows how we can use a match guard to fix this +outer variable. Listing 19-27 shows how we can use a match guard to fix this problem. Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-27/src/main.rs}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-27/src/main.rs}} ``` -Listing 18-27: Using a match guard to test for equality +Listing 19-27: Using a match guard to test for equality with an outer variable This code will now print `Default case, x = Some(5)`. The pattern in the second @@ -510,16 +510,16 @@ we can look for a value that has the same value as the outer `y` by comparing You can also use the *or* operator `|` in a match guard to specify multiple patterns; the match guard condition will apply to all the patterns. Listing -18-28 shows the precedence when combining a pattern that uses `|` with a match +19-28 shows the precedence when combining a pattern that uses `|` with a match guard. The important part of this example is that the `if y` match guard applies to `4`, `5`, *and* `6`, even though it might look like `if y` only applies to `6`. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-28/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-28/src/main.rs:here}} ``` -Listing 18-28: Combining multiple patterns with a match +Listing 19-28: Combining multiple patterns with a match guard The match condition states that the arm only matches if the value of `x` is @@ -549,17 +549,17 @@ were applied only to the final value in the list of values specified using the ### `@` Bindings The *at* operator `@` lets us create a variable that holds a value at the same -time as we’re testing that value for a pattern match. In Listing 18-29, we want +time as we’re testing that value for a pattern match. In Listing 19-29, we want to test that a `Message::Hello` `id` field is within the range `3..=7`. We also want to bind the value to the variable `id_variable` so we can use it in the code associated with the arm. We could name this variable `id`, the same as the field, but for this example we’ll use a different name. ```rust -{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-29/src/main.rs:here}} +{{#rustdoc_include ../listings/ch19-patterns-and-matching/listing-19-29/src/main.rs:here}} ``` -Listing 18-29: Using `@` to bind to a value in a pattern +Listing 19-29: Using `@` to bind to a value in a pattern while also testing it This example will print `Found an id in range: 5`. By specifying `id_variable From c8f446419adcbfa78cdac2f54c75cf62fc054438 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 26 Sep 2024 14:10:09 -0600 Subject: [PATCH 245/249] Ch. 17: Listings for old Ch. 17 -> Ch. 18 --- .../listing-18-01}/Cargo.lock | 0 .../listing-18-01}/Cargo.toml | 0 .../listing-18-01}/src/lib.rs | 0 .../listing-18-02}/Cargo.lock | 0 .../listing-18-02}/Cargo.toml | 0 .../listing-18-02}/src/lib.rs | 0 .../listing-18-03}/Cargo.lock | 0 .../listing-18-03}/Cargo.toml | 0 .../listing-18-03}/src/lib.rs | 0 .../listing-18-04}/Cargo.lock | 0 .../listing-18-04}/Cargo.toml | 0 .../listing-18-04}/src/lib.rs | 0 .../listing-18-05}/Cargo.lock | 0 .../listing-18-05}/Cargo.toml | 0 .../listing-18-05}/src/lib.rs | 0 .../listing-18-06}/Cargo.lock | 0 .../listing-18-06}/Cargo.toml | 0 .../listing-18-06}/src/lib.rs | 0 .../listing-18-07}/Cargo.lock | 0 .../listing-18-07}/Cargo.toml | 0 .../listing-18-07}/src/lib.rs | 0 .../listing-18-08}/Cargo.lock | 0 .../listing-18-08}/Cargo.toml | 0 .../listing-18-08}/src/lib.rs | 0 .../listing-18-08}/src/main.rs | 0 .../listing-18-09}/Cargo.lock | 0 .../listing-18-09}/Cargo.toml | 0 .../listing-18-09}/src/lib.rs | 0 .../listing-18-09}/src/main.rs | 0 .../listing-18-10}/Cargo.lock | 0 .../listing-18-10}/Cargo.toml | 0 .../listing-18-10}/output.txt | 0 .../listing-18-10}/src/lib.rs | 0 .../listing-18-10}/src/main.rs | 0 .../listing-18-11}/Cargo.lock | 0 .../listing-18-11}/Cargo.toml | 0 .../listing-18-11}/src/main.rs | 0 .../listing-18-12}/Cargo.lock | 0 .../listing-18-12}/Cargo.toml | 0 .../listing-18-12}/src/lib.rs | 0 .../listing-18-12}/src/main.rs | 0 .../listing-18-13}/Cargo.lock | 0 .../listing-18-13}/Cargo.toml | 0 .../listing-18-13}/src/lib.rs | 0 .../listing-18-13}/src/main.rs | 0 .../listing-18-14}/Cargo.lock | 0 .../listing-18-14}/Cargo.toml | 0 .../listing-18-14}/src/lib.rs | 0 .../listing-18-14}/src/main.rs | 0 .../listing-18-15}/Cargo.lock | 0 .../listing-18-15}/Cargo.toml | 0 .../listing-18-15}/src/lib.rs | 0 .../listing-18-15}/src/main.rs | 0 .../listing-18-16}/Cargo.lock | 0 .../listing-18-16}/Cargo.toml | 0 .../listing-18-16}/src/lib.rs | 0 .../listing-18-16}/src/main.rs | 0 .../listing-18-17}/Cargo.lock | 0 .../listing-18-17}/Cargo.toml | 0 .../listing-18-17}/src/lib.rs | 0 .../listing-18-17}/src/main.rs | 0 .../listing-18-18}/Cargo.lock | 0 .../listing-18-18}/Cargo.toml | 0 .../listing-18-18}/src/lib.rs | 0 .../listing-18-18}/src/main.rs | 0 .../listing-18-19}/Cargo.lock | 0 .../listing-18-19}/Cargo.toml | 0 .../listing-18-19}/src/lib.rs | 0 .../listing-18-20}/Cargo.lock | 0 .../listing-18-20}/Cargo.toml | 0 .../listing-18-20}/src/lib.rs | 0 .../listing-18-21}/Cargo.lock | 0 .../listing-18-21}/Cargo.toml | 0 .../listing-18-21}/src/lib.rs | 0 .../listing-18-21}/src/main.rs | 0 src/ch18-01-what-is-oo.md | 12 +-- src/ch18-02-trait-objects.md | 56 ++++++------- src/ch18-03-oo-design-patterns.md | 82 +++++++++---------- 78 files changed, 75 insertions(+), 75 deletions(-) rename listings/{ch17-oop/listing-17-01 => ch18-oop/listing-18-01}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-01 => ch18-oop/listing-18-01}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-01 => ch18-oop/listing-18-01}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-02 => ch18-oop/listing-18-02}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-02 => ch18-oop/listing-18-02}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-02 => ch18-oop/listing-18-02}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-03 => ch18-oop/listing-18-03}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-03 => ch18-oop/listing-18-03}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-03 => ch18-oop/listing-18-03}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-04 => ch18-oop/listing-18-04}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-04 => ch18-oop/listing-18-04}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-04 => ch18-oop/listing-18-04}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-05 => ch18-oop/listing-18-05}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-05 => ch18-oop/listing-18-05}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-05 => ch18-oop/listing-18-05}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-06 => ch18-oop/listing-18-06}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-06 => ch18-oop/listing-18-06}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-06 => ch18-oop/listing-18-06}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-07 => ch18-oop/listing-18-07}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-07 => ch18-oop/listing-18-07}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-07 => ch18-oop/listing-18-07}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-08 => ch18-oop/listing-18-08}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-08 => ch18-oop/listing-18-08}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-08 => ch18-oop/listing-18-08}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-08 => ch18-oop/listing-18-08}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-09 => ch18-oop/listing-18-09}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-09 => ch18-oop/listing-18-09}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-09 => ch18-oop/listing-18-09}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-09 => ch18-oop/listing-18-09}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-10 => ch18-oop/listing-18-10}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-10 => ch18-oop/listing-18-10}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-10 => ch18-oop/listing-18-10}/output.txt (100%) rename listings/{ch17-oop/listing-17-10 => ch18-oop/listing-18-10}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-10 => ch18-oop/listing-18-10}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-11 => ch18-oop/listing-18-11}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-11 => ch18-oop/listing-18-11}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-11 => ch18-oop/listing-18-11}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-12 => ch18-oop/listing-18-12}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-12 => ch18-oop/listing-18-12}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-12 => ch18-oop/listing-18-12}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-12 => ch18-oop/listing-18-12}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-13 => ch18-oop/listing-18-13}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-13 => ch18-oop/listing-18-13}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-13 => ch18-oop/listing-18-13}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-13 => ch18-oop/listing-18-13}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-14 => ch18-oop/listing-18-14}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-14 => ch18-oop/listing-18-14}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-14 => ch18-oop/listing-18-14}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-14 => ch18-oop/listing-18-14}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-15 => ch18-oop/listing-18-15}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-15 => ch18-oop/listing-18-15}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-15 => ch18-oop/listing-18-15}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-15 => ch18-oop/listing-18-15}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-16 => ch18-oop/listing-18-16}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-16 => ch18-oop/listing-18-16}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-16 => ch18-oop/listing-18-16}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-16 => ch18-oop/listing-18-16}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-17 => ch18-oop/listing-18-17}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-17 => ch18-oop/listing-18-17}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-17 => ch18-oop/listing-18-17}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-17 => ch18-oop/listing-18-17}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-18 => ch18-oop/listing-18-18}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-18 => ch18-oop/listing-18-18}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-18 => ch18-oop/listing-18-18}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-18 => ch18-oop/listing-18-18}/src/main.rs (100%) rename listings/{ch17-oop/listing-17-19 => ch18-oop/listing-18-19}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-19 => ch18-oop/listing-18-19}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-19 => ch18-oop/listing-18-19}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-20 => ch18-oop/listing-18-20}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-20 => ch18-oop/listing-18-20}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-20 => ch18-oop/listing-18-20}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-21 => ch18-oop/listing-18-21}/Cargo.lock (100%) rename listings/{ch17-oop/listing-17-21 => ch18-oop/listing-18-21}/Cargo.toml (100%) rename listings/{ch17-oop/listing-17-21 => ch18-oop/listing-18-21}/src/lib.rs (100%) rename listings/{ch17-oop/listing-17-21 => ch18-oop/listing-18-21}/src/main.rs (100%) diff --git a/listings/ch17-oop/listing-17-01/Cargo.lock b/listings/ch18-oop/listing-18-01/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-01/Cargo.lock rename to listings/ch18-oop/listing-18-01/Cargo.lock diff --git a/listings/ch17-oop/listing-17-01/Cargo.toml b/listings/ch18-oop/listing-18-01/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-01/Cargo.toml rename to listings/ch18-oop/listing-18-01/Cargo.toml diff --git a/listings/ch17-oop/listing-17-01/src/lib.rs b/listings/ch18-oop/listing-18-01/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-01/src/lib.rs rename to listings/ch18-oop/listing-18-01/src/lib.rs diff --git a/listings/ch17-oop/listing-17-02/Cargo.lock b/listings/ch18-oop/listing-18-02/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-02/Cargo.lock rename to listings/ch18-oop/listing-18-02/Cargo.lock diff --git a/listings/ch17-oop/listing-17-02/Cargo.toml b/listings/ch18-oop/listing-18-02/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-02/Cargo.toml rename to listings/ch18-oop/listing-18-02/Cargo.toml diff --git a/listings/ch17-oop/listing-17-02/src/lib.rs b/listings/ch18-oop/listing-18-02/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-02/src/lib.rs rename to listings/ch18-oop/listing-18-02/src/lib.rs diff --git a/listings/ch17-oop/listing-17-03/Cargo.lock b/listings/ch18-oop/listing-18-03/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-03/Cargo.lock rename to listings/ch18-oop/listing-18-03/Cargo.lock diff --git a/listings/ch17-oop/listing-17-03/Cargo.toml b/listings/ch18-oop/listing-18-03/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-03/Cargo.toml rename to listings/ch18-oop/listing-18-03/Cargo.toml diff --git a/listings/ch17-oop/listing-17-03/src/lib.rs b/listings/ch18-oop/listing-18-03/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-03/src/lib.rs rename to listings/ch18-oop/listing-18-03/src/lib.rs diff --git a/listings/ch17-oop/listing-17-04/Cargo.lock b/listings/ch18-oop/listing-18-04/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-04/Cargo.lock rename to listings/ch18-oop/listing-18-04/Cargo.lock diff --git a/listings/ch17-oop/listing-17-04/Cargo.toml b/listings/ch18-oop/listing-18-04/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-04/Cargo.toml rename to listings/ch18-oop/listing-18-04/Cargo.toml diff --git a/listings/ch17-oop/listing-17-04/src/lib.rs b/listings/ch18-oop/listing-18-04/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-04/src/lib.rs rename to listings/ch18-oop/listing-18-04/src/lib.rs diff --git a/listings/ch17-oop/listing-17-05/Cargo.lock b/listings/ch18-oop/listing-18-05/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-05/Cargo.lock rename to listings/ch18-oop/listing-18-05/Cargo.lock diff --git a/listings/ch17-oop/listing-17-05/Cargo.toml b/listings/ch18-oop/listing-18-05/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-05/Cargo.toml rename to listings/ch18-oop/listing-18-05/Cargo.toml diff --git a/listings/ch17-oop/listing-17-05/src/lib.rs b/listings/ch18-oop/listing-18-05/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-05/src/lib.rs rename to listings/ch18-oop/listing-18-05/src/lib.rs diff --git a/listings/ch17-oop/listing-17-06/Cargo.lock b/listings/ch18-oop/listing-18-06/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-06/Cargo.lock rename to listings/ch18-oop/listing-18-06/Cargo.lock diff --git a/listings/ch17-oop/listing-17-06/Cargo.toml b/listings/ch18-oop/listing-18-06/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-06/Cargo.toml rename to listings/ch18-oop/listing-18-06/Cargo.toml diff --git a/listings/ch17-oop/listing-17-06/src/lib.rs b/listings/ch18-oop/listing-18-06/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-06/src/lib.rs rename to listings/ch18-oop/listing-18-06/src/lib.rs diff --git a/listings/ch17-oop/listing-17-07/Cargo.lock b/listings/ch18-oop/listing-18-07/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-07/Cargo.lock rename to listings/ch18-oop/listing-18-07/Cargo.lock diff --git a/listings/ch17-oop/listing-17-07/Cargo.toml b/listings/ch18-oop/listing-18-07/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-07/Cargo.toml rename to listings/ch18-oop/listing-18-07/Cargo.toml diff --git a/listings/ch17-oop/listing-17-07/src/lib.rs b/listings/ch18-oop/listing-18-07/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-07/src/lib.rs rename to listings/ch18-oop/listing-18-07/src/lib.rs diff --git a/listings/ch17-oop/listing-17-08/Cargo.lock b/listings/ch18-oop/listing-18-08/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-08/Cargo.lock rename to listings/ch18-oop/listing-18-08/Cargo.lock diff --git a/listings/ch17-oop/listing-17-08/Cargo.toml b/listings/ch18-oop/listing-18-08/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-08/Cargo.toml rename to listings/ch18-oop/listing-18-08/Cargo.toml diff --git a/listings/ch17-oop/listing-17-08/src/lib.rs b/listings/ch18-oop/listing-18-08/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-08/src/lib.rs rename to listings/ch18-oop/listing-18-08/src/lib.rs diff --git a/listings/ch17-oop/listing-17-08/src/main.rs b/listings/ch18-oop/listing-18-08/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-08/src/main.rs rename to listings/ch18-oop/listing-18-08/src/main.rs diff --git a/listings/ch17-oop/listing-17-09/Cargo.lock b/listings/ch18-oop/listing-18-09/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-09/Cargo.lock rename to listings/ch18-oop/listing-18-09/Cargo.lock diff --git a/listings/ch17-oop/listing-17-09/Cargo.toml b/listings/ch18-oop/listing-18-09/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-09/Cargo.toml rename to listings/ch18-oop/listing-18-09/Cargo.toml diff --git a/listings/ch17-oop/listing-17-09/src/lib.rs b/listings/ch18-oop/listing-18-09/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-09/src/lib.rs rename to listings/ch18-oop/listing-18-09/src/lib.rs diff --git a/listings/ch17-oop/listing-17-09/src/main.rs b/listings/ch18-oop/listing-18-09/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-09/src/main.rs rename to listings/ch18-oop/listing-18-09/src/main.rs diff --git a/listings/ch17-oop/listing-17-10/Cargo.lock b/listings/ch18-oop/listing-18-10/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-10/Cargo.lock rename to listings/ch18-oop/listing-18-10/Cargo.lock diff --git a/listings/ch17-oop/listing-17-10/Cargo.toml b/listings/ch18-oop/listing-18-10/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-10/Cargo.toml rename to listings/ch18-oop/listing-18-10/Cargo.toml diff --git a/listings/ch17-oop/listing-17-10/output.txt b/listings/ch18-oop/listing-18-10/output.txt similarity index 100% rename from listings/ch17-oop/listing-17-10/output.txt rename to listings/ch18-oop/listing-18-10/output.txt diff --git a/listings/ch17-oop/listing-17-10/src/lib.rs b/listings/ch18-oop/listing-18-10/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-10/src/lib.rs rename to listings/ch18-oop/listing-18-10/src/lib.rs diff --git a/listings/ch17-oop/listing-17-10/src/main.rs b/listings/ch18-oop/listing-18-10/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-10/src/main.rs rename to listings/ch18-oop/listing-18-10/src/main.rs diff --git a/listings/ch17-oop/listing-17-11/Cargo.lock b/listings/ch18-oop/listing-18-11/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-11/Cargo.lock rename to listings/ch18-oop/listing-18-11/Cargo.lock diff --git a/listings/ch17-oop/listing-17-11/Cargo.toml b/listings/ch18-oop/listing-18-11/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-11/Cargo.toml rename to listings/ch18-oop/listing-18-11/Cargo.toml diff --git a/listings/ch17-oop/listing-17-11/src/main.rs b/listings/ch18-oop/listing-18-11/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-11/src/main.rs rename to listings/ch18-oop/listing-18-11/src/main.rs diff --git a/listings/ch17-oop/listing-17-12/Cargo.lock b/listings/ch18-oop/listing-18-12/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-12/Cargo.lock rename to listings/ch18-oop/listing-18-12/Cargo.lock diff --git a/listings/ch17-oop/listing-17-12/Cargo.toml b/listings/ch18-oop/listing-18-12/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-12/Cargo.toml rename to listings/ch18-oop/listing-18-12/Cargo.toml diff --git a/listings/ch17-oop/listing-17-12/src/lib.rs b/listings/ch18-oop/listing-18-12/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-12/src/lib.rs rename to listings/ch18-oop/listing-18-12/src/lib.rs diff --git a/listings/ch17-oop/listing-17-12/src/main.rs b/listings/ch18-oop/listing-18-12/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-12/src/main.rs rename to listings/ch18-oop/listing-18-12/src/main.rs diff --git a/listings/ch17-oop/listing-17-13/Cargo.lock b/listings/ch18-oop/listing-18-13/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-13/Cargo.lock rename to listings/ch18-oop/listing-18-13/Cargo.lock diff --git a/listings/ch17-oop/listing-17-13/Cargo.toml b/listings/ch18-oop/listing-18-13/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-13/Cargo.toml rename to listings/ch18-oop/listing-18-13/Cargo.toml diff --git a/listings/ch17-oop/listing-17-13/src/lib.rs b/listings/ch18-oop/listing-18-13/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-13/src/lib.rs rename to listings/ch18-oop/listing-18-13/src/lib.rs diff --git a/listings/ch17-oop/listing-17-13/src/main.rs b/listings/ch18-oop/listing-18-13/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-13/src/main.rs rename to listings/ch18-oop/listing-18-13/src/main.rs diff --git a/listings/ch17-oop/listing-17-14/Cargo.lock b/listings/ch18-oop/listing-18-14/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-14/Cargo.lock rename to listings/ch18-oop/listing-18-14/Cargo.lock diff --git a/listings/ch17-oop/listing-17-14/Cargo.toml b/listings/ch18-oop/listing-18-14/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-14/Cargo.toml rename to listings/ch18-oop/listing-18-14/Cargo.toml diff --git a/listings/ch17-oop/listing-17-14/src/lib.rs b/listings/ch18-oop/listing-18-14/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-14/src/lib.rs rename to listings/ch18-oop/listing-18-14/src/lib.rs diff --git a/listings/ch17-oop/listing-17-14/src/main.rs b/listings/ch18-oop/listing-18-14/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-14/src/main.rs rename to listings/ch18-oop/listing-18-14/src/main.rs diff --git a/listings/ch17-oop/listing-17-15/Cargo.lock b/listings/ch18-oop/listing-18-15/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-15/Cargo.lock rename to listings/ch18-oop/listing-18-15/Cargo.lock diff --git a/listings/ch17-oop/listing-17-15/Cargo.toml b/listings/ch18-oop/listing-18-15/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-15/Cargo.toml rename to listings/ch18-oop/listing-18-15/Cargo.toml diff --git a/listings/ch17-oop/listing-17-15/src/lib.rs b/listings/ch18-oop/listing-18-15/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-15/src/lib.rs rename to listings/ch18-oop/listing-18-15/src/lib.rs diff --git a/listings/ch17-oop/listing-17-15/src/main.rs b/listings/ch18-oop/listing-18-15/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-15/src/main.rs rename to listings/ch18-oop/listing-18-15/src/main.rs diff --git a/listings/ch17-oop/listing-17-16/Cargo.lock b/listings/ch18-oop/listing-18-16/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-16/Cargo.lock rename to listings/ch18-oop/listing-18-16/Cargo.lock diff --git a/listings/ch17-oop/listing-17-16/Cargo.toml b/listings/ch18-oop/listing-18-16/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-16/Cargo.toml rename to listings/ch18-oop/listing-18-16/Cargo.toml diff --git a/listings/ch17-oop/listing-17-16/src/lib.rs b/listings/ch18-oop/listing-18-16/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-16/src/lib.rs rename to listings/ch18-oop/listing-18-16/src/lib.rs diff --git a/listings/ch17-oop/listing-17-16/src/main.rs b/listings/ch18-oop/listing-18-16/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-16/src/main.rs rename to listings/ch18-oop/listing-18-16/src/main.rs diff --git a/listings/ch17-oop/listing-17-17/Cargo.lock b/listings/ch18-oop/listing-18-17/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-17/Cargo.lock rename to listings/ch18-oop/listing-18-17/Cargo.lock diff --git a/listings/ch17-oop/listing-17-17/Cargo.toml b/listings/ch18-oop/listing-18-17/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-17/Cargo.toml rename to listings/ch18-oop/listing-18-17/Cargo.toml diff --git a/listings/ch17-oop/listing-17-17/src/lib.rs b/listings/ch18-oop/listing-18-17/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-17/src/lib.rs rename to listings/ch18-oop/listing-18-17/src/lib.rs diff --git a/listings/ch17-oop/listing-17-17/src/main.rs b/listings/ch18-oop/listing-18-17/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-17/src/main.rs rename to listings/ch18-oop/listing-18-17/src/main.rs diff --git a/listings/ch17-oop/listing-17-18/Cargo.lock b/listings/ch18-oop/listing-18-18/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-18/Cargo.lock rename to listings/ch18-oop/listing-18-18/Cargo.lock diff --git a/listings/ch17-oop/listing-17-18/Cargo.toml b/listings/ch18-oop/listing-18-18/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-18/Cargo.toml rename to listings/ch18-oop/listing-18-18/Cargo.toml diff --git a/listings/ch17-oop/listing-17-18/src/lib.rs b/listings/ch18-oop/listing-18-18/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-18/src/lib.rs rename to listings/ch18-oop/listing-18-18/src/lib.rs diff --git a/listings/ch17-oop/listing-17-18/src/main.rs b/listings/ch18-oop/listing-18-18/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-18/src/main.rs rename to listings/ch18-oop/listing-18-18/src/main.rs diff --git a/listings/ch17-oop/listing-17-19/Cargo.lock b/listings/ch18-oop/listing-18-19/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-19/Cargo.lock rename to listings/ch18-oop/listing-18-19/Cargo.lock diff --git a/listings/ch17-oop/listing-17-19/Cargo.toml b/listings/ch18-oop/listing-18-19/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-19/Cargo.toml rename to listings/ch18-oop/listing-18-19/Cargo.toml diff --git a/listings/ch17-oop/listing-17-19/src/lib.rs b/listings/ch18-oop/listing-18-19/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-19/src/lib.rs rename to listings/ch18-oop/listing-18-19/src/lib.rs diff --git a/listings/ch17-oop/listing-17-20/Cargo.lock b/listings/ch18-oop/listing-18-20/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-20/Cargo.lock rename to listings/ch18-oop/listing-18-20/Cargo.lock diff --git a/listings/ch17-oop/listing-17-20/Cargo.toml b/listings/ch18-oop/listing-18-20/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-20/Cargo.toml rename to listings/ch18-oop/listing-18-20/Cargo.toml diff --git a/listings/ch17-oop/listing-17-20/src/lib.rs b/listings/ch18-oop/listing-18-20/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-20/src/lib.rs rename to listings/ch18-oop/listing-18-20/src/lib.rs diff --git a/listings/ch17-oop/listing-17-21/Cargo.lock b/listings/ch18-oop/listing-18-21/Cargo.lock similarity index 100% rename from listings/ch17-oop/listing-17-21/Cargo.lock rename to listings/ch18-oop/listing-18-21/Cargo.lock diff --git a/listings/ch17-oop/listing-17-21/Cargo.toml b/listings/ch18-oop/listing-18-21/Cargo.toml similarity index 100% rename from listings/ch17-oop/listing-17-21/Cargo.toml rename to listings/ch18-oop/listing-18-21/Cargo.toml diff --git a/listings/ch17-oop/listing-17-21/src/lib.rs b/listings/ch18-oop/listing-18-21/src/lib.rs similarity index 100% rename from listings/ch17-oop/listing-17-21/src/lib.rs rename to listings/ch18-oop/listing-18-21/src/lib.rs diff --git a/listings/ch17-oop/listing-17-21/src/main.rs b/listings/ch18-oop/listing-18-21/src/main.rs similarity index 100% rename from listings/ch17-oop/listing-17-21/src/main.rs rename to listings/ch18-oop/listing-18-21/src/main.rs diff --git a/src/ch18-01-what-is-oo.md b/src/ch18-01-what-is-oo.md index 4a11b7cc08..f9f22a3a00 100644 --- a/src/ch18-01-what-is-oo.md +++ b/src/ch18-01-what-is-oo.md @@ -41,16 +41,16 @@ can define a struct `AveragedCollection` that has a field containing a vector of `i32` values. The struct can also have a field that contains the average of the values in the vector, meaning the average doesn’t have to be computed on demand whenever anyone needs it. In other words, `AveragedCollection` will -cache the calculated average for us. Listing 17-1 has the definition of the +cache the calculated average for us. Listing 18-1 has the definition of the `AveragedCollection` struct: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-01/src/lib.rs}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-01/src/lib.rs}} ``` -Listing 17-1: An `AveragedCollection` struct that +Listing 18-1: An `AveragedCollection` struct that maintains a list of integers and the average of the items in the collection @@ -58,15 +58,15 @@ The struct is marked `pub` so that other code can use it, but the fields within the struct remain private. This is important in this case because we want to ensure that whenever a value is added or removed from the list, the average is also updated. We do this by implementing `add`, `remove`, and `average` methods -on the struct, as shown in Listing 17-2: +on the struct, as shown in Listing 18-2: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-02/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-02/src/lib.rs:here}} ``` -Listing 17-2: Implementations of the public methods +Listing 18-2: Implementations of the public methods `add`, `remove`, and `average` on `AveragedCollection` The public methods `add`, `remove`, and `average` are the only ways to access diff --git a/src/ch18-02-trait-objects.md b/src/ch18-02-trait-objects.md index c6a90ab2ff..d4f7ee7b51 100644 --- a/src/ch18-02-trait-objects.md +++ b/src/ch18-02-trait-objects.md @@ -63,19 +63,19 @@ a trait object. Trait objects aren’t as generally useful as objects in other languages: their specific purpose is to allow abstraction across common behavior. -Listing 17-3 shows how to define a trait named `Draw` with one method named +Listing 18-3 shows how to define a trait named `Draw` with one method named `draw`: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-03/src/lib.rs}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-03/src/lib.rs}} ``` -Listing 17-3: Definition of the `Draw` trait +Listing 18-3: Definition of the `Draw` trait This syntax should look familiar from our discussions on how to define traits -in Chapter 10. Next comes some new syntax: Listing 17-4 defines a struct named +in Chapter 10. Next comes some new syntax: Listing 18-4 defines a struct named `Screen` that holds a vector named `components`. This vector is of type `Box`, which is a trait object; it’s a stand-in for any type inside a `Box` that implements the `Draw` trait. @@ -83,23 +83,23 @@ a `Box` that implements the `Draw` trait. Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-04/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-04/src/lib.rs:here}} ``` -Listing 17-4: Definition of the `Screen` struct with a +Listing 18-4: Definition of the `Screen` struct with a `components` field holding a vector of trait objects that implement the `Draw` trait On the `Screen` struct, we’ll define a method named `run` that will call the -`draw` method on each of its `components`, as shown in Listing 17-5: +`draw` method on each of its `components`, as shown in Listing 18-5: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-05/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-05/src/lib.rs:here}} ``` -Listing 17-5: A `run` method on `Screen` that calls the +Listing 18-5: A `run` method on `Screen` that calls the `draw` method on each component This works differently from defining a struct that uses a generic type @@ -107,15 +107,15 @@ parameter with trait bounds. A generic type parameter can only be substituted with one concrete type at a time, whereas trait objects allow for multiple concrete types to fill in for the trait object at runtime. For example, we could have defined the `Screen` struct using a generic type and a trait bound -as in Listing 17-6: +as in Listing 18-6: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-06/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-06/src/lib.rs:here}} ``` -Listing 17-6: An alternate implementation of the `Screen` +Listing 18-6: An alternate implementation of the `Screen` struct and its `run` method using generics and trait bounds This restricts us to a `Screen` instance that has a list of components all of @@ -134,15 +134,15 @@ Now we’ll add some types that implement the `Draw` trait. We’ll provide the `Button` type. Again, actually implementing a GUI library is beyond the scope of this book, so the `draw` method won’t have any useful implementation in its body. To imagine what the implementation might look like, a `Button` struct -might have fields for `width`, `height`, and `label`, as shown in Listing 17-7: +might have fields for `width`, `height`, and `label`, as shown in Listing 18-7: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-07/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-07/src/lib.rs:here}} ``` -Listing 17-7: A `Button` struct that implements the +Listing 18-7: A `Button` struct that implements the `Draw` trait The `width`, `height`, and `label` fields on `Button` will differ from the @@ -157,30 +157,30 @@ types like `TextField`. If someone using our library decides to implement a `SelectBox` struct that has `width`, `height`, and `options` fields, they implement the `Draw` trait on the -`SelectBox` type as well, as shown in Listing 17-8: +`SelectBox` type as well, as shown in Listing 18-8: Filename: src/main.rs ```rust,ignore -{{#rustdoc_include ../listings/ch17-oop/listing-17-08/src/main.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-08/src/main.rs:here}} ``` -Listing 17-8: Another crate using `gui` and implementing +Listing 18-8: Another crate using `gui` and implementing the `Draw` trait on a `SelectBox` struct Our library’s user can now write their `main` function to create a `Screen` instance. To the `Screen` instance, they can add a `SelectBox` and a `Button` by putting each in a `Box` to become a trait object. They can then call the `run` method on the `Screen` instance, which will call `draw` on each of the -components. Listing 17-9 shows this implementation: +components. Listing 18-9 shows this implementation: Filename: src/main.rs ```rust,ignore -{{#rustdoc_include ../listings/ch17-oop/listing-17-09/src/main.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-09/src/main.rs:here}} ``` -Listing 17-9: Using trait objects to store values of +Listing 18-9: Using trait objects to store values of different types that implement the same trait When we wrote the library, we didn’t know that someone might add the @@ -192,7 +192,7 @@ This concept—of being concerned only with the messages a value responds to rather than the value’s concrete type—is similar to the concept of *duck typing* in dynamically typed languages: if it walks like a duck and quacks like a duck, then it must be a duck! In the implementation of `run` on `Screen` -in Listing 17-5, `run` doesn’t need to know what the concrete type of each +in Listing 18-5, `run` doesn’t need to know what the concrete type of each component is. It doesn’t check whether a component is an instance of a `Button` or a `SelectBox`, it just calls the `draw` method on the component. By specifying `Box` as the type of the values in the `components` @@ -205,22 +205,22 @@ value implements a particular method at runtime or worry about getting errors if a value doesn’t implement a method but we call it anyway. Rust won’t compile our code if the values don’t implement the traits that the trait objects need. -For example, Listing 17-10 shows what happens if we try to create a `Screen` +For example, Listing 18-10 shows what happens if we try to create a `Screen` with a `String` as a component: Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-oop/listing-17-10/src/main.rs}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-10/src/main.rs}} ``` -Listing 17-10: Attempting to use a type that doesn’t +Listing 18-10: Attempting to use a type that doesn’t implement the trait object’s trait We’ll get this error because `String` doesn’t implement the `Draw` trait: ```console -{{#include ../listings/ch17-oop/listing-17-10/output.txt}} +{{#include ../listings/ch18-oop/listing-18-10/output.txt}} ``` This error lets us know that either we’re passing something to `Screen` we @@ -248,8 +248,8 @@ runtime, Rust uses the pointers inside the trait object to know which method to call. This lookup incurs a runtime cost that doesn’t occur with static dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a method’s code, which in turn prevents some optimizations. However, we did get -extra flexibility in the code that we wrote in Listing 17-5 and were able to -support in Listing 17-9, so it’s a trade-off to consider. +extra flexibility in the code that we wrote in Listing 18-5 and were able to +support in Listing 18-9, so it’s a trade-off to consider. [performance-of-code-using-generics]: ch10-01-syntax.html#performance-of-code-using-generics diff --git a/src/ch18-03-oo-design-patterns.md b/src/ch18-03-oo-design-patterns.md index 6044841631..9306572825 100644 --- a/src/ch18-03-oo-design-patterns.md +++ b/src/ch18-03-oo-design-patterns.md @@ -36,17 +36,17 @@ Any other changes attempted on a post should have no effect. For example, if we try to approve a draft blog post before we’ve requested a review, the post should remain an unpublished draft. -Listing 17-11 shows this workflow in code form: this is an example usage of the +Listing 18-11 shows this workflow in code form: this is an example usage of the API we’ll implement in a library crate named `blog`. This won’t compile yet because we haven’t implemented the `blog` crate. Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-oop/listing-17-11/src/main.rs:all}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-11/src/main.rs:all}} ``` -Listing 17-11: Code that demonstrates the desired +Listing 18-11: Code that demonstrates the desired behavior we want our `blog` crate to have We want to allow the user to create a new draft blog post with `Post::new`. We @@ -76,7 +76,7 @@ make a mistake with the states, like publishing a post before it’s reviewed. Let’s get started on the implementation of the library! We know we need a public `Post` struct that holds some content, so we’ll start with the definition of the struct and an associated public `new` function to create an -instance of `Post`, as shown in Listing 17-12. We’ll also make a private +instance of `Post`, as shown in Listing 18-12. We’ll also make a private `State` trait that will define the behavior that all state objects for a `Post` must have. @@ -87,10 +87,10 @@ in a private field named `state` to hold the state object. You’ll see why the Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-12/src/lib.rs}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-12/src/lib.rs}} ``` -Listing 17-12: Definition of a `Post` struct and a `new` +Listing 18-12: Definition of a `Post` struct and a `new` function that creates a new `Post` instance, a `State` trait, and a `Draft` struct @@ -109,21 +109,21 @@ create a `Post` in any other state! In the `Post::new` function, we set the ### Storing the Text of the Post Content -We saw in Listing 17-11 that we want to be able to call a method named +We saw in Listing 18-11 that we want to be able to call a method named `add_text` and pass it a `&str` that is then added as the text content of the blog post. We implement this as a method, rather than exposing the `content` field as `pub`, so that later we can implement a method that will control how the `content` field’s data is read. The `add_text` method is pretty -straightforward, so let’s add the implementation in Listing 17-13 to the `impl +straightforward, so let’s add the implementation in Listing 18-13 to the `impl Post` block: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-13/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-13/src/lib.rs:here}} ``` -Listing 17-13: Implementing the `add_text` method to add +Listing 18-13: Implementing the `add_text` method to add text to a post’s `content` The `add_text` method takes a mutable reference to `self`, because we’re @@ -138,37 +138,37 @@ support. Even after we’ve called `add_text` and added some content to our post, we still want the `content` method to return an empty string slice because the post is -still in the draft state, as shown on line 7 of Listing 17-11. For now, let’s +still in the draft state, as shown on line 7 of Listing 18-11. For now, let’s implement the `content` method with the simplest thing that will fulfill this requirement: always returning an empty string slice. We’ll change this later once we implement the ability to change a post’s state so it can be published. So far, posts can only be in the draft state, so the post content should always -be empty. Listing 17-14 shows this placeholder implementation: +be empty. Listing 18-14 shows this placeholder implementation: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-14/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-14/src/lib.rs:here}} ``` -Listing 17-14: Adding a placeholder implementation for +Listing 18-14: Adding a placeholder implementation for the `content` method on `Post` that always returns an empty string slice -With this added `content` method, everything in Listing 17-11 up to line 7 +With this added `content` method, everything in Listing 18-11 up to line 7 works as intended. ### Requesting a Review of the Post Changes Its State Next, we need to add functionality to request a review of a post, which should -change its state from `Draft` to `PendingReview`. Listing 17-15 shows this code: +change its state from `Draft` to `PendingReview`. Listing 18-15 shows this code: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-15/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-15/src/lib.rs:here}} ``` -Listing 17-15: Implementing `request_review` methods on +Listing 18-15: Implementing `request_review` methods on `Post` and the `State` trait We give `Post` a public method named `request_review` that will take a mutable @@ -211,7 +211,7 @@ state is responsible for its own rules. We’ll leave the `content` method on `Post` as is, returning an empty string slice. We can now have a `Post` in the `PendingReview` state as well as in the `Draft` state, but we want the same behavior in the `PendingReview` state. -Listing 17-11 now works up to line 10! +Listing 18-11 now works up to line 10! @@ -220,15 +220,15 @@ Listing 17-11 now works up to line 10! The `approve` method will be similar to the `request_review` method: it will set `state` to the value that the current state says it should have when that -state is approved, as shown in Listing 17-16: +state is approved, as shown in Listing 18-16: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-16/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-16/src/lib.rs:here}} ``` -Listing 17-16: Implementing the `approve` method on +Listing 18-16: Implementing the `approve` method on `Post` and the `State` trait We add the `approve` method to the `State` trait and add a new struct that @@ -245,15 +245,15 @@ state in those cases. Now we need to update the `content` method on `Post`. We want the value returned from `content` to depend on the current state of the `Post`, so we’re going to have the `Post` delegate to a `content` method defined on its `state`, -as shown in Listing 17-17: +as shown in Listing 18-17: Filename: src/lib.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch17-oop/listing-17-17/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-17/src/lib.rs:here}} ``` -Listing 17-17: Updating the `content` method on `Post` to +Listing 18-17: Updating the `content` method on `Post` to delegate to a `content` method on `State` Because the goal is to keep all these rules inside the structs that implement @@ -280,15 +280,15 @@ will take effect on the `&` and the `Box` so the `content` method will ultimately be called on the type that implements the `State` trait. That means we need to add `content` to the `State` trait definition, and that is where we’ll put the logic for what content to return depending on which state we -have, as shown in Listing 17-18: +have, as shown in Listing 18-18: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-18/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-18/src/lib.rs:here}} ``` -Listing 17-18: Adding the `content` method to the `State` +Listing 18-18: Adding the `content` method to the `State` trait We add a default implementation for the `content` method that returns an empty @@ -301,7 +301,7 @@ Chapter 10. We’re taking a reference to a `post` as an argument and returning reference to part of that `post`, so the lifetime of the returned reference is related to the lifetime of the `post` argument. -And we’re done—all of Listing 17-11 now works! We’ve implemented the state +And we’re done—all of Listing 18-11 now works! We’ve implemented the state pattern with the rules of the blog post workflow. The logic related to the rules lives in the state objects rather than being scattered throughout `Post`. @@ -381,12 +381,12 @@ outside code has no knowledge of them, we’ll encode the states into different types. Consequently, Rust’s type checking system will prevent attempts to use draft posts where only published posts are allowed by issuing a compiler error. -Let’s consider the first part of `main` in Listing 17-11: +Let’s consider the first part of `main` in Listing 18-11: Filename: src/main.rs ```rust,ignore -{{#rustdoc_include ../listings/ch17-oop/listing-17-11/src/main.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-11/src/main.rs:here}} ``` We still enable the creation of new posts in the draft state using `Post::new` @@ -396,16 +396,16 @@ draft posts don’t have the `content` method at all. That way, if we try to get a draft post’s content, we’ll get a compiler error telling us the method doesn’t exist. As a result, it will be impossible for us to accidentally display draft post content in production, because that code won’t even compile. -Listing 17-19 shows the definition of a `Post` struct and a `DraftPost` struct, +Listing 18-19 shows the definition of a `Post` struct and a `DraftPost` struct, as well as methods on each: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-19/src/lib.rs}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-19/src/lib.rs}} ``` -Listing 17-19: A `Post` with a `content` method and a +Listing 18-19: A `Post` with a `content` method and a `DraftPost` without a `content` method Both the `Post` and `DraftPost` structs have a private `content` field that @@ -433,15 +433,15 @@ pending review state should still not display any content. Let’s implement these constraints by adding another struct, `PendingReviewPost`, defining the `request_review` method on `DraftPost` to return a `PendingReviewPost`, and defining an `approve` method on `PendingReviewPost` to return a `Post`, as -shown in Listing 17-20: +shown in Listing 18-20: Filename: src/lib.rs ```rust,noplayground -{{#rustdoc_include ../listings/ch17-oop/listing-17-20/src/lib.rs:here}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-20/src/lib.rs:here}} ``` -Listing 17-20: A `PendingReviewPost` that gets created by +Listing 18-20: A `PendingReviewPost` that gets created by calling `request_review` on `DraftPost` and an `approve` method that turns a `PendingReviewPost` into a published `Post` @@ -463,15 +463,15 @@ called on, so we need to add more `let post =` shadowing assignments to save the returned instances. We also can’t have the assertions about the draft and pending review posts’ contents be empty strings, nor do we need them: we can’t compile code that tries to use the content of posts in those states any longer. -The updated code in `main` is shown in Listing 17-21: +The updated code in `main` is shown in Listing 18-21: Filename: src/main.rs ```rust,ignore -{{#rustdoc_include ../listings/ch17-oop/listing-17-21/src/main.rs}} +{{#rustdoc_include ../listings/ch18-oop/listing-18-21/src/main.rs}} ``` -Listing 17-21: Modifications to `main` to use the new +Listing 18-21: Modifications to `main` to use the new implementation of the blog post workflow The changes we needed to make to `main` to reassign `post` mean that this @@ -483,7 +483,7 @@ compile time! This ensures that certain bugs, such as display of the content of an unpublished post, will be discovered before they make it to production. Try the tasks suggested at the start of this section on the `blog` crate as it -is after Listing 17-21 to see what you think about the design of this version +is after Listing 18-21 to see what you think about the design of this version of the code. Note that some of the tasks might be completed already in this design. From 1fb74c3f1d8aeba39373e9f4cdb9a4bdca95604f Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 26 Sep 2024 14:17:57 -0600 Subject: [PATCH 246/249] Ch. 17: update all other text references for new ordering --- src/appendix-03-derivable-traits.md | 2 +- src/ch00-00-introduction.md | 15 +++++++++------ src/ch01-02-hello-world.md | 2 +- src/ch02-00-guessing-game-tutorial.md | 4 ++-- src/ch08-01-vectors.md | 2 +- src/ch09-02-recoverable-errors-with-result.md | 2 +- src/ch09-03-to-panic-or-not-to-panic.md | 2 +- src/ch10-02-traits.md | 2 +- src/ch10-03-lifetime-syntax.md | 2 +- src/ch12-00-an-io-project.md | 4 ++-- ...-03-improving-error-handling-and-modularity.md | 4 ++-- src/ch13-02-iterators.md | 2 +- src/ch14-02-publishing-to-crates-io.md | 2 +- src/ch15-01-box.md | 6 +++--- src/ch15-02-deref.md | 2 +- src/ch15-05-interior-mutability.md | 2 +- src/ch16-02-message-passing.md | 2 +- ...h16-04-extensible-concurrency-sync-and-send.md | 6 +++--- src/ch18-02-trait-objects.md | 2 +- src/ch18-03-oo-design-patterns.md | 2 +- src/ch20-00-advanced-features.md | 2 +- src/ch20-04-advanced-types.md | 4 ++-- src/ch20-05-advanced-functions-and-closures.md | 2 +- src/ch20-06-macros.md | 2 +- src/ch21-01-single-threaded.md | 2 +- src/ch21-02-multithreaded.md | 6 +++--- src/ch21-03-graceful-shutdown-and-cleanup.md | 2 +- 27 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/appendix-03-derivable-traits.md b/src/appendix-03-derivable-traits.md index d3951f9e5f..4214f091b9 100644 --- a/src/appendix-03-derivable-traits.md +++ b/src/appendix-03-derivable-traits.md @@ -34,7 +34,7 @@ The list of derivable traits provided in this appendix is not comprehensive: libraries can implement `derive` for their own traits, making the list of traits you can use `derive` with truly open-ended. Implementing `derive` involves using a procedural macro, which is covered in the -[“Macros”][macros] section of Chapter 19. +[“Macros”][macros] section of Chapter 20. ### `Debug` for Programmer Output diff --git a/src/ch00-00-introduction.md b/src/ch00-00-introduction.md index 12632aa0bf..050a627818 100644 --- a/src/ch00-00-introduction.md +++ b/src/ch00-00-introduction.md @@ -141,17 +141,20 @@ depth and talk about best practices for sharing your libraries with others. Chapter 15 discusses smart pointers that the standard library provides and the traits that enable their functionality. -In Chapter 16, we’ll walk through different models of concurrent programming -and talk about how Rust helps you to program in multiple threads fearlessly. -Chapter 17 looks at how Rust idioms compare to object-oriented programming +In Chapter 16, we’ll walk through different models of concurrent programming and +talk about how Rust helps you to program in multiple threads fearlessly. In +Chapter 17, we will build on that by exploring Rust’s async and await syntax and +the lightweight concurrency model they support. + +Chapter 18 looks at how Rust idioms compare to object-oriented programming principles you might be familiar with. -Chapter 18 is a reference on patterns and pattern matching, which are powerful -ways of expressing ideas throughout Rust programs. Chapter 19 contains a +Chapter 19 is a reference on patterns and pattern matching, which are powerful +ways of expressing ideas throughout Rust programs. Chapter 20 contains a smorgasbord of advanced topics of interest, including unsafe Rust, macros, and more about lifetimes, traits, types, functions, and closures. -In Chapter 20, we’ll complete a project in which we’ll implement a low-level +In Chapter 21, we’ll complete a project in which we’ll implement a low-level multithreaded web server! Finally, some appendices contain useful information about the language in a diff --git a/src/ch01-02-hello-world.md b/src/ch01-02-hello-world.md index f0b97e4949..7efd5726e0 100644 --- a/src/ch01-02-hello-world.md +++ b/src/ch01-02-hello-world.md @@ -125,7 +125,7 @@ First, Rust style is to indent with four spaces, not a tab. Second, `println!` calls a Rust macro. If it had called a function instead, it would be entered as `println` (without the `!`). We’ll discuss Rust macros in -more detail in Chapter 19. For now, you just need to know that using a `!` +more detail in Chapter 20. For now, you just need to know that using a `!` means that you’re calling a macro instead of a normal function and that macros don’t always follow the same rules as functions. diff --git a/src/ch02-00-guessing-game-tutorial.md b/src/ch02-00-guessing-game-tutorial.md index 9c9601bf6a..d0d27f2b1b 100644 --- a/src/ch02-00-guessing-game-tutorial.md +++ b/src/ch02-00-guessing-game-tutorial.md @@ -79,7 +79,7 @@ allow the player to input a guess. Enter the code in Listing 2-1 into {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:all}} ``` - +
This code contains a lot of information, so let’s go over it line by line. To obtain user input and then print the result as output, we need to bring the @@ -612,7 +612,7 @@ fits that arm’s pattern. Rust takes the value given to `match` and looks through each arm’s pattern in turn. Patterns and the `match` construct are powerful Rust features: they let you express a variety of situations your code might encounter and they make sure you handle them all. These features will be -covered in detail in Chapter 6 and Chapter 18, respectively. +covered in detail in Chapter 6 and Chapter 19, respectively. Let’s walk through an example with the `match` expression we use here. Say that the user has guessed 50 and the randomly generated secret number this time is diff --git a/src/ch08-01-vectors.md b/src/ch08-01-vectors.md index ece5d59dce..7138b35fde 100644 --- a/src/ch08-01-vectors.md +++ b/src/ch08-01-vectors.md @@ -219,7 +219,7 @@ at compile time that every possible case is handled, as discussed in Chapter 6. If you don’t know the exhaustive set of types a program will get at runtime to store in a vector, the enum technique won’t work. Instead, you can use a trait -object, which we’ll cover in Chapter 17. +object, which we’ll cover in Chapter 18. Now that we’ve discussed some of the most common ways to use vectors, be sure to review [the API documentation][vec-api] for all of the many diff --git a/src/ch09-02-recoverable-errors-with-result.md b/src/ch09-02-recoverable-errors-with-result.md index 78a87c7392..41031c1276 100644 --- a/src/ch09-02-recoverable-errors-with-result.md +++ b/src/ch09-02-recoverable-errors-with-result.md @@ -507,7 +507,7 @@ allows the use of the `?` operator on `Result` values. The `Box` type is a *trait object*, which we’ll talk about in the [“Using Trait Objects that Allow for Values of Different -Types”][trait-objects] section in Chapter 17. For now, you can +Types”][trait-objects] section in Chapter 18. For now, you can read `Box` to mean “any kind of error.” Using `?` on a `Result` value in a `main` function with the error type `Box` is allowed because it allows any `Err` value to be returned early. Even though the body of diff --git a/src/ch09-03-to-panic-or-not-to-panic.md b/src/ch09-03-to-panic-or-not-to-panic.md index 138a783d00..88e30fd5e1 100644 --- a/src/ch09-03-to-panic-or-not-to-panic.md +++ b/src/ch09-03-to-panic-or-not-to-panic.md @@ -78,7 +78,7 @@ more of the following: rather than checking for the problem at every step. * There’s not a good way to encode this information in the types you use. We’ll work through an example of what we mean in the [“Encoding States and Behavior - as Types”][encoding] section of Chapter 17. + as Types”][encoding] section of Chapter 18. If someone calls your code and passes in values that don’t make sense, it’s best to return an error if you can so the user of the library can decide what diff --git a/src/ch10-02-traits.md b/src/ch10-02-traits.md index 855ee1fc4b..25eaaa3cc0 100644 --- a/src/ch10-02-traits.md +++ b/src/ch10-02-traits.md @@ -325,7 +325,7 @@ around how the `impl Trait` syntax is implemented in the compiler. We’ll cover how to write a function with this behavior in the [“Using Trait Objects That Allow for Values of Different Types”][using-trait-objects-that-allow-for-values-of-different-types] section of Chapter 17. +ignore --> section of Chapter 18. ### Using Trait Bounds to Conditionally Implement Methods diff --git a/src/ch10-03-lifetime-syntax.md b/src/ch10-03-lifetime-syntax.md index d327e512b9..c87f38c4ce 100644 --- a/src/ch10-03-lifetime-syntax.md +++ b/src/ch10-03-lifetime-syntax.md @@ -608,7 +608,7 @@ that this flexible code won’t have any dangling references. And all of this analysis happens at compile time, which doesn’t affect runtime performance! Believe it or not, there is much more to learn on the topics we discussed in -this chapter: Chapter 17 discusses trait objects, which are another way to use +this chapter: Chapter 18 discusses trait objects, which are another way to use traits. There are also more complex scenarios involving lifetime annotations that you will only need in very advanced scenarios; for those, you should read the [Rust Reference][reference]. But next, you’ll learn how to write tests in diff --git a/src/ch12-00-an-io-project.md b/src/ch12-00-an-io-project.md index f40edcbafe..e179e11800 100644 --- a/src/ch12-00-an-io-project.md +++ b/src/ch12-00-an-io-project.md @@ -36,7 +36,7 @@ Our `grep` project will combine a number of concepts you’ve learned so far: * Writing tests ([Chapter 11][ch11]) We’ll also briefly introduce closures, iterators, and trait objects, which -[Chapter 13][ch13] and [Chapter 17][ch17] will +[Chapter 13][ch13] and [Chapter 18][ch18] will cover in detail. [ch7]: ch07-00-managing-growing-projects-with-packages-crates-and-modules.html @@ -45,4 +45,4 @@ cover in detail. [ch10]: ch10-00-generics.html [ch11]: ch11-00-testing.html [ch13]: ch13-00-functional-features.html -[ch17]: ch18-00-oop.html +[ch18]: ch18-00-oop.html diff --git a/src/ch12-03-improving-error-handling-and-modularity.md b/src/ch12-03-improving-error-handling-and-modularity.md index 64fe188b52..bf2b7c35bd 100644 --- a/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/ch12-03-improving-error-handling-and-modularity.md @@ -381,7 +381,7 @@ returned the unit type, `()`, and we keep that as the value returned in the For the error type, we used the *trait object* `Box` (and we’ve brought `std::error::Error` into scope with a `use` statement at the top). -We’ll cover trait objects in [Chapter 17][ch17]. For now, just +We’ll cover trait objects in [Chapter 18][ch18]. For now, just know that `Box` means the function will return a type that implements the `Error` trait, but we don’t have to specify what particular type the return value will be. This gives us flexibility to return error values that @@ -490,5 +490,5 @@ write some tests! [ch9-custom-types]: ch09-03-to-panic-or-not-to-panic.html#creating-custom-types-for-validation [ch9-error-guidelines]: ch09-03-to-panic-or-not-to-panic.html#guidelines-for-error-handling [ch9-result]: ch09-02-recoverable-errors-with-result.html -[ch17]: ch18-00-oop.html +[ch18]: ch18-00-oop.html [ch9-question-mark]: ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator diff --git a/src/ch13-02-iterators.md b/src/ch13-02-iterators.md index 4ce9170de0..5942a62c5a 100644 --- a/src/ch13-02-iterators.md +++ b/src/ch13-02-iterators.md @@ -66,7 +66,7 @@ pub trait Iterator { Notice this definition uses some new syntax: `type Item` and `Self::Item`, which are defining an *associated type* with this trait. We’ll talk about -associated types in depth in Chapter 19. For now, all you need to know is that +associated types in depth in Chapter 20. For now, all you need to know is that this code says implementing the `Iterator` trait requires that you also define an `Item` type, and this `Item` type is used in the return type of the `next` method. In other words, the `Item` type will be the type returned from the diff --git a/src/ch14-02-publishing-to-crates-io.md b/src/ch14-02-publishing-to-crates-io.md index b4cfb22d6c..87887a32ac 100644 --- a/src/ch14-02-publishing-to-crates-io.md +++ b/src/ch14-02-publishing-to-crates-io.md @@ -66,7 +66,7 @@ authors commonly use in their documentation: returned can be helpful to callers so they can write code to handle the different kinds of errors in different ways. * **Safety**: If the function is `unsafe` to call (we discuss unsafety in - Chapter 19), there should be a section explaining why the function is unsafe + Chapter 20), there should be a section explaining why the function is unsafe and covering the invariants that the function expects callers to uphold. Most documentation comments don’t need all of these sections, but this is a diff --git a/src/ch15-01-box.md b/src/ch15-01-box.md index 1878f6f195..bc16c2504f 100644 --- a/src/ch15-01-box.md +++ b/src/ch15-01-box.md @@ -23,10 +23,10 @@ time because the data is copied around on the stack. To improve performance in this situation, we can store the large amount of data on the heap in a box. Then, only the small amount of pointer data is copied around on the stack, while the data it references stays in one place on the heap. The third case is -known as a *trait object*, and Chapter 17 devotes an entire section, [“Using +known as a *trait object*, and Chapter 18 devotes an entire section, [“Using Trait Objects That Allow for Values of Different Types,”][trait-objects] just to that topic. So what you learn here you’ll apply again in -Chapter 17! +Chapter 18! ### Using a `Box` to Store Data on the Heap @@ -242,7 +242,7 @@ other special capabilities, like those we’ll see with the other smart pointer types. They also don’t have the performance overhead that these special capabilities incur, so they can be useful in cases like the cons list where the indirection is the only feature we need. We’ll look at more use cases for boxes -in Chapter 17, too. +in Chapter 18, too. The `Box` type is a smart pointer because it implements the `Deref` trait, which allows `Box` values to be treated like references. When a `Box` diff --git a/src/ch15-02-deref.md b/src/ch15-02-deref.md index 56db7c0a02..5017fca434 100644 --- a/src/ch15-02-deref.md +++ b/src/ch15-02-deref.md @@ -148,7 +148,7 @@ contains an implementation of `Deref` to add to the definition of `MyBox`: The `type Target = T;` syntax defines an associated type for the `Deref` trait to use. Associated types are a slightly different way of declaring a generic parameter, but you don’t need to worry about them for now; we’ll cover -them in more detail in Chapter 19. +them in more detail in Chapter 20. We fill in the body of the `deref` method with `&self.0` so `deref` returns a reference to the value we want to access with the `*` operator; recall from the diff --git a/src/ch15-05-interior-mutability.md b/src/ch15-05-interior-mutability.md index 7b5e825d7e..4c7d3c4f66 100644 --- a/src/ch15-05-interior-mutability.md +++ b/src/ch15-05-interior-mutability.md @@ -6,7 +6,7 @@ action is disallowed by the borrowing rules. To mutate data, the pattern uses `unsafe` code inside a data structure to bend Rust’s usual rules that govern mutation and borrowing. Unsafe code indicates to the compiler that we’re checking the rules manually instead of relying on the compiler to check them -for us; we will discuss unsafe code more in Chapter 19. +for us; we will discuss unsafe code more in Chapter 20. We can use types that use the interior mutability pattern only when we can ensure that the borrowing rules will be followed at runtime, even though the diff --git a/src/ch16-02-message-passing.md b/src/ch16-02-message-passing.md index c468b94c33..3782fa5dec 100644 --- a/src/ch16-02-message-passing.md +++ b/src/ch16-02-message-passing.md @@ -57,7 +57,7 @@ receiver. The abbreviations `tx` and `rx` are traditionally used in many fields for *transmitter* and *receiver* respectively, so we name our variables as such to indicate each end. We’re using a `let` statement with a pattern that destructures the tuples; we’ll discuss the use of patterns in `let` statements -and destructuring in Chapter 18. For now, know that using a `let` statement +and destructuring in Chapter 19. For now, know that using a `let` statement this way is a convenient approach to extract the pieces of the tuple returned by `mpsc::channel`. diff --git a/src/ch16-04-extensible-concurrency-sync-and-send.md b/src/ch16-04-extensible-concurrency-sync-and-send.md index ede5c66856..148b68ab3d 100644 --- a/src/ch16-04-extensible-concurrency-sync-and-send.md +++ b/src/ch16-04-extensible-concurrency-sync-and-send.md @@ -28,7 +28,7 @@ compiled. Any type composed entirely of `Send` types is automatically marked as `Send` as well. Almost all primitive types are `Send`, aside from raw pointers, which -we’ll discuss in Chapter 19. +we’ll discuss in Chapter 20. ### Allowing Access from Multiple Threads with `Sync` @@ -54,7 +54,7 @@ marker traits, they don’t even have any methods to implement. They’re just useful for enforcing invariants related to concurrency. Manually implementing these traits involves implementing unsafe Rust code. -We’ll talk about using unsafe Rust code in Chapter 19; for now, the important +We’ll talk about using unsafe Rust code in Chapter 20; for now, the important information is that building new concurrent types not made up of `Send` and `Sync` parts requires careful thought to uphold the safety guarantees. [“The Rustonomicon”][nomicon] has more information about these guarantees and how to @@ -63,7 +63,7 @@ uphold them. ## Summary This isn’t the last you’ll see of concurrency in this book: the whole next -chapter focuses on async programming, and the project in Chapter 20 will use the +chapter focuses on async programming, and the project in Chapter 21 will use the concepts in this chapter in a more realistic situation than the smaller examples discussed here. diff --git a/src/ch18-02-trait-objects.md b/src/ch18-02-trait-objects.md index d4f7ee7b51..751fdaa033 100644 --- a/src/ch18-02-trait-objects.md +++ b/src/ch18-02-trait-objects.md @@ -45,7 +45,7 @@ implementing our specified trait and a table used to look up trait methods on that type at runtime. We create a trait object by specifying some sort of pointer, such as a `&` reference or a `Box` smart pointer, then the `dyn` keyword, and then specifying the relevant trait. (We’ll talk about the reason -trait objects must use a pointer in Chapter 19 in the section [“Dynamically +trait objects must use a pointer in Chapter 20 in the section [“Dynamically Sized Types and the `Sized` Trait.”][dynamically-sized]) We can use trait objects in place of a generic or concrete type. Wherever we use a trait object, Rust’s type system will ensure at compile time that any value diff --git a/src/ch18-03-oo-design-patterns.md b/src/ch18-03-oo-design-patterns.md index 9306572825..9a73091cda 100644 --- a/src/ch18-03-oo-design-patterns.md +++ b/src/ch18-03-oo-design-patterns.md @@ -366,7 +366,7 @@ and `approve` methods on `Post`. Both methods delegate to the implementation of the same method on the value in the `state` field of `Option` and set the new value of the `state` field to the result. If we had a lot of methods on `Post` that followed this pattern, we might consider defining a macro to eliminate the -repetition (see the [“Macros”][macros] section in Chapter 19). +repetition (see the [“Macros”][macros] section in Chapter 20). By implementing the state pattern exactly as it’s defined for object-oriented languages, we’re not taking as full advantage of Rust’s strengths as we could. diff --git a/src/ch20-00-advanced-features.md b/src/ch20-00-advanced-features.md index a0db41fde4..3e612d2af2 100644 --- a/src/ch20-00-advanced-features.md +++ b/src/ch20-00-advanced-features.md @@ -1,7 +1,7 @@ # Advanced Features By now, you’ve learned the most commonly used parts of the Rust programming -language. Before we do one more project in Chapter 20, we’ll look at a few +language. Before we do one more project in Chapter 21, we’ll look at a few aspects of the language you might run into every once in a while, but may not use every day. You can use this chapter as a reference for when you encounter any unknowns. The features covered here are useful in very specific situations. diff --git a/src/ch20-04-advanced-types.md b/src/ch20-04-advanced-types.md index a626529842..1e5b08c106 100644 --- a/src/ch20-04-advanced-types.md +++ b/src/ch20-04-advanced-types.md @@ -34,7 +34,7 @@ internally. The newtype pattern is a lightweight way to achieve encapsulation to hide implementation details, which we discussed in the [“Encapsulation that Hides Implementation Details”][encapsulation-that-hides-implementation-details] -section of Chapter 17. +section of Chapter 18. ### Creating Type Synonyms with Type Aliases @@ -245,7 +245,7 @@ types behind a pointer of some kind. We can combine `str` with all kinds of pointers: for example, `Box` or `Rc`. In fact, you’ve seen this before but with a different dynamically sized type: traits. Every trait is a dynamically sized type we can refer to by -using the name of the trait. In Chapter 17 in the [“Using Trait Objects That +using the name of the trait. In Chapter 18 in the [“Using Trait Objects That Allow for Values of Different Types”][using-trait-objects-that-allow-for-values-of-different-types] section, we mentioned that to use traits as trait objects, we must diff --git a/src/ch20-05-advanced-functions-and-closures.md b/src/ch20-05-advanced-functions-and-closures.md index ac8305736d..ef6a6e46f7 100644 --- a/src/ch20-05-advanced-functions-and-closures.md +++ b/src/ch20-05-advanced-functions-and-closures.md @@ -119,7 +119,7 @@ We can use a trait object: This code will compile just fine. For more about trait objects, refer to the section [“Using Trait Objects That Allow for Values of Different Types”][using-trait-objects-that-allow-for-values-of-different-types] in Chapter 18. +ignore --> in Chapter 19. Next, let’s look at macros! diff --git a/src/ch20-06-macros.md b/src/ch20-06-macros.md index b9b97201cc..2406942df2 100644 --- a/src/ch20-06-macros.md +++ b/src/ch20-06-macros.md @@ -105,7 +105,7 @@ other pattern will result in an error. More complex macros will have more than one arm. Valid pattern syntax in macro definitions is different than the pattern syntax -covered in Chapter 18 because macro patterns are matched against Rust code +covered in Chapter 19 because macro patterns are matched against Rust code structure rather than values. Let’s walk through what the pattern pieces in Listing 20-28 mean; for the full macro pattern syntax, see the [Rust Reference][ref]. diff --git a/src/ch21-01-single-threaded.md b/src/ch21-01-single-threaded.md index 11ae851b78..744a2a7829 100644 --- a/src/ch21-01-single-threaded.md +++ b/src/ch21-01-single-threaded.md @@ -441,7 +441,7 @@ contain only the code that differs between the two cases Now the `if` and `else` blocks only return the appropriate values for the status line and filename in a tuple; we then use destructuring to assign these two values to `status_line` and `filename` using a pattern in the `let` -statement, as discussed in Chapter 18. +statement, as discussed in Chapter 19. The previously duplicated code is now outside the `if` and `else` blocks and uses the `status_line` and `filename` variables. This makes it easier to see diff --git a/src/ch21-02-multithreaded.md b/src/ch21-02-multithreaded.md index bcb0b133b0..4204693508 100644 --- a/src/ch21-02-multithreaded.md +++ b/src/ch21-02-multithreaded.md @@ -546,7 +546,7 @@ Let’s finally implement the `execute` method on `ThreadPool`. We’ll also cha `Job` from a struct to a type alias for a trait object that holds the type of closure that `execute` receives. As discussed in the [“Creating Type Synonyms with Type Aliases”][creating-type-synonyms-with-type-aliases] -section of Chapter 19, type aliases allow us to make long types shorter for +section of Chapter 20, type aliases allow us to make long types shorter for ease of use. Look at Listing 21-19. Filename: src/lib.rs @@ -658,8 +658,8 @@ thread run them. > multiple instances of the same request sequentially for caching reasons. This > limitation is not caused by our web server. -After learning about the `while let` loop in Chapter 18, you might be wondering -why we didn’t write the worker thread code as shown in Listing 21-21. +After learning about the `while let` loop in Chapters 17 and 18, you might be +wondering why we didn’t write the worker thread code as shown in Listing 21-21. Filename: src/lib.rs diff --git a/src/ch21-03-graceful-shutdown-and-cleanup.md b/src/ch21-03-graceful-shutdown-and-cleanup.md index 38180a580d..24a8aabf6f 100644 --- a/src/ch21-03-graceful-shutdown-and-cleanup.md +++ b/src/ch21-03-graceful-shutdown-and-cleanup.md @@ -90,7 +90,7 @@ The following changes will do so: {{#rustdoc_include ../listings/ch21-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs:here}} ``` -As discussed in Chapter 17, the `take` method on `Option` takes the `Some` +As discussed in Chapter 18, the `take` method on `Option` takes the `Some` variant out and leaves `None` in its place. We’re using `if let` to destructure the `Some` and get the thread; then we call `join` on the thread. If a worker’s thread is already `None`, we know that worker has already had its thread From 54c567b5b23e5358feac45bd8c6a27f85abc8b34 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 26 Sep 2024 14:40:12 -0600 Subject: [PATCH 247/249] Ch. 17: update all internal links for new ordering --- 2018-edition/src/ch17-00-oop.md | 4 ++-- 2018-edition/src/ch17-01-what-is-oo.md | 4 ++-- 2018-edition/src/ch17-02-trait-objects.md | 4 ++-- 2018-edition/src/ch17-03-oo-design-patterns.md | 2 +- 2018-edition/src/ch18-00-patterns.md | 4 ++-- 2018-edition/src/ch18-01-all-the-places-for-patterns.md | 4 ++-- 2018-edition/src/ch18-02-refutability.md | 4 ++-- 2018-edition/src/ch18-03-pattern-syntax.md | 4 ++-- 2018-edition/src/ch19-00-advanced-features.md | 4 ++-- 2018-edition/src/ch19-01-unsafe-rust.md | 4 ++-- 2018-edition/src/ch19-03-advanced-traits.md | 4 ++-- 2018-edition/src/ch19-04-advanced-types.md | 4 ++-- 2018-edition/src/ch19-05-advanced-functions-and-closures.md | 4 ++-- 2018-edition/src/ch19-06-macros.md | 4 ++-- 2018-edition/src/ch20-00-final-project-a-web-server.md | 4 ++-- 2018-edition/src/ch20-01-single-threaded.md | 4 ++-- 2018-edition/src/ch20-02-multithreaded.md | 4 ++-- 2018-edition/src/ch20-03-graceful-shutdown-and-cleanup.md | 4 ++-- first-edition/src/associated-types.md | 2 +- first-edition/src/const-and-static.md | 2 +- first-edition/src/ffi.md | 2 +- first-edition/src/macros.md | 2 +- first-edition/src/operators-and-overloading.md | 2 +- first-edition/src/patterns.md | 2 +- first-edition/src/procedural-macros.md | 2 +- first-edition/src/raw-pointers.md | 2 +- first-edition/src/trait-objects.md | 2 +- first-edition/src/type-aliases.md | 2 +- first-edition/src/unsafe.md | 2 +- first-edition/src/unsized-types.md | 2 +- listings/ch19-patterns-and-matching/listing-19-08/output.txt | 2 +- redirects/associated-types.md | 2 +- redirects/const-and-static.md | 2 +- redirects/ffi.md | 2 +- redirects/macros.md | 2 +- redirects/match.md | 2 +- redirects/operators-and-overloading.md | 2 +- redirects/procedural-macros.md | 2 +- redirects/raw-pointers.md | 2 +- redirects/trait-objects.md | 2 +- redirects/traits.md | 2 +- redirects/type-aliases.md | 2 +- redirects/ufcs.md | 2 +- redirects/unsafe.md | 2 +- redirects/unsized-types.md | 2 +- second-edition/src/appendix-04-macros.md | 4 ++-- second-edition/src/ch17-00-oop.md | 4 ++-- second-edition/src/ch17-01-what-is-oo.md | 4 ++-- second-edition/src/ch17-02-trait-objects.md | 4 ++-- second-edition/src/ch18-01-all-the-places-for-patterns.md | 4 ++-- second-edition/src/ch18-02-refutability.md | 4 ++-- second-edition/src/ch18-03-pattern-syntax.md | 4 ++-- second-edition/src/ch19-00-advanced-features.md | 4 ++-- second-edition/src/ch19-01-unsafe-rust.md | 4 ++-- second-edition/src/ch19-03-advanced-traits.md | 4 ++-- second-edition/src/ch19-04-advanced-types.md | 4 ++-- second-edition/src/ch19-05-advanced-functions-and-closures.md | 4 ++-- second-edition/src/ch20-00-final-project-a-web-server.md | 4 ++-- second-edition/src/ch20-01-single-threaded.md | 4 ++-- second-edition/src/ch20-02-multithreaded.md | 4 ++-- second-edition/src/ch20-03-graceful-shutdown-and-cleanup.md | 4 ++-- 61 files changed, 94 insertions(+), 94 deletions(-) diff --git a/2018-edition/src/ch17-00-oop.md b/2018-edition/src/ch17-00-oop.md index c731bbc95b..6ff4dc33e8 100644 --- a/2018-edition/src/ch17-00-oop.md +++ b/2018-edition/src/ch17-00-oop.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-00-oop.html) instead. +version of the book](../ch18-00-oop.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-00-oop.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-00-oop.html). diff --git a/2018-edition/src/ch17-01-what-is-oo.md b/2018-edition/src/ch17-01-what-is-oo.md index ed1ec4013d..28835201bf 100644 --- a/2018-edition/src/ch17-01-what-is-oo.md +++ b/2018-edition/src/ch17-01-what-is-oo.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-01-what-is-oo.html) instead. +version of the book](../ch18-01-what-is-oo.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-01-what-is-oo.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-01-what-is-oo.html). diff --git a/2018-edition/src/ch17-02-trait-objects.md b/2018-edition/src/ch17-02-trait-objects.md index 1999647aae..b83ab904ee 100644 --- a/2018-edition/src/ch17-02-trait-objects.md +++ b/2018-edition/src/ch17-02-trait-objects.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-02-trait-objects.html) instead. +version of the book](../ch18-02-trait-objects.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-02-trait-objects.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch17-02-trait-objects.html). diff --git a/2018-edition/src/ch17-03-oo-design-patterns.md b/2018-edition/src/ch17-03-oo-design-patterns.md index 9513538f57..c161b3decf 100644 --- a/2018-edition/src/ch17-03-oo-design-patterns.md +++ b/2018-edition/src/ch17-03-oo-design-patterns.md @@ -3,7 +3,7 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-03-oo-design-patterns.html) instead. +version of the book](../ch19-03-oo-design-patterns.html) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/2018-edition/src/ch18-00-patterns.md b/2018-edition/src/ch18-00-patterns.md index f3da1f40d2..213bac305d 100644 --- a/2018-edition/src/ch18-00-patterns.md +++ b/2018-edition/src/ch18-00-patterns.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-00-patterns.html) instead. +version of the book](../ch19-00-patterns.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-00-patterns.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-00-patterns.html). diff --git a/2018-edition/src/ch18-01-all-the-places-for-patterns.md b/2018-edition/src/ch18-01-all-the-places-for-patterns.md index ccf3884069..f2dfa71a32 100644 --- a/2018-edition/src/ch18-01-all-the-places-for-patterns.md +++ b/2018-edition/src/ch18-01-all-the-places-for-patterns.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-01-all-the-places-for-patterns.html) instead. +version of the book](../ch19-01-all-the-places-for-patterns.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-01-all-the-places-for-patterns.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-01-all-the-places-for-patterns.html). diff --git a/2018-edition/src/ch18-02-refutability.md b/2018-edition/src/ch18-02-refutability.md index a3e2bcff76..3eddb4dcd5 100644 --- a/2018-edition/src/ch18-02-refutability.md +++ b/2018-edition/src/ch18-02-refutability.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-02-refutability.html) instead. +version of the book](../ch19-02-refutability.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-02-refutability.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-02-refutability.html). diff --git a/2018-edition/src/ch18-03-pattern-syntax.md b/2018-edition/src/ch18-03-pattern-syntax.md index 0e0929e7b8..44c73500e1 100644 --- a/2018-edition/src/ch18-03-pattern-syntax.md +++ b/2018-edition/src/ch18-03-pattern-syntax.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-03-pattern-syntax.html) instead. +version of the book](../ch19-03-pattern-syntax.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-03-pattern-syntax.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch18-03-pattern-syntax.html). diff --git a/2018-edition/src/ch19-00-advanced-features.md b/2018-edition/src/ch19-00-advanced-features.md index b34d6b9b67..16c72a906a 100644 --- a/2018-edition/src/ch19-00-advanced-features.md +++ b/2018-edition/src/ch19-00-advanced-features.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-00-advanced-features.html) instead. +version of the book](../ch20-00-advanced-features.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-00-advanced-features.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-00-advanced-features.html). diff --git a/2018-edition/src/ch19-01-unsafe-rust.md b/2018-edition/src/ch19-01-unsafe-rust.md index 34b569fee6..7316eb44a9 100644 --- a/2018-edition/src/ch19-01-unsafe-rust.md +++ b/2018-edition/src/ch19-01-unsafe-rust.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-01-unsafe-rust.html) instead. +version of the book](../ch20-01-unsafe-rust.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-01-unsafe-rust.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-01-unsafe-rust.html). diff --git a/2018-edition/src/ch19-03-advanced-traits.md b/2018-edition/src/ch19-03-advanced-traits.md index 4219b208b9..88ca1a55b4 100644 --- a/2018-edition/src/ch19-03-advanced-traits.md +++ b/2018-edition/src/ch19-03-advanced-traits.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-03-advanced-traits.html) instead. +version of the book](../ch20-03-advanced-traits.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-03-advanced-traits.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-03-advanced-traits.html). diff --git a/2018-edition/src/ch19-04-advanced-types.md b/2018-edition/src/ch19-04-advanced-types.md index fecbd52dc8..c7c24439f9 100644 --- a/2018-edition/src/ch19-04-advanced-types.md +++ b/2018-edition/src/ch19-04-advanced-types.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-04-advanced-types.html) instead. +version of the book](../ch20-04-advanced-types.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-04-advanced-types.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-04-advanced-types.html). diff --git a/2018-edition/src/ch19-05-advanced-functions-and-closures.md b/2018-edition/src/ch19-05-advanced-functions-and-closures.md index 1bf0450904..c46fd485e1 100644 --- a/2018-edition/src/ch19-05-advanced-functions-and-closures.md +++ b/2018-edition/src/ch19-05-advanced-functions-and-closures.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-05-advanced-functions-and-closures.html) instead. +version of the book](../ch20-05-advanced-functions-and-closures.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-05-advanced-functions-and-closures.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-05-advanced-functions-and-closures.html). diff --git a/2018-edition/src/ch19-06-macros.md b/2018-edition/src/ch19-06-macros.md index bf019c5d68..838a0b8328 100644 --- a/2018-edition/src/ch19-06-macros.md +++ b/2018-edition/src/ch19-06-macros.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-06-macros.html) instead. +version of the book](../ch20-06-macros.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-06-macros.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch19-06-macros.html). diff --git a/2018-edition/src/ch20-00-final-project-a-web-server.md b/2018-edition/src/ch20-00-final-project-a-web-server.md index f9b9e5c2d2..cac5584895 100644 --- a/2018-edition/src/ch20-00-final-project-a-web-server.md +++ b/2018-edition/src/ch20-00-final-project-a-web-server.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-00-final-project-a-web-server.html) instead. +version of the book](../ch21-00-final-project-a-web-server.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-00-final-project-a-web-server.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-00-final-project-a-web-server.html). diff --git a/2018-edition/src/ch20-01-single-threaded.md b/2018-edition/src/ch20-01-single-threaded.md index 30d0884adb..e1b4200be8 100644 --- a/2018-edition/src/ch20-01-single-threaded.md +++ b/2018-edition/src/ch20-01-single-threaded.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-01-single-threaded.html) instead. +version of the book](../ch21-01-single-threaded.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-01-single-threaded.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-01-single-threaded.html). diff --git a/2018-edition/src/ch20-02-multithreaded.md b/2018-edition/src/ch20-02-multithreaded.md index e8b592ad22..7d54d56bc8 100644 --- a/2018-edition/src/ch20-02-multithreaded.md +++ b/2018-edition/src/ch20-02-multithreaded.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-02-multithreaded.html) instead. +version of the book](../ch21-02-multithreaded.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-02-multithreaded.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-02-multithreaded.html). diff --git a/2018-edition/src/ch20-03-graceful-shutdown-and-cleanup.md b/2018-edition/src/ch20-03-graceful-shutdown-and-cleanup.md index 928d199bee..f4879c4ac7 100644 --- a/2018-edition/src/ch20-03-graceful-shutdown-and-cleanup.md +++ b/2018-edition/src/ch20-03-graceful-shutdown-and-cleanup.md @@ -3,8 +3,8 @@ The 2018 edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-03-graceful-shutdown-and-cleanup.html) instead. +version of the book](../ch21-03-graceful-shutdown-and-cleanup.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-03-graceful-shutdown-and-cleanup.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/2018-edition/ch20-03-graceful-shutdown-and-cleanup.html). diff --git a/first-edition/src/associated-types.md b/first-edition/src/associated-types.md index 626048e9e6..be78034984 100644 --- a/first-edition/src/associated-types.md +++ b/first-edition/src/associated-types.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types) instead. +version of the book](../ch20-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/const-and-static.md b/first-edition/src/const-and-static.md index aa634112b2..7e667e50c6 100644 --- a/first-edition/src/const-and-static.md +++ b/first-edition/src/const-and-static.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable) instead. +version of the book](../ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/ffi.md b/first-edition/src/ffi.md index 2adaff9d8f..a8c3f818ee 100644 --- a/first-edition/src/ffi.md +++ b/first-edition/src/ffi.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-01-unsafe-rust.html#calling-rust-functions-from-other-languages) instead. +version of the book](../ch20-01-unsafe-rust.html#calling-rust-functions-from-other-languages) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/macros.md b/first-edition/src/macros.md index 6bafdc1e43..eb9871ca4a 100644 --- a/first-edition/src/macros.md +++ b/first-edition/src/macros.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-06-macros.html) instead. +version of the book](../ch20-06-macros.html) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/operators-and-overloading.md b/first-edition/src/operators-and-overloading.md index 921a2a6854..a13f444376 100644 --- a/first-edition/src/operators-and-overloading.md +++ b/first-edition/src/operators-and-overloading.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-03-advanced-traits.html#default-generic-type-parameters-and-operator-overloading) instead. +version of the book](../ch20-03-advanced-traits.html#default-generic-type-parameters-and-operator-overloading) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/patterns.md b/first-edition/src/patterns.md index d722d397e9..7bc6949b2f 100644 --- a/first-edition/src/patterns.md +++ b/first-edition/src/patterns.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-03-pattern-syntax.html) instead. +version of the book](../ch19-03-pattern-syntax.html) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/procedural-macros.md b/first-edition/src/procedural-macros.md index 9778383d80..3b683a9759 100644 --- a/first-edition/src/procedural-macros.md +++ b/first-edition/src/procedural-macros.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-06-macros.html?highlight=procedural#procedural-macros-for-generating-code-from-attributes) instead. +version of the book](../ch20-06-macros.html?highlight=procedural#procedural-macros-for-generating-code-from-attributes) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/raw-pointers.md b/first-edition/src/raw-pointers.md index c149da8681..a4cc68d474 100644 --- a/first-edition/src/raw-pointers.md +++ b/first-edition/src/raw-pointers.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer) instead. +version of the book](../ch20-01-unsafe-rust.html#dereferencing-a-raw-pointer) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/trait-objects.md b/first-edition/src/trait-objects.md index 871bad6140..a04d16b4b2 100644 --- a/first-edition/src/trait-objects.md +++ b/first-edition/src/trait-objects.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-02-trait-objects.html) instead. +version of the book](../ch18-02-trait-objects.html) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/type-aliases.md b/first-edition/src/type-aliases.md index 7ac51ff191..d79974e550 100644 --- a/first-edition/src/type-aliases.md +++ b/first-edition/src/type-aliases.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases) instead. +version of the book](../ch20-04-advanced-types.html#creating-type-synonyms-with-type-aliases) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/unsafe.md b/first-edition/src/unsafe.md index be816dfd3d..187fef52e1 100644 --- a/first-edition/src/unsafe.md +++ b/first-edition/src/unsafe.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-01-unsafe-rust.html) instead. +version of the book](../ch20-01-unsafe-rust.html) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/first-edition/src/unsized-types.md b/first-edition/src/unsized-types.md index 4ec43ecadf..5fb51b1fd2 100644 --- a/first-edition/src/unsized-types.md +++ b/first-edition/src/unsized-types.md @@ -3,7 +3,7 @@ The first edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait) instead. +version of the book](../ch20-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait) instead. If you have an internet connection, you can [find a copy distributed with Rust diff --git a/listings/ch19-patterns-and-matching/listing-19-08/output.txt b/listings/ch19-patterns-and-matching/listing-19-08/output.txt index 6ce3dfc582..0ed34b7164 100644 --- a/listings/ch19-patterns-and-matching/listing-19-08/output.txt +++ b/listings/ch19-patterns-and-matching/listing-19-08/output.txt @@ -7,7 +7,7 @@ error[E0005]: refutable pattern in local binding | ^^^^^^^ pattern `None` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `Option` help: you might want to use `let else` to handle the variant that isn't matched | diff --git a/redirects/associated-types.md b/redirects/associated-types.md index b222f3298f..af052c160d 100644 --- a/redirects/associated-types.md +++ b/redirects/associated-types.md @@ -14,4 +14,4 @@ pub trait Iterator { --- You can find the latest version of this information -[here](ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types). \ No newline at end of file +[here](ch20-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types). diff --git a/redirects/const-and-static.md b/redirects/const-and-static.md index b87bdd3831..60b13f62ac 100644 --- a/redirects/const-and-static.md +++ b/redirects/const-and-static.md @@ -16,6 +16,6 @@ static HELLO_WORLD: &str = "Hello, world!"; You can find the latest version about constants [here](ch03-01-variables-and-mutability.html#constants), and about statics -[here](ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable). +[here](ch20-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable). diff --git a/redirects/ffi.md b/redirects/ffi.md index 20ed3963ef..63308ab1de 100644 --- a/redirects/ffi.md +++ b/redirects/ffi.md @@ -20,4 +20,4 @@ fn main() { --- You can find the latest version of this information -[here](ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code) \ No newline at end of file +[here](ch20-01-unsafe-rust.html#using-extern-functions-to-call-external-code) diff --git a/redirects/macros.md b/redirects/macros.md index 08217d115d..828d484dd6 100644 --- a/redirects/macros.md +++ b/redirects/macros.md @@ -25,6 +25,6 @@ Here are the relevant sections in the new and old books: [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/macros.html -[2]: ch19-06-macros.html +[2]: ch20-06-macros.html [3]: https://rustbyexample.com/macros.html [4]: ../reference/macros-by-example.html diff --git a/redirects/match.md b/redirects/match.md index fd28ba8dea..5bcbc89495 100644 --- a/redirects/match.md +++ b/redirects/match.md @@ -34,5 +34,5 @@ Here are the relevant sections in the new and old books: [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/match.html [2]: ch06-02-match.html -[3]: ch18-00-patterns.html +[3]: ch19-00-patterns.html diff --git a/redirects/operators-and-overloading.md b/redirects/operators-and-overloading.md index ff9a33048a..3a61fbabc4 100644 --- a/redirects/operators-and-overloading.md +++ b/redirects/operators-and-overloading.md @@ -33,4 +33,4 @@ fn main() { --- You can find the latest version of this information -[here](ch19-03-advanced-traits.html). +[here](ch20-03-advanced-traits.html). diff --git a/redirects/procedural-macros.md b/redirects/procedural-macros.md index bf6665f1a6..07657f6c88 100644 --- a/redirects/procedural-macros.md +++ b/redirects/procedural-macros.md @@ -16,6 +16,6 @@ You can check out other resources that describe macros. [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/procedural-macros.html -[2]: ch19-06-macros.html +[2]: ch20-06-macros.html [3]: ../proc_macro/index.html [4]: ../reference/procedural-macros.html diff --git a/redirects/raw-pointers.md b/redirects/raw-pointers.md index 773f3abc48..4076907b5c 100644 --- a/redirects/raw-pointers.md +++ b/redirects/raw-pointers.md @@ -14,4 +14,4 @@ let r2 = &mut num as *mut i32; --- You can find the latest version of this information -[here](ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer) \ No newline at end of file +[here](ch20-01-unsafe-rust.html#dereferencing-a-raw-pointer) diff --git a/redirects/trait-objects.md b/redirects/trait-objects.md index 3200e26a15..44ca328235 100644 --- a/redirects/trait-objects.md +++ b/redirects/trait-objects.md @@ -65,4 +65,4 @@ Here are the relevant sections in the new and old books: [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/trait-objects.html -[2]: ch17-02-trait-objects.html +[2]: ch18-02-trait-objects.html diff --git a/redirects/traits.md b/redirects/traits.md index dcb577e97b..b36ede6640 100644 --- a/redirects/traits.md +++ b/redirects/traits.md @@ -21,4 +21,4 @@ Here are the relevant sections in the new and old books: [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/traits.html [2]: ch10-02-traits.html -[3]: ch19-03-advanced-traits.html +[3]: ch20-03-advanced-traits.html diff --git a/redirects/type-aliases.md b/redirects/type-aliases.md index 85cd4c9ecc..84f94e41e9 100644 --- a/redirects/type-aliases.md +++ b/redirects/type-aliases.md @@ -11,4 +11,4 @@ type Kilometers = i32; --- You can find the latest version of this information -[here](ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases). \ No newline at end of file +[here](ch20-04-advanced-types.html#creating-type-synonyms-with-type-aliases). diff --git a/redirects/ufcs.md b/redirects/ufcs.md index 2959c06bd0..684c02ec77 100644 --- a/redirects/ufcs.md +++ b/redirects/ufcs.md @@ -45,4 +45,4 @@ fn main() { --- You can find the latest version of this information -[here](ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name). \ No newline at end of file +[here](ch20-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name). diff --git a/redirects/unsafe.md b/redirects/unsafe.md index 8628c7aa95..94ee8ad777 100644 --- a/redirects/unsafe.md +++ b/redirects/unsafe.md @@ -14,5 +14,5 @@ Here are the relevant sections in the new and old books: [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/unsafe.html -[2]: ch19-01-unsafe-rust.html +[2]: ch20-01-unsafe-rust.html [3]: ../nomicon/index.html diff --git a/redirects/unsized-types.md b/redirects/unsized-types.md index bd9582cbac..6e8d19da4a 100644 --- a/redirects/unsized-types.md +++ b/redirects/unsized-types.md @@ -15,4 +15,4 @@ fn generic(t: &T) { --- You can find the latest version of this information -[here](ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait). \ No newline at end of file +[here](ch20-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait). diff --git a/second-edition/src/appendix-04-macros.md b/second-edition/src/appendix-04-macros.md index 2798b5d50a..dfcdcec07c 100644 --- a/second-edition/src/appendix-04-macros.md +++ b/second-edition/src/appendix-04-macros.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-06-macros.html) instead. +version of the book](../ch20-06-macros.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/appendix-04-macros.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/appendix-04-macros.html). diff --git a/second-edition/src/ch17-00-oop.md b/second-edition/src/ch17-00-oop.md index 752130915e..e3633405f1 100644 --- a/second-edition/src/ch17-00-oop.md +++ b/second-edition/src/ch17-00-oop.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-00-oop.html) instead. +version of the book](../ch18-00-oop.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-00-oop.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-00-oop.html). diff --git a/second-edition/src/ch17-01-what-is-oo.md b/second-edition/src/ch17-01-what-is-oo.md index 82c1ed8f9c..a705d19416 100644 --- a/second-edition/src/ch17-01-what-is-oo.md +++ b/second-edition/src/ch17-01-what-is-oo.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-01-what-is-oo.html) instead. +version of the book](../ch18-01-what-is-oo.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-01-what-is-oo.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-01-what-is-oo.html). diff --git a/second-edition/src/ch17-02-trait-objects.md b/second-edition/src/ch17-02-trait-objects.md index 35f0c18835..16dad6368e 100644 --- a/second-edition/src/ch17-02-trait-objects.md +++ b/second-edition/src/ch17-02-trait-objects.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch17-02-trait-objects.html) instead. +version of the book](../ch18-02-trait-objects.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-02-trait-objects.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch17-02-trait-objects.html). diff --git a/second-edition/src/ch18-01-all-the-places-for-patterns.md b/second-edition/src/ch18-01-all-the-places-for-patterns.md index 0374a9a883..4a76aded0a 100644 --- a/second-edition/src/ch18-01-all-the-places-for-patterns.md +++ b/second-edition/src/ch18-01-all-the-places-for-patterns.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-01-all-the-places-for-patterns.html) instead. +version of the book](../ch19-01-all-the-places-for-patterns.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-01-all-the-places-for-patterns.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-01-all-the-places-for-patterns.html). diff --git a/second-edition/src/ch18-02-refutability.md b/second-edition/src/ch18-02-refutability.md index 2ef5206afd..768df16b25 100644 --- a/second-edition/src/ch18-02-refutability.md +++ b/second-edition/src/ch18-02-refutability.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-02-refutability.html) instead. +version of the book](../ch19-02-refutability.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-02-refutability.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-02-refutability.html). diff --git a/second-edition/src/ch18-03-pattern-syntax.md b/second-edition/src/ch18-03-pattern-syntax.md index 31c5f79203..08676091e1 100644 --- a/second-edition/src/ch18-03-pattern-syntax.md +++ b/second-edition/src/ch18-03-pattern-syntax.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch18-03-pattern-syntax.html) instead. +version of the book](../ch19-03-pattern-syntax.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-03-pattern-syntax.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch18-03-pattern-syntax.html). diff --git a/second-edition/src/ch19-00-advanced-features.md b/second-edition/src/ch19-00-advanced-features.md index f6df05f0aa..3633c0548e 100644 --- a/second-edition/src/ch19-00-advanced-features.md +++ b/second-edition/src/ch19-00-advanced-features.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-00-advanced-features.html) instead. +version of the book](../ch20-00-advanced-features.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-00-advanced-features.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-00-advanced-features.html). diff --git a/second-edition/src/ch19-01-unsafe-rust.md b/second-edition/src/ch19-01-unsafe-rust.md index 8a9a29c096..0e740ce03d 100644 --- a/second-edition/src/ch19-01-unsafe-rust.md +++ b/second-edition/src/ch19-01-unsafe-rust.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-01-unsafe-rust.html) instead. +version of the book](../ch20-01-unsafe-rust.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-01-unsafe-rust.html). diff --git a/second-edition/src/ch19-03-advanced-traits.md b/second-edition/src/ch19-03-advanced-traits.md index cc8433fb38..56b9c7e662 100644 --- a/second-edition/src/ch19-03-advanced-traits.md +++ b/second-edition/src/ch19-03-advanced-traits.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-03-advanced-traits.html) instead. +version of the book](../ch20-03-advanced-traits.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-03-advanced-traits.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-03-advanced-traits.html). diff --git a/second-edition/src/ch19-04-advanced-types.md b/second-edition/src/ch19-04-advanced-types.md index 5081457292..c217a12b5a 100644 --- a/second-edition/src/ch19-04-advanced-types.md +++ b/second-edition/src/ch19-04-advanced-types.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-04-advanced-types.html) instead. +version of the book](../ch20-04-advanced-types.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-04-advanced-types.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-04-advanced-types.html). diff --git a/second-edition/src/ch19-05-advanced-functions-and-closures.md b/second-edition/src/ch19-05-advanced-functions-and-closures.md index 18d369c60d..6c296b9efe 100644 --- a/second-edition/src/ch19-05-advanced-functions-and-closures.md +++ b/second-edition/src/ch19-05-advanced-functions-and-closures.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch19-05-advanced-functions-and-closures.html) instead. +version of the book](../ch20-05-advanced-functions-and-closures.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-05-advanced-functions-and-closures.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch19-05-advanced-functions-and-closures.html). diff --git a/second-edition/src/ch20-00-final-project-a-web-server.md b/second-edition/src/ch20-00-final-project-a-web-server.md index 059d6824c3..0c99ac623b 100644 --- a/second-edition/src/ch20-00-final-project-a-web-server.md +++ b/second-edition/src/ch20-00-final-project-a-web-server.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-00-final-project-a-web-server.html) instead. +version of the book](../ch21-00-final-project-a-web-server.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-00-final-project-a-web-server.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-00-final-project-a-web-server.html). diff --git a/second-edition/src/ch20-01-single-threaded.md b/second-edition/src/ch20-01-single-threaded.md index 5ff97a2ee1..a06b0cbc1a 100644 --- a/second-edition/src/ch20-01-single-threaded.md +++ b/second-edition/src/ch20-01-single-threaded.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-01-single-threaded.html) instead. +version of the book](../ch21-01-single-threaded.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-01-single-threaded.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-01-single-threaded.html). diff --git a/second-edition/src/ch20-02-multithreaded.md b/second-edition/src/ch20-02-multithreaded.md index 0695d2451c..8826bd9f1a 100644 --- a/second-edition/src/ch20-02-multithreaded.md +++ b/second-edition/src/ch20-02-multithreaded.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-02-multithreaded.html) instead. +version of the book](../ch21-02-multithreaded.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-02-multithreaded.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-02-multithreaded.html). diff --git a/second-edition/src/ch20-03-graceful-shutdown-and-cleanup.md b/second-edition/src/ch20-03-graceful-shutdown-and-cleanup.md index eb7ed59879..457b294f90 100644 --- a/second-edition/src/ch20-03-graceful-shutdown-and-cleanup.md +++ b/second-edition/src/ch20-03-graceful-shutdown-and-cleanup.md @@ -3,8 +3,8 @@ The second edition of the book is no longer distributed with Rust's documentation. If you came here via a link or web search, you may want to check out [the current -version of the book](../ch20-03-graceful-shutdown-and-cleanup.html) instead. +version of the book](../ch21-03-graceful-shutdown-and-cleanup.html) instead. If you have an internet connection, you can [find a copy distributed with Rust -1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-03-graceful-shutdown-and-cleanup.html). \ No newline at end of file +1.30](https://doc.rust-lang.org/1.30.0/book/second-edition/ch20-03-graceful-shutdown-and-cleanup.html). From 809b24a21b1da5479f0339a0cf21900fa37454ac Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 3 Oct 2024 08:24:47 -0600 Subject: [PATCH 248/249] Fix another listing number --- src/ch20-01-unsafe-rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch20-01-unsafe-rust.md b/src/ch20-01-unsafe-rust.md index f444ce9f20..4aadf82d83 100644 --- a/src/ch20-01-unsafe-rust.md +++ b/src/ch20-01-unsafe-rust.md @@ -136,7 +136,7 @@ dereference operator `*` on a raw pointer that requires an `unsafe` block. Creating a pointer does no harm; it’s only when we try to access the value that it points at that we might end up dealing with an invalid value. -Note also that in Listing 20-1 and 19-3, we created `*const i32` and `*mut i32` +Note also that in Listing 20-1 and 20-3, we created `*const i32` and `*mut i32` raw pointers that both pointed to the same memory location, where `num` is stored. If we instead tried to create an immutable and a mutable reference to `num`, the code would not have compiled because Rust’s ownership rules don’t From fc62e4055b100bf05ff30ea87e713367187eaaa2 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Tue, 8 Oct 2024 11:45:06 -0600 Subject: [PATCH 249/249] Fix one more listing number --- src/ch20-01-unsafe-rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ch20-01-unsafe-rust.md b/src/ch20-01-unsafe-rust.md index 4aadf82d83..dfdef6c393 100644 --- a/src/ch20-01-unsafe-rust.md +++ b/src/ch20-01-unsafe-rust.md @@ -175,7 +175,7 @@ We must call the `dangerous` function within a separate `unsafe` block. If we try to call `dangerous` without the `unsafe` block, we’ll get an error: ```console -{{#include ../listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt}} +{{#include ../listings/ch20-advanced-features/output-only-01-missing-unsafe/output.txt}} ``` With the `unsafe` block, we’re asserting to Rust that we’ve read the function’s