diff --git a/Cargo.lock b/Cargo.lock index 7641aa9653..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", @@ -1588,6 +1623,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[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 = "siphasher" version = "0.3.11" @@ -1775,7 +1819,9 @@ dependencies = [ "libc", "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.48.0", @@ -1893,6 +1939,14 @@ dependencies = [ "once_cell", ] +[[package]] +name = "trpl" +version = "0.1.0" +dependencies = [ + "futures", + "tokio", +] + [[package]] name = "try-lock" version = "0.2.5" 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..e766efdf18 --- /dev/null +++ b/listings/ch17-async-await/listing-TODO-01/src/main.rs @@ -0,0 +1,25 @@ +// 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!"); + 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-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/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/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/listings/ch19-advanced-features/listing-19-01/Cargo.lock b/listings/ch20-advanced-features/listing-20-01/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-01/Cargo.lock rename to listings/ch20-advanced-features/listing-20-01/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-01/Cargo.toml b/listings/ch20-advanced-features/listing-20-01/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-01/Cargo.toml rename to listings/ch20-advanced-features/listing-20-01/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-01/src/main.rs b/listings/ch20-advanced-features/listing-20-01/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-01/src/main.rs rename to listings/ch20-advanced-features/listing-20-01/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-02/Cargo.lock b/listings/ch20-advanced-features/listing-20-02/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-02/Cargo.lock rename to listings/ch20-advanced-features/listing-20-02/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-02/Cargo.toml b/listings/ch20-advanced-features/listing-20-02/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-02/Cargo.toml rename to listings/ch20-advanced-features/listing-20-02/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-02/src/main.rs b/listings/ch20-advanced-features/listing-20-02/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-02/src/main.rs rename to listings/ch20-advanced-features/listing-20-02/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-03/Cargo.lock b/listings/ch20-advanced-features/listing-20-03/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-03/Cargo.lock rename to listings/ch20-advanced-features/listing-20-03/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-03/Cargo.toml b/listings/ch20-advanced-features/listing-20-03/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-03/Cargo.toml rename to listings/ch20-advanced-features/listing-20-03/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-03/src/main.rs b/listings/ch20-advanced-features/listing-20-03/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-03/src/main.rs rename to listings/ch20-advanced-features/listing-20-03/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-04/Cargo.lock b/listings/ch20-advanced-features/listing-20-04/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-04/Cargo.lock rename to listings/ch20-advanced-features/listing-20-04/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-04/Cargo.toml b/listings/ch20-advanced-features/listing-20-04/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-04/Cargo.toml rename to listings/ch20-advanced-features/listing-20-04/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-04/src/main.rs b/listings/ch20-advanced-features/listing-20-04/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-04/src/main.rs rename to listings/ch20-advanced-features/listing-20-04/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-05/Cargo.lock b/listings/ch20-advanced-features/listing-20-05/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-05/Cargo.lock rename to listings/ch20-advanced-features/listing-20-05/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-05/Cargo.toml b/listings/ch20-advanced-features/listing-20-05/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-05/Cargo.toml rename to listings/ch20-advanced-features/listing-20-05/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-05/output.txt b/listings/ch20-advanced-features/listing-20-05/output.txt similarity index 100% rename from listings/ch19-advanced-features/listing-19-05/output.txt rename to listings/ch20-advanced-features/listing-20-05/output.txt diff --git a/listings/ch19-advanced-features/listing-19-05/src/main.rs b/listings/ch20-advanced-features/listing-20-05/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-05/src/main.rs rename to listings/ch20-advanced-features/listing-20-05/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-06/Cargo.lock b/listings/ch20-advanced-features/listing-20-06/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-06/Cargo.lock rename to listings/ch20-advanced-features/listing-20-06/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-06/Cargo.toml b/listings/ch20-advanced-features/listing-20-06/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-06/Cargo.toml rename to listings/ch20-advanced-features/listing-20-06/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-06/src/main.rs b/listings/ch20-advanced-features/listing-20-06/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-06/src/main.rs rename to listings/ch20-advanced-features/listing-20-06/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-07/Cargo.lock b/listings/ch20-advanced-features/listing-20-07/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-07/Cargo.lock rename to listings/ch20-advanced-features/listing-20-07/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-07/Cargo.toml b/listings/ch20-advanced-features/listing-20-07/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-07/Cargo.toml rename to listings/ch20-advanced-features/listing-20-07/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-07/src/main.rs b/listings/ch20-advanced-features/listing-20-07/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-07/src/main.rs rename to listings/ch20-advanced-features/listing-20-07/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-08/Cargo.lock b/listings/ch20-advanced-features/listing-20-08/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-08/Cargo.lock rename to listings/ch20-advanced-features/listing-20-08/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-08/Cargo.toml b/listings/ch20-advanced-features/listing-20-08/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-08/Cargo.toml rename to listings/ch20-advanced-features/listing-20-08/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-08/src/main.rs b/listings/ch20-advanced-features/listing-20-08/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-08/src/main.rs rename to listings/ch20-advanced-features/listing-20-08/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-09/Cargo.lock b/listings/ch20-advanced-features/listing-20-09/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-09/Cargo.lock rename to listings/ch20-advanced-features/listing-20-09/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-09/Cargo.toml b/listings/ch20-advanced-features/listing-20-09/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-09/Cargo.toml rename to listings/ch20-advanced-features/listing-20-09/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-09/src/main.rs b/listings/ch20-advanced-features/listing-20-09/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-09/src/main.rs rename to listings/ch20-advanced-features/listing-20-09/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-10/Cargo.lock b/listings/ch20-advanced-features/listing-20-10/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-10/Cargo.lock rename to listings/ch20-advanced-features/listing-20-10/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-10/Cargo.toml b/listings/ch20-advanced-features/listing-20-10/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-10/Cargo.toml rename to listings/ch20-advanced-features/listing-20-10/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-10/src/main.rs b/listings/ch20-advanced-features/listing-20-10/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-10/src/main.rs rename to listings/ch20-advanced-features/listing-20-10/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-11/Cargo.lock b/listings/ch20-advanced-features/listing-20-11/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-11/Cargo.lock rename to listings/ch20-advanced-features/listing-20-11/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-11/Cargo.toml b/listings/ch20-advanced-features/listing-20-11/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-11/Cargo.toml rename to listings/ch20-advanced-features/listing-20-11/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-11/src/main.rs b/listings/ch20-advanced-features/listing-20-11/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-11/src/main.rs rename to listings/ch20-advanced-features/listing-20-11/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-12/Cargo.lock b/listings/ch20-advanced-features/listing-20-12/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-12/Cargo.lock rename to listings/ch20-advanced-features/listing-20-12/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-12/Cargo.toml b/listings/ch20-advanced-features/listing-20-12/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-12/Cargo.toml rename to listings/ch20-advanced-features/listing-20-12/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-12/src/lib.rs b/listings/ch20-advanced-features/listing-20-12/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-12/src/lib.rs rename to listings/ch20-advanced-features/listing-20-12/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-13/Cargo.lock b/listings/ch20-advanced-features/listing-20-13/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-13/Cargo.lock rename to listings/ch20-advanced-features/listing-20-13/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-13/Cargo.toml b/listings/ch20-advanced-features/listing-20-13/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-13/Cargo.toml rename to listings/ch20-advanced-features/listing-20-13/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-13/src/lib.rs b/listings/ch20-advanced-features/listing-20-13/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-13/src/lib.rs rename to listings/ch20-advanced-features/listing-20-13/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-14/Cargo.lock b/listings/ch20-advanced-features/listing-20-14/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-14/Cargo.lock rename to listings/ch20-advanced-features/listing-20-14/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-14/Cargo.toml b/listings/ch20-advanced-features/listing-20-14/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-14/Cargo.toml rename to listings/ch20-advanced-features/listing-20-14/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-14/src/main.rs b/listings/ch20-advanced-features/listing-20-14/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-14/src/main.rs rename to listings/ch20-advanced-features/listing-20-14/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-15/Cargo.lock b/listings/ch20-advanced-features/listing-20-15/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-15/Cargo.lock rename to listings/ch20-advanced-features/listing-20-15/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-15/Cargo.toml b/listings/ch20-advanced-features/listing-20-15/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-15/Cargo.toml rename to listings/ch20-advanced-features/listing-20-15/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-15/src/lib.rs b/listings/ch20-advanced-features/listing-20-15/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-15/src/lib.rs rename to listings/ch20-advanced-features/listing-20-15/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-16/Cargo.lock b/listings/ch20-advanced-features/listing-20-16/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-16/Cargo.lock rename to listings/ch20-advanced-features/listing-20-16/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-16/Cargo.toml b/listings/ch20-advanced-features/listing-20-16/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-16/Cargo.toml rename to listings/ch20-advanced-features/listing-20-16/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-16/src/main.rs b/listings/ch20-advanced-features/listing-20-16/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-16/src/main.rs rename to listings/ch20-advanced-features/listing-20-16/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-17/Cargo.lock b/listings/ch20-advanced-features/listing-20-17/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-17/Cargo.lock rename to listings/ch20-advanced-features/listing-20-17/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-17/Cargo.toml b/listings/ch20-advanced-features/listing-20-17/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-17/Cargo.toml rename to listings/ch20-advanced-features/listing-20-17/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-17/src/main.rs b/listings/ch20-advanced-features/listing-20-17/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-17/src/main.rs rename to listings/ch20-advanced-features/listing-20-17/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-18/Cargo.lock b/listings/ch20-advanced-features/listing-20-18/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-18/Cargo.lock rename to listings/ch20-advanced-features/listing-20-18/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-18/Cargo.toml b/listings/ch20-advanced-features/listing-20-18/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-18/Cargo.toml rename to listings/ch20-advanced-features/listing-20-18/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-18/output.txt b/listings/ch20-advanced-features/listing-20-18/output.txt similarity index 100% rename from listings/ch19-advanced-features/listing-19-18/output.txt rename to listings/ch20-advanced-features/listing-20-18/output.txt diff --git a/listings/ch19-advanced-features/listing-19-18/src/main.rs b/listings/ch20-advanced-features/listing-20-18/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-18/src/main.rs rename to listings/ch20-advanced-features/listing-20-18/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-19/Cargo.lock b/listings/ch20-advanced-features/listing-20-19/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-19/Cargo.lock rename to listings/ch20-advanced-features/listing-20-19/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-19/Cargo.toml b/listings/ch20-advanced-features/listing-20-19/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-19/Cargo.toml rename to listings/ch20-advanced-features/listing-20-19/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-19/output.txt b/listings/ch20-advanced-features/listing-20-19/output.txt similarity index 100% rename from listings/ch19-advanced-features/listing-19-19/output.txt rename to listings/ch20-advanced-features/listing-20-19/output.txt diff --git a/listings/ch19-advanced-features/listing-19-19/src/main.rs b/listings/ch20-advanced-features/listing-20-19/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-19/src/main.rs rename to listings/ch20-advanced-features/listing-20-19/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-20/Cargo.lock b/listings/ch20-advanced-features/listing-20-20/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-20/Cargo.lock rename to listings/ch20-advanced-features/listing-20-20/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-20/Cargo.toml b/listings/ch20-advanced-features/listing-20-20/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-20/Cargo.toml rename to listings/ch20-advanced-features/listing-20-20/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-20/output.txt b/listings/ch20-advanced-features/listing-20-20/output.txt similarity index 100% rename from listings/ch19-advanced-features/listing-19-20/output.txt rename to listings/ch20-advanced-features/listing-20-20/output.txt diff --git a/listings/ch19-advanced-features/listing-19-20/src/main.rs b/listings/ch20-advanced-features/listing-20-20/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-20/src/main.rs rename to listings/ch20-advanced-features/listing-20-20/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-21/Cargo.lock b/listings/ch20-advanced-features/listing-20-21/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-21/Cargo.lock rename to listings/ch20-advanced-features/listing-20-21/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-21/Cargo.toml b/listings/ch20-advanced-features/listing-20-21/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-21/Cargo.toml rename to listings/ch20-advanced-features/listing-20-21/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-21/output.txt b/listings/ch20-advanced-features/listing-20-21/output.txt similarity index 100% rename from listings/ch19-advanced-features/listing-19-21/output.txt rename to listings/ch20-advanced-features/listing-20-21/output.txt diff --git a/listings/ch19-advanced-features/listing-19-21/src/main.rs b/listings/ch20-advanced-features/listing-20-21/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-21/src/main.rs rename to listings/ch20-advanced-features/listing-20-21/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-22/Cargo.lock b/listings/ch20-advanced-features/listing-20-22/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-22/Cargo.lock rename to listings/ch20-advanced-features/listing-20-22/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-22/Cargo.toml b/listings/ch20-advanced-features/listing-20-22/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-22/Cargo.toml rename to listings/ch20-advanced-features/listing-20-22/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-22/src/main.rs b/listings/ch20-advanced-features/listing-20-22/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-22/src/main.rs rename to listings/ch20-advanced-features/listing-20-22/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-23/Cargo.lock b/listings/ch20-advanced-features/listing-20-23/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-23/Cargo.lock rename to listings/ch20-advanced-features/listing-20-23/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-23/Cargo.toml b/listings/ch20-advanced-features/listing-20-23/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-23/Cargo.toml rename to listings/ch20-advanced-features/listing-20-23/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-23/src/main.rs b/listings/ch20-advanced-features/listing-20-23/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-23/src/main.rs rename to listings/ch20-advanced-features/listing-20-23/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-24/Cargo.lock b/listings/ch20-advanced-features/listing-20-24/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-24/Cargo.lock rename to listings/ch20-advanced-features/listing-20-24/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-24/Cargo.toml b/listings/ch20-advanced-features/listing-20-24/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-24/Cargo.toml rename to listings/ch20-advanced-features/listing-20-24/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-24/src/main.rs b/listings/ch20-advanced-features/listing-20-24/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-24/src/main.rs rename to listings/ch20-advanced-features/listing-20-24/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-25/Cargo.lock b/listings/ch20-advanced-features/listing-20-25/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-25/Cargo.lock rename to listings/ch20-advanced-features/listing-20-25/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-25/Cargo.toml b/listings/ch20-advanced-features/listing-20-25/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-25/Cargo.toml rename to listings/ch20-advanced-features/listing-20-25/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-25/src/main.rs b/listings/ch20-advanced-features/listing-20-25/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-25/src/main.rs rename to listings/ch20-advanced-features/listing-20-25/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-27/Cargo.lock b/listings/ch20-advanced-features/listing-20-27/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-27/Cargo.lock rename to listings/ch20-advanced-features/listing-20-27/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-27/Cargo.toml b/listings/ch20-advanced-features/listing-20-27/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-27/Cargo.toml rename to listings/ch20-advanced-features/listing-20-27/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-27/src/main.rs b/listings/ch20-advanced-features/listing-20-27/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-27/src/main.rs rename to listings/ch20-advanced-features/listing-20-27/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-28/Cargo.lock b/listings/ch20-advanced-features/listing-20-28/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-28/Cargo.lock rename to listings/ch20-advanced-features/listing-20-28/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-28/Cargo.toml b/listings/ch20-advanced-features/listing-20-28/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-28/Cargo.toml rename to listings/ch20-advanced-features/listing-20-28/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-28/src/lib.rs b/listings/ch20-advanced-features/listing-20-28/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-28/src/lib.rs rename to listings/ch20-advanced-features/listing-20-28/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-30/Cargo.lock b/listings/ch20-advanced-features/listing-20-30/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-30/Cargo.lock rename to listings/ch20-advanced-features/listing-20-30/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-30/Cargo.toml b/listings/ch20-advanced-features/listing-20-30/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-30/Cargo.toml rename to listings/ch20-advanced-features/listing-20-30/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-30/src/main.rs b/listings/ch20-advanced-features/listing-20-30/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-30/src/main.rs rename to listings/ch20-advanced-features/listing-20-30/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.lock b/listings/ch20-advanced-features/listing-20-31/hello_macro/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.lock rename to listings/ch20-advanced-features/listing-20-31/hello_macro/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml b/listings/ch20-advanced-features/listing-20-31/hello_macro/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml rename to listings/ch20-advanced-features/listing-20-31/hello_macro/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.lock b/listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.lock rename to listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml b/listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml rename to listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs rename to listings/ch20-advanced-features/listing-20-31/hello_macro/hello_macro_derive/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/src/lib.rs b/listings/ch20-advanced-features/listing-20-31/hello_macro/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-31/hello_macro/src/lib.rs rename to listings/ch20-advanced-features/listing-20-31/hello_macro/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/src/main.rs b/listings/ch20-advanced-features/listing-20-31/hello_macro/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-31/hello_macro/src/main.rs rename to listings/ch20-advanced-features/listing-20-31/hello_macro/src/main.rs diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.lock b/listings/ch20-advanced-features/listing-20-33/hello_macro/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.lock rename to listings/ch20-advanced-features/listing-20-33/hello_macro/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml b/listings/ch20-advanced-features/listing-20-33/hello_macro/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml rename to listings/ch20-advanced-features/listing-20-33/hello_macro/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.lock b/listings/ch20-advanced-features/listing-20-33/hello_macro/hello_macro_derive/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.lock rename to listings/ch20-advanced-features/listing-20-33/hello_macro/hello_macro_derive/Cargo.lock diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml b/listings/ch20-advanced-features/listing-20-33/hello_macro/hello_macro_derive/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml rename to listings/ch20-advanced-features/listing-20-33/hello_macro/hello_macro_derive/Cargo.toml diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch20-advanced-features/listing-20-33/hello_macro/hello_macro_derive/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs rename to listings/ch20-advanced-features/listing-20-33/hello_macro/hello_macro_derive/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/src/lib.rs b/listings/ch20-advanced-features/listing-20-33/hello_macro/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-33/hello_macro/src/lib.rs rename to listings/ch20-advanced-features/listing-20-33/hello_macro/src/lib.rs diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/src/main.rs b/listings/ch20-advanced-features/listing-20-33/hello_macro/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/listing-19-33/hello_macro/src/main.rs rename to listings/ch20-advanced-features/listing-20-33/hello_macro/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.lock b/listings/ch20-advanced-features/no-listing-01-unsafe-fn/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.lock rename to listings/ch20-advanced-features/no-listing-01-unsafe-fn/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml b/listings/ch20-advanced-features/no-listing-01-unsafe-fn/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml rename to listings/ch20-advanced-features/no-listing-01-unsafe-fn/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-01-unsafe-fn/src/main.rs b/listings/ch20-advanced-features/no-listing-01-unsafe-fn/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-01-unsafe-fn/src/main.rs rename to listings/ch20-advanced-features/no-listing-01-unsafe-fn/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.lock b/listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.lock rename to listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml b/listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml rename to listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt b/listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt similarity index 100% rename from listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt rename to listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt diff --git a/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs b/listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs rename to listings/ch20-advanced-features/no-listing-02-impl-outlineprint-for-point/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.lock b/listings/ch20-advanced-features/no-listing-03-impl-display-for-point/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.lock rename to listings/ch20-advanced-features/no-listing-03-impl-display-for-point/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml b/listings/ch20-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml rename to listings/ch20-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/src/main.rs b/listings/ch20-advanced-features/no-listing-03-impl-display-for-point/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-03-impl-display-for-point/src/main.rs rename to listings/ch20-advanced-features/no-listing-03-impl-display-for-point/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.lock b/listings/ch20-advanced-features/no-listing-04-kilometers-alias/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.lock rename to listings/ch20-advanced-features/no-listing-04-kilometers-alias/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml b/listings/ch20-advanced-features/no-listing-04-kilometers-alias/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml rename to listings/ch20-advanced-features/no-listing-04-kilometers-alias/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs b/listings/ch20-advanced-features/no-listing-04-kilometers-alias/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs rename to listings/ch20-advanced-features/no-listing-04-kilometers-alias/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.lock b/listings/ch20-advanced-features/no-listing-05-write-trait/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.lock rename to listings/ch20-advanced-features/no-listing-05-write-trait/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml b/listings/ch20-advanced-features/no-listing-05-write-trait/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml rename to listings/ch20-advanced-features/no-listing-05-write-trait/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-05-write-trait/src/lib.rs b/listings/ch20-advanced-features/no-listing-05-write-trait/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-05-write-trait/src/lib.rs rename to listings/ch20-advanced-features/no-listing-05-write-trait/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.lock b/listings/ch20-advanced-features/no-listing-06-result-alias/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.lock rename to listings/ch20-advanced-features/no-listing-06-result-alias/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml b/listings/ch20-advanced-features/no-listing-06-result-alias/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml rename to listings/ch20-advanced-features/no-listing-06-result-alias/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs b/listings/ch20-advanced-features/no-listing-06-result-alias/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs rename to listings/ch20-advanced-features/no-listing-06-result-alias/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.lock b/listings/ch20-advanced-features/no-listing-07-never-type/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-07-never-type/Cargo.lock rename to listings/ch20-advanced-features/no-listing-07-never-type/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml b/listings/ch20-advanced-features/no-listing-07-never-type/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml rename to listings/ch20-advanced-features/no-listing-07-never-type/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs b/listings/ch20-advanced-features/no-listing-07-never-type/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs rename to listings/ch20-advanced-features/no-listing-07-never-type/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.lock b/listings/ch20-advanced-features/no-listing-08-match-arms-different-types/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.lock rename to listings/ch20-advanced-features/no-listing-08-match-arms-different-types/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml b/listings/ch20-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml rename to listings/ch20-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/src/main.rs b/listings/ch20-advanced-features/no-listing-08-match-arms-different-types/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-08-match-arms-different-types/src/main.rs rename to listings/ch20-advanced-features/no-listing-08-match-arms-different-types/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.lock b/listings/ch20-advanced-features/no-listing-09-unwrap-definition/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.lock rename to listings/ch20-advanced-features/no-listing-09-unwrap-definition/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml b/listings/ch20-advanced-features/no-listing-09-unwrap-definition/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml rename to listings/ch20-advanced-features/no-listing-09-unwrap-definition/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-09-unwrap-definition/src/lib.rs b/listings/ch20-advanced-features/no-listing-09-unwrap-definition/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-09-unwrap-definition/src/lib.rs rename to listings/ch20-advanced-features/no-listing-09-unwrap-definition/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.lock b/listings/ch20-advanced-features/no-listing-10-loop-returns-never/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.lock rename to listings/ch20-advanced-features/no-listing-10-loop-returns-never/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml b/listings/ch20-advanced-features/no-listing-10-loop-returns-never/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml rename to listings/ch20-advanced-features/no-listing-10-loop-returns-never/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-10-loop-returns-never/src/main.rs b/listings/ch20-advanced-features/no-listing-10-loop-returns-never/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-10-loop-returns-never/src/main.rs rename to listings/ch20-advanced-features/no-listing-10-loop-returns-never/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.lock b/listings/ch20-advanced-features/no-listing-11-cant-create-str/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.lock rename to listings/ch20-advanced-features/no-listing-11-cant-create-str/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml b/listings/ch20-advanced-features/no-listing-11-cant-create-str/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml rename to listings/ch20-advanced-features/no-listing-11-cant-create-str/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-11-cant-create-str/src/main.rs b/listings/ch20-advanced-features/no-listing-11-cant-create-str/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-11-cant-create-str/src/main.rs rename to listings/ch20-advanced-features/no-listing-11-cant-create-str/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.lock b/listings/ch20-advanced-features/no-listing-12-generic-fn-definition/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.lock rename to listings/ch20-advanced-features/no-listing-12-generic-fn-definition/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml b/listings/ch20-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml rename to listings/ch20-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs b/listings/ch20-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs rename to listings/ch20-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.lock b/listings/ch20-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.lock rename to listings/ch20-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml b/listings/ch20-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml rename to listings/ch20-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs b/listings/ch20-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs rename to listings/ch20-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.lock b/listings/ch20-advanced-features/no-listing-14-generic-maybe-sized/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.lock rename to listings/ch20-advanced-features/no-listing-14-generic-maybe-sized/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml b/listings/ch20-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml rename to listings/ch20-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs b/listings/ch20-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs rename to listings/ch20-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.lock b/listings/ch20-advanced-features/no-listing-15-map-closure/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.lock rename to listings/ch20-advanced-features/no-listing-15-map-closure/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml b/listings/ch20-advanced-features/no-listing-15-map-closure/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml rename to listings/ch20-advanced-features/no-listing-15-map-closure/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-15-map-closure/src/main.rs b/listings/ch20-advanced-features/no-listing-15-map-closure/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-15-map-closure/src/main.rs rename to listings/ch20-advanced-features/no-listing-15-map-closure/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.lock b/listings/ch20-advanced-features/no-listing-16-map-function/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-16-map-function/Cargo.lock rename to listings/ch20-advanced-features/no-listing-16-map-function/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml b/listings/ch20-advanced-features/no-listing-16-map-function/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml rename to listings/ch20-advanced-features/no-listing-16-map-function/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-16-map-function/src/main.rs b/listings/ch20-advanced-features/no-listing-16-map-function/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-16-map-function/src/main.rs rename to listings/ch20-advanced-features/no-listing-16-map-function/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.lock b/listings/ch20-advanced-features/no-listing-17-map-initializer/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.lock rename to listings/ch20-advanced-features/no-listing-17-map-initializer/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml b/listings/ch20-advanced-features/no-listing-17-map-initializer/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml rename to listings/ch20-advanced-features/no-listing-17-map-initializer/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-17-map-initializer/src/main.rs b/listings/ch20-advanced-features/no-listing-17-map-initializer/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-17-map-initializer/src/main.rs rename to listings/ch20-advanced-features/no-listing-17-map-initializer/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.lock b/listings/ch20-advanced-features/no-listing-18-returns-closure/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.lock rename to listings/ch20-advanced-features/no-listing-18-returns-closure/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml b/listings/ch20-advanced-features/no-listing-18-returns-closure/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml rename to listings/ch20-advanced-features/no-listing-18-returns-closure/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt b/listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt similarity index 100% rename from listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt rename to listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/src/lib.rs b/listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-18-returns-closure/src/lib.rs rename to listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.lock b/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.lock rename to listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml b/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml rename to listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs b/listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs rename to listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.lock b/listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.lock rename to listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml b/listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml rename to listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/src/lib.rs b/listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/src/lib.rs rename to listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.lock b/listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.lock rename to listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml b/listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml rename to listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/src/main.rs b/listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/src/main.rs rename to listings/ch20-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.lock b/listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.lock rename to listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml b/listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml rename to listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.lock b/listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.lock rename to listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml b/listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml rename to listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs rename to listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/src/lib.rs b/listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/src/lib.rs rename to listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/src/lib.rs diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/src/main.rs b/listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/src/main.rs rename to listings/ch20-advanced-features/no-listing-21-pancakes/hello_macro/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.lock b/listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.lock rename to listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml b/listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml rename to listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/src/main.rs b/listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/src/main.rs rename to listings/ch20-advanced-features/no-listing-21-pancakes/pancakes/src/main.rs diff --git a/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock b/listings/ch20-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock rename to listings/ch20-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock diff --git a/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml b/listings/ch20-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml rename to listings/ch20-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml diff --git a/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs b/listings/ch20-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs similarity index 100% rename from listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs rename to listings/ch20-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs diff --git a/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.lock b/listings/ch20-advanced-features/output-only-01-missing-unsafe/Cargo.lock similarity index 100% rename from listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.lock rename to listings/ch20-advanced-features/output-only-01-missing-unsafe/Cargo.lock diff --git a/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml b/listings/ch20-advanced-features/output-only-01-missing-unsafe/Cargo.toml similarity index 100% rename from listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml rename to listings/ch20-advanced-features/output-only-01-missing-unsafe/Cargo.toml diff --git a/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt b/listings/ch20-advanced-features/output-only-01-missing-unsafe/output.txt similarity index 100% rename from listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt rename to listings/ch20-advanced-features/output-only-01-missing-unsafe/output.txt diff --git a/listings/ch19-advanced-features/output-only-01-missing-unsafe/src/main.rs b/listings/ch20-advanced-features/output-only-01-missing-unsafe/src/main.rs similarity index 100% rename from listings/ch19-advanced-features/output-only-01-missing-unsafe/src/main.rs rename to listings/ch20-advanced-features/output-only-01-missing-unsafe/src/main.rs 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/packages/trpl/CONTRIBUTING.md b/packages/trpl/CONTRIBUTING.md new file mode 100644 index 0000000000..bd14bf21d7 --- /dev/null +++ b/packages/trpl/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/packages/trpl/Cargo.toml b/packages/trpl/Cargo.toml new file mode 100644 index 0000000000..046f95da5b --- /dev/null +++ b/packages/trpl/Cargo.toml @@ -0,0 +1,10 @@ +[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 + +[dependencies] +futures = "0.3.30" +tokio = { version = "1", features = ["full"] } diff --git a/packages/trpl/README.md b/packages/trpl/README.md new file mode 100644 index 0000000000..3906da15a4 --- /dev/null +++ b/packages/trpl/README.md @@ -0,0 +1,23 @@ +# 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. + +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 + + +This crate currently requires at least Rust 1.77. diff --git a/packages/trpl/src/lib.rs b/packages/trpl/src/lib.rs new file mode 100644 index 0000000000..521aa28cb1 --- /dev/null +++ b/packages/trpl/src/lib.rs @@ -0,0 +1,34 @@ +//! 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. + +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 new file mode 100644 index 0000000000..e55aea5703 --- /dev/null +++ b/packages/trpl/tests/integration/main.rs @@ -0,0 +1,43 @@ +//! 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::{block_on, sleep, spawn_task}; + +/// 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_block_on_works() { + let val = 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" }); + vec![handle_a.await.unwrap(), handle_b.await.unwrap()] + }); + + assert_eq!(result, vec!["Hello", "Goodbye"]); +} + +#[test] +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/SUMMARY.md b/src/SUMMARY.md index b4b58afdee..60680d1983 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -101,29 +101,33 @@ - [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) + - [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) + - [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/ch03-03-how-functions-work.md b/src/ch03-03-how-functions-work.md index 2b59f0cd45..c43bb5fe58 100644 --- a/src/ch03-03-how-functions-work.md +++ b/src/ch03-03-how-functions-work.md @@ -53,13 +53,13 @@ In this version of `another_function` we add a parameter: Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs}} +{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-parameters/src/main.rs}} ``` Try running this program; you should get the following output: ```console -{{#include ../listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/output.txt}} +{{#include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-parameters/output.txt}} ``` The declaration of `another_function` has one parameter named `x`. The type of @@ -79,7 +79,7 @@ commas, like this: Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs}} +{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-19-functions-with-multiple-parameters/src/main.rs}} ``` This example creates a function named `print_labeled_measurement` with two @@ -92,7 +92,7 @@ project’s *src/main.rs* file with the preceding example and run it using `carg run`: ```console -{{#include ../listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/output.txt}} +{{#include ../listings/ch03-common-programming-concepts/no-listing-19-functions-with-multiple-parameters/output.txt}} ``` Because we called the function with `5` as the value for `value` and `'h'` as @@ -133,13 +133,13 @@ to another variable, as the following code tries to do; you’ll get an error: Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/src/main.rs}} +{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-20-statements-vs-expressions/src/main.rs}} ``` When you run this program, the error you’ll get looks like this: ```console -{{#include ../listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt}} +{{#include ../listings/ch03-common-programming-concepts/no-listing-20-statements-vs-expressions/output.txt}} ``` The `let y = 6` statement does not return a value, so there isn’t anything for @@ -159,7 +159,7 @@ curly brackets is an expression, for example: Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs}} +{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-21-blocks-are-expressions/src/main.rs}} ``` This expression: diff --git a/src/ch04-03-slices.md b/src/ch04-03-slices.md index 7f8c9b7af2..da506e8a32 100644 --- a/src/ch04-03-slices.md +++ b/src/ch04-03-slices.md @@ -108,7 +108,7 @@ Luckily, Rust has a solution to this problem: string slices. A *string slice* is a reference to part of a `String`, and it looks like this: ```rust -{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-17-slice/src/main.rs:here}} +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-18-slice/src/main.rs:here}} ``` Rather than a reference to the entire `String`, `hello` is a reference to a @@ -179,7 +179,7 @@ slice. The type that signifies “string slice” is written as `&str`: Filename: src/main.rs ```rust -{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-18-first-word-slice/src/main.rs:here}} +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-19-first-word-slice/src/main.rs:here}} ``` We get the index for the end of the word the same way we did in Listing 4-7, by @@ -210,13 +210,13 @@ compile-time error: Filename: src/main.rs ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-19-slice-error/src/main.rs:here}} +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-20-slice-error/src/main.rs:here}} ``` Here’s the compiler error: ```console -{{#include ../listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt}} +{{#include ../listings/ch04-understanding-ownership/no-listing-20-slice-error/output.txt}} ``` Recall from the borrowing rules that if we have an immutable reference to diff --git a/src/ch06-02-match.md b/src/ch06-02-match.md index 6a510df402..d76744aaba 100644 --- a/src/ch06-02-match.md +++ b/src/ch06-02-match.md @@ -238,7 +238,7 @@ that by using the unit value (the empty tuple type we mentioned in [“The Tuple Type”][tuples] section) as the code that goes with the `_` arm: ```rust -{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs:here}} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-18-underscore-unit/src/main.rs:here}} ``` Here, we’re telling Rust explicitly that we aren’t going to use any other value diff --git a/src/ch13-02-iterators.md b/src/ch13-02-iterators.md index 030ebf48eb..9e1cbecfa5 100644 --- a/src/ch13-02-iterators.md +++ b/src/ch13-02-iterators.md @@ -1,228 +1 @@ -## Processing a Series of Items with Iterators - -The iterator pattern allows you to perform some task on a sequence of items in -turn. An iterator is responsible for the logic of iterating over each item and -determining when the sequence has finished. When you use iterators, you don’t -have to reimplement that logic yourself. - -In Rust, iterators are *lazy*, meaning they have no effect until you call -methods that consume the iterator to use it up. For example, the code in -Listing 13-10 creates an iterator over the items in the vector `v1` by calling -the `iter` method defined on `Vec`. This code by itself doesn’t do anything -useful. - -```rust -{{#rustdoc_include ../listings/ch13-functional-features/listing-13-10/src/main.rs:here}} -``` - -Listing 13-10: Creating an iterator - -The iterator is stored in the `v1_iter` variable. Once we’ve created an -iterator, we can use it in a variety of ways. In Listing 3-5 in Chapter 3, we -iterated over an array using a `for` loop to execute some code on each of its -items. Under the hood this implicitly created and then consumed an iterator, -but we glossed over how exactly that works until now. - -In the example in Listing 13-11, we separate the creation of the iterator from -the use of the iterator in the `for` loop. When the `for` loop is called using -the iterator in `v1_iter`, each element in the iterator is used in one -iteration of the loop, which prints out each value. - -```rust -{{#rustdoc_include ../listings/ch13-functional-features/listing-13-11/src/main.rs:here}} -``` - -Listing 13-11: Using an iterator in a `for` loop - -In languages that don’t have iterators provided by their standard libraries, -you would likely write this same functionality by starting a variable at index -0, using that variable to index into the vector to get a value, and -incrementing the variable value in a loop until it reached the total number of -items in the vector. - -Iterators handle all that logic for you, cutting down on repetitive code you -could potentially mess up. Iterators give you more flexibility to use the same -logic with many different kinds of sequences, not just data structures you can -index into, like vectors. Let’s examine how iterators do that. - -### The `Iterator` Trait and the `next` Method - -All iterators implement a trait named `Iterator` that is defined in the -standard library. The definition of the trait looks like this: - -```rust -pub trait Iterator { - type Item; - - fn next(&mut self) -> Option; - - // methods with default implementations elided -} -``` - -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 -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 -iterator. - -The `Iterator` trait only requires implementors to define one method: the -`next` method, which returns one item of the iterator at a time wrapped in -`Some` and, when iteration is over, returns `None`. - -We can call the `next` method on iterators directly; Listing 13-12 demonstrates -what values are returned from repeated calls to `next` on the iterator created -from the vector. - -Filename: src/lib.rs - -```rust,noplayground -{{#rustdoc_include ../listings/ch13-functional-features/listing-13-12/src/lib.rs:here}} -``` - -Listing 13-12: Calling the `next` method on an -iterator - -Note that we needed to make `v1_iter` mutable: calling the `next` method on an -iterator changes internal state that the iterator uses to keep track of where -it is in the sequence. In other words, this code *consumes*, or uses up, the -iterator. Each call to `next` eats up an item from the iterator. We didn’t need -to make `v1_iter` mutable when we used a `for` loop because the loop took -ownership of `v1_iter` and made it mutable behind the scenes. - -Also note that the values we get from the calls to `next` are immutable -references to the values in the vector. The `iter` method produces an iterator -over immutable references. If we want to create an iterator that takes -ownership of `v1` and returns owned values, we can call `into_iter` instead of -`iter`. Similarly, if we want to iterate over mutable references, we can call -`iter_mut` instead of `iter`. - -### Methods that Consume the Iterator - -The `Iterator` trait has a number of different methods with default -implementations provided by the standard library; you can find out about these -methods by looking in the standard library API documentation for the `Iterator` -trait. Some of these methods call the `next` method in their definition, which -is why you’re required to implement the `next` method when implementing the -`Iterator` trait. - -Methods that call `next` are called *consuming adaptors*, because calling them -uses up the iterator. One example is the `sum` method, which takes ownership of -the iterator and iterates through the items by repeatedly calling `next`, thus -consuming the iterator. As it iterates through, it adds each item to a running -total and returns the total when iteration is complete. Listing 13-13 has a -test illustrating a use of the `sum` method: - -Filename: src/lib.rs - -```rust,noplayground -{{#rustdoc_include ../listings/ch13-functional-features/listing-13-13/src/lib.rs:here}} -``` - -Listing 13-13: Calling the `sum` method to get the total -of all items in the iterator - -We aren’t allowed to use `v1_iter` after the call to `sum` because `sum` takes -ownership of the iterator we call it on. - -### Methods that Produce Other Iterators - -*Iterator adaptors* are methods defined on the `Iterator` trait that don’t -consume the iterator. Instead, they produce different iterators by changing -some aspect of the original iterator. - -Listing 13-14 shows an example of calling the iterator adaptor method `map`, -which takes a closure to call on each item as the items are iterated through. -The `map` method returns a new iterator that produces the modified items. The -closure here creates a new iterator in which each item from the vector will be -incremented by 1: - -Filename: src/main.rs - -```rust,not_desired_behavior -{{#rustdoc_include ../listings/ch13-functional-features/listing-13-14/src/main.rs:here}} -``` - -Listing 13-14: Calling the iterator adaptor `map` to -create a new iterator - -However, this code produces a warning: - -```console -{{#include ../listings/ch13-functional-features/listing-13-14/output.txt}} -``` - -The code in Listing 13-14 doesn’t do anything; the closure we’ve specified -never gets called. The warning reminds us why: iterator adaptors are lazy, and -we need to consume the iterator here. - -To fix this warning and consume the iterator, we’ll use the `collect` method, -which we used in Chapter 12 with `env::args` in Listing 12-1. This method -consumes the iterator and collects the resulting values into a collection data -type. - -In Listing 13-15, we collect the results of iterating over the iterator that’s -returned from the call to `map` into a vector. This vector will end up -containing each item from the original vector incremented by 1. - -Filename: src/main.rs - -```rust -{{#rustdoc_include ../listings/ch13-functional-features/listing-13-15/src/main.rs:here}} -``` - -Listing 13-15: Calling the `map` method to create a new -iterator and then calling the `collect` method to consume the new iterator and -create a vector - -Because `map` takes a closure, we can specify any operation we want to perform -on each item. This is a great example of how closures let you customize some -behavior while reusing the iteration behavior that the `Iterator` trait -provides. - -You can chain multiple calls to iterator adaptors to perform complex actions in -a readable way. But because all iterators are lazy, you have to call one of the -consuming adaptor methods to get results from calls to iterator adaptors. - -### Using Closures that Capture Their Environment - -Many iterator adapters take closures as arguments, and commonly the closures -we’ll specify as arguments to iterator adapters will be closures that capture -their environment. - -For this example, we’ll use the `filter` method that takes a closure. The -closure gets an item from the iterator and returns a `bool`. If the closure -returns `true`, the value will be included in the iteration produced by -`filter`. If the closure returns `false`, the value won’t be included. - -In Listing 13-16, we use `filter` with a closure that captures the `shoe_size` -variable from its environment to iterate over a collection of `Shoe` struct -instances. It will return only shoes that are the specified size. - -Filename: src/lib.rs - -```rust,noplayground -{{#rustdoc_include ../listings/ch13-functional-features/listing-13-16/src/lib.rs}} -``` - -Listing 13-16: Using the `filter` method with a closure -that captures `shoe_size` - -The `shoes_in_size` function takes ownership of a vector of shoes and a shoe -size as parameters. It returns a vector containing only shoes of the specified -size. - -In the body of `shoes_in_size`, we call `into_iter` to create an iterator -that takes ownership of the vector. Then we call `filter` to adapt that -iterator into a new iterator that only contains elements for which the closure -returns `true`. - -The closure captures the `shoe_size` parameter from the environment and -compares the value with each shoe’s size, keeping only shoes of the size -specified. Finally, calling `collect` gathers the values returned by the -adapted iterator into a vector that’s returned by the function. - -The test shows that when we call `shoes_in_size`, we get back only shoes -that have the same size as the value we specified. +# Processing a Series of Items with Iterators diff --git a/src/ch16-01-threads.md b/src/ch16-01-threads.md index cfdd0c7066..f3cdbff907 100644 --- a/src/ch16-01-threads.md +++ b/src/ch16-01-threads.md @@ -26,11 +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. +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 new file mode 100644 index 0000000000..f34caf2e66 --- /dev/null +++ b/src/ch17-00-async-await.md @@ -0,0 +1,89 @@ +## 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*. + +In the rest of 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, 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. + +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! + +> 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. + +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. diff --git a/src/ch17-01-futures-and-syntax.md b/src/ch17-01-futures-and-syntax.md new file mode 100644 index 0000000000..0654274fe3 --- /dev/null +++ b/src/ch17-01-futures-and-syntax.md @@ -0,0 +1,319 @@ +## 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. + +Let’s write our first async function, and call it: + ++ +```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 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. + +That means these two are roughly equivalent: + +```rust +async fn hello_async() { + println!("Hello, async!"); +} +``` + +```rust +fn hello_async() -> impl Future { + async { + println!("Hello, async!"); + } +} +``` + +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. + ++ + + +```rust +fn main() { + hello_async().await; +} +``` + + + +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 +``` + +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 +> +> 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 +$ cargo add trpl +``` + +Then, 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() { + trpl::block_on(hello_async()); +} + +async fn hello_async() { + println!("Hello, async!"); +} +``` + + + +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! 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. + +### 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: + +```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 { + Ready(T), + Pending +} +``` + +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. + +> 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. + +Under the hood, when you call `.await`, Rust compiles that to code which calls +`poll`, 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 + } + } +} +``` + +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 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 +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 +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 +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 +[tokio]: https://tokio.rs + + 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-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. + + 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 95% rename from src/ch17-01-what-is-oo.md rename to src/ch18-01-what-is-oo.md index 4a11b7cc08..f9f22a3a00 100644 --- a/src/ch17-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/ch17-02-trait-objects.md b/src/ch18-02-trait-objects.md similarity index 87% rename from src/ch17-02-trait-objects.md rename to src/ch18-02-trait-objects.md index 2d3fea24a1..f66b27dfdc 100644 --- a/src/ch17-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/ch17-03-oo-design-patterns.md b/src/ch18-03-oo-design-patterns.md similarity index 90% rename from src/ch17-03-oo-design-patterns.md rename to src/ch18-03-oo-design-patterns.md index 13503ef02b..676cf2bcd3 100644 --- a/src/ch17-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. 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 84% rename from src/ch18-01-all-the-places-for-patterns.md rename to src/ch19-01-all-the-places-for-patterns.md index 58f5af573b..b3adf7f8ee 100644 --- a/src/ch18-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. @@ -104,10 +104,10 @@ Similar in construction to `if let`, the `while let` conditional loop allows a 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 @@ -172,10 +172,10 @@ To see the pattern matching aspect of `let` more clearly, consider Listing 18-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/ch18-02-refutability.md b/src/ch19-02-refutability.md similarity index 83% rename from src/ch18-02-refutability.md rename to src/ch19-02-refutability.md index c8ca8b5766..7a7477924c 100644 --- a/src/ch18-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. +18-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/ch18-03-pattern-syntax.md b/src/ch19-03-pattern-syntax.md similarity index 83% rename from src/ch18-03-pattern-syntax.md rename to src/ch19-03-pattern-syntax.md index aeaa766ff3..f12f353a51 100644 --- a/src/ch18-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 @@ -516,10 +516,10 @@ 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 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 89% rename from src/ch19-01-unsafe-rust.md rename to src/ch20-01-unsafe-rust.md index a8133ca8e5..2431c7c3ee 100644 --- a/src/ch19-01-unsafe-rust.md +++ b/src/ch20-01-unsafe-rust.md @@ -88,14 +88,14 @@ 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. -Listing 19-1 shows how to create an immutable and a mutable raw pointer from +Listing 20-1 shows how to create an immutable and a mutable raw pointer from references. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-01/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-01/src/main.rs:here}} ``` -Listing 19-1: Creating raw pointers from references +Listing 20-1: Creating raw pointers from references 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 @@ -108,7 +108,7 @@ pointers are valid, but we can’t make that assumption about just any raw pointer. 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 +so certain of. Listing 20-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 error with a segmentation @@ -116,27 +116,27 @@ fault. Usually, there is no good reason to write code like this, but it is possible. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-02/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-02/src/main.rs:here}} ``` -Listing 19-2: Creating a raw pointer to an arbitrary +Listing 20-2: Creating a raw pointer to an arbitrary memory address 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 +raw pointers and read the data being pointed to. In Listing 20-3, we use the dereference operator `*` on a raw pointer that requires an `unsafe` block. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-03/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-03/src/main.rs:here}} ``` -Listing 19-3: Dereferencing raw pointers within an +Listing 20-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 Listing 19-1 and 19-3, we created `*const i32` and `*mut i32` +Note also that in Listing 20-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 @@ -168,14 +168,14 @@ Here is an unsafe function named `dangerous` that doesn’t do anything in its body: ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-01-unsafe-fn/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-01-unsafe-fn/src/main.rs:here}} ``` 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 @@ -194,25 +194,25 @@ 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`. +argument. Listing 20-4 shows how to use `split_at_mut`. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-04/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-04/src/main.rs:here}} ``` -Listing 19-4: Using the safe `split_at_mut` +Listing 20-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 +something like Listing 20-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`. ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-05/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-05/src/main.rs:here}} ``` -Listing 19-5: An attempted implementation of +Listing 20-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 @@ -225,10 +225,10 @@ 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. +When we try to compile the code in Listing 20-5, we’ll get an error. ```console -{{#include ../listings/ch19-advanced-features/listing-19-05/output.txt}} +{{#include ../listings/ch20-advanced-features/listing-20-05/output.txt}} ``` Rust’s borrow checker can’t understand that we’re borrowing different parts of @@ -237,14 +237,14 @@ 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 +Listing 20-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. ```rust -{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-06/src/main.rs:here}} +{{#rustdoc_include ../listings/ch20-advanced-features/listing-20-06/src/main.rs:here}} ``` -Listing 19-6: Using unsafe code in the implementation of +Listing 20-6: Using unsafe code in the implementation of the `split_at_mut` function Recall from [“The Slice Type”][the-slice-type] 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/ch19-03-advanced-traits.md b/src/ch20-03-advanced-traits.md similarity index 87% rename from src/ch19-03-advanced-traits.md rename to src/ch20-03-advanced-traits.md index 789591357b..0de68417e1 100644 --- a/src/ch19-03-advanced-traits.md +++ b/src/ch20-03-advanced-traits.md @@ -26,10 +26,10 @@ iterating over. The definition of the `Iterator` trait is as shown in Listing 19-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/ch19-04-advanced-types.md b/src/ch20-04-advanced-types.md similarity index 89% rename from src/ch19-04-advanced-types.md rename to src/ch20-04-advanced-types.md index 2dfed23cca..4c2f556769 100644 --- a/src/ch19-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/ch19-05-advanced-functions-and-closures.md b/src/ch20-05-advanced-functions-and-closures.md similarity index 88% rename from src/ch19-05-advanced-functions-and-closures.md rename to src/ch20-05-advanced-functions-and-closures.md index 88c46847d5..2355f31bc8 100644 --- a/src/ch19-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-18-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-19-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-19-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-20-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/ch19-06-macros.md b/src/ch20-06-macros.md similarity index 92% rename from src/ch19-06-macros.md rename to src/ch20-06-macros.md index f24a818c18..7b1e8a19c7 100644 --- a/src/ch19-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-21-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-21-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!` @@ -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 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 91% rename from src/ch20-01-single-threaded.md rename to src/ch21-01-single-threaded.md index b980856fd2..93ff11d09e 100644 --- a/src/ch20-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/ch20-02-multithreaded.md b/src/ch21-02-multithreaded.md similarity index 90% rename from src/ch20-02-multithreaded.md rename to src/ch21-02-multithreaded.md index cec2272db5..8c618b32fa 100644 --- a/src/ch20-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: