diff --git a/README.md b/README.md index cc7da8a..659055b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## 状态 -2021 edition 施工中。 +施工中。 PS: diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock index 0a2f222..edc2038 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -8,9 +10,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -26,33 +28,32 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -60,24 +61,15 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt index ac8b5c6..70a0c93 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt @@ -5,41 +5,19 @@ $ cargo build Compiling ppv-lite86 v0.2.10 Compiling rand_core v0.6.2 Compiling rand_chacha v0.3.0 - Compiling rand v0.8.3 + Compiling rand v0.8.5 Compiling guessing_game v0.1.0 (file:///projects/guessing_game) error[E0308]: mismatched types --> src/main.rs:22:21 | 22 | match guess.cmp(&secret_number) { - | ^^^^^^^^^^^^^^ expected struct `String`, found integer + | --- ^^^^^^^^^^^^^^ expected struct `String`, found integer + | | + | arguments to this function are incorrect | = note: expected reference `&String` found reference `&{integer}` +note: associated function defined here -error[E0283]: type annotations needed for `{integer}` - --> src/main.rs:8:44 - | -8 | let secret_number = rand::thread_rng().gen_range(1..=100); - | ------------- ^^^^^^^^^ cannot infer type for type `{integer}` - | | - | consider giving `secret_number` a type - | - = note: multiple `impl`s satisfying `{integer}: SampleUniform` found in the `rand` crate: - - impl SampleUniform for i128; - - impl SampleUniform for i16; - - impl SampleUniform for i32; - - impl SampleUniform for i64; - and 8 more -note: required by a bound in `gen_range` - --> /Users/carolnichols/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.3/src/rng.rs:129:12 - | -129 | T: SampleUniform, - | ^^^^^^^^^^^^^ required by this bound in `gen_range` -help: consider specifying the type arguments in the function call - | -8 | let secret_number = rand::thread_rng().gen_range::(1..=100); - | ++++++++ - -Some errors have detailed explanations: E0283, E0308. -For more information about an error, try `rustc --explain E0283`. -error: could not compile `guessing_game` due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. +error: could not compile `guessing_game` due to previous error diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs index 9d3b481..23ea227 100755 --- a/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs @@ -10,7 +10,7 @@ fn main() { // division let quotient = 56.7 / 32.2; - let floored = 2 / 3; // Results in 0 + let truncated = -5 / 3; // 结果为 -1 // remainder let remainder = 43 % 5; diff --git a/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt b/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt index a5a85f4..6ae56e0 100755 --- a/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt @@ -1,5 +1,11 @@ $ cargo run Compiling functions v0.1.0 (file:///projects/functions) +error: expected expression, found `let` statement + --> src/main.rs:2:14 + | +2 | let x = (let y = 6); + | ^^^ + error: expected expression, found statement (`let`) --> src/main.rs:2:14 | @@ -27,8 +33,8 @@ help: remove these parentheses | 2 - let x = (let y = 6); 2 + let x = let y = 6; - | + | For more information about this error, try `rustc --explain E0658`. warning: `functions` (bin "functions") generated 1 warning -error: could not compile `functions` due to 2 previous errors; 1 warning emitted +error: could not compile `functions` due to 3 previous errors; 1 warning emitted diff --git a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt index 4566ab7..c0484ea 100755 --- a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt @@ -8,7 +8,7 @@ error[E0308]: mismatched types | | | implicitly returns `()` as its body has no tail or `return` expression 8 | x + 1; - | - help: consider removing this semicolon + | - help: remove this semicolon For more information about this error, try `rustc --explain E0308`. error: could not compile `functions` due to previous error diff --git a/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt b/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt index d9807ce..8a11ccc 100755 --- a/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt +++ b/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt @@ -4,7 +4,12 @@ error[E0282]: type annotations needed --> src/main.rs:2:9 | 2 | let guess = "42".parse().expect("Not a number!"); - | ^^^^^ consider giving `guess` a type + | ^^^^^ + | +help: consider giving `guess` an explicit type + | +2 | let guess: _ = "42".parse().expect("Not a number!"); + | +++ For more information about this error, try `rustc --explain E0282`. error: could not compile `no_type_annotations` due to previous error diff --git a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt index 210ed9a..05987f7 100755 --- a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt @@ -7,9 +7,11 @@ error[E0382]: borrow of moved value: `s1` | -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait 3 | let s2 = s1; | -- value moved here -4 | +4 | 5 | println!("{}, world!", s1); | ^^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `ownership` due to previous error diff --git a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt index 71c29f6..8820d2d 100755 --- a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt @@ -7,7 +7,7 @@ error[E0499]: cannot borrow `s` as mutable more than once at a time | ------ first mutable borrow occurs here 5 | let r2 = &mut s; | ^^^^^^ second mutable borrow occurs here -6 | +6 | 7 | println!("{}, {}", r1, r2); | -- first borrow later used here diff --git a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt index df94c30..d1e9db2 100755 --- a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt @@ -8,7 +8,7 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta 5 | let r2 = &s; // no problem 6 | let r3 = &mut s; // BIG PROBLEM | ^^^^^^ mutable borrow occurs here -7 | +7 | 8 | println!("{}, {}, and {}", r1, r2, r3); | -- immutable borrow later used here diff --git a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt index fddca68..b466a3d 100755 --- a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt @@ -10,7 +10,7 @@ error[E0106]: missing lifetime specifier help: consider using the `'static` lifetime | 5 | fn dangle() -> &'static String { - | ~~~~~~~~ + | +++++++ For more information about this error, try `rustc --explain E0106`. error: could not compile `ownership` due to previous error diff --git a/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt b/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt index 62dc4ad..ab0c41f 100755 --- a/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt @@ -5,10 +5,10 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta | 16 | let word = first_word(&s); | -- immutable borrow occurs here -17 | +17 | 18 | s.clear(); // error! | ^^^^^^^^^ mutable borrow occurs here -19 | +19 | 20 | println!("the first word is: {}", word); | ---- immutable borrow later used here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs index e0f7a6c..122d251 100755 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs @@ -8,9 +8,9 @@ struct User { // ANCHOR: here fn main() { let user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), active: true, + username: String::from("someusername123"), + email: String::from("someone@example.com"), sign_in_count: 1, }; } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs index 7a078e7..35eea8a 100755 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs @@ -8,9 +8,9 @@ struct User { // ANCHOR: here fn main() { let mut user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), active: true, + username: String::from("someusername123"), + email: String::from("someone@example.com"), sign_in_count: 1, }; diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs index aa7823a..8614561 100755 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs @@ -8,9 +8,9 @@ struct User { // ANCHOR: here fn build_user(email: String, username: String) -> User { User { - email: email, - username: username, active: true, + username: username, + email: email, sign_in_count: 1, } } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs index 8d84a30..c893c86 100755 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs @@ -8,9 +8,9 @@ struct User { // ANCHOR: here fn build_user(email: String, username: String) -> User { User { - email, - username, active: true, + username, + email, sign_in_count: 1, } } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt index b761fcc..7d3bfcd 100755 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt @@ -8,7 +8,7 @@ error[E0277]: `Rectangle` doesn't implement `std::fmt::Display` | = help: the trait `std::fmt::Display` is not implemented for `Rectangle` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0277`. error: could not compile `rectangles` due to previous error diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.lock index 5804b18..bede081 100755 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.lock @@ -3,3 +3,4 @@ [[package]] name = "structs" version = "0.1.0" + diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt index 8b9c2ab..58cb842 100755 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt @@ -8,7 +8,11 @@ error[E0277]: `Rectangle` doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `Rectangle` = note: add `#[derive(Debug)]` to `Rectangle` or manually `impl Debug for Rectangle` - = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Rectangle` with `#[derive(Debug)]` + | +1 | #[derive(Debug)] + | For more information about this error, try `rustc --explain E0277`. error: could not compile `rectangles` due to previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt index 343b9d2..d4a040e 100755 --- a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt @@ -7,6 +7,16 @@ error[E0277]: cannot add `Option` to `i8` | ^ no implementation for `i8 + Option` | = help: the trait `Add>` is not implemented for `i8` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> + and 48 others For more information about this error, try `rustc --explain E0277`. error: could not compile `enums` due to previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt index 8054e7d..bec7284 100755 --- a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt @@ -1,13 +1,18 @@ $ cargo run Compiling enums v0.1.0 (file:///projects/enums) error[E0004]: non-exhaustive patterns: `None` not covered - --> src/main.rs:3:15 - | -3 | match x { - | ^ pattern `None` not covered - | - = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms - = note: the matched value is of type `Option` + --> src/main.rs:3:15 + | +3 | match x { + | ^ pattern `None` not covered + | +note: `Option` defined here + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +4 ~ Some(i) => Some(i + 1), +5 ~ None => todo!(), + | For more information about this error, try `rustc --explain E0004`. error: could not compile `enums` due to previous error diff --git a/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs index 7d4b597..b3ddb4f 100755 --- a/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs @@ -1,9 +1,9 @@ -fn serve_order() {} +fn deliver_order() {} mod back_of_house { fn fix_incorrect_order() { cook_order(); - super::serve_order(); + super::deliver_order(); } fn cook_order() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs index 44defd0..cf31a9c 100755 --- a/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs @@ -8,6 +8,4 @@ use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/listing-07-12/output.txt b/listings/ch07-managing-growing-projects/listing-07-12/output.txt new file mode 100755 index 0000000..39b6505 --- /dev/null +++ b/listings/ch07-managing-growing-projects/listing-07-12/output.txt @@ -0,0 +1,19 @@ +$ cargo build + Compiling restaurant v0.1.0 (file:///projects/restaurant) +error[E0433]: failed to resolve: use of undeclared crate or module `hosting` + --> src/lib.rs:11:9 + | +11 | hosting::add_to_waitlist(); + | ^^^^^^^ use of undeclared crate or module `hosting` + +warning: unused import: `crate::front_of_house::hosting` + --> src/lib.rs:7:5 + | +7 | use crate::front_of_house::hosting; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +For more information about this error, try `rustc --explain E0433`. +warning: `restaurant` (lib) generated 1 warning +error: could not compile `restaurant` due to previous error; 1 warning emitted diff --git a/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs index 671bc10..afc7594 100755 --- a/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs @@ -4,10 +4,10 @@ mod front_of_house { } } -use self::front_of_house::hosting; +use crate::front_of_house::hosting; -pub fn eat_at_restaurant() { - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); +mod customer { + pub fn eat_at_restaurant() { + hosting::add_to_waitlist(); + } } diff --git a/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs index e886c24..c72994e 100755 --- a/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs @@ -8,6 +8,4 @@ use crate::front_of_house::hosting::add_to_waitlist; pub fn eat_at_restaurant() { add_to_waitlist(); - add_to_waitlist(); - add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs index 835e571..45cf1ba 100755 --- a/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs @@ -8,6 +8,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock +++ b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml index 15b3fff..d508e95 100755 --- a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs b/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs index 6c88bc4..2f69412 100755 --- a/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs +++ b/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs @@ -8,9 +8,9 @@ use std::{cmp::Ordering, io}; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -22,7 +22,7 @@ fn main() { let guess: u32 = guess.trim().parse().expect("Please type a number!"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs index 065b1b8..d676955 100755 --- a/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs @@ -4,6 +4,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml index cc63f6f..7eda67a 100755 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs index af1b2b4..3a02c99 100755 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs @@ -9,9 +9,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -21,7 +21,7 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs index 065b1b8..d676955 100755 --- a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs +++ b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs @@ -4,6 +4,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch08-common-collections/listing-08-04/src/main.rs b/listings/ch08-common-collections/listing-08-04/src/main.rs index 625ff2c..fca332d 100755 --- a/listings/ch08-common-collections/listing-08-04/src/main.rs +++ b/listings/ch08-common-collections/listing-08-04/src/main.rs @@ -1,9 +1,14 @@ fn main() { // ANCHOR: here - { - let v = vec![1, 2, 3, 4]; + let v = vec![1, 2, 3, 4, 5]; - // 处理变量 v - } // <- 这里 v 离开作用域并被丢弃 - // ANCHOR_END: here + let third: &i32 = &v[2]; + println!("The third element is {third}"); + + let third: Option<&i32> = v.get(2); + match third { + Some(third) => println!("The third element is {third}"), + None => println!("There is no third element."), + } + // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-05/src/main.rs b/listings/ch08-common-collections/listing-08-05/src/main.rs index 9bfa37a..783d9b1 100755 --- a/listings/ch08-common-collections/listing-08-05/src/main.rs +++ b/listings/ch08-common-collections/listing-08-05/src/main.rs @@ -2,12 +2,7 @@ fn main() { // ANCHOR: here let v = vec![1, 2, 3, 4, 5]; - let third: &i32 = &v[2]; - println!("The third element is {}", third); - - match v.get(2) { - Some(third) => println!("The third element is {}", third), - None => println!("There is no third element."), - } + let does_not_exist = &v[100]; + let does_not_exist = v.get(100); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-06/output.txt b/listings/ch08-common-collections/listing-08-06/output.txt new file mode 100755 index 0000000..3104205 --- /dev/null +++ b/listings/ch08-common-collections/listing-08-06/output.txt @@ -0,0 +1,16 @@ +$ cargo run + Compiling collections v0.1.0 (file:///projects/collections) +error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable + --> src/main.rs:6:5 + | +4 | let first = &v[0]; + | - immutable borrow occurs here +5 | +6 | v.push(6); + | ^^^^^^^^^ mutable borrow occurs here +7 | +8 | println!("The first element is: {first}"); + | ----- immutable borrow later used here + +For more information about this error, try `rustc --explain E0502`. +error: could not compile `collections` due to previous error diff --git a/listings/ch08-common-collections/listing-08-06/src/main.rs b/listings/ch08-common-collections/listing-08-06/src/main.rs index 783d9b1..653ac27 100755 --- a/listings/ch08-common-collections/listing-08-06/src/main.rs +++ b/listings/ch08-common-collections/listing-08-06/src/main.rs @@ -1,8 +1,11 @@ fn main() { // ANCHOR: here - let v = vec![1, 2, 3, 4, 5]; + let mut v = vec![1, 2, 3, 4, 5]; - let does_not_exist = &v[100]; - let does_not_exist = v.get(100); + let first = &v[0]; + + v.push(6); + + println!("The first element is: {first}"); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-07/src/main.rs b/listings/ch08-common-collections/listing-08-07/src/main.rs index 1b42274..aebf855 100755 --- a/listings/ch08-common-collections/listing-08-07/src/main.rs +++ b/listings/ch08-common-collections/listing-08-07/src/main.rs @@ -1,11 +1,8 @@ fn main() { // ANCHOR: here - let mut v = vec![1, 2, 3, 4, 5]; - - let first = &v[0]; - - v.push(6); - - println!("The first element is: {}", first); + let v = vec![100, 32, 57]; + for i in &v { + println!("{i}"); + } // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-08/src/main.rs b/listings/ch08-common-collections/listing-08-08/src/main.rs index 38b9778..c62ba21 100755 --- a/listings/ch08-common-collections/listing-08-08/src/main.rs +++ b/listings/ch08-common-collections/listing-08-08/src/main.rs @@ -1,8 +1,8 @@ fn main() { // ANCHOR: here - let v = vec![100, 32, 57]; - for i in &v { - println!("{}", i); + let mut v = vec![100, 32, 57]; + for i in &mut v { + *i += 50; } // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-09/src/main.rs b/listings/ch08-common-collections/listing-08-09/src/main.rs index c62ba21..c219888 100755 --- a/listings/ch08-common-collections/listing-08-09/src/main.rs +++ b/listings/ch08-common-collections/listing-08-09/src/main.rs @@ -1,8 +1,15 @@ fn main() { // ANCHOR: here - let mut v = vec![100, 32, 57]; - for i in &mut v { - *i += 50; + enum SpreadsheetCell { + Int(i32), + Float(f64), + Text(String), } + + let row = vec![ + SpreadsheetCell::Int(3), + SpreadsheetCell::Text(String::from("blue")), + SpreadsheetCell::Float(10.12), + ]; // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-10/src/main.rs b/listings/ch08-common-collections/listing-08-10/src/main.rs index c219888..abda2db 100755 --- a/listings/ch08-common-collections/listing-08-10/src/main.rs +++ b/listings/ch08-common-collections/listing-08-10/src/main.rs @@ -1,15 +1,9 @@ fn main() { // ANCHOR: here - enum SpreadsheetCell { - Int(i32), - Float(f64), - Text(String), - } + { + let v = vec![1, 2, 3, 4]; - let row = vec![ - SpreadsheetCell::Int(3), - SpreadsheetCell::Text(String::from("blue")), - SpreadsheetCell::Float(10.12), - ]; - // ANCHOR_END: here + // do stuff with v + } // <- v goes out of scope and is freed here + // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-16/src/main.rs b/listings/ch08-common-collections/listing-08-16/src/main.rs index 8938dc1..db57cdd 100755 --- a/listings/ch08-common-collections/listing-08-16/src/main.rs +++ b/listings/ch08-common-collections/listing-08-16/src/main.rs @@ -3,6 +3,6 @@ fn main() { let mut s1 = String::from("foo"); let s2 = "bar"; s1.push_str(s2); - println!("s2 is {}", s2); + println!("s2 is {s2}"); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-19/output.txt b/listings/ch08-common-collections/listing-08-19/output.txt index 2e5ad54..9557777 100755 --- a/listings/ch08-common-collections/listing-08-19/output.txt +++ b/listings/ch08-common-collections/listing-08-19/output.txt @@ -7,6 +7,14 @@ error[E0277]: the type `String` cannot be indexed by `{integer}` | ^^^^^ `String` cannot be indexed by `{integer}` | = help: the trait `Index<{integer}>` is not implemented for `String` + = help: the following other types implement trait `Index`: + >> + > + >> + >> + >> + >> + > For more information about this error, try `rustc --explain E0277`. error: could not compile `collections` due to previous error diff --git a/listings/ch08-common-collections/listing-08-21/src/main.rs b/listings/ch08-common-collections/listing-08-21/src/main.rs index 0ebd20d..0755154 100755 --- a/listings/ch08-common-collections/listing-08-21/src/main.rs +++ b/listings/ch08-common-collections/listing-08-21/src/main.rs @@ -2,10 +2,12 @@ fn main() { // ANCHOR: here use std::collections::HashMap; - let teams = vec![String::from("Blue"), String::from("Yellow")]; - let initial_scores = vec![10, 50]; + let mut scores = HashMap::new(); - let mut scores: HashMap<_, _> = - teams.into_iter().zip(initial_scores.into_iter()).collect(); + scores.insert(String::from("Blue"), 10); + scores.insert(String::from("Yellow"), 50); + + let team_name = String::from("Blue"); + let score = scores.get(&team_name).copied().unwrap_or(0); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-23/src/main.rs b/listings/ch08-common-collections/listing-08-23/src/main.rs index 508e33c..e8684cf 100755 --- a/listings/ch08-common-collections/listing-08-23/src/main.rs +++ b/listings/ch08-common-collections/listing-08-23/src/main.rs @@ -5,9 +5,8 @@ fn main() { let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10); - scores.insert(String::from("Yellow"), 50); + scores.insert(String::from("Blue"), 25); - let team_name = String::from("Blue"); - let score = scores.get(&team_name); + println!("{:?}", scores); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-24/src/main.rs b/listings/ch08-common-collections/listing-08-24/src/main.rs index e8684cf..3ad97b5 100755 --- a/listings/ch08-common-collections/listing-08-24/src/main.rs +++ b/listings/ch08-common-collections/listing-08-24/src/main.rs @@ -3,9 +3,10 @@ fn main() { use std::collections::HashMap; let mut scores = HashMap::new(); - scores.insert(String::from("Blue"), 10); - scores.insert(String::from("Blue"), 25); + + scores.entry(String::from("Yellow")).or_insert(50); + scores.entry(String::from("Blue")).or_insert(50); println!("{:?}", scores); // ANCHOR_END: here diff --git a/listings/ch08-common-collections/listing-08-25/src/main.rs b/listings/ch08-common-collections/listing-08-25/src/main.rs index 3ad97b5..f3f6aa1 100755 --- a/listings/ch08-common-collections/listing-08-25/src/main.rs +++ b/listings/ch08-common-collections/listing-08-25/src/main.rs @@ -2,12 +2,15 @@ fn main() { // ANCHOR: here use std::collections::HashMap; - let mut scores = HashMap::new(); - scores.insert(String::from("Blue"), 10); + let text = "hello world wonderful world"; - scores.entry(String::from("Yellow")).or_insert(50); - scores.entry(String::from("Blue")).or_insert(50); + let mut map = HashMap::new(); - println!("{:?}", scores); + for word in text.split_whitespace() { + let count = map.entry(word).or_insert(0); + *count += 1; + } + + println!("{:?}", map); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/no-listing-02-format/src/main.rs b/listings/ch08-common-collections/no-listing-02-format/src/main.rs index 4a38e63..db408e2 100755 --- a/listings/ch08-common-collections/no-listing-02-format/src/main.rs +++ b/listings/ch08-common-collections/no-listing-02-format/src/main.rs @@ -4,6 +4,6 @@ fn main() { let s2 = String::from("tac"); let s3 = String::from("toe"); - let s = format!("{}-{}-{}", s1, s2, s3); + let s = format!("{s1}-{s2}-{s3}"); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs b/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs index 2e7dc02..bb13c86 100755 --- a/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs +++ b/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs @@ -8,7 +8,7 @@ fn main() { scores.insert(String::from("Yellow"), 50); for (key, value) in &scores { - println!("{}: {}", key, value); + println!("{key}: {value}"); } // ANCHOR_END: here } diff --git a/listings/ch09-error-handling/listing-09-03/src/main.rs b/listings/ch09-error-handling/listing-09-03/src/main.rs index 0dfd10b..2342904 100755 --- a/listings/ch09-error-handling/listing-09-03/src/main.rs +++ b/listings/ch09-error-handling/listing-09-03/src/main.rs @@ -1,5 +1,5 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt"); + let greeting_file_result = File::open("hello.txt"); } diff --git a/listings/ch09-error-handling/listing-09-04/src/main.rs b/listings/ch09-error-handling/listing-09-04/src/main.rs index 070fc33..69da109 100755 --- a/listings/ch09-error-handling/listing-09-04/src/main.rs +++ b/listings/ch09-error-handling/listing-09-04/src/main.rs @@ -1,9 +1,9 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt"); + let greeting_file_result = File::open("hello.txt"); - let f = match f { + let greeting_file = match greeting_file_result { Ok(file) => file, Err(error) => panic!("Problem opening the file: {:?}", error), }; diff --git a/listings/ch09-error-handling/listing-09-05/src/main.rs b/listings/ch09-error-handling/listing-09-05/src/main.rs index 8c4f773..83ea010 100755 --- a/listings/ch09-error-handling/listing-09-05/src/main.rs +++ b/listings/ch09-error-handling/listing-09-05/src/main.rs @@ -2,9 +2,9 @@ use std::fs::File; use std::io::ErrorKind; fn main() { - let f = File::open("hello.txt"); + let greeting_file_result = File::open("hello.txt"); - let f = match f { + let greeting_file = match greeting_file_result { Ok(file) => file, Err(error) => match error.kind() { ErrorKind::NotFound => match File::create("hello.txt") { @@ -12,7 +12,7 @@ fn main() { Err(e) => panic!("Problem creating the file: {:?}", e), }, other_error => { - panic!("Problem opening the file: {:?}", other_error) + panic!("Problem opening the file: {:?}", other_error); } }, }; diff --git a/listings/ch09-error-handling/listing-09-06/src/main.rs b/listings/ch09-error-handling/listing-09-06/src/main.rs index 4f0a521..a70734c 100755 --- a/listings/ch09-error-handling/listing-09-06/src/main.rs +++ b/listings/ch09-error-handling/listing-09-06/src/main.rs @@ -3,17 +3,17 @@ use std::fs::File; use std::io::{self, Read}; fn read_username_from_file() -> Result { - let f = File::open("hello.txt"); + let username_file_result = File::open("hello.txt"); - let mut f = match f { + let mut username_file = match username_file_result { Ok(file) => file, Err(e) => return Err(e), }; - let mut s = String::new(); + let mut username = String::new(); - match f.read_to_string(&mut s) { - Ok(_) => Ok(s), + match username_file.read_to_string(&mut username) { + Ok(_) => Ok(username), Err(e) => Err(e), } } diff --git a/listings/ch09-error-handling/listing-09-07/src/main.rs b/listings/ch09-error-handling/listing-09-07/src/main.rs index b9f6172..0295949 100755 --- a/listings/ch09-error-handling/listing-09-07/src/main.rs +++ b/listings/ch09-error-handling/listing-09-07/src/main.rs @@ -1,13 +1,12 @@ // ANCHOR: here use std::fs::File; -use std::io; -use std::io::Read; +use std::io::{self, Read}; fn read_username_from_file() -> Result { - let mut f = File::open("hello.txt")?; - let mut s = String::new(); - f.read_to_string(&mut s)?; - Ok(s) + let mut username_file = File::open("hello.txt")?; + let mut username = String::new(); + username_file.read_to_string(&mut username)?; + Ok(username) } // ANCHOR_END: here diff --git a/listings/ch09-error-handling/listing-09-08/src/main.rs b/listings/ch09-error-handling/listing-09-08/src/main.rs index f36e4d0..ca672ca 100755 --- a/listings/ch09-error-handling/listing-09-08/src/main.rs +++ b/listings/ch09-error-handling/listing-09-08/src/main.rs @@ -1,14 +1,13 @@ // ANCHOR: here use std::fs::File; -use std::io; -use std::io::Read; +use std::io::{self, Read}; fn read_username_from_file() -> Result { - let mut s = String::new(); + let mut username = String::new(); - File::open("hello.txt")?.read_to_string(&mut s)?; + File::open("hello.txt")?.read_to_string(&mut username)?; - Ok(s) + Ok(username) } // ANCHOR_END: here diff --git a/listings/ch09-error-handling/listing-09-10/output.txt b/listings/ch09-error-handling/listing-09-10/output.txt index 6a8b1a4..75b9cf2 100755 --- a/listings/ch09-error-handling/listing-09-10/output.txt +++ b/listings/ch09-error-handling/listing-09-10/output.txt @@ -1,13 +1,12 @@ $ cargo run Compiling error-handling v0.1.0 (file:///projects/error-handling) error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> src/main.rs:4:36 + --> src/main.rs:4:48 | -3 | / fn main() { -4 | | let f = File::open("hello.txt")?; - | | ^ cannot use the `?` operator in a function that returns `()` -5 | | } - | |_- this function should return `Result` or `Option` to accept `?` +3 | fn main() { + | --------- this function should return `Result` or `Option` to accept `?` +4 | let greeting_file = File::open("hello.txt")?; + | ^ cannot use the `?` operator in a function that returns `()` | = help: the trait `FromResidual>` is not implemented for `()` diff --git a/listings/ch09-error-handling/listing-09-10/src/main.rs b/listings/ch09-error-handling/listing-09-10/src/main.rs index 8608dc1..38b0054 100755 --- a/listings/ch09-error-handling/listing-09-10/src/main.rs +++ b/listings/ch09-error-handling/listing-09-10/src/main.rs @@ -1,5 +1,5 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt")?; + let greeting_file = File::open("hello.txt")?; } diff --git a/listings/ch09-error-handling/listing-09-12/src/main.rs b/listings/ch09-error-handling/listing-09-12/src/main.rs index 7f16b8e..b0f7445 100755 --- a/listings/ch09-error-handling/listing-09-12/src/main.rs +++ b/listings/ch09-error-handling/listing-09-12/src/main.rs @@ -2,7 +2,7 @@ use std::error::Error; use std::fs::File; fn main() -> Result<(), Box> { - let f = File::open("hello.txt")?; + let greeting_file = File::open("hello.txt")?; Ok(()) } diff --git a/listings/ch09-error-handling/listing-09-13/Cargo.lock b/listings/ch09-error-handling/listing-09-13/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch09-error-handling/listing-09-13/Cargo.lock +++ b/listings/ch09-error-handling/listing-09-13/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch09-error-handling/listing-09-13/Cargo.toml b/listings/ch09-error-handling/listing-09-13/Cargo.toml index 15b3fff..d508e95 100755 --- a/listings/ch09-error-handling/listing-09-13/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-13/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch09-error-handling/listing-09-13/src/main.rs b/listings/ch09-error-handling/listing-09-13/src/main.rs index 3375279..9e07c1e 100755 --- a/listings/ch09-error-handling/listing-09-13/src/main.rs +++ b/listings/ch09-error-handling/listing-09-13/src/main.rs @@ -25,7 +25,7 @@ impl Guess { fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); loop { println!("Please input your guess."); diff --git a/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs b/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs index 7b6b13a..92e9452 100755 --- a/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs +++ b/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs @@ -1,5 +1,5 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt").unwrap(); + let greeting_file = File::open("hello.txt").unwrap(); } diff --git a/listings/ch09-error-handling/no-listing-05-expect/src/main.rs b/listings/ch09-error-handling/no-listing-05-expect/src/main.rs index cab643b..3d36fa5 100755 --- a/listings/ch09-error-handling/no-listing-05-expect/src/main.rs +++ b/listings/ch09-error-handling/no-listing-05-expect/src/main.rs @@ -1,5 +1,6 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt").expect("Failed to open hello.txt"); + let greeting_file = File::open("hello.txt") + .expect("hello.txt should be included in this project"); } diff --git a/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs b/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs index e829724..3e18352 100755 --- a/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs +++ b/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs @@ -2,6 +2,8 @@ fn main() { // ANCHOR: here use std::net::IpAddr; - let home: IpAddr = "127.0.0.1".parse().unwrap(); + let home: IpAddr = "127.0.0.1" + .parse() + .expect("Hardcoded IP address should be valid"); // ANCHOR_END: here } diff --git a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock index 0a2f222..2ae9e45 100755 --- a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock +++ b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml index 15b3fff..d508e95 100755 --- a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml +++ b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs index cbe8fbc..fc22cbc 100755 --- a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs +++ b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs @@ -5,7 +5,7 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); // ANCHOR: here loop { diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs index d2ba23b..a4dba7e 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs @@ -2,9 +2,9 @@ fn main() { let number_list = vec![34, 50, 25, 100, 65]; - let mut largest = number_list[0]; + let mut largest = &number_list[0]; - for number in number_list { + for number in &number_list { if number > largest { largest = number; } @@ -12,7 +12,7 @@ fn main() { println!("The largest number is {}", largest); // ANCHOR_END: here - assert_eq!(largest, 100); + assert_eq!(*largest, 100); // ANCHOR: here } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs index 9138dfc..8c523a8 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs @@ -1,9 +1,9 @@ fn main() { let number_list = vec![34, 50, 25, 100, 65]; - let mut largest = number_list[0]; + let mut largest = &number_list[0]; - for number in number_list { + for number in &number_list { if number > largest { largest = number; } @@ -13,9 +13,9 @@ fn main() { let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; - let mut largest = number_list[0]; + let mut largest = &number_list[0]; - for number in number_list { + for number in &number_list { if number > largest { largest = number; } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs index 7704ff3..8992229 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs @@ -1,8 +1,8 @@ // ANCHOR: here -fn largest(list: &[i32]) -> i32 { - let mut largest = list[0]; +fn largest(list: &[i32]) -> &i32 { + let mut largest = &list[0]; - for &item in list { + for item in list { if item > largest { largest = item; } @@ -17,7 +17,7 @@ fn main() { let result = largest(&number_list); println!("The largest number is {}", result); // ANCHOR_END: here - assert_eq!(result, 100); + assert_eq!(*result, 100); // ANCHOR: here let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; @@ -25,7 +25,7 @@ fn main() { let result = largest(&number_list); println!("The largest number is {}", result); // ANCHOR_END: here - assert_eq!(result, 6000); + assert_eq!(*result, 6000); // ANCHOR: here } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs index 6b483ec..a47e3f2 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs @@ -1,8 +1,8 @@ // ANCHOR: here -fn largest_i32(list: &[i32]) -> i32 { - let mut largest = list[0]; +fn largest_i32(list: &[i32]) -> &i32 { + let mut largest = &list[0]; - for &item in list { + for item in list { if item > largest { largest = item; } @@ -11,10 +11,10 @@ fn largest_i32(list: &[i32]) -> i32 { largest } -fn largest_char(list: &[char]) -> char { - let mut largest = list[0]; +fn largest_char(list: &[char]) -> &char { + let mut largest = &list[0]; - for &item in list { + for item in list { if item > largest { largest = item; } @@ -29,7 +29,7 @@ fn main() { let result = largest_i32(&number_list); println!("The largest number is {}", result); // ANCHOR_END: here - assert_eq!(result, 100); + assert_eq!(*result, 100); // ANCHOR: here let char_list = vec!['y', 'm', 'a', 'q']; @@ -37,7 +37,7 @@ fn main() { let result = largest_char(&char_list); println!("The largest char is {}", result); // ANCHOR_END: here - assert_eq!(result, 'y'); + assert_eq!(*result, 'y'); // ANCHOR: here } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt index 0530f54..1a705ed 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt @@ -1,16 +1,16 @@ $ cargo run Compiling chapter10 v0.1.0 (file:///projects/chapter10) -error[E0369]: binary operation `>` cannot be applied to type `T` +error[E0369]: binary operation `>` cannot be applied to type `&T` --> src/main.rs:5:17 | 5 | if item > largest { - | ---- ^ ------- T + | ---- ^ ------- &T | | - | T + | &T | help: consider restricting type parameter `T` | -1 | fn largest(list: &[T]) -> T { +1 | fn largest(list: &[T]) -> &T { | ++++++++++++++++++++++ For more information about this error, try `rustc --explain E0369`. diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs index e731157..df33743 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs @@ -1,7 +1,7 @@ -fn largest(list: &[T]) -> T { - let mut largest = list[0]; +fn largest(list: &[T]) -> &T { + let mut largest = &list[0]; - for &item in list { + for item in list { if item > largest { largest = item; } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs new file mode 100755 index 0000000..669cc5f --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs @@ -0,0 +1,22 @@ +use std::fmt::Display; + +struct Pair { + x: T, + y: T, +} + +impl Pair { + fn new(x: T, y: T) -> Self { + Self { x, y } + } +} + +impl Pair { + fn cmp_display(&self) { + if self.x >= self.y { + println!("The largest member is x = {}", self.x); + } else { + println!("The largest member is y = {}", self.y); + } + } +} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/output.txt new file mode 100755 index 0000000..ad73272 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/output.txt @@ -0,0 +1,15 @@ +$ cargo run + Compiling chapter10 v0.1.0 (file:///projects/chapter10) +error[E0597]: `x` does not live long enough + --> src/main.rs:6:13 + | +6 | r = &x; + | ^^ borrowed value does not live long enough +7 | } + | - `x` dropped here while still borrowed +8 | +9 | println!("r: {}", r); + | - borrow later used here + +For more information about this error, try `rustc --explain E0597`. +error: could not compile `chapter10` due to previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs new file mode 100755 index 0000000..d71134e --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs @@ -0,0 +1,10 @@ +fn main() { + let r; + + { + let x = 5; + r = &x; + } + + println!("r: {}", r); +} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock index e8007a1..6388bb2 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock @@ -1,5 +1,3 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. [[package]] name = "chapter10" version = "0.1.0" diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/rustfmt-ignore b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/rustfmt-ignore new file mode 100755 index 0000000..9a53c71 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/rustfmt-ignore @@ -0,0 +1,3 @@ +We have some weird comments pointing out borrowing scopes that we don't want to change; +unfortunately I haven't found a way to skip them with rustfmt that works so for now we're going to +manually skip those listings. See: https://github.com/rust-lang/rustfmt/issues/4028 diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs index 16adb6a..e8ca923 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs @@ -1,14 +1,10 @@ fn main() { - // ANCHOR: here - { - let r; - - { - let x = 5; - r = &x; - } - - println!("r: {}", r); - } - // ANCHOR_END: here -} + let r; // ---------+-- 'a + // | + { // | + let x = 5; // -+-- 'b | + r = &x; // | | + } // -+ | + // | + println!("r: {}", r); // | +} // ---------+ diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs index 65dbf37..09ae391 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs @@ -1,14 +1,8 @@ fn main() { - // ANCHOR: here - { - let r; // ---------+-- 'a - // | - { // | - let x = 5; // -+-- 'b | - r = &x; // | | - } // -+ | - // | - println!("r: {}", r); // | - } // ---------+ - // ANCHOR_END: here -} + let x = 5; // ----------+-- 'b + // | + let r = &x; // --+-- 'a | + // | | + println!("r: {}", r); // | | + // --+ | +} // ----------+ diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock index 6388bb2..e8007a1 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "chapter10" version = "0.1.0" diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs index 94e70f0..0f076a7 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs @@ -1,12 +1,7 @@ fn main() { - // ANCHOR: here - { - let x = 5; // ----------+-- 'b - // | - let r = &x; // --+-- 'a | - // | | - println!("r: {}", r); // | | - // --+ | - } // ----------+ - // ANCHOR_END: here + let string1 = String::from("abcd"); + let string2 = "xyz"; + + let result = longest(string1.as_str(), string2); + println!("The longest string is {}", result); } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/output.txt new file mode 100755 index 0000000..534a984 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/output.txt @@ -0,0 +1,16 @@ +$ cargo run + Compiling chapter10 v0.1.0 (file:///projects/chapter10) +error[E0106]: missing lifetime specifier + --> src/main.rs:9:33 + | +9 | fn longest(x: &str, y: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` +help: consider introducing a named lifetime parameter + | +9 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + | ++++ ++ ++ ++ + +For more information about this error, try `rustc --explain E0106`. +error: could not compile `chapter10` due to previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs index 0f076a7..6af8c9f 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs @@ -5,3 +5,13 @@ fn main() { let result = longest(string1.as_str(), string2); println!("The longest string is {}", result); } + +// ANCHOR: here +fn longest(x: &str, y: &str) -> &str { + if x.len() > y.len() { + x + } else { + y + } +} +// ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs index 6af8c9f..09c3a0d 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs @@ -7,7 +7,7 @@ fn main() { } // ANCHOR: here -fn longest(x: &str, y: &str) -> &str { +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs index 09c3a0d..836ec72 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs @@ -1,12 +1,15 @@ +// ANCHOR: here fn main() { - let string1 = String::from("abcd"); - let string2 = "xyz"; + let string1 = String::from("long string is long"); - let result = longest(string1.as_str(), string2); - println!("The longest string is {}", result); + { + let string2 = String::from("xyz"); + let result = longest(string1.as_str(), string2.as_str()); + println!("The longest string is {}", result); + } } +// ANCHOR_END: here -// ANCHOR: here fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x @@ -14,4 +17,3 @@ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { y } } -// ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/output.txt new file mode 100755 index 0000000..7f31ce0 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/output.txt @@ -0,0 +1,14 @@ +$ cargo run + Compiling chapter10 v0.1.0 (file:///projects/chapter10) +error[E0597]: `string2` does not live long enough + --> src/main.rs:6:44 + | +6 | result = longest(string1.as_str(), string2.as_str()); + | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough +7 | } + | - `string2` dropped here while still borrowed +8 | println!("The longest string is {}", result); + | ------ borrow later used here + +For more information about this error, try `rustc --explain E0597`. +error: could not compile `chapter10` due to previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs index 836ec72..2a6fa58 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs @@ -1,12 +1,12 @@ // ANCHOR: here fn main() { let string1 = String::from("long string is long"); - + let result; { let string2 = String::from("xyz"); - let result = longest(string1.as_str(), string2.as_str()); - println!("The longest string is {}", result); + result = longest(string1.as_str(), string2.as_str()); } + println!("The longest string is {}", result); } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs index 2a6fa58..2937b19 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs @@ -1,19 +1,11 @@ -// ANCHOR: here -fn main() { - let string1 = String::from("long string is long"); - let result; - { - let string2 = String::from("xyz"); - result = longest(string1.as_str(), string2.as_str()); - } - println!("The longest string is {}", result); +struct ImportantExcerpt<'a> { + part: &'a str, } -// ANCHOR_END: here -fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { - if x.len() > y.len() { - x - } else { - y - } +fn main() { + let novel = String::from("Call me Ishmael. Some years ago..."); + let first_sentence = novel.split('.').next().expect("Could not find a '.'"); + let i = ImportantExcerpt { + part: first_sentence, + }; } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock index e8007a1..2aa4918 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "chapter10" +name = "ownership" version = "0.1.0" diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml index 489f809..e884752 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "chapter10" +name = "ownership" version = "0.1.0" edition = "2021" diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs index 2937b19..431a261 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs @@ -1,11 +1,29 @@ -struct ImportantExcerpt<'a> { - part: &'a str, +// ANCHOR: here +fn first_word(s: &str) -> &str { + let bytes = s.as_bytes(); + + for (i, &item) in bytes.iter().enumerate() { + if item == b' ' { + return &s[0..i]; + } + } + + &s[..] } +// ANCHOR_END: here fn main() { - let novel = String::from("Call me Ishmael. Some years ago..."); - let first_sentence = novel.split('.').next().expect("Could not find a '.'"); - let i = ImportantExcerpt { - part: first_sentence, - }; + let my_string = String::from("hello world"); + + // first_word works on slices of `String`s + let word = first_word(&my_string[..]); + + let my_string_literal = "hello world"; + + // first_word works on slices of string literals + let word = first_word(&my_string_literal[..]); + + // Because string literals *are* string slices already, + // this works too, without the slice syntax! + let word = first_word(my_string_literal); } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs index 44c9c64..cc9b98e 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs @@ -1,4 +1,4 @@ -use chapter10::{self, NewsArticle, Summary}; +use aggregator::{self, NewsArticle, Summary}; fn main() { // ANCHOR: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs index 466dc4d..e05e8e1 100755 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs @@ -1,4 +1,4 @@ -use chapter10::{self, Summary, Tweet}; +use aggregator::{self, Summary, Tweet}; fn main() { // ANCHOR: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/Cargo.toml new file mode 100755 index 0000000..4dbde90 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "chapter10" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/src/lib.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/src/lib.rs new file mode 100755 index 0000000..05b07c3 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/src/lib.rs @@ -0,0 +1,9 @@ +// ANCHOR: here +fn some_function(t: &T, u: &U) -> i32 +where + T: Display + Clone, + U: Clone + Debug, +{ + // ANCHOR_END: here + unimplemented!() +} diff --git a/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock b/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock index d37189b..8b8c69d 100755 --- a/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock +++ b/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "adder" version = "0.1.0" - diff --git a/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml b/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml index e61cb12..b7d36d4 100755 --- a/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml +++ b/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml @@ -3,4 +3,6 @@ name = "adder" version = "0.1.0" edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [dependencies] diff --git a/listings/ch11-writing-automated-tests/listing-11-01/output.txt b/listings/ch11-writing-automated-tests/listing-11-01/output.txt index c07ffd2..c3e812e 100755 --- a/listings/ch11-writing-automated-tests/listing-11-01/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-01/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.57s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 1 test test tests::it_works ... ok diff --git a/listings/ch11-writing-automated-tests/listing-11-01/src/lib.rs b/listings/ch11-writing-automated-tests/listing-11-01/src/lib.rs index 31e1bb2..1b4a90c 100755 --- a/listings/ch11-writing-automated-tests/listing-11-01/src/lib.rs +++ b/listings/ch11-writing-automated-tests/listing-11-01/src/lib.rs @@ -2,6 +2,7 @@ mod tests { #[test] fn it_works() { - assert_eq!(2 + 2, 4); + let result = 2 + 2; + assert_eq!(result, 4); } } diff --git a/listings/ch11-writing-automated-tests/listing-11-03/output.txt b/listings/ch11-writing-automated-tests/listing-11-03/output.txt index 9680e7c..2fa5cf0 100755 --- a/listings/ch11-writing-automated-tests/listing-11-03/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-03/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.72s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 2 tests test tests::another ... FAILED @@ -19,4 +19,4 @@ failures: test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/listing-11-06/output.txt b/listings/ch11-writing-automated-tests/listing-11-06/output.txt index 820c75b..dad02b4 100755 --- a/listings/ch11-writing-automated-tests/listing-11-06/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-06/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling rectangle v0.1.0 (file:///projects/rectangle) Finished test [unoptimized + debuginfo] target(s) in 0.66s - Running unittests (target/debug/deps/rectangle-6584c4561e48942e) + Running unittests src/lib.rs (target/debug/deps/rectangle-6584c4561e48942e) running 1 test test tests::larger_can_hold_smaller ... ok diff --git a/listings/ch11-writing-automated-tests/listing-11-07/output.txt b/listings/ch11-writing-automated-tests/listing-11-07/output.txt index aa30cdb..fa02835 100755 --- a/listings/ch11-writing-automated-tests/listing-11-07/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-07/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.58s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 1 test test tests::it_adds_two ... ok diff --git a/listings/ch11-writing-automated-tests/listing-11-08/output.txt b/listings/ch11-writing-automated-tests/listing-11-08/output.txt index 6c17acf..caca154 100755 --- a/listings/ch11-writing-automated-tests/listing-11-08/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-08/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Finished test [unoptimized + debuginfo] target(s) in 0.58s - Running unittests (target/debug/deps/guessing_game-57d70c3acb738f4d) + Running unittests src/lib.rs (target/debug/deps/guessing_game-57d70c3acb738f4d) running 1 test test tests::greater_than_100 - should panic ... ok diff --git a/listings/ch11-writing-automated-tests/listing-11-09/src/lib.rs b/listings/ch11-writing-automated-tests/listing-11-09/src/lib.rs index 475d4b9..cc1c5c3 100755 --- a/listings/ch11-writing-automated-tests/listing-11-09/src/lib.rs +++ b/listings/ch11-writing-automated-tests/listing-11-09/src/lib.rs @@ -4,6 +4,7 @@ pub struct Guess { // ANCHOR: here // --snip-- + impl Guess { pub fn new(value: i32) -> Guess { if value < 1 { @@ -27,7 +28,7 @@ mod tests { use super::*; #[test] - #[should_panic(expected = "Guess value must be less than or equal to 100")] + #[should_panic(expected = "less than or equal to 100")] fn greater_than_100() { Guess::new(200); } diff --git a/listings/ch11-writing-automated-tests/listing-11-10/output.txt b/listings/ch11-writing-automated-tests/listing-11-10/output.txt index ce98316..681cfbb 100755 --- a/listings/ch11-writing-automated-tests/listing-11-10/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-10/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling silly-function v0.1.0 (file:///projects/silly-function) Finished test [unoptimized + debuginfo] target(s) in 0.58s - Running unittests (target/debug/deps/silly_function-160869f38cff9166) + Running unittests src/lib.rs (target/debug/deps/silly_function-160869f38cff9166) running 2 tests test tests::this_test_will_fail ... FAILED @@ -22,4 +22,4 @@ failures: test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/listing-11-11/output.txt b/listings/ch11-writing-automated-tests/listing-11-11/output.txt index 9be5abe..fe19c83 100755 --- a/listings/ch11-writing-automated-tests/listing-11-11/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-11/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.62s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 3 tests test tests::add_three_and_two ... ok diff --git a/listings/ch11-writing-automated-tests/listing-11-13/output.txt b/listings/ch11-writing-automated-tests/listing-11-13/output.txt index 12e231c..22970e9 100755 --- a/listings/ch11-writing-automated-tests/listing-11-13/output.txt +++ b/listings/ch11-writing-automated-tests/listing-11-13/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 1.31s - Running unittests (target/debug/deps/adder-1082c4b063a8fbe6) + Running unittests src/lib.rs (target/debug/deps/adder-1082c4b063a8fbe6) running 1 test test tests::internal ... ok diff --git a/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/output.txt b/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/output.txt index 5de1386..8a33308 100755 --- a/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.59s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 1 test test tests::exploration ... ok diff --git a/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/output.txt b/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/output.txt index 29320be..30e45e5 100755 --- a/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling rectangle v0.1.0 (file:///projects/rectangle) Finished test [unoptimized + debuginfo] target(s) in 0.66s - Running unittests (target/debug/deps/rectangle-6584c4561e48942e) + Running unittests src/lib.rs (target/debug/deps/rectangle-6584c4561e48942e) running 2 tests test tests::larger_can_hold_smaller ... ok diff --git a/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt b/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt index 6629b53..7c62822 100755 --- a/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling rectangle v0.1.0 (file:///projects/rectangle) Finished test [unoptimized + debuginfo] target(s) in 0.66s - Running unittests (target/debug/deps/rectangle-6584c4561e48942e) + Running unittests src/lib.rs (target/debug/deps/rectangle-6584c4561e48942e) running 2 tests test tests::larger_can_hold_smaller ... FAILED @@ -19,4 +19,4 @@ failures: test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt b/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt index 2c0ffe8..28e2414 100755 --- a/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.61s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 1 test test tests::it_adds_two ... FAILED @@ -20,4 +20,4 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt b/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt index d54451f..3366e3a 100755 --- a/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling greeter v0.1.0 (file:///projects/greeter) Finished test [unoptimized + debuginfo] target(s) in 0.91s - Running unittests (target/debug/deps/greeter-170b942eb5bf5e3a) + Running unittests src/lib.rs (target/debug/deps/greeter-170b942eb5bf5e3a) running 1 test test tests::greeting_contains_name ... FAILED @@ -18,4 +18,4 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt b/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt index 2ecf804..cebebda 100755 --- a/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling greeter v0.1.0 (file:///projects/greeter) Finished test [unoptimized + debuginfo] target(s) in 0.93s - Running unittests (target/debug/deps/greeter-170b942eb5bf5e3a) + Running unittests src/lib.rs (target/debug/deps/greeter-170b942eb5bf5e3a) running 1 test test tests::greeting_contains_name ... FAILED @@ -18,4 +18,4 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/output.txt b/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/output.txt index 9d64476..9318d4c 100755 --- a/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Finished test [unoptimized + debuginfo] target(s) in 0.62s - Running unittests (target/debug/deps/guessing_game-57d70c3acb738f4d) + Running unittests src/lib.rs (target/debug/deps/guessing_game-57d70c3acb738f4d) running 1 test test tests::greater_than_100 - should panic ... FAILED @@ -16,4 +16,4 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt b/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt index ca13feb..c176e88 100755 --- a/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Finished test [unoptimized + debuginfo] target(s) in 0.66s - Running unittests (target/debug/deps/guessing_game-57d70c3acb738f4d) + Running unittests src/lib.rs (target/debug/deps/guessing_game-57d70c3acb738f4d) running 1 test test tests::greater_than_100 - should panic ... FAILED @@ -13,11 +13,11 @@ thread 'main' panicked at 'Guess value must be greater than or equal to 1, got 2 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: panic did not contain expected string panic message: `"Guess value must be greater than or equal to 1, got 200."`, - expected substring: `"Guess value must be less than or equal to 100"` + expected substring: `"less than or equal to 100"` failures: tests::greater_than_100 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/src/lib.rs b/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/src/lib.rs index 2165004..7703dd7 100755 --- a/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/src/lib.rs +++ b/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/src/lib.rs @@ -27,7 +27,7 @@ mod tests { use super::*; #[test] - #[should_panic(expected = "Guess value must be less than or equal to 100")] + #[should_panic(expected = "less than or equal to 100")] fn greater_than_100() { Guess::new(200); } diff --git a/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt b/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt index fcdff25..c559de8 100755 --- a/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.60s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 2 tests test expensive_test ... ignored diff --git a/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/output.txt b/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/output.txt index 0afdb52..324d566 100755 --- a/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/output.txt +++ b/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.89s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 1 test test tests::internal ... ok diff --git a/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt b/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt index 94b0b4b..4ececf2 100755 --- a/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt +++ b/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt @@ -1,7 +1,7 @@ $ cargo test -- --show-output Compiling silly-function v0.1.0 (file:///projects/silly-function) Finished test [unoptimized + debuginfo] target(s) in 0.60s - Running unittests (target/debug/deps/silly_function-160869f38cff9166) + Running unittests src/lib.rs (target/debug/deps/silly_function-160869f38cff9166) running 2 tests test tests::this_test_will_fail ... FAILED @@ -31,4 +31,4 @@ failures: test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch11-writing-automated-tests/output-only-02-single-test/output.txt b/listings/ch11-writing-automated-tests/output-only-02-single-test/output.txt index e5e9ffd..f2da984 100755 --- a/listings/ch11-writing-automated-tests/output-only-02-single-test/output.txt +++ b/listings/ch11-writing-automated-tests/output-only-02-single-test/output.txt @@ -1,7 +1,7 @@ $ cargo test one_hundred Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.69s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 1 test test tests::one_hundred ... ok diff --git a/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/output.txt b/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/output.txt index 822cbb5..255a051 100755 --- a/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/output.txt +++ b/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/output.txt @@ -1,7 +1,7 @@ $ cargo test add Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.61s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 2 tests test tests::add_three_and_two ... ok diff --git a/listings/ch11-writing-automated-tests/output-only-04-running-ignored/output.txt b/listings/ch11-writing-automated-tests/output-only-04-running-ignored/output.txt index 009ac4a..b37868d 100755 --- a/listings/ch11-writing-automated-tests/output-only-04-running-ignored/output.txt +++ b/listings/ch11-writing-automated-tests/output-only-04-running-ignored/output.txt @@ -1,7 +1,7 @@ $ cargo test -- --ignored Compiling adder v0.1.0 (file:///projects/adder) Finished test [unoptimized + debuginfo] target(s) in 0.61s - Running unittests (target/debug/deps/adder-92948b65e88960b4) + Running unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4) running 1 test test expensive_test ... ok diff --git a/listings/ch12-an-io-project/listing-12-01/output.txt b/listings/ch12-an-io-project/listing-12-01/output.txt index d0ef998..529115f 100755 --- a/listings/ch12-an-io-project/listing-12-01/output.txt +++ b/listings/ch12-an-io-project/listing-12-01/output.txt @@ -2,4 +2,6 @@ $ cargo run Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.61s Running `target/debug/minigrep` -["target/debug/minigrep"] +[src/main.rs:5] args = [ + "target/debug/minigrep", +] diff --git a/listings/ch12-an-io-project/listing-12-01/src/main.rs b/listings/ch12-an-io-project/listing-12-01/src/main.rs index aa3056d..ae7def5 100755 --- a/listings/ch12-an-io-project/listing-12-01/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-01/src/main.rs @@ -2,5 +2,5 @@ use std::env; fn main() { let args: Vec = env::args().collect(); - println!("{:?}", args); + dbg!(args); } diff --git a/listings/ch12-an-io-project/listing-12-02/output.txt b/listings/ch12-an-io-project/listing-12-02/output.txt index f759eea..6ef87f7 100755 --- a/listings/ch12-an-io-project/listing-12-02/output.txt +++ b/listings/ch12-an-io-project/listing-12-02/output.txt @@ -1,4 +1,4 @@ -$ cargo run test sample.txt +$ cargo run -- test sample.txt Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.0s Running `target/debug/minigrep test sample.txt` diff --git a/listings/ch12-an-io-project/listing-12-02/src/main.rs b/listings/ch12-an-io-project/listing-12-02/src/main.rs index 8daf125..ae2fa7b 100755 --- a/listings/ch12-an-io-project/listing-12-02/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-02/src/main.rs @@ -4,8 +4,8 @@ fn main() { let args: Vec = env::args().collect(); let query = &args[1]; - let filename = &args[2]; + let file_path = &args[2]; println!("Searching for {}", query); - println!("In file {}", filename); + println!("In file {}", file_path); } diff --git a/listings/ch12-an-io-project/listing-12-03/src/main.rs b/listings/ch12-an-io-project/listing-12-03/src/main.rs index 8daf125..ae2fa7b 100755 --- a/listings/ch12-an-io-project/listing-12-03/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-03/src/main.rs @@ -4,8 +4,8 @@ fn main() { let args: Vec = env::args().collect(); let query = &args[1]; - let filename = &args[2]; + let file_path = &args[2]; println!("Searching for {}", query); - println!("In file {}", filename); + println!("In file {}", file_path); } diff --git a/listings/ch12-an-io-project/listing-12-04/output.txt b/listings/ch12-an-io-project/listing-12-04/output.txt index 5f31c8c..6582ca1 100755 --- a/listings/ch12-an-io-project/listing-12-04/output.txt +++ b/listings/ch12-an-io-project/listing-12-04/output.txt @@ -1,4 +1,4 @@ -$ cargo run the poem.txt +$ cargo run -- the poem.txt Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.0s Running `target/debug/minigrep the poem.txt` diff --git a/listings/ch12-an-io-project/listing-12-04/src/main.rs b/listings/ch12-an-io-project/listing-12-04/src/main.rs index 9a0eade..944e430 100755 --- a/listings/ch12-an-io-project/listing-12-04/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-04/src/main.rs @@ -8,15 +8,15 @@ fn main() { let args: Vec = env::args().collect(); let query = &args[1]; - let filename = &args[2]; + let file_path = &args[2]; println!("Searching for {}", query); // ANCHOR: here - println!("In file {}", filename); + println!("In file {}", file_path); - let contents = fs::read_to_string(filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(file_path) + .expect("Should have been able to read the file"); - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); } // ANCHOR_END: here diff --git a/listings/ch12-an-io-project/listing-12-05/src/main.rs b/listings/ch12-an-io-project/listing-12-05/src/main.rs index fb88056..0615918 100755 --- a/listings/ch12-an-io-project/listing-12-05/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-05/src/main.rs @@ -5,25 +5,25 @@ use std::fs; fn main() { let args: Vec = env::args().collect(); - let (query, filename) = parse_config(&args); + let (query, file_path) = parse_config(&args); // --snip-- // ANCHOR_END: here println!("Searching for {}", query); - println!("In file {}", filename); + println!("In file {}", file_path); - let contents = fs::read_to_string(filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(file_path) + .expect("Should have been able to read the file"); - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); // ANCHOR: here } fn parse_config(args: &[String]) -> (&str, &str) { let query = &args[1]; - let filename = &args[2]; + let file_path = &args[2]; - (query, filename) + (query, file_path) } // ANCHOR_END: here diff --git a/listings/ch12-an-io-project/listing-12-06/src/main.rs b/listings/ch12-an-io-project/listing-12-06/src/main.rs index b5d89bc..c77e848 100755 --- a/listings/ch12-an-io-project/listing-12-06/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-06/src/main.rs @@ -8,27 +8,27 @@ fn main() { let config = parse_config(&args); println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); - let contents = fs::read_to_string(config.filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(config.file_path) + .expect("Should have been able to read the file"); // --snip-- // ANCHOR_END: here - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); // ANCHOR: here } struct Config { query: String, - filename: String, + file_path: String, } fn parse_config(args: &[String]) -> Config { let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Config { query, filename } + Config { query, file_path } } // ANCHOR_END: here diff --git a/listings/ch12-an-io-project/listing-12-07/src/main.rs b/listings/ch12-an-io-project/listing-12-07/src/main.rs index 36d35ce..ff6c294 100755 --- a/listings/ch12-an-io-project/listing-12-07/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-07/src/main.rs @@ -9,12 +9,12 @@ fn main() { // ANCHOR_END: here println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); - let contents = fs::read_to_string(config.filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(config.file_path) + .expect("Should have been able to read the file"); - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); // ANCHOR: here // --snip-- @@ -25,16 +25,16 @@ fn main() { // ANCHOR_END: here struct Config { query: String, - filename: String, + file_path: String, } // ANCHOR: here impl Config { fn new(args: &[String]) -> Config { let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Config { query, filename } + Config { query, file_path } } } // ANCHOR_END: here diff --git a/listings/ch12-an-io-project/listing-12-08/src/main.rs b/listings/ch12-an-io-project/listing-12-08/src/main.rs index dddf10b..cecd15a 100755 --- a/listings/ch12-an-io-project/listing-12-08/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-08/src/main.rs @@ -7,17 +7,17 @@ fn main() { let config = Config::new(&args); println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); - let contents = fs::read_to_string(config.filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(config.file_path) + .expect("Should have been able to read the file"); - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); } struct Config { query: String, - filename: String, + file_path: String, } impl Config { @@ -31,8 +31,8 @@ impl Config { // ANCHOR_END: here let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Config { query, filename } + Config { query, file_path } } } diff --git a/listings/ch12-an-io-project/listing-12-09/src/main.rs b/listings/ch12-an-io-project/listing-12-09/src/main.rs index 83f46ee..3418e71 100755 --- a/listings/ch12-an-io-project/listing-12-09/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-09/src/main.rs @@ -7,30 +7,30 @@ fn main() { let config = Config::new(&args); println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); - let contents = fs::read_to_string(config.filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(config.file_path) + .expect("Should have been able to read the file"); - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); } struct Config { query: String, - filename: String, + file_path: String, } // ANCHOR: here impl Config { - fn new(args: &[String]) -> Result { + fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } // ANCHOR_END: here diff --git a/listings/ch12-an-io-project/listing-12-10/src/main.rs b/listings/ch12-an-io-project/listing-12-10/src/main.rs index c8aeb1d..ab6d3e5 100755 --- a/listings/ch12-an-io-project/listing-12-10/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-10/src/main.rs @@ -6,8 +6,8 @@ use std::process; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); @@ -15,28 +15,28 @@ fn main() { // ANCHOR_END: here println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); - let contents = fs::read_to_string(config.filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(config.file_path) + .expect("Should have been able to read the file"); - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); } struct Config { query: String, - filename: String, + file_path: String, } impl Config { - fn new(args: &[String]) -> Result { + fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } diff --git a/listings/ch12-an-io-project/listing-12-11/src/main.rs b/listings/ch12-an-io-project/listing-12-11/src/main.rs index 974b503..3f476b9 100755 --- a/listings/ch12-an-io-project/listing-12-11/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-11/src/main.rs @@ -9,23 +9,23 @@ fn main() { // ANCHOR_END: here let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); // ANCHOR: here println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); run(config); } fn run(config: Config) { - let contents = fs::read_to_string(config.filename) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(config.file_path) + .expect("Should have been able to read the file"); - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); } // --snip-- @@ -33,18 +33,18 @@ fn run(config: Config) { struct Config { query: String, - filename: String, + file_path: String, } impl Config { - fn new(args: &[String]) -> Result { + fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } diff --git a/listings/ch12-an-io-project/listing-12-12/src/main.rs b/listings/ch12-an-io-project/listing-12-12/src/main.rs index f2e0e6b..ab5fdb8 100755 --- a/listings/ch12-an-io-project/listing-12-12/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-12/src/main.rs @@ -11,22 +11,22 @@ use std::error::Error; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); run(config); } // ANCHOR: here fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); Ok(()) } @@ -34,18 +34,18 @@ fn run(config: Config) -> Result<(), Box> { struct Config { query: String, - filename: String, + file_path: String, } impl Config { - fn new(args: &[String]) -> Result { + fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } diff --git a/listings/ch12-an-io-project/listing-12-13/src/lib.rs b/listings/ch12-an-io-project/listing-12-13/src/lib.rs index 5b2850a..1a3c480 100755 --- a/listings/ch12-an-io-project/listing-12-13/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-13/src/lib.rs @@ -4,11 +4,11 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { // --snip-- // ANCHOR_END: here if args.len() < 3 { @@ -16,9 +16,9 @@ impl Config { } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) // ANCHOR: here } } @@ -26,9 +26,9 @@ impl Config { pub fn run(config: Config) -> Result<(), Box> { // --snip-- // ANCHOR_END: here - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); Ok(()) // ANCHOR: here diff --git a/listings/ch12-an-io-project/listing-12-13/src/main.rs b/listings/ch12-an-io-project/listing-12-13/src/main.rs index b2447dc..09756ca 100755 --- a/listings/ch12-an-io-project/listing-12-13/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-13/src/main.rs @@ -4,17 +4,16 @@ use std::process; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); if let Err(e) = run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-14/src/lib.rs b/listings/ch12-an-io-project/listing-12-14/src/lib.rs index 2ba2fd1..4f3a4e8 100755 --- a/listings/ch12-an-io-project/listing-12-14/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-14/src/lib.rs @@ -3,26 +3,26 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); Ok(()) } diff --git a/listings/ch12-an-io-project/listing-12-14/src/main.rs b/listings/ch12-an-io-project/listing-12-14/src/main.rs index 5eb4024..3b76009 100755 --- a/listings/ch12-an-io-project/listing-12-14/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-14/src/main.rs @@ -9,20 +9,19 @@ fn main() { // ANCHOR_END: here let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); // ANCHOR: here if let Err(e) = minigrep::run(config) { // --snip-- // ANCHOR_END: here - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); // ANCHOR: here } diff --git a/listings/ch12-an-io-project/listing-12-15/src/lib.rs b/listings/ch12-an-io-project/listing-12-15/src/lib.rs index c677188..20c4a78 100755 --- a/listings/ch12-an-io-project/listing-12-15/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-15/src/lib.rs @@ -3,24 +3,24 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; Ok(()) } diff --git a/listings/ch12-an-io-project/listing-12-15/src/main.rs b/listings/ch12-an-io-project/listing-12-15/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-15/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-15/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-16/output.txt b/listings/ch12-an-io-project/listing-12-16/output.txt index 63ea400..3c34e39 100755 --- a/listings/ch12-an-io-project/listing-12-16/output.txt +++ b/listings/ch12-an-io-project/listing-12-16/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished test [unoptimized + debuginfo] target(s) in 0.97s - Running unittests (target/debug/deps/minigrep-9cd200e5fac0fc94) + Running unittests src/lib.rs (target/debug/deps/minigrep-9cd200e5fac0fc94) running 1 test test tests::one_result ... FAILED @@ -20,4 +20,4 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch12-an-io-project/listing-12-16/src/lib.rs b/listings/ch12-an-io-project/listing-12-16/src/lib.rs index 8729c32..f5e5934 100755 --- a/listings/ch12-an-io-project/listing-12-16/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-16/src/lib.rs @@ -3,24 +3,24 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; Ok(()) } diff --git a/listings/ch12-an-io-project/listing-12-16/src/main.rs b/listings/ch12-an-io-project/listing-12-16/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-16/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-16/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-17/src/lib.rs b/listings/ch12-an-io-project/listing-12-17/src/lib.rs index 5c467f6..cb9fab4 100755 --- a/listings/ch12-an-io-project/listing-12-17/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-17/src/lib.rs @@ -3,24 +3,24 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; Ok(()) } @@ -28,7 +28,7 @@ pub fn run(config: Config) -> Result<(), Box> { // ANCHOR: here pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { for line in contents.lines() { - // 对文本行进行操作 + // do something with line } } // ANCHOR_END: here diff --git a/listings/ch12-an-io-project/listing-12-17/src/main.rs b/listings/ch12-an-io-project/listing-12-17/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-17/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-17/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-18/src/lib.rs b/listings/ch12-an-io-project/listing-12-18/src/lib.rs index 7dd7c91..8fc09d3 100755 --- a/listings/ch12-an-io-project/listing-12-18/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-18/src/lib.rs @@ -3,24 +3,24 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; Ok(()) } diff --git a/listings/ch12-an-io-project/listing-12-18/src/main.rs b/listings/ch12-an-io-project/listing-12-18/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-18/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-18/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-19/output.txt b/listings/ch12-an-io-project/listing-12-19/output.txt index 176d1b9..9b2078c 100755 --- a/listings/ch12-an-io-project/listing-12-19/output.txt +++ b/listings/ch12-an-io-project/listing-12-19/output.txt @@ -1,14 +1,14 @@ $ cargo test Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished test [unoptimized + debuginfo] target(s) in 1.22s - Running unittests (target/debug/deps/minigrep-9cd200e5fac0fc94) + Running unittests src/lib.rs (target/debug/deps/minigrep-9cd200e5fac0fc94) running 1 test test tests::one_result ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s - Running unittests (target/debug/deps/minigrep-9cd200e5fac0fc94) + Running unittests src/main.rs (target/debug/deps/minigrep-9cd200e5fac0fc94) running 0 tests diff --git a/listings/ch12-an-io-project/listing-12-19/src/lib.rs b/listings/ch12-an-io-project/listing-12-19/src/lib.rs index de8897b..f5d3ffa 100755 --- a/listings/ch12-an-io-project/listing-12-19/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-19/src/lib.rs @@ -3,24 +3,24 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; Ok(()) } diff --git a/listings/ch12-an-io-project/listing-12-19/src/main.rs b/listings/ch12-an-io-project/listing-12-19/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-19/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-19/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-20/src/lib.rs b/listings/ch12-an-io-project/listing-12-20/src/lib.rs index 542d088..a757f7f 100755 --- a/listings/ch12-an-io-project/listing-12-20/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-20/src/lib.rs @@ -3,27 +3,27 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; for line in search(&config.query, &contents) { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/listing-12-20/src/main.rs b/listings/ch12-an-io-project/listing-12-20/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-20/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-20/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-21/output.txt b/listings/ch12-an-io-project/listing-12-21/output.txt index 97ae4a4..dafeb78 100755 --- a/listings/ch12-an-io-project/listing-12-21/output.txt +++ b/listings/ch12-an-io-project/listing-12-21/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished test [unoptimized + debuginfo] target(s) in 1.33s - Running unittests (target/debug/deps/minigrep-9cd200e5fac0fc94) + Running unittests src/lib.rs (target/debug/deps/minigrep-9cd200e5fac0fc94) running 2 tests test tests::case_insensitive ... ok @@ -9,7 +9,7 @@ test tests::case_sensitive ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s - Running unittests (target/debug/deps/minigrep-9cd200e5fac0fc94) + Running unittests src/main.rs (target/debug/deps/minigrep-9cd200e5fac0fc94) running 0 tests diff --git a/listings/ch12-an-io-project/listing-12-21/src/lib.rs b/listings/ch12-an-io-project/listing-12-21/src/lib.rs index 10f6dea..3aaa040 100755 --- a/listings/ch12-an-io-project/listing-12-21/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-21/src/lib.rs @@ -3,27 +3,27 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; for line in search(&config.query, &contents) { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/listing-12-21/src/main.rs b/listings/ch12-an-io-project/listing-12-21/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-21/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-21/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-22/src/lib.rs b/listings/ch12-an-io-project/listing-12-22/src/lib.rs index 3402a27..c3f4723 100755 --- a/listings/ch12-an-io-project/listing-12-22/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-22/src/lib.rs @@ -4,36 +4,36 @@ use std::fs; // ANCHOR: here pub struct Config { pub query: String, - pub filename: String, - pub case_sensitive: bool, + pub file_path: String, + pub ignore_case: bool, } // ANCHOR_END: here impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } // ANCHOR: there pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - let results = if config.case_sensitive { - search(&config.query, &contents) - } else { + let results = if config.ignore_case { search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) }; for line in results { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/listing-12-22/src/main.rs b/listings/ch12-an-io-project/listing-12-22/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-22/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-22/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-23/output.txt b/listings/ch12-an-io-project/listing-12-23/output.txt index 0f0f07f..eaffc2f 100755 --- a/listings/ch12-an-io-project/listing-12-23/output.txt +++ b/listings/ch12-an-io-project/listing-12-23/output.txt @@ -1,4 +1,4 @@ -$ cargo run to poem.txt +$ cargo run -- to poem.txt Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.0s Running `target/debug/minigrep to poem.txt` diff --git a/listings/ch12-an-io-project/listing-12-23/src/lib.rs b/listings/ch12-an-io-project/listing-12-23/src/lib.rs index fa63a8c..20eda21 100755 --- a/listings/ch12-an-io-project/listing-12-23/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-23/src/lib.rs @@ -8,42 +8,42 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, - pub case_sensitive: bool, + pub file_path: String, + pub ignore_case: bool, } // ANCHOR: here impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); + let ignore_case = env::var("IGNORE_CASE").is_ok(); Ok(Config { query, - filename, - case_sensitive, + file_path, + ignore_case, }) } } // ANCHOR_END: here pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - let results = if config.case_sensitive { - search(&config.query, &contents) - } else { + let results = if config.ignore_case { search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) }; for line in results { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/listing-12-23/src/main.rs b/listings/ch12-an-io-project/listing-12-23/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/listing-12-23/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-23/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/listing-12-24/src/lib.rs b/listings/ch12-an-io-project/listing-12-24/src/lib.rs index fe1dccf..292b097 100755 --- a/listings/ch12-an-io-project/listing-12-24/src/lib.rs +++ b/listings/ch12-an-io-project/listing-12-24/src/lib.rs @@ -4,40 +4,40 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, - pub case_sensitive: bool, + pub file_path: String, + pub ignore_case: bool, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); + let ignore_case = env::var("IGNORE_CASE").is_ok(); Ok(Config { query, - filename, - case_sensitive, + file_path, + ignore_case, }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - let results = if config.case_sensitive { - search(&config.query, &contents) - } else { + let results = if config.ignore_case { search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) }; for line in results { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/listing-12-24/src/main.rs b/listings/ch12-an-io-project/listing-12-24/src/main.rs index 9e38553..1278a6c 100755 --- a/listings/ch12-an-io-project/listing-12-24/src/main.rs +++ b/listings/ch12-an-io-project/listing-12-24/src/main.rs @@ -7,14 +7,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - eprintln!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - eprintln!("Application error: {}", e); - + eprintln!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs b/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs index 44bcfea..e51319e 100755 --- a/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs +++ b/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs @@ -10,45 +10,44 @@ fn main() { // ANCHOR_END: here let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); // ANCHOR: here println!("Searching for {}", config.query); - println!("In file {}", config.filename); + println!("In file {}", config.file_path); if let Err(e) = run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } // ANCHOR_END: here fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - println!("With text:\n{}", contents); + println!("With text:\n{contents}"); Ok(()) } struct Config { query: String, - filename: String, + file_path: String, } impl Config { - fn new(args: &[String]) -> Result { + fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } diff --git a/listings/ch12-an-io-project/no-listing-02-using-search-in-run/output.txt b/listings/ch12-an-io-project/no-listing-02-using-search-in-run/output.txt index 91532d0..a5a4ef8 100755 --- a/listings/ch12-an-io-project/no-listing-02-using-search-in-run/output.txt +++ b/listings/ch12-an-io-project/no-listing-02-using-search-in-run/output.txt @@ -1,4 +1,4 @@ -$ cargo run frog poem.txt +$ cargo run -- frog poem.txt Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.38s Running `target/debug/minigrep frog poem.txt` diff --git a/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs b/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs index ede4eb4..e06eae4 100755 --- a/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs +++ b/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs @@ -3,28 +3,28 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } // ANCHOR: here pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; for line in search(&config.query, &contents) { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/main.rs b/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/main.rs +++ b/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/output-only-01-with-args/output.txt b/listings/ch12-an-io-project/output-only-01-with-args/output.txt index eb88d9a..b48bb0e 100755 --- a/listings/ch12-an-io-project/output-only-01-with-args/output.txt +++ b/listings/ch12-an-io-project/output-only-01-with-args/output.txt @@ -1,5 +1,9 @@ -$ cargo run needle haystack +$ cargo run -- needle haystack Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 1.57s Running `target/debug/minigrep needle haystack` -["target/debug/minigrep", "needle", "haystack"] +[src/main.rs:5] args = [ + "target/debug/minigrep", + "needle", + "haystack", +] diff --git a/listings/ch12-an-io-project/output-only-01-with-args/src/main.rs b/listings/ch12-an-io-project/output-only-01-with-args/src/main.rs index aa3056d..ae7def5 100755 --- a/listings/ch12-an-io-project/output-only-01-with-args/src/main.rs +++ b/listings/ch12-an-io-project/output-only-01-with-args/src/main.rs @@ -2,5 +2,5 @@ use std::env; fn main() { let args: Vec = env::args().collect(); - println!("{:?}", args); + dbg!(args); } diff --git a/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs b/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs index 65af968..df623bd 100755 --- a/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs +++ b/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs @@ -3,24 +3,24 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; Ok(()) } diff --git a/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/main.rs b/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/main.rs +++ b/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/output-only-03-multiple-matches/output.txt b/listings/ch12-an-io-project/output-only-03-multiple-matches/output.txt index 2b19bf9..b468357 100755 --- a/listings/ch12-an-io-project/output-only-03-multiple-matches/output.txt +++ b/listings/ch12-an-io-project/output-only-03-multiple-matches/output.txt @@ -1,4 +1,4 @@ -$ cargo run body poem.txt +$ cargo run -- body poem.txt Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.0s Running `target/debug/minigrep body poem.txt` diff --git a/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs b/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs index ede4eb4..e06eae4 100755 --- a/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs +++ b/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs @@ -3,28 +3,28 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } // ANCHOR: here pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; for line in search(&config.query, &contents) { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/output-only-03-multiple-matches/src/main.rs b/listings/ch12-an-io-project/output-only-03-multiple-matches/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/output-only-03-multiple-matches/src/main.rs +++ b/listings/ch12-an-io-project/output-only-03-multiple-matches/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch12-an-io-project/output-only-04-no-matches/output.txt b/listings/ch12-an-io-project/output-only-04-no-matches/output.txt index 4cd6c8a..a53624f 100755 --- a/listings/ch12-an-io-project/output-only-04-no-matches/output.txt +++ b/listings/ch12-an-io-project/output-only-04-no-matches/output.txt @@ -1,4 +1,4 @@ -$ cargo run monomorphization poem.txt +$ cargo run -- monomorphization poem.txt Compiling minigrep v0.1.0 (file:///projects/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.0s Running `target/debug/minigrep monomorphization poem.txt` diff --git a/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs b/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs index ede4eb4..e06eae4 100755 --- a/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs +++ b/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs @@ -3,28 +3,28 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, + pub file_path: String, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - Ok(Config { query, filename }) + Ok(Config { query, file_path }) } } // ANCHOR: here pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; for line in search(&config.query, &contents) { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch12-an-io-project/output-only-04-no-matches/src/main.rs b/listings/ch12-an-io-project/output-only-04-no-matches/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch12-an-io-project/output-only-04-no-matches/src/main.rs +++ b/listings/ch12-an-io-project/output-only-04-no-matches/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs b/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs index 7f0178d..e54343d 100755 --- a/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs +++ b/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs @@ -4,42 +4,42 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, - pub case_sensitive: bool, + pub file_path: String, + pub ignore_case: bool, } // ANCHOR: ch13 impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); + let ignore_case = env::var("IGNORE_CASE").is_ok(); Ok(Config { query, - filename, - case_sensitive, + file_path, + ignore_case, }) } } // ANCHOR_END: ch13 pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - let results = if config.case_sensitive { - search(&config.query, &contents) - } else { + let results = if config.ignore_case { search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) }; for line in results { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch13-functional-features/listing-12-23-reproduced/src/main.rs b/listings/ch13-functional-features/listing-12-23-reproduced/src/main.rs index 53af83f..a4f8a74 100755 --- a/listings/ch13-functional-features/listing-12-23-reproduced/src/main.rs +++ b/listings/ch13-functional-features/listing-12-23-reproduced/src/main.rs @@ -6,14 +6,13 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - println!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + println!("Problem parsing arguments: {err}"); process::exit(1); }); if let Err(e) = minigrep::run(config) { - println!("Application error: {}", e); - + println!("Application error: {e}"); process::exit(1); } } diff --git a/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs b/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs index fe1dccf..292b097 100755 --- a/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs +++ b/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs @@ -4,40 +4,40 @@ use std::fs; pub struct Config { pub query: String, - pub filename: String, - pub case_sensitive: bool, + pub file_path: String, + pub ignore_case: bool, } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn build(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } let query = args[1].clone(); - let filename = args[2].clone(); + let file_path = args[2].clone(); - let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); + let ignore_case = env::var("IGNORE_CASE").is_ok(); Ok(Config { query, - filename, - case_sensitive, + file_path, + ignore_case, }) } } pub fn run(config: Config) -> Result<(), Box> { - let contents = fs::read_to_string(config.filename)?; + let contents = fs::read_to_string(config.file_path)?; - let results = if config.case_sensitive { - search(&config.query, &contents) - } else { + let results = if config.ignore_case { search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) }; for line in results { - println!("{}", line); + println!("{line}"); } Ok(()) diff --git a/listings/ch13-functional-features/listing-12-24-reproduced/src/main.rs b/listings/ch13-functional-features/listing-12-24-reproduced/src/main.rs index ec27e67..f9d179c 100755 --- a/listings/ch13-functional-features/listing-12-24-reproduced/src/main.rs +++ b/listings/ch13-functional-features/listing-12-24-reproduced/src/main.rs @@ -7,8 +7,8 @@ use minigrep::Config; fn main() { let args: Vec = env::args().collect(); - let config = Config::new(&args).unwrap_or_else(|err| { - eprintln!("Problem parsing arguments: {}", err); + let config = Config::build(&args).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {err}"); process::exit(1); }); @@ -16,8 +16,7 @@ fn main() { // ANCHOR_END: ch13 if let Err(e) = minigrep::run(config) { - eprintln!("Application error: {}", e); - + eprintln!("Application error: {e}"); process::exit(1); } // ANCHOR: ch13 diff --git a/listings/ch13-functional-features/listing-13-01/Cargo.lock b/listings/ch13-functional-features/listing-13-01/Cargo.lock index 75ff09e..6f974d1 100755 --- a/listings/ch13-functional-features/listing-13-01/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-01/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "workout-app" +name = "shirt-company" version = "0.1.0" - diff --git a/listings/ch13-functional-features/listing-13-01/Cargo.toml b/listings/ch13-functional-features/listing-13-01/Cargo.toml index f09a737..1eb392d 100755 --- a/listings/ch13-functional-features/listing-13-01/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-01/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "workout-app" +name = "shirt-company" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-01/output.txt b/listings/ch13-functional-features/listing-13-01/output.txt new file mode 100755 index 0000000..b64a4d8 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-01/output.txt @@ -0,0 +1,6 @@ +$ cargo run + Compiling shirt-company v0.1.0 (file:///projects/shirt-company) + Finished dev [unoptimized + debuginfo] target(s) in 0.27s + Running `target/debug/shirt-company` +The user with preference Some(Red) gets Red +The user with preference None gets Blue diff --git a/listings/ch13-functional-features/listing-13-01/src/main.rs b/listings/ch13-functional-features/listing-13-01/src/main.rs index 97eace0..2c87d69 100755 --- a/listings/ch13-functional-features/listing-13-01/src/main.rs +++ b/listings/ch13-functional-features/listing-13-01/src/main.rs @@ -1,12 +1,52 @@ -// ANCHOR: here -use std::thread; -use std::time::Duration; +#[derive(Debug, PartialEq, Copy, Clone)] +enum ShirtColor { + Red, + Blue, +} + +struct Inventory { + shirts: Vec, +} + +impl Inventory { + fn giveaway(&self, user_preference: Option) -> ShirtColor { + user_preference.unwrap_or_else(|| self.most_stocked()) + } -fn simulated_expensive_calculation(intensity: u32) -> u32 { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - intensity + fn most_stocked(&self) -> ShirtColor { + let mut num_red = 0; + let mut num_blue = 0; + + for color in &self.shirts { + match color { + ShirtColor::Red => num_red += 1, + ShirtColor::Blue => num_blue += 1, + } + } + if num_red > num_blue { + ShirtColor::Red + } else { + ShirtColor::Blue + } + } } -// ANCHOR_END: here -fn main() {} +fn main() { + let store = Inventory { + shirts: vec![ShirtColor::Blue, ShirtColor::Red, ShirtColor::Blue], + }; + + let user_pref1 = Some(ShirtColor::Red); + let giveaway1 = store.giveaway(user_pref1); + println!( + "The user with preference {:?} gets {:?}", + user_pref1, giveaway1 + ); + + let user_pref2 = None; + let giveaway2 = store.giveaway(user_pref2); + println!( + "The user with preference {:?} gets {:?}", + user_pref2, giveaway2 + ); +} diff --git a/listings/ch13-functional-features/listing-13-02/src/main.rs b/listings/ch13-functional-features/listing-13-02/src/main.rs index 96d06c7..b3f4cc2 100755 --- a/listings/ch13-functional-features/listing-13-02/src/main.rs +++ b/listings/ch13-functional-features/listing-13-02/src/main.rs @@ -1,19 +1,33 @@ use std::thread; use std::time::Duration; -fn simulated_expensive_calculation(intensity: u32) -> u32 { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - intensity -} +fn generate_workout(intensity: u32, random_number: u32) { + // ANCHOR: here + let expensive_closure = |num: u32| -> u32 { + println!("calculating slowly..."); + thread::sleep(Duration::from_secs(2)); + num + }; + // ANCHOR_END: here -fn generate_workout(intensity: u32, random_number: u32) {} + if intensity < 25 { + println!("Today, do {} pushups!", expensive_closure(intensity)); + println!("Next, do {} situps!", expensive_closure(intensity)); + } else { + if random_number == 3 { + println!("Take a break today! Remember to stay hydrated!"); + } else { + println!( + "Today, run for {} minutes!", + expensive_closure(intensity) + ); + } + } +} -// ANCHOR: here fn main() { let simulated_user_specified_value = 10; let simulated_random_number = 7; generate_workout(simulated_user_specified_value, simulated_random_number); } -// ANCHOR_END: here diff --git a/listings/ch13-functional-features/listing-13-03/Cargo.lock b/listings/ch13-functional-features/listing-13-03/Cargo.lock index 75ff09e..c190d3a 100755 --- a/listings/ch13-functional-features/listing-13-03/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-03/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "workout-app" +name = "closure-example" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-03/Cargo.toml b/listings/ch13-functional-features/listing-13-03/Cargo.toml index f09a737..914c4cf 100755 --- a/listings/ch13-functional-features/listing-13-03/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-03/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "workout-app" +name = "closure-example" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-03/output.txt b/listings/ch13-functional-features/listing-13-03/output.txt new file mode 100755 index 0000000..68838de --- /dev/null +++ b/listings/ch13-functional-features/listing-13-03/output.txt @@ -0,0 +1,19 @@ +$ cargo run + Compiling closure-example v0.1.0 (file:///projects/closure-example) +error[E0308]: mismatched types + --> src/main.rs:5:29 + | +5 | let n = example_closure(5); + | --------------- ^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found integer + | arguments to this function are incorrect + | +note: closure parameter defined here + --> src/main.rs:2:28 + | +2 | let example_closure = |x| x; + | ^ + +For more information about this error, try `rustc --explain E0308`. +error: could not compile `closure-example` due to previous error diff --git a/listings/ch13-functional-features/listing-13-03/src/main.rs b/listings/ch13-functional-features/listing-13-03/src/main.rs index d43c9b2..ebb2489 100755 --- a/listings/ch13-functional-features/listing-13-03/src/main.rs +++ b/listings/ch13-functional-features/listing-13-03/src/main.rs @@ -1,39 +1,8 @@ -use std::thread; -use std::time::Duration; - -fn simulated_expensive_calculation(intensity: u32) -> u32 { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - intensity -} - -// ANCHOR: here -fn generate_workout(intensity: u32, random_number: u32) { - if intensity < 25 { - println!( - "Today, do {} pushups!", - simulated_expensive_calculation(intensity) - ); - println!( - "Next, do {} situps!", - simulated_expensive_calculation(intensity) - ); - } else { - if random_number == 3 { - println!("Take a break today! Remember to stay hydrated!"); - } else { - println!( - "Today, run for {} minutes!", - simulated_expensive_calculation(intensity) - ); - } - } -} -// ANCHOR_END: here - fn main() { - let simulated_user_specified_value = 10; - let simulated_random_number = 7; + // ANCHOR: here + let example_closure = |x| x; - generate_workout(simulated_user_specified_value, simulated_random_number); + let s = example_closure(String::from("hello")); + let n = example_closure(5); + // ANCHOR_END: here } diff --git a/listings/ch13-functional-features/listing-13-04/Cargo.toml b/listings/ch13-functional-features/listing-13-04/Cargo.toml index f09a737..914c4cf 100755 --- a/listings/ch13-functional-features/listing-13-04/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-04/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "workout-app" +name = "closure-example" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-04/output.txt b/listings/ch13-functional-features/listing-13-04/output.txt new file mode 100755 index 0000000..64d763b --- /dev/null +++ b/listings/ch13-functional-features/listing-13-04/output.txt @@ -0,0 +1,8 @@ +$ cargo run + Compiling closure-example v0.1.0 (file:///projects/closure-example) + Finished dev [unoptimized + debuginfo] target(s) in 0.43s + Running `target/debug/closure-example` +Before defining closure: [1, 2, 3] +Before calling closure: [1, 2, 3] +From closure: [1, 2, 3] +After calling closure: [1, 2, 3] diff --git a/listings/ch13-functional-features/listing-13-04/src/main.rs b/listings/ch13-functional-features/listing-13-04/src/main.rs index fabe0fb..43b91bb 100755 --- a/listings/ch13-functional-features/listing-13-04/src/main.rs +++ b/listings/ch13-functional-features/listing-13-04/src/main.rs @@ -1,32 +1,10 @@ -use std::thread; -use std::time::Duration; - -fn simulated_expensive_calculation(intensity: u32) -> u32 { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - intensity -} - -// ANCHOR: here -fn generate_workout(intensity: u32, random_number: u32) { - let expensive_result = simulated_expensive_calculation(intensity); - - if intensity < 25 { - println!("Today, do {} pushups!", expensive_result); - println!("Next, do {} situps!", expensive_result); - } else { - if random_number == 3 { - println!("Take a break today! Remember to stay hydrated!"); - } else { - println!("Today, run for {} minutes!", expensive_result); - } - } -} -// ANCHOR_END: here - fn main() { - let simulated_user_specified_value = 10; - let simulated_random_number = 7; + let list = vec![1, 2, 3]; + println!("Before defining closure: {:?}", list); + + let only_borrows = || println!("From closure: {:?}", list); - generate_workout(simulated_user_specified_value, simulated_random_number); + println!("Before calling closure: {:?}", list); + only_borrows(); + println!("After calling closure: {:?}", list); } diff --git a/listings/ch13-functional-features/listing-13-05/Cargo.toml b/listings/ch13-functional-features/listing-13-05/Cargo.toml index f09a737..914c4cf 100755 --- a/listings/ch13-functional-features/listing-13-05/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-05/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "workout-app" +name = "closure-example" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-05/output.txt b/listings/ch13-functional-features/listing-13-05/output.txt new file mode 100755 index 0000000..ce0ad5e --- /dev/null +++ b/listings/ch13-functional-features/listing-13-05/output.txt @@ -0,0 +1,6 @@ +$ cargo run + Compiling closure-example v0.1.0 (file:///projects/closure-example) + Finished dev [unoptimized + debuginfo] target(s) in 0.43s + Running `target/debug/closure-example` +Before defining closure: [1, 2, 3] +After calling closure: [1, 2, 3, 7] diff --git a/listings/ch13-functional-features/listing-13-05/src/main.rs b/listings/ch13-functional-features/listing-13-05/src/main.rs index 6984a27..37f8130 100755 --- a/listings/ch13-functional-features/listing-13-05/src/main.rs +++ b/listings/ch13-functional-features/listing-13-05/src/main.rs @@ -1,33 +1,9 @@ -use std::thread; -use std::time::Duration; - -fn generate_workout(intensity: u32, random_number: u32) { - // ANCHOR: here - let expensive_closure = |num| { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - num - }; - // ANCHOR_END: here - - if intensity < 25 { - println!("Today, do {} pushups!", expensive_closure(intensity)); - println!("Next, do {} situps!", expensive_closure(intensity)); - } else { - if random_number == 3 { - println!("Take a break today! Remember to stay hydrated!"); - } else { - println!( - "Today, run for {} minutes!", - expensive_closure(intensity) - ); - } - } -} - fn main() { - let simulated_user_specified_value = 10; - let simulated_random_number = 7; + let mut list = vec![1, 2, 3]; + println!("Before defining closure: {:?}", list); + + let mut borrows_mutably = || list.push(7); - generate_workout(simulated_user_specified_value, simulated_random_number); + borrows_mutably(); + println!("After calling closure: {:?}", list); } diff --git a/listings/ch13-functional-features/listing-13-06/Cargo.toml b/listings/ch13-functional-features/listing-13-06/Cargo.toml index f09a737..8085ade 100755 --- a/listings/ch13-functional-features/listing-13-06/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-06/Cargo.toml @@ -1,6 +1,8 @@ [package] -name = "workout-app" +name = "closure-example" version = "0.1.0" edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [dependencies] diff --git a/listings/ch13-functional-features/listing-13-06/src/main.rs b/listings/ch13-functional-features/listing-13-06/src/main.rs index 8850e58..2c8e18c 100755 --- a/listings/ch13-functional-features/listing-13-06/src/main.rs +++ b/listings/ch13-functional-features/listing-13-06/src/main.rs @@ -1,33 +1,10 @@ use std::thread; -use std::time::Duration; - -// ANCHOR: here -fn generate_workout(intensity: u32, random_number: u32) { - let expensive_closure = |num| { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - num - }; - - if intensity < 25 { - println!("Today, do {} pushups!", expensive_closure(intensity)); - println!("Next, do {} situps!", expensive_closure(intensity)); - } else { - if random_number == 3 { - println!("Take a break today! Remember to stay hydrated!"); - } else { - println!( - "Today, run for {} minutes!", - expensive_closure(intensity) - ); - } - } -} -// ANCHOR_END: here fn main() { - let simulated_user_specified_value = 10; - let simulated_random_number = 7; + let list = vec![1, 2, 3]; + println!("Before defining closure: {:?}", list); - generate_workout(simulated_user_specified_value, simulated_random_number); + thread::spawn(move || println!("From thread: {:?}", list)) + .join() + .unwrap(); } diff --git a/listings/ch13-functional-features/listing-13-07/.rustfmt.toml b/listings/ch13-functional-features/listing-13-07/.rustfmt.toml new file mode 100755 index 0000000..ee10c63 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-07/.rustfmt.toml @@ -0,0 +1,2 @@ +struct_lit_width = 50 + diff --git a/listings/ch13-functional-features/listing-13-07/Cargo.toml b/listings/ch13-functional-features/listing-13-07/Cargo.toml index f09a737..4a279a4 100755 --- a/listings/ch13-functional-features/listing-13-07/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-07/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "workout-app" +name = "rectangles" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-07/output.txt b/listings/ch13-functional-features/listing-13-07/output.txt new file mode 100755 index 0000000..f18fce4 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-07/output.txt @@ -0,0 +1,18 @@ +$ cargo run + Compiling rectangles v0.1.0 (file:///projects/rectangles) + Finished dev [unoptimized + debuginfo] target(s) in 0.41s + Running `target/debug/rectangles` +[ + Rectangle { + width: 3, + height: 5, + }, + Rectangle { + width: 7, + height: 12, + }, + Rectangle { + width: 10, + height: 1, + }, +] diff --git a/listings/ch13-functional-features/listing-13-07/src/main.rs b/listings/ch13-functional-features/listing-13-07/src/main.rs index b3f4cc2..73a25e5 100755 --- a/listings/ch13-functional-features/listing-13-07/src/main.rs +++ b/listings/ch13-functional-features/listing-13-07/src/main.rs @@ -1,33 +1,16 @@ -use std::thread; -use std::time::Duration; - -fn generate_workout(intensity: u32, random_number: u32) { - // ANCHOR: here - let expensive_closure = |num: u32| -> u32 { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - num - }; - // ANCHOR_END: here - - if intensity < 25 { - println!("Today, do {} pushups!", expensive_closure(intensity)); - println!("Next, do {} situps!", expensive_closure(intensity)); - } else { - if random_number == 3 { - println!("Take a break today! Remember to stay hydrated!"); - } else { - println!( - "Today, run for {} minutes!", - expensive_closure(intensity) - ); - } - } +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, } fn main() { - let simulated_user_specified_value = 10; - let simulated_random_number = 7; + let mut list = [ + Rectangle { width: 10, height: 1 }, + Rectangle { width: 3, height: 5 }, + Rectangle { width: 7, height: 12 }, + ]; - generate_workout(simulated_user_specified_value, simulated_random_number); + list.sort_by_key(|r| r.width); + println!("{:#?}", list); } diff --git a/listings/ch13-functional-features/listing-13-08/.rustfmt.toml b/listings/ch13-functional-features/listing-13-08/.rustfmt.toml new file mode 100755 index 0000000..ee10c63 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-08/.rustfmt.toml @@ -0,0 +1,2 @@ +struct_lit_width = 50 + diff --git a/listings/ch13-functional-features/listing-13-08/Cargo.toml b/listings/ch13-functional-features/listing-13-08/Cargo.toml index 914c4cf..703c9d9 100755 --- a/listings/ch13-functional-features/listing-13-08/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-08/Cargo.toml @@ -1,6 +1,8 @@ [package] -name = "closure-example" +name = "rectangles" version = "0.1.0" edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [dependencies] diff --git a/listings/ch13-functional-features/listing-13-08/output.txt b/listings/ch13-functional-features/listing-13-08/output.txt index 37d8361..a910537 100755 --- a/listings/ch13-functional-features/listing-13-08/output.txt +++ b/listings/ch13-functional-features/listing-13-08/output.txt @@ -1,12 +1,15 @@ $ cargo run - Compiling closure-example v0.1.0 (file:///projects/closure-example) -error[E0308]: mismatched types - --> src/main.rs:5:29 - | -5 | let n = example_closure(5); - | ^- help: try using a conversion method: `.to_string()` - | | - | expected struct `String`, found integer + Compiling rectangles v0.1.0 (file:///projects/rectangles) +error[E0507]: cannot move out of `value`, a captured variable in an `FnMut` closure + --> src/main.rs:18:30 + | +15 | let value = String::from("by key called"); + | ----- captured outer variable +16 | +17 | list.sort_by_key(|r| { + | --- captured by this `FnMut` closure +18 | sort_operations.push(value); + | ^^^^^ move occurs because `value` has type `String`, which does not implement the `Copy` trait -For more information about this error, try `rustc --explain E0308`. -error: could not compile `closure-example` due to previous error +For more information about this error, try `rustc --explain E0507`. +error: could not compile `rectangles` due to previous error diff --git a/listings/ch13-functional-features/listing-13-08/src/main.rs b/listings/ch13-functional-features/listing-13-08/src/main.rs index ebb2489..3b9c9cb 100755 --- a/listings/ch13-functional-features/listing-13-08/src/main.rs +++ b/listings/ch13-functional-features/listing-13-08/src/main.rs @@ -1,8 +1,22 @@ +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + fn main() { - // ANCHOR: here - let example_closure = |x| x; + let mut list = [ + Rectangle { width: 10, height: 1 }, + Rectangle { width: 3, height: 5 }, + Rectangle { width: 7, height: 12 }, + ]; + + let mut sort_operations = vec![]; + let value = String::from("by key called"); - let s = example_closure(String::from("hello")); - let n = example_closure(5); - // ANCHOR_END: here + list.sort_by_key(|r| { + sort_operations.push(value); + r.width + }); + println!("{:#?}", list); } diff --git a/listings/ch13-functional-features/listing-13-09/.rustfmt.toml b/listings/ch13-functional-features/listing-13-09/.rustfmt.toml new file mode 100755 index 0000000..ee10c63 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-09/.rustfmt.toml @@ -0,0 +1,2 @@ +struct_lit_width = 50 + diff --git a/listings/ch13-functional-features/listing-13-09/Cargo.toml b/listings/ch13-functional-features/listing-13-09/Cargo.toml index 6b81ef9..4a279a4 100755 --- a/listings/ch13-functional-features/listing-13-09/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-09/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "cacher" +name = "rectangles" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-09/src/main.rs b/listings/ch13-functional-features/listing-13-09/src/main.rs index 3fd4ed0..a60d6fd 100755 --- a/listings/ch13-functional-features/listing-13-09/src/main.rs +++ b/listings/ch13-functional-features/listing-13-09/src/main.rs @@ -1,11 +1,20 @@ -// ANCHOR: here -struct Cacher -where - T: Fn(u32) -> u32, -{ - calculation: T, - value: Option, +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, } -// ANCHOR_END: here -fn main() {} +fn main() { + let mut list = [ + Rectangle { width: 10, height: 1 }, + Rectangle { width: 3, height: 5 }, + Rectangle { width: 7, height: 12 }, + ]; + + let mut num_sort_operations = 0; + list.sort_by_key(|r| { + num_sort_operations += 1; + r.width + }); + println!("{:#?}, sorted in {num_sort_operations} operations", list); +} diff --git a/listings/ch13-functional-features/listing-13-10/Cargo.lock b/listings/ch13-functional-features/listing-13-10/Cargo.lock index e090432..e91eaa8 100755 --- a/listings/ch13-functional-features/listing-13-10/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-10/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "cacher" +name = "iterators" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-10/Cargo.toml b/listings/ch13-functional-features/listing-13-10/Cargo.toml index 6b81ef9..2652a8a 100755 --- a/listings/ch13-functional-features/listing-13-10/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-10/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "cacher" +name = "iterators" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-10/src/main.rs b/listings/ch13-functional-features/listing-13-10/src/main.rs index 4d1034d..55a0dd3 100755 --- a/listings/ch13-functional-features/listing-13-10/src/main.rs +++ b/listings/ch13-functional-features/listing-13-10/src/main.rs @@ -1,34 +1,7 @@ -struct Cacher -where - T: Fn(u32) -> u32, -{ - calculation: T, - value: Option, -} - -// ANCHOR: here -impl Cacher -where - T: Fn(u32) -> u32, -{ - fn new(calculation: T) -> Cacher { - Cacher { - calculation, - value: None, - } - } +fn main() { + // ANCHOR: here + let v1 = vec![1, 2, 3]; - fn value(&mut self, arg: u32) -> u32 { - match self.value { - Some(v) => v, - None => { - let v = (self.calculation)(arg); - self.value = Some(v); - v - } - } - } + let v1_iter = v1.iter(); + // ANCHOR_END: here } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch13-functional-features/listing-13-11/Cargo.lock b/listings/ch13-functional-features/listing-13-11/Cargo.lock index 75ff09e..e91eaa8 100755 --- a/listings/ch13-functional-features/listing-13-11/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-11/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "workout-app" +name = "iterators" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-11/Cargo.toml b/listings/ch13-functional-features/listing-13-11/Cargo.toml index f09a737..2652a8a 100755 --- a/listings/ch13-functional-features/listing-13-11/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-11/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "workout-app" +name = "iterators" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-11/src/main.rs b/listings/ch13-functional-features/listing-13-11/src/main.rs index 9f378b7..712aff4 100755 --- a/listings/ch13-functional-features/listing-13-11/src/main.rs +++ b/listings/ch13-functional-features/listing-13-11/src/main.rs @@ -1,64 +1,11 @@ -use std::thread; -use std::time::Duration; - -struct Cacher -where - T: Fn(u32) -> u32, -{ - calculation: T, - value: Option, -} - -impl Cacher -where - T: Fn(u32) -> u32, -{ - fn new(calculation: T) -> Cacher { - Cacher { - calculation, - value: None, - } - } - - fn value(&mut self, arg: u32) -> u32 { - match self.value { - Some(v) => v, - None => { - let v = (self.calculation)(arg); - self.value = Some(v); - v - } - } - } -} +fn main() { + // ANCHOR: here + let v1 = vec![1, 2, 3]; -// ANCHOR: here -fn generate_workout(intensity: u32, random_number: u32) { - let mut expensive_result = Cacher::new(|num| { - println!("calculating slowly..."); - thread::sleep(Duration::from_secs(2)); - num - }); + let v1_iter = v1.iter(); - if intensity < 25 { - println!("Today, do {} pushups!", expensive_result.value(intensity)); - println!("Next, do {} situps!", expensive_result.value(intensity)); - } else { - if random_number == 3 { - println!("Take a break today! Remember to stay hydrated!"); - } else { - println!( - "Today, run for {} minutes!", - expensive_result.value(intensity) - ); - } + for val in v1_iter { + println!("Got: {}", val); } -} -// ANCHOR_END: here - -fn main() { - let simulated_user_specified_value = 10; - let simulated_random_number = 7; - - generate_workout(simulated_user_specified_value, simulated_random_number); + // ANCHOR_END: here } diff --git a/listings/ch13-functional-features/listing-13-12/Cargo.lock b/listings/ch13-functional-features/listing-13-12/Cargo.lock index a96532a..e91eaa8 100755 --- a/listings/ch13-functional-features/listing-13-12/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-12/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "equal-to-x" +name = "iterators" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-12/Cargo.toml b/listings/ch13-functional-features/listing-13-12/Cargo.toml index ca73ff7..2652a8a 100755 --- a/listings/ch13-functional-features/listing-13-12/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-12/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "equal-to-x" +name = "iterators" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-12/src/lib.rs b/listings/ch13-functional-features/listing-13-12/src/lib.rs new file mode 100755 index 0000000..7582840 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-12/src/lib.rs @@ -0,0 +1,16 @@ +#[cfg(test)] +mod tests { + // ANCHOR: here + #[test] + fn iterator_demonstration() { + let v1 = vec![1, 2, 3]; + + let mut v1_iter = v1.iter(); + + assert_eq!(v1_iter.next(), Some(&1)); + assert_eq!(v1_iter.next(), Some(&2)); + assert_eq!(v1_iter.next(), Some(&3)); + assert_eq!(v1_iter.next(), None); + } + // ANCHOR_END: here +} diff --git a/listings/ch13-functional-features/listing-13-13/src/lib.rs b/listings/ch13-functional-features/listing-13-13/src/lib.rs new file mode 100755 index 0000000..d1cb54d --- /dev/null +++ b/listings/ch13-functional-features/listing-13-13/src/lib.rs @@ -0,0 +1,15 @@ +#[cfg(test)] +mod tests { + // ANCHOR: here + #[test] + fn iterator_sum() { + let v1 = vec![1, 2, 3]; + + let v1_iter = v1.iter(); + + let total: i32 = v1_iter.sum(); + + assert_eq!(total, 6); + } + // ANCHOR_END: here +} diff --git a/listings/ch13-functional-features/listing-13-14/output.txt b/listings/ch13-functional-features/listing-13-14/output.txt new file mode 100755 index 0000000..228c764 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-14/output.txt @@ -0,0 +1,14 @@ +$ cargo run + Compiling iterators v0.1.0 (file:///projects/iterators) +warning: unused `Map` that must be used + --> src/main.rs:4:5 + | +4 | v1.iter().map(|x| x + 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: iterators are lazy and do nothing unless consumed + +warning: `iterators` (bin "iterators") generated 1 warning + Finished dev [unoptimized + debuginfo] target(s) in 0.47s + Running `target/debug/iterators` diff --git a/listings/ch13-functional-features/listing-13-14/src/main.rs b/listings/ch13-functional-features/listing-13-14/src/main.rs index 712aff4..62a68be 100755 --- a/listings/ch13-functional-features/listing-13-14/src/main.rs +++ b/listings/ch13-functional-features/listing-13-14/src/main.rs @@ -1,11 +1,7 @@ fn main() { // ANCHOR: here - let v1 = vec![1, 2, 3]; + let v1: Vec = vec![1, 2, 3]; - let v1_iter = v1.iter(); - - for val in v1_iter { - println!("Got: {}", val); - } + v1.iter().map(|x| x + 1); // ANCHOR_END: here } diff --git a/listings/ch13-functional-features/listing-13-15/src/main.rs b/listings/ch13-functional-features/listing-13-15/src/main.rs new file mode 100755 index 0000000..db9025d --- /dev/null +++ b/listings/ch13-functional-features/listing-13-15/src/main.rs @@ -0,0 +1,9 @@ +fn main() { + // ANCHOR: here + let v1: Vec = vec![1, 2, 3]; + + let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); + + assert_eq!(v2, vec![2, 3, 4]); + // ANCHOR_END: here +} diff --git a/listings/ch13-functional-features/listing-13-16/Cargo.lock b/listings/ch13-functional-features/listing-13-16/Cargo.lock index e91eaa8..0b15e21 100755 --- a/listings/ch13-functional-features/listing-13-16/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-16/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "iterators" +name = "shoe_size" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-16/Cargo.toml b/listings/ch13-functional-features/listing-13-16/Cargo.toml index 2652a8a..cc80377 100755 --- a/listings/ch13-functional-features/listing-13-16/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-16/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "iterators" +name = "shoe_size" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-16/src/lib.rs b/listings/ch13-functional-features/listing-13-16/src/lib.rs index d1cb54d..281c3c9 100755 --- a/listings/ch13-functional-features/listing-13-16/src/lib.rs +++ b/listings/ch13-functional-features/listing-13-16/src/lib.rs @@ -1,15 +1,48 @@ +#[derive(PartialEq, Debug)] +struct Shoe { + size: u32, + style: String, +} + +fn shoes_in_size(shoes: Vec, shoe_size: u32) -> Vec { + shoes.into_iter().filter(|s| s.size == shoe_size).collect() +} + #[cfg(test)] mod tests { - // ANCHOR: here - #[test] - fn iterator_sum() { - let v1 = vec![1, 2, 3]; + use super::*; - let v1_iter = v1.iter(); + #[test] + fn filters_by_size() { + let shoes = vec![ + Shoe { + size: 10, + style: String::from("sneaker"), + }, + Shoe { + size: 13, + style: String::from("sandal"), + }, + Shoe { + size: 10, + style: String::from("boot"), + }, + ]; - let total: i32 = v1_iter.sum(); + let in_my_size = shoes_in_size(shoes, 10); - assert_eq!(total, 6); + assert_eq!( + in_my_size, + vec![ + Shoe { + size: 10, + style: String::from("sneaker") + }, + Shoe { + size: 10, + style: String::from("boot") + }, + ] + ); } - // ANCHOR_END: here } diff --git a/listings/ch13-functional-features/listing-13-18/Cargo.lock b/listings/ch13-functional-features/listing-13-18/Cargo.lock index e91eaa8..88bf82d 100755 --- a/listings/ch13-functional-features/listing-13-18/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-18/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "iterators" +name = "minigrep" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-18/Cargo.toml b/listings/ch13-functional-features/listing-13-18/Cargo.toml index 2652a8a..64c2a3f 100755 --- a/listings/ch13-functional-features/listing-13-18/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-18/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "iterators" +name = "minigrep" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-18/poem.txt b/listings/ch13-functional-features/listing-13-18/poem.txt new file mode 100755 index 0000000..8707527 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-18/poem.txt @@ -0,0 +1,9 @@ +I'm nobody! Who are you? +Are you nobody, too? +Then there's a pair of us - don't tell! +They'd banish us, you know. + +How dreary to be somebody! +How public, like a frog +To tell your name the livelong day +To an admiring bog! diff --git a/listings/ch13-functional-features/listing-13-18/src/lib.rs b/listings/ch13-functional-features/listing-13-18/src/lib.rs new file mode 100755 index 0000000..292b097 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-18/src/lib.rs @@ -0,0 +1,104 @@ +use std::env; +use std::error::Error; +use std::fs; + +pub struct Config { + pub query: String, + pub file_path: String, + pub ignore_case: bool, +} + +impl Config { + pub fn build(args: &[String]) -> Result { + if args.len() < 3 { + return Err("not enough arguments"); + } + + let query = args[1].clone(); + let file_path = args[2].clone(); + + let ignore_case = env::var("IGNORE_CASE").is_ok(); + + Ok(Config { + query, + file_path, + ignore_case, + }) + } +} + +pub fn run(config: Config) -> Result<(), Box> { + let contents = fs::read_to_string(config.file_path)?; + + let results = if config.ignore_case { + search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) + }; + + for line in results { + println!("{line}"); + } + + Ok(()) +} + +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + let mut results = Vec::new(); + + for line in contents.lines() { + if line.contains(query) { + results.push(line); + } + } + + results +} + +pub fn search_case_insensitive<'a>( + query: &str, + contents: &'a str, +) -> Vec<&'a str> { + let query = query.to_lowercase(); + let mut results = Vec::new(); + + for line in contents.lines() { + if line.to_lowercase().contains(&query) { + results.push(line); + } + } + + results +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn case_sensitive() { + let query = "duct"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Duct tape."; + + assert_eq!(vec!["safe, fast, productive."], search(query, contents)); + } + + #[test] + fn case_insensitive() { + let query = "rUsT"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Trust me."; + + assert_eq!( + vec!["Rust:", "Trust me."], + search_case_insensitive(query, contents) + ); + } +} diff --git a/listings/ch13-functional-features/listing-13-18/src/main.rs b/listings/ch13-functional-features/listing-13-18/src/main.rs index db9025d..40109ef 100755 --- a/listings/ch13-functional-features/listing-13-18/src/main.rs +++ b/listings/ch13-functional-features/listing-13-18/src/main.rs @@ -1,9 +1,22 @@ -fn main() { - // ANCHOR: here - let v1: Vec = vec![1, 2, 3]; +use std::env; +use std::process; + +use minigrep::Config; - let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); +// ANCHOR: here +fn main() { + let config = Config::build(env::args()).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {err}"); + process::exit(1); + }); - assert_eq!(v2, vec![2, 3, 4]); + // --snip-- // ANCHOR_END: here + + if let Err(e) = minigrep::run(config) { + eprintln!("Application error: {e}"); + process::exit(1); + } + // ANCHOR: here } +// ANCHOR_END: here diff --git a/listings/ch13-functional-features/listing-13-19/Cargo.lock b/listings/ch13-functional-features/listing-13-19/Cargo.lock index 0b15e21..88bf82d 100755 --- a/listings/ch13-functional-features/listing-13-19/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-19/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "shoe_size" +name = "minigrep" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-19/Cargo.toml b/listings/ch13-functional-features/listing-13-19/Cargo.toml index cc80377..64c2a3f 100755 --- a/listings/ch13-functional-features/listing-13-19/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-19/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "shoe_size" +name = "minigrep" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-19/poem.txt b/listings/ch13-functional-features/listing-13-19/poem.txt new file mode 100755 index 0000000..8707527 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-19/poem.txt @@ -0,0 +1,9 @@ +I'm nobody! Who are you? +Are you nobody, too? +Then there's a pair of us - don't tell! +They'd banish us, you know. + +How dreary to be somebody! +How public, like a frog +To tell your name the livelong day +To an admiring bog! diff --git a/listings/ch13-functional-features/listing-13-19/src/lib.rs b/listings/ch13-functional-features/listing-13-19/src/lib.rs index 281c3c9..79ae2b8 100755 --- a/listings/ch13-functional-features/listing-13-19/src/lib.rs +++ b/listings/ch13-functional-features/listing-13-19/src/lib.rs @@ -1,11 +1,79 @@ -#[derive(PartialEq, Debug)] -struct Shoe { - size: u32, - style: String, +use std::env; +use std::error::Error; +use std::fs; + +pub struct Config { + pub query: String, + pub file_path: String, + pub ignore_case: bool, } -fn shoes_in_size(shoes: Vec, shoe_size: u32) -> Vec { - shoes.into_iter().filter(|s| s.size == shoe_size).collect() +// ANCHOR: here +impl Config { + pub fn build( + mut args: impl Iterator, + ) -> Result { + // --snip-- + // ANCHOR_END: here + if args.len() < 3 { + return Err("not enough arguments"); + } + + let query = args[1].clone(); + let file_path = args[2].clone(); + + let ignore_case = env::var("IGNORE_CASE").is_ok(); + + Ok(Config { + query, + file_path, + ignore_case, + }) + } +} + +pub fn run(config: Config) -> Result<(), Box> { + let contents = fs::read_to_string(config.file_path)?; + + let results = if config.ignore_case { + search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) + }; + + for line in results { + println!("{line}"); + } + + Ok(()) +} + +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + let mut results = Vec::new(); + + for line in contents.lines() { + if line.contains(query) { + results.push(line); + } + } + + results +} + +pub fn search_case_insensitive<'a>( + query: &str, + contents: &'a str, +) -> Vec<&'a str> { + let query = query.to_lowercase(); + let mut results = Vec::new(); + + for line in contents.lines() { + if line.to_lowercase().contains(&query) { + results.push(line); + } + } + + results } #[cfg(test)] @@ -13,36 +81,29 @@ mod tests { use super::*; #[test] - fn filters_by_size() { - let shoes = vec![ - Shoe { - size: 10, - style: String::from("sneaker"), - }, - Shoe { - size: 13, - style: String::from("sandal"), - }, - Shoe { - size: 10, - style: String::from("boot"), - }, - ]; - - let in_my_size = shoes_in_size(shoes, 10); + fn case_sensitive() { + let query = "duct"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Duct tape."; + + assert_eq!(vec!["safe, fast, productive."], search(query, contents)); + } + + #[test] + fn case_insensitive() { + let query = "rUsT"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Trust me."; assert_eq!( - in_my_size, - vec![ - Shoe { - size: 10, - style: String::from("sneaker") - }, - Shoe { - size: 10, - style: String::from("boot") - }, - ] + vec!["Rust:", "Trust me."], + search_case_insensitive(query, contents) ); } } diff --git a/listings/ch13-functional-features/listing-13-19/src/main.rs b/listings/ch13-functional-features/listing-13-19/src/main.rs new file mode 100755 index 0000000..9ac0225 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-19/src/main.rs @@ -0,0 +1,16 @@ +use std::env; +use std::process; + +use minigrep::Config; + +fn main() { + let config = Config::build(env::args()).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {err}"); + process::exit(1); + }); + + if let Err(e) = minigrep::run(config) { + eprintln!("Application error: {e}"); + process::exit(1); + } +} diff --git a/listings/ch13-functional-features/listing-13-20/Cargo.lock b/listings/ch13-functional-features/listing-13-20/Cargo.lock index 58b70c5..88bf82d 100755 --- a/listings/ch13-functional-features/listing-13-20/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-20/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "counter" +name = "minigrep" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-20/Cargo.toml b/listings/ch13-functional-features/listing-13-20/Cargo.toml index 9e103f3..64c2a3f 100755 --- a/listings/ch13-functional-features/listing-13-20/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-20/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "counter" +name = "minigrep" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-20/poem.txt b/listings/ch13-functional-features/listing-13-20/poem.txt new file mode 100755 index 0000000..8707527 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-20/poem.txt @@ -0,0 +1,9 @@ +I'm nobody! Who are you? +Are you nobody, too? +Then there's a pair of us - don't tell! +They'd banish us, you know. + +How dreary to be somebody! +How public, like a frog +To tell your name the livelong day +To an admiring bog! diff --git a/listings/ch13-functional-features/listing-13-20/src/lib.rs b/listings/ch13-functional-features/listing-13-20/src/lib.rs index fb8a0cb..4410964 100755 --- a/listings/ch13-functional-features/listing-13-20/src/lib.rs +++ b/listings/ch13-functional-features/listing-13-20/src/lib.rs @@ -1,9 +1,113 @@ -struct Counter { - count: u32, +use std::env; +use std::error::Error; +use std::fs; + +pub struct Config { + pub query: String, + pub file_path: String, + pub ignore_case: bool, +} + +// ANCHOR: here +impl Config { + pub fn build( + mut args: impl Iterator, + ) -> Result { + args.next(); + + let query = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a query string"), + }; + + let file_path = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a file path"), + }; + + let ignore_case = env::var("IGNORE_CASE").is_ok(); + + Ok(Config { + query, + file_path, + ignore_case, + }) + } } +// ANCHOR_END: here + +pub fn run(config: Config) -> Result<(), Box> { + let contents = fs::read_to_string(config.file_path)?; + + let results = if config.ignore_case { + search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) + }; + + for line in results { + println!("{line}"); + } + + Ok(()) +} + +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + let mut results = Vec::new(); + + for line in contents.lines() { + if line.contains(query) { + results.push(line); + } + } + + results +} + +pub fn search_case_insensitive<'a>( + query: &str, + contents: &'a str, +) -> Vec<&'a str> { + let query = query.to_lowercase(); + let mut results = Vec::new(); + + for line in contents.lines() { + if line.to_lowercase().contains(&query) { + results.push(line); + } + } + + results +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn case_sensitive() { + let query = "duct"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Duct tape."; + + assert_eq!(vec!["safe, fast, productive."], search(query, contents)); + } + + #[test] + fn case_insensitive() { + let query = "rUsT"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Trust me."; -impl Counter { - fn new() -> Counter { - Counter { count: 0 } + assert_eq!( + vec!["Rust:", "Trust me."], + search_case_insensitive(query, contents) + ); } } diff --git a/listings/ch13-functional-features/listing-13-20/src/main.rs b/listings/ch13-functional-features/listing-13-20/src/main.rs new file mode 100755 index 0000000..9ac0225 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-20/src/main.rs @@ -0,0 +1,16 @@ +use std::env; +use std::process; + +use minigrep::Config; + +fn main() { + let config = Config::build(env::args()).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {err}"); + process::exit(1); + }); + + if let Err(e) = minigrep::run(config) { + eprintln!("Application error: {e}"); + process::exit(1); + } +} diff --git a/listings/ch13-functional-features/listing-13-22/Cargo.lock b/listings/ch13-functional-features/listing-13-22/Cargo.lock index 58b70c5..88bf82d 100755 --- a/listings/ch13-functional-features/listing-13-22/Cargo.lock +++ b/listings/ch13-functional-features/listing-13-22/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "counter" +name = "minigrep" version = "0.1.0" diff --git a/listings/ch13-functional-features/listing-13-22/Cargo.toml b/listings/ch13-functional-features/listing-13-22/Cargo.toml index 9e103f3..64c2a3f 100755 --- a/listings/ch13-functional-features/listing-13-22/Cargo.toml +++ b/listings/ch13-functional-features/listing-13-22/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "counter" +name = "minigrep" version = "0.1.0" edition = "2021" diff --git a/listings/ch13-functional-features/listing-13-22/poem.txt b/listings/ch13-functional-features/listing-13-22/poem.txt new file mode 100755 index 0000000..8707527 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-22/poem.txt @@ -0,0 +1,9 @@ +I'm nobody! Who are you? +Are you nobody, too? +Then there's a pair of us - don't tell! +They'd banish us, you know. + +How dreary to be somebody! +How public, like a frog +To tell your name the livelong day +To an admiring bog! diff --git a/listings/ch13-functional-features/listing-13-22/src/lib.rs b/listings/ch13-functional-features/listing-13-22/src/lib.rs index 05afa41..d694669 100755 --- a/listings/ch13-functional-features/listing-13-22/src/lib.rs +++ b/listings/ch13-functional-features/listing-13-22/src/lib.rs @@ -1,41 +1,108 @@ -struct Counter { - count: u32, +use std::env; +use std::error::Error; +use std::fs; + +pub struct Config { + pub query: String, + pub file_path: String, + pub ignore_case: bool, } -impl Counter { - fn new() -> Counter { - Counter { count: 0 } +impl Config { + pub fn build( + mut args: impl Iterator, + ) -> Result { + args.next(); + + let query = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a query string"), + }; + + let file_path = match args.next() { + Some(arg) => arg, + None => return Err("Didn't get a file path"), + }; + + let ignore_case = env::var("IGNORE_CASE").is_ok(); + + Ok(Config { + query, + file_path, + ignore_case, + }) } } -impl Iterator for Counter { - type Item = u32; +pub fn run(config: Config) -> Result<(), Box> { + let contents = fs::read_to_string(config.file_path)?; + + let results = if config.ignore_case { + search_case_insensitive(&config.query, &contents) + } else { + search(&config.query, &contents) + }; + + for line in results { + println!("{line}"); + } + + Ok(()) +} - fn next(&mut self) -> Option { - if self.count < 5 { - self.count += 1; - Some(self.count) - } else { - None +// ANCHOR: here +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + contents + .lines() + .filter(|line| line.contains(query)) + .collect() +} +// ANCHOR_END: here + +pub fn search_case_insensitive<'a>( + query: &str, + contents: &'a str, +) -> Vec<&'a str> { + let query = query.to_lowercase(); + let mut results = Vec::new(); + + for line in contents.lines() { + if line.to_lowercase().contains(&query) { + results.push(line); } } + + results } #[cfg(test)] mod tests { use super::*; - // ANCHOR: here #[test] - fn calling_next_directly() { - let mut counter = Counter::new(); - - assert_eq!(counter.next(), Some(1)); - assert_eq!(counter.next(), Some(2)); - assert_eq!(counter.next(), Some(3)); - assert_eq!(counter.next(), Some(4)); - assert_eq!(counter.next(), Some(5)); - assert_eq!(counter.next(), None); + fn case_sensitive() { + let query = "duct"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Duct tape."; + + assert_eq!(vec!["safe, fast, productive."], search(query, contents)); + } + + #[test] + fn case_insensitive() { + let query = "rUsT"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Trust me."; + + assert_eq!( + vec!["Rust:", "Trust me."], + search_case_insensitive(query, contents) + ); } - // ANCHOR_END: here } diff --git a/listings/ch13-functional-features/listing-13-22/src/main.rs b/listings/ch13-functional-features/listing-13-22/src/main.rs new file mode 100755 index 0000000..9ac0225 --- /dev/null +++ b/listings/ch13-functional-features/listing-13-22/src/main.rs @@ -0,0 +1,16 @@ +use std::env; +use std::process; + +use minigrep::Config; + +fn main() { + let config = Config::build(env::args()).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {err}"); + process::exit(1); + }); + + if let Err(e) = minigrep::run(config) { + eprintln!("Application error: {e}"); + process::exit(1); + } +} diff --git a/listings/ch14-more-about-cargo/listing-14-07/add/adder/src/main.rs b/listings/ch14-more-about-cargo/listing-14-07/add/adder/src/main.rs index 7deb796..1316294 100755 --- a/listings/ch14-more-about-cargo/listing-14-07/add/adder/src/main.rs +++ b/listings/ch14-more-about-cargo/listing-14-07/add/adder/src/main.rs @@ -2,9 +2,5 @@ use add_one; fn main() { let num = 10; - println!( - "Hello, world! {} plus one is {}!", - num, - add_one::add_one(num) - ); + println!("Hello, world! {num} plus one is {}!", add_one::add_one(num)); } diff --git a/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock b/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock index eec3a9e..bf6974b 100755 --- a/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock +++ b/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "add_one" version = "0.1.0" @@ -45,14 +47,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -74,15 +75,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml b/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml index fd4942a..bc758bd 100755 --- a/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml +++ b/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock b/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock index eec3a9e..bf6974b 100755 --- a/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock +++ b/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "add_one" version = "0.1.0" @@ -45,14 +47,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -74,15 +75,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml b/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml index fd4942a..bc758bd 100755 --- a/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml +++ b/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch15-smart-pointers/listing-15-03/output.txt b/listings/ch15-smart-pointers/listing-15-03/output.txt index 87e7b57..d5522cd 100755 --- a/listings/ch15-smart-pointers/listing-15-03/output.txt +++ b/listings/ch15-smart-pointers/listing-15-03/output.txt @@ -13,15 +13,5 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` repre 2 | Cons(i32, Box), | ++++ + -error[E0391]: cycle detected when computing drop-check constraints for `List` - --> src/main.rs:1:1 - | -1 | enum List { - | ^^^^^^^^^ - | - = note: ...which immediately requires computing drop-check constraints for `List` again - = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: List } }` - -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. -error: could not compile `cons-list` due to 2 previous errors +For more information about this error, try `rustc --explain E0072`. +error: could not compile `cons-list` due to previous error diff --git a/listings/ch15-smart-pointers/listing-15-11/src/main.rs b/listings/ch15-smart-pointers/listing-15-11/src/main.rs index b73ad89..77a88c9 100755 --- a/listings/ch15-smart-pointers/listing-15-11/src/main.rs +++ b/listings/ch15-smart-pointers/listing-15-11/src/main.rs @@ -1,6 +1,6 @@ // ANCHOR: here fn hello(name: &str) { - println!("Hello, {}!", name); + println!("Hello, {name}!"); } // ANCHOR_END: here diff --git a/listings/ch15-smart-pointers/listing-15-12/src/main.rs b/listings/ch15-smart-pointers/listing-15-12/src/main.rs index 6a3e143..8cd3893 100755 --- a/listings/ch15-smart-pointers/listing-15-12/src/main.rs +++ b/listings/ch15-smart-pointers/listing-15-12/src/main.rs @@ -17,7 +17,7 @@ impl MyBox { } fn hello(name: &str) { - println!("Hello, {}!", name); + println!("Hello, {name}!"); } // ANCHOR: here diff --git a/listings/ch15-smart-pointers/listing-15-13/src/main.rs b/listings/ch15-smart-pointers/listing-15-13/src/main.rs index ef5361c..9debe2a 100755 --- a/listings/ch15-smart-pointers/listing-15-13/src/main.rs +++ b/listings/ch15-smart-pointers/listing-15-13/src/main.rs @@ -17,7 +17,7 @@ impl MyBox { } fn hello(name: &str) { - println!("Hello, {}!", name); + println!("Hello, {name}!"); } // ANCHOR: here diff --git a/listings/ch15-smart-pointers/listing-15-20/src/lib.rs b/listings/ch15-smart-pointers/listing-15-20/src/lib.rs index d3a9003..a518183 100755 --- a/listings/ch15-smart-pointers/listing-15-20/src/lib.rs +++ b/listings/ch15-smart-pointers/listing-15-20/src/lib.rs @@ -12,7 +12,7 @@ impl<'a, T> LimitTracker<'a, T> where T: Messenger, { - pub fn new(messenger: &T, max: usize) -> LimitTracker { + pub fn new(messenger: &'a T, max: usize) -> LimitTracker<'a, T> { LimitTracker { messenger, value: 0, diff --git a/listings/ch15-smart-pointers/listing-15-21/output.txt b/listings/ch15-smart-pointers/listing-15-21/output.txt index 91a928e..6b07b66 100755 --- a/listings/ch15-smart-pointers/listing-15-21/output.txt +++ b/listings/ch15-smart-pointers/listing-15-21/output.txt @@ -12,4 +12,3 @@ error[E0596]: cannot borrow `self.sent_messages` as mutable, as it is behind a ` For more information about this error, try `rustc --explain E0596`. error: could not compile `limit-tracker` due to previous error warning: build failed, waiting for other jobs to finish... -error: build failed diff --git a/listings/ch15-smart-pointers/listing-15-21/src/lib.rs b/listings/ch15-smart-pointers/listing-15-21/src/lib.rs index 9e403e3..4572d43 100755 --- a/listings/ch15-smart-pointers/listing-15-21/src/lib.rs +++ b/listings/ch15-smart-pointers/listing-15-21/src/lib.rs @@ -12,7 +12,7 @@ impl<'a, T> LimitTracker<'a, T> where T: Messenger, { - pub fn new(messenger: &T, max: usize) -> LimitTracker { + pub fn new(messenger: &'a T, max: usize) -> LimitTracker<'a, T> { LimitTracker { messenger, value: 0, diff --git a/listings/ch15-smart-pointers/listing-15-22/src/lib.rs b/listings/ch15-smart-pointers/listing-15-22/src/lib.rs index 539578e..a77ffa4 100755 --- a/listings/ch15-smart-pointers/listing-15-22/src/lib.rs +++ b/listings/ch15-smart-pointers/listing-15-22/src/lib.rs @@ -12,7 +12,7 @@ impl<'a, T> LimitTracker<'a, T> where T: Messenger, { - pub fn new(messenger: &T, max: usize) -> LimitTracker { + pub fn new(messenger: &'a T, max: usize) -> LimitTracker<'a, T> { LimitTracker { messenger, value: 0, diff --git a/listings/ch15-smart-pointers/listing-15-23/output.txt b/listings/ch15-smart-pointers/listing-15-23/output.txt index 22c2f79..3749c84 100755 --- a/listings/ch15-smart-pointers/listing-15-23/output.txt +++ b/listings/ch15-smart-pointers/listing-15-23/output.txt @@ -1,7 +1,7 @@ $ cargo test Compiling limit-tracker v0.1.0 (file:///projects/limit-tracker) Finished test [unoptimized + debuginfo] target(s) in 0.91s - Running unittests (target/debug/deps/limit_tracker-e599811fa246dbde) + Running unittests src/lib.rs (target/debug/deps/limit_tracker-e599811fa246dbde) running 1 test test tests::it_sends_an_over_75_percent_warning_message ... FAILED @@ -18,4 +18,4 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s -error: test failed, to rerun pass '--lib' +error: test failed, to rerun pass `--lib` diff --git a/listings/ch15-smart-pointers/listing-15-23/src/lib.rs b/listings/ch15-smart-pointers/listing-15-23/src/lib.rs index 4e599dd..7d288e6 100755 --- a/listings/ch15-smart-pointers/listing-15-23/src/lib.rs +++ b/listings/ch15-smart-pointers/listing-15-23/src/lib.rs @@ -12,7 +12,7 @@ impl<'a, T> LimitTracker<'a, T> where T: Messenger, { - pub fn new(messenger: &T, max: usize) -> LimitTracker { + pub fn new(messenger: &'a T, max: usize) -> LimitTracker<'a, T> { LimitTracker { messenger, value: 0, diff --git a/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt b/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt index ed54370..a03cc34 100755 --- a/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt +++ b/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt @@ -7,6 +7,16 @@ error[E0277]: can't compare `{integer}` with `&{integer}` | ^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}` | = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}` + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0277`. diff --git a/listings/ch16-fearless-concurrency/listing-16-09/output.txt b/listings/ch16-fearless-concurrency/listing-16-09/output.txt index bb2639d..db85185 100755 --- a/listings/ch16-fearless-concurrency/listing-16-09/output.txt +++ b/listings/ch16-fearless-concurrency/listing-16-09/output.txt @@ -9,6 +9,8 @@ error[E0382]: borrow of moved value: `val` | --- value moved here 10 | println!("val is {}", val); | ^^^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `message-passing` due to previous error diff --git a/listings/ch16-fearless-concurrency/listing-16-14/output.txt b/listings/ch16-fearless-concurrency/listing-16-14/output.txt index 9546e1e..0634b86 100755 --- a/listings/ch16-fearless-concurrency/listing-16-14/output.txt +++ b/listings/ch16-fearless-concurrency/listing-16-14/output.txt @@ -1,20 +1,26 @@ $ cargo run Compiling shared-state v0.1.0 (file:///projects/shared-state) error[E0277]: `Rc>` cannot be sent between threads safely - --> src/main.rs:11:22 - | -11 | let handle = thread::spawn(move || { - | ______________________^^^^^^^^^^^^^_- - | | | - | | `Rc>` cannot be sent between threads safely -12 | | let mut num = counter.lock().unwrap(); -13 | | -14 | | *num += 1; -15 | | }); - | |_________- within this `[closure@src/main.rs:11:36: 15:10]` - | - = help: within `[closure@src/main.rs:11:36: 15:10]`, the trait `Send` is not implemented for `Rc>` - = note: required because it appears within the type `[closure@src/main.rs:11:36: 15:10]` + --> src/main.rs:11:36 + | +11 | let handle = thread::spawn(move || { + | ------------- ^------ + | | | + | ______________________|_____________within this `[closure@src/main.rs:11:36: 11:43]` + | | | + | | required by a bound introduced by this call +12 | | let mut num = counter.lock().unwrap(); +13 | | +14 | | *num += 1; +15 | | }); + | |_________^ `Rc>` cannot be sent between threads safely + | + = help: within `[closure@src/main.rs:11:36: 11:43]`, the trait `Send` is not implemented for `Rc>` +note: required because it's used within this closure + --> src/main.rs:11:36 + | +11 | let handle = thread::spawn(move || { + | ^^^^^^^ note: required by a bound in `spawn` For more information about this error, try `rustc --explain E0277`. diff --git a/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt b/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt index f7be53b..301a9a4 100755 --- a/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt +++ b/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt @@ -5,7 +5,7 @@ error[E0382]: use of moved value: `v` | 4 | let v = vec![1, 2, 3]; | - move occurs because `v` has type `Vec`, which does not implement the `Copy` trait -5 | +5 | 6 | let handle = thread::spawn(move || { | ------- value moved into closure here 7 | println!("Here's a vector: {:?}", v); diff --git a/listings/ch17-oop/listing-17-10/output.txt b/listings/ch17-oop/listing-17-10/output.txt index 4015577..e0a455f 100755 --- a/listings/ch17-oop/listing-17-10/output.txt +++ b/listings/ch17-oop/listing-17-10/output.txt @@ -6,7 +6,8 @@ error[E0277]: the trait bound `String: Draw` is not satisfied 5 | components: vec![Box::new(String::from("Hi"))], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Draw` is not implemented for `String` | - = note: required for the cast to the object type `dyn Draw` + = help: the trait `Draw` is implemented for `Button` + = note: required for the cast from `String` to the object type `dyn Draw` For more information about this error, try `rustc --explain E0277`. error: could not compile `gui` due to previous error diff --git a/listings/ch18-patterns-and-matching/listing-18-01/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-01/src/main.rs index d28c369..fc87768 100755 --- a/listings/ch18-patterns-and-matching/listing-18-01/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-01/src/main.rs @@ -4,7 +4,7 @@ fn main() { let age: Result = "34".parse(); if let Some(color) = favorite_color { - println!("Using your favorite color, {}, as the background", color); + println!("Using your favorite color, {color}, as the background"); } else if is_tuesday { println!("Tuesday is green day!"); } else if let Ok(age) = age { diff --git a/listings/ch18-patterns-and-matching/listing-18-08/output.txt b/listings/ch18-patterns-and-matching/listing-18-08/output.txt index 5915c39..0fd5373 100755 --- a/listings/ch18-patterns-and-matching/listing-18-08/output.txt +++ b/listings/ch18-patterns-and-matching/listing-18-08/output.txt @@ -1,18 +1,19 @@ $ cargo run Compiling patterns v0.1.0 (file:///projects/patterns) error[E0005]: refutable pattern in local binding: `None` not covered - --> src/main.rs:3:9 - | -3 | let Some(x) = some_option_value; - | ^^^^^^^ pattern `None` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html - = note: the matched value is of type `Option` + --> src/main.rs:3:9 + | +3 | let Some(x) = some_option_value; + | ^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Option` defined here + = note: the matched value is of type `Option` help: you might want to use `if let` to ignore the variant that isn't matched - | -3 | if let Some(x) = some_option_value { /* */ } - | + | +3 | let x = if let Some(x) = some_option_value { x } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ For more information about this error, try `rustc --explain E0005`. error: could not compile `patterns` due to previous error diff --git a/listings/ch18-patterns-and-matching/listing-18-11/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-11/src/main.rs index 25eaa79..db942b7 100755 --- a/listings/ch18-patterns-and-matching/listing-18-11/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-11/src/main.rs @@ -5,10 +5,10 @@ fn main() { match x { Some(50) => println!("Got 50"), - Some(y) => println!("Matched, y = {:?}", y), + Some(y) => println!("Matched, y = {y}"), _ => println!("Default case, x = {:?}", x), } - println!("at the end: x = {:?}, y = {:?}", x, y); + println!("at the end: x = {:?}, y = {y}", x); // ANCHOR_END: here } diff --git a/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs index 8d445d9..b71da9a 100755 --- a/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs @@ -8,9 +8,11 @@ fn main() { let p = Point { x: 0, y: 7 }; match p { - Point { x, y: 0 } => println!("On the x axis at {}", x), - Point { x: 0, y } => println!("On the y axis at {}", y), - Point { x, y } => println!("On neither axis: ({}, {})", x, y), + Point { x, y: 0 } => println!("On the x axis at {x}"), + Point { x: 0, y } => println!("On the y axis at {y}"), + Point { x, y } => { + println!("On neither axis: ({x}, {y})"); + } } } // ANCHOR_END: here diff --git a/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs index 9b8dac1..a3138b2 100755 --- a/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs @@ -10,18 +10,16 @@ fn main() { match msg { Message::Quit => { - println!("The Quit variant has no data to destructure.") + println!("The Quit variant has no data to destructure."); } Message::Move { x, y } => { - println!( - "Move in the x direction {} and in the y direction {}", - x, y - ); + println!("Move in the x direction {x} and in the y direction {y}"); + } + Message::Write(text) => { + println!("Text message: {text}"); + } + Message::ChangeColor(r, g, b) => { + println!("Change the color to red {r}, green {g}, and blue {b}",) } - Message::Write(text) => println!("Text message: {}", text), - Message::ChangeColor(r, g, b) => println!( - "Change the color to red {}, green {}, and blue {}", - r, g, b - ), } } diff --git a/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs index ed6a20b..1e7ad5f 100755 --- a/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs @@ -14,14 +14,12 @@ fn main() { let msg = Message::ChangeColor(Color::Hsv(0, 160, 255)); match msg { - Message::ChangeColor(Color::Rgb(r, g, b)) => println!( - "Change the color to red {}, green {}, and blue {}", - r, g, b - ), - Message::ChangeColor(Color::Hsv(h, s, v)) => println!( - "Change the color to hue {}, saturation {}, and value {}", - h, s, v - ), + Message::ChangeColor(Color::Rgb(r, g, b)) => { + println!("Change color to red {r}, green {g}, and blue {b}"); + } + Message::ChangeColor(Color::Hsv(h, s, v)) => { + println!("Change color to hue {h}, saturation {s}, value {v}") + } _ => (), } } diff --git a/listings/ch18-patterns-and-matching/listing-18-19/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-19/src/main.rs index 59b48c9..e28dab1 100755 --- a/listings/ch18-patterns-and-matching/listing-18-19/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-19/src/main.rs @@ -4,7 +4,7 @@ fn main() { match numbers { (first, _, third, _, fifth) => { - println!("Some numbers: {}, {}, {}", first, third, fifth) + println!("Some numbers: {first}, {third}, {fifth}") } } // ANCHOR_END: here diff --git a/listings/ch18-patterns-and-matching/listing-18-24/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-24/src/main.rs index f22dbe8..3f9aaaf 100755 --- a/listings/ch18-patterns-and-matching/listing-18-24/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-24/src/main.rs @@ -3,7 +3,7 @@ fn main() { match numbers { (first, .., last) => { - println!("Some numbers: {}, {}", first, last); + println!("Some numbers: {first}, {last}"); } } } diff --git a/listings/ch18-patterns-and-matching/listing-18-26/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-26/src/main.rs index 4ec86cb..41fce97 100755 --- a/listings/ch18-patterns-and-matching/listing-18-26/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-26/src/main.rs @@ -3,8 +3,8 @@ fn main() { let num = Some(4); match num { - Some(x) if x < 5 => println!("less than five: {}", x), - Some(x) => println!("{}", x), + Some(x) if x % 2 == 0 => println!("The number {} is even", x), + Some(x) => println!("The number {} is odd", x), None => (), } // ANCHOR_END: here diff --git a/listings/ch18-patterns-and-matching/listing-18-27/src/main.rs b/listings/ch18-patterns-and-matching/listing-18-27/src/main.rs index 348e367..8386a0a 100755 --- a/listings/ch18-patterns-and-matching/listing-18-27/src/main.rs +++ b/listings/ch18-patterns-and-matching/listing-18-27/src/main.rs @@ -4,9 +4,9 @@ fn main() { match x { Some(50) => println!("Got 50"), - Some(n) if n == y => println!("Matched, n = {}", n), + Some(n) if n == y => println!("Matched, n = {n}"), _ => println!("Default case, x = {:?}", x), } - println!("at the end: x = {:?}, y = {}", x, y); + println!("at the end: x = {:?}, y = {y}", x); } diff --git a/listings/ch19-advanced-features/listing-19-05/output.txt b/listings/ch19-advanced-features/listing-19-05/output.txt index 18191f8..f4b7582 100755 --- a/listings/ch19-advanced-features/listing-19-05/output.txt +++ b/listings/ch19-advanced-features/listing-19-05/output.txt @@ -1,17 +1,17 @@ $ cargo run Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example) -error[E0499]: cannot borrow `*slice` as mutable more than once at a time - --> src/main.rs:6:30 +error[E0499]: cannot borrow `*values` as mutable more than once at a time + --> src/main.rs:6:31 | -1 | fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { - | - let's call the lifetime of this reference `'1` +1 | fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { + | - let's call the lifetime of this reference `'1` ... -6 | (&mut slice[..mid], &mut slice[mid..]) - | -------------------------^^^^^-------- - | | | | - | | | second mutable borrow occurs here +6 | (&mut values[..mid], &mut values[mid..]) + | --------------------------^^^^^^-------- + | | | | + | | | second mutable borrow occurs here | | first mutable borrow occurs here - | returning this value requires that `*slice` is borrowed for `'1` + | returning this value requires that `*values` is borrowed for `'1` For more information about this error, try `rustc --explain E0499`. error: could not compile `unsafe-example` due to previous error diff --git a/listings/ch19-advanced-features/listing-19-05/src/main.rs b/listings/ch19-advanced-features/listing-19-05/src/main.rs index c4b83ef..dabf63d 100755 --- a/listings/ch19-advanced-features/listing-19-05/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-05/src/main.rs @@ -1,10 +1,10 @@ // ANCHOR: here -fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { - let len = slice.len(); +fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { + let len = values.len(); assert!(mid <= len); - (&mut slice[..mid], &mut slice[mid..]) + (&mut values[..mid], &mut values[mid..]) } // ANCHOR_END: here diff --git a/listings/ch19-advanced-features/listing-19-06/src/main.rs b/listings/ch19-advanced-features/listing-19-06/src/main.rs index f25cbf4..3af21f7 100755 --- a/listings/ch19-advanced-features/listing-19-06/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-06/src/main.rs @@ -1,9 +1,9 @@ // ANCHOR: here use std::slice; -fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { - let len = slice.len(); - let ptr = slice.as_mut_ptr(); +fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { + let len = values.len(); + let ptr = values.as_mut_ptr(); assert!(mid <= len); diff --git a/listings/ch19-advanced-features/listing-19-07/src/main.rs b/listings/ch19-advanced-features/listing-19-07/src/main.rs index 0ab39ae..b4d6cdb 100755 --- a/listings/ch19-advanced-features/listing-19-07/src/main.rs +++ b/listings/ch19-advanced-features/listing-19-07/src/main.rs @@ -5,6 +5,6 @@ fn main() { let address = 0x01234usize; let r = address as *mut i32; - let slice: &[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) }; + let values: &[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) }; // ANCHOR_END: here } diff --git a/listings/ch19-advanced-features/listing-19-20/output.txt b/listings/ch19-advanced-features/listing-19-20/output.txt index 6845082..a3b281e 100755 --- a/listings/ch19-advanced-features/listing-19-20/output.txt +++ b/listings/ch19-advanced-features/listing-19-20/output.txt @@ -1,12 +1,18 @@ $ cargo run Compiling traits-example v0.1.0 (file:///projects/traits-example) -error[E0283]: type annotations needed +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> src/main.rs:20:43 | +2 | fn baby_name() -> String; + | ------------------------- `Animal::baby_name` defined here +... 20 | println!("A baby dog is called a {}", Animal::baby_name()); - | ^^^^^^^^^^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | - = note: cannot satisfy `_: Animal` +help: use the fully-qualified path to the only available implementation + | +20 | println!("A baby dog is called a {}", <::Dog as Animal>::baby_name()); + | +++++++++ + -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0790`. error: could not compile `traits-example` due to previous error diff --git a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs index 4bcec44..11643a8 100755 --- a/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs +++ b/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/src/lib.rs @@ -1,5 +1,3 @@ -extern crate proc_macro; - use proc_macro::TokenStream; use quote::quote; use syn; diff --git a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs index 591f0c3..dac6c98 100755 --- a/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs +++ b/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/src/lib.rs @@ -1,5 +1,3 @@ -extern crate proc_macro; - use proc_macro::TokenStream; use quote::quote; use syn; diff --git a/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt b/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt index d6fffc9..104f2cf 100755 --- a/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt +++ b/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt @@ -7,7 +7,7 @@ error[E0746]: return type cannot have an unboxed trait object | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see -help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of type `[closure@src/lib.rs:2:5: 2:14]`, which implements `Fn(i32) -> i32` +help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of type `[closure@src/lib.rs:2:5: 2:8]`, which implements `Fn(i32) -> i32` | 1 | fn returns_closure() -> impl Fn(i32) -> i32 { | ~~~~~~~~~~~~~~~~~~~ diff --git a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs index 7a3279d..5e0b96c 100755 --- a/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs +++ b/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/src/lib.rs @@ -1,5 +1,3 @@ -extern crate proc_macro; - use proc_macro::TokenStream; use quote::quote; use syn; diff --git a/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock new file mode 100755 index 0000000..58b70c5 --- /dev/null +++ b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "counter" +version = "0.1.0" + diff --git a/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml new file mode 100755 index 0000000..9e103f3 --- /dev/null +++ b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "counter" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs new file mode 100755 index 0000000..04c7f38 --- /dev/null +++ b/listings/ch19-advanced-features/no-listing-22-iterator-on-counter/src/lib.rs @@ -0,0 +1,25 @@ +struct Counter { + count: u32, +} + +impl Counter { + fn new() -> Counter { + Counter { count: 0 } + } +} + +// ANCHOR: ch19 +impl Iterator for Counter { + type Item = u32; + + fn next(&mut self) -> Option { + // --snip-- + // ANCHOR_END: ch19 + if self.count < 5 { + self.count += 1; + Some(self.count) + } else { + None + } + } +} diff --git a/listings/ch20-web-server/listing-20-02/src/main.rs b/listings/ch20-web-server/listing-20-02/src/main.rs index 2e68f2f..7240c73 100755 --- a/listings/ch20-web-server/listing-20-02/src/main.rs +++ b/listings/ch20-web-server/listing-20-02/src/main.rs @@ -1,6 +1,7 @@ -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; +use std::{ + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); @@ -13,9 +14,12 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let mut buffer = [0; 1024]; + let buf_reader = BufReader::new(&mut stream); + let http_request: Vec<_> = buf_reader + .lines() + .map(|result| result.unwrap()) + .take_while(|line| !line.is_empty()) + .collect(); - stream.read(&mut buffer).unwrap(); - - println!("Request: {}", String::from_utf8_lossy(&buffer[..])); + println!("Request: {:#?}", http_request); } diff --git a/listings/ch20-web-server/listing-20-03/src/main.rs b/listings/ch20-web-server/listing-20-03/src/main.rs index afa579a..c72d4a9 100755 --- a/listings/ch20-web-server/listing-20-03/src/main.rs +++ b/listings/ch20-web-server/listing-20-03/src/main.rs @@ -1,6 +1,7 @@ -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; +use std::{ + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); @@ -14,13 +15,15 @@ fn main() { // ANCHOR: here fn handle_connection(mut stream: TcpStream) { - let mut buffer = [0; 1024]; - - stream.read(&mut buffer).unwrap(); + let buf_reader = BufReader::new(&mut stream); + let http_request: Vec<_> = buf_reader + .lines() + .map(|result| result.unwrap()) + .take_while(|line| !line.is_empty()) + .collect(); let response = "HTTP/1.1 200 OK\r\n\r\n"; - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); } // ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-05/src/main.rs b/listings/ch20-web-server/listing-20-05/src/main.rs index d20417c..d4b78b6 100755 --- a/listings/ch20-web-server/listing-20-05/src/main.rs +++ b/listings/ch20-web-server/listing-20-05/src/main.rs @@ -1,12 +1,12 @@ // ANCHOR: here -use std::fs; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; // --snip-- // ANCHOR_END: here -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; - fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); @@ -19,18 +19,20 @@ fn main() { // ANCHOR: here fn handle_connection(mut stream: TcpStream) { - let mut buffer = [0; 1024]; - stream.read(&mut buffer).unwrap(); - + let buf_reader = BufReader::new(&mut stream); + let http_request: Vec<_> = buf_reader + .lines() + .map(|result| result.unwrap()) + .take_while(|line| !line.is_empty()) + .collect(); + + let status_line = "HTTP/1.1 200 OK"; let contents = fs::read_to_string("hello.html").unwrap(); + let length = contents.len(); - let response = format!( - "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}", - contents.len(), - contents - ); + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); } // ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-06/src/main.rs b/listings/ch20-web-server/listing-20-06/src/main.rs index 8353244..5523a42 100755 --- a/listings/ch20-web-server/listing-20-06/src/main.rs +++ b/listings/ch20-web-server/listing-20-06/src/main.rs @@ -1,7 +1,8 @@ -use std::fs; -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); @@ -12,27 +13,23 @@ fn main() { handle_connection(stream); } } - // ANCHOR: here // --snip-- fn handle_connection(mut stream: TcpStream) { - let mut buffer = [0; 1024]; - stream.read(&mut buffer).unwrap(); - - let get = b"GET / HTTP/1.1\r\n"; + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); - if buffer.starts_with(get) { + if request_line == "GET / HTTP/1.1" { + let status_line = "HTTP/1.1 200 OK"; let contents = fs::read_to_string("hello.html").unwrap(); + let length = contents.len(); let response = format!( - "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}", - contents.len(), - contents + "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}" ); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); } else { // some other request } diff --git a/listings/ch20-web-server/listing-20-07/404.html b/listings/ch20-web-server/listing-20-07/404.html new file mode 100755 index 0000000..88d8e91 --- /dev/null +++ b/listings/ch20-web-server/listing-20-07/404.html @@ -0,0 +1,11 @@ + + + + + Hello! + + +

Oops!

+

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

+ + diff --git a/listings/ch20-web-server/listing-20-07/src/main.rs b/listings/ch20-web-server/listing-20-07/src/main.rs index 4d19e04..a14b7d5 100755 --- a/listings/ch20-web-server/listing-20-07/src/main.rs +++ b/listings/ch20-web-server/listing-20-07/src/main.rs @@ -1,7 +1,8 @@ -use std::fs; -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); @@ -14,37 +15,31 @@ fn main() { } fn handle_connection(mut stream: TcpStream) { - let mut buffer = [0; 1024]; - stream.read(&mut buffer).unwrap(); + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); - let get = b"GET / HTTP/1.1\r\n"; - - if buffer.starts_with(get) { + if request_line == "GET / HTTP/1.1" { + let status_line = "HTTP/1.1 200 OK"; let contents = fs::read_to_string("hello.html").unwrap(); + let length = contents.len(); let response = format!( - "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}", - contents.len(), - contents + "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}" ); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); // ANCHOR: here // --snip-- } else { let status_line = "HTTP/1.1 404 NOT FOUND"; let contents = fs::read_to_string("404.html").unwrap(); + let length = contents.len(); let response = format!( - "{}\r\nContent-Length: {}\r\n\r\n{}", - status_line, - contents.len(), - contents + "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}" ); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); } // ANCHOR_END: here } diff --git a/listings/ch20-web-server/listing-20-09/src/main.rs b/listings/ch20-web-server/listing-20-09/src/main.rs index e2f2f9f..ffc51e8 100755 --- a/listings/ch20-web-server/listing-20-09/src/main.rs +++ b/listings/ch20-web-server/listing-20-09/src/main.rs @@ -1,7 +1,8 @@ -use std::fs; -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, +}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); @@ -12,36 +13,28 @@ fn main() { handle_connection(stream); } } - // ANCHOR: here // --snip-- fn handle_connection(mut stream: TcpStream) { // --snip-- - // ANCHOR_END: here - let mut buffer = [0; 1024]; - stream.read(&mut buffer).unwrap(); - - let get = b"GET / HTTP/1.1\r\n"; - + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); // ANCHOR: here - let (status_line, filename) = if buffer.starts_with(get) { + + let (status_line, filename) = if request_line == "GET / HTTP/1.1" { ("HTTP/1.1 200 OK", "hello.html") } else { ("HTTP/1.1 404 NOT FOUND", "404.html") }; let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); - let response = format!( - "{}\r\nContent-Length: {}\r\n\r\n{}", - status_line, - contents.len(), - contents - ); + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); } // ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-10/src/main.rs b/listings/ch20-web-server/listing-20-10/src/main.rs index c4361e5..5a18b45 100755 --- a/listings/ch20-web-server/listing-20-10/src/main.rs +++ b/listings/ch20-web-server/listing-20-10/src/main.rs @@ -1,10 +1,11 @@ -use std::fs; -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; // ANCHOR: here -use std::thread; -use std::time::Duration; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; // --snip-- // ANCHOR_END: here @@ -23,36 +24,29 @@ fn handle_connection(mut stream: TcpStream) { // --snip-- // ANCHOR_END: here - let mut buffer = [0; 1024]; - stream.read(&mut buffer).unwrap(); + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); // ANCHOR: here - let get = b"GET / HTTP/1.1\r\n"; - let sleep = b"GET /sleep HTTP/1.1\r\n"; - - let (status_line, filename) = if buffer.starts_with(get) { - ("HTTP/1.1 200 OK", "hello.html") - } else if buffer.starts_with(sleep) { - thread::sleep(Duration::from_secs(5)); - ("HTTP/1.1 200 OK", "hello.html") - } else { - ("HTTP/1.1 404 NOT FOUND", "404.html") + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), }; // --snip-- // ANCHOR_END: here let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); - let response = format!( - "{}\r\nContent-Length: {}\r\n\r\n{}", - status_line, - contents.len(), - contents - ); + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); // ANCHOR: here } // ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-11/src/main.rs b/listings/ch20-web-server/listing-20-11/src/main.rs index bf88f94..1181357 100755 --- a/listings/ch20-web-server/listing-20-11/src/main.rs +++ b/listings/ch20-web-server/listing-20-11/src/main.rs @@ -1,9 +1,10 @@ -use std::fs; -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; -use std::thread; -use std::time::Duration; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; // ANCHOR: here fn main() { @@ -20,30 +21,23 @@ fn main() { // ANCHOR_END: here fn handle_connection(mut stream: TcpStream) { - let mut buffer = [0; 1024]; - stream.read(&mut buffer).unwrap(); - - let get = b"GET / HTTP/1.1\r\n"; - let sleep = b"GET /sleep HTTP/1.1\r\n"; - - let (status_line, filename) = if buffer.starts_with(get) { - ("HTTP/1.1 200 OK", "hello.html") - } else if buffer.starts_with(sleep) { - thread::sleep(Duration::from_secs(5)); - ("HTTP/1.1 200 OK", "hello.html") - } else { - ("HTTP/1.1 404 NOT FOUND", "404.html") + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), }; let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); - let response = format!( - "{}\r\nContent-Length: {}\r\n\r\n{}", - status_line, - contents.len(), - contents - ); + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); } diff --git a/listings/ch20-web-server/listing-20-12/output.txt b/listings/ch20-web-server/listing-20-12/output.txt index d320061..57a58b9 100755 --- a/listings/ch20-web-server/listing-20-12/output.txt +++ b/listings/ch20-web-server/listing-20-12/output.txt @@ -1,9 +1,9 @@ $ cargo check Checking hello v0.1.0 (file:///projects/hello) error[E0433]: failed to resolve: use of undeclared type `ThreadPool` - --> src/main.rs:10:16 + --> src/main.rs:11:16 | -10 | let pool = ThreadPool::new(4); +11 | let pool = ThreadPool::new(4); | ^^^^^^^^^^ use of undeclared type `ThreadPool` For more information about this error, try `rustc --explain E0433`. diff --git a/listings/ch20-web-server/listing-20-12/src/main.rs b/listings/ch20-web-server/listing-20-12/src/main.rs index ff0fd45..21b9a80 100755 --- a/listings/ch20-web-server/listing-20-12/src/main.rs +++ b/listings/ch20-web-server/listing-20-12/src/main.rs @@ -1,9 +1,10 @@ -use std::fs; -use std::io::prelude::*; -use std::net::TcpListener; -use std::net::TcpStream; -use std::thread; -use std::time::Duration; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; // ANCHOR: here fn main() { @@ -21,30 +22,23 @@ fn main() { // ANCHOR_END: here fn handle_connection(mut stream: TcpStream) { - let mut buffer = [0; 1024]; - stream.read(&mut buffer).unwrap(); - - let get = b"GET / HTTP/1.1\r\n"; - let sleep = b"GET /sleep HTTP/1.1\r\n"; - - let (status_line, filename) = if buffer.starts_with(get) { - ("HTTP/1.1 200 OK", "hello.html") - } else if buffer.starts_with(sleep) { - thread::sleep(Duration::from_secs(5)); - ("HTTP/1.1 200 OK", "hello.html") - } else { - ("HTTP/1.1 404 NOT FOUND", "404.html") + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), }; let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); - let response = format!( - "{}\r\nContent-Length: {}\r\n\r\n{}", - status_line, - contents.len(), - contents - ); + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); - stream.write(response.as_bytes()).unwrap(); - stream.flush().unwrap(); + stream.write_all(response.as_bytes()).unwrap(); } diff --git a/listings/ch20-web-server/listing-20-13/src/lib.rs b/listings/ch20-web-server/listing-20-13/src/lib.rs index 248fb52..34e5410 100755 --- a/listings/ch20-web-server/listing-20-13/src/lib.rs +++ b/listings/ch20-web-server/listing-20-13/src/lib.rs @@ -17,7 +17,6 @@ impl ThreadPool { // --snip-- // ANCHOR_END: here - pub fn execute(&self, f: F) where F: FnOnce() + Send + 'static, diff --git a/listings/ch20-web-server/listing-20-13/src/main.rs b/listings/ch20-web-server/listing-20-13/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-13/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-14/src/lib.rs b/listings/ch20-web-server/listing-20-14/src/lib.rs index 509a62e..c1fa182 100755 --- a/listings/ch20-web-server/listing-20-14/src/lib.rs +++ b/listings/ch20-web-server/listing-20-14/src/lib.rs @@ -27,7 +27,6 @@ impl ThreadPool { ThreadPool { threads } } - // --snip-- // ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-14/src/main.rs b/listings/ch20-web-server/listing-20-14/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-14/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-15/src/main.rs b/listings/ch20-web-server/listing-20-15/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-15/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-16/src/lib.rs b/listings/ch20-web-server/listing-20-16/src/lib.rs index 02d20cb..411c1d0 100755 --- a/listings/ch20-web-server/listing-20-16/src/lib.rs +++ b/listings/ch20-web-server/listing-20-16/src/lib.rs @@ -1,7 +1,5 @@ -use std::thread; // ANCHOR: here -// --snip-- -use std::sync::mpsc; +use std::{sync::mpsc, thread}; pub struct ThreadPool { workers: Vec, diff --git a/listings/ch20-web-server/listing-20-16/src/main.rs b/listings/ch20-web-server/listing-20-16/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-16/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-17/output.txt b/listings/ch20-web-server/listing-20-17/output.txt index da2301e..8bedfec 100755 --- a/listings/ch20-web-server/listing-20-17/output.txt +++ b/listings/ch20-web-server/listing-20-17/output.txt @@ -1,12 +1,12 @@ $ cargo check Checking hello v0.1.0 (file:///projects/hello) error[E0382]: use of moved value: `receiver` - --> src/lib.rs:27:42 + --> src/lib.rs:26:42 | -22 | let (sender, receiver) = mpsc::channel(); +21 | let (sender, receiver) = mpsc::channel(); | -------- move occurs because `receiver` has type `std::sync::mpsc::Receiver`, which does not implement the `Copy` trait ... -27 | workers.push(Worker::new(id, receiver)); +26 | workers.push(Worker::new(id, receiver)); | ^^^^^^^^ value moved here, in previous iteration of loop For more information about this error, try `rustc --explain E0382`. diff --git a/listings/ch20-web-server/listing-20-17/src/lib.rs b/listings/ch20-web-server/listing-20-17/src/lib.rs index f3ce7d0..d764879 100755 --- a/listings/ch20-web-server/listing-20-17/src/lib.rs +++ b/listings/ch20-web-server/listing-20-17/src/lib.rs @@ -1,5 +1,4 @@ -use std::sync::mpsc; -use std::thread; +use std::{sync::mpsc, thread}; pub struct ThreadPool { workers: Vec, diff --git a/listings/ch20-web-server/listing-20-17/src/main.rs b/listings/ch20-web-server/listing-20-17/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-17/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-18/src/lib.rs b/listings/ch20-web-server/listing-20-18/src/lib.rs index 8197353..4bff8ac 100755 --- a/listings/ch20-web-server/listing-20-18/src/lib.rs +++ b/listings/ch20-web-server/listing-20-18/src/lib.rs @@ -1,8 +1,8 @@ -use std::sync::mpsc; -use std::thread; // ANCHOR: here -use std::sync::Arc; -use std::sync::Mutex; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; // --snip-- // ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-18/src/main.rs b/listings/ch20-web-server/listing-20-18/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-18/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-19/src/lib.rs b/listings/ch20-web-server/listing-20-19/src/lib.rs index 734d4c2..aeb1fac 100755 --- a/listings/ch20-web-server/listing-20-19/src/lib.rs +++ b/listings/ch20-web-server/listing-20-19/src/lib.rs @@ -1,7 +1,7 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, diff --git a/listings/ch20-web-server/listing-20-19/src/main.rs b/listings/ch20-web-server/listing-20-19/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-19/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-20/src/lib.rs b/listings/ch20-web-server/listing-20-20/src/lib.rs index 5fdc32e..86157c9 100755 --- a/listings/ch20-web-server/listing-20-20/src/lib.rs +++ b/listings/ch20-web-server/listing-20-20/src/lib.rs @@ -1,7 +1,7 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, @@ -57,7 +57,7 @@ impl Worker { let thread = thread::spawn(move || loop { let job = receiver.lock().unwrap().recv().unwrap(); - println!("Worker {} got a job; executing.", id); + println!("Worker {id} got a job; executing."); job(); }); diff --git a/listings/ch20-web-server/listing-20-20/src/main.rs b/listings/ch20-web-server/listing-20-20/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-20/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-21/src/lib.rs b/listings/ch20-web-server/listing-20-21/src/lib.rs index 6bde524..17b37e7 100755 --- a/listings/ch20-web-server/listing-20-21/src/lib.rs +++ b/listings/ch20-web-server/listing-20-21/src/lib.rs @@ -1,7 +1,7 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, @@ -55,7 +55,7 @@ impl Worker { fn new(id: usize, receiver: Arc>>) -> Worker { let thread = thread::spawn(move || { while let Ok(job) = receiver.lock().unwrap().recv() { - println!("Worker {} got a job; executing.", id); + println!("Worker {id} got a job; executing."); job(); } diff --git a/listings/ch20-web-server/listing-20-21/src/main.rs b/listings/ch20-web-server/listing-20-21/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-21/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-22/output.txt b/listings/ch20-web-server/listing-20-22/output.txt index 39801ac..a6c9e8d 100755 --- a/listings/ch20-web-server/listing-20-22/output.txt +++ b/listings/ch20-web-server/listing-20-22/output.txt @@ -4,7 +4,11 @@ error[E0507]: cannot move out of `worker.thread` which is behind a mutable refer --> src/lib.rs:52:13 | 52 | worker.thread.join().unwrap(); - | ^^^^^^^^^^^^^ move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait + | ^^^^^^^^^^^^^ ------ `worker.thread` moved due to this method call + | | + | move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait + | +note: this function takes ownership of the receiver `self`, which moves `worker.thread` For more information about this error, try `rustc --explain E0507`. error: could not compile `hello` due to previous error diff --git a/listings/ch20-web-server/listing-20-22/src/lib.rs b/listings/ch20-web-server/listing-20-22/src/lib.rs index 8242578..72a8c48 100755 --- a/listings/ch20-web-server/listing-20-22/src/lib.rs +++ b/listings/ch20-web-server/listing-20-22/src/lib.rs @@ -1,7 +1,7 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, @@ -66,7 +66,7 @@ impl Worker { let thread = thread::spawn(move || loop { let job = receiver.lock().unwrap().recv().unwrap(); - println!("Worker {} got a job; executing.", id); + println!("Worker {id} got a job; executing."); job(); }); diff --git a/listings/ch20-web-server/listing-20-22/src/main.rs b/listings/ch20-web-server/listing-20-22/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/listing-20-22/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-23/src/lib.rs b/listings/ch20-web-server/listing-20-23/src/lib.rs index 6ccaee7..eea339b 100755 --- a/listings/ch20-web-server/listing-20-23/src/lib.rs +++ b/listings/ch20-web-server/listing-20-23/src/lib.rs @@ -1,28 +1,20 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; // ANCHOR: here pub struct ThreadPool { workers: Vec, - sender: mpsc::Sender, + sender: Option>, } - // --snip-- - // ANCHOR_END: here -type Job = Box; -enum Message { - NewJob(Job), - Terminate, -} +type Job = Box; // ANCHOR: here impl ThreadPool { - // --snip-- - // ANCHOR_END: here /// Create a new ThreadPool. /// @@ -31,7 +23,11 @@ impl ThreadPool { /// # Panics /// /// The `new` function will panic if the size is zero. + // ANCHOR: here pub fn new(size: usize) -> ThreadPool { + // --snip-- + + // ANCHOR_END: here assert!(size > 0); let (sender, receiver) = mpsc::channel(); @@ -44,25 +40,27 @@ impl ThreadPool { workers.push(Worker::new(id, Arc::clone(&receiver))); } - ThreadPool { workers, sender } + // ANCHOR: here + ThreadPool { + workers, + sender: Some(sender), + } } - // ANCHOR: here pub fn execute(&self, f: F) where F: FnOnce() + Send + 'static, { let job = Box::new(f); - self.sender.send(Message::NewJob(job)).unwrap(); + self.sender.as_ref().unwrap().send(job).unwrap(); } } -// --snip-- - -// ANCHOR_END: here impl Drop for ThreadPool { fn drop(&mut self) { + drop(self.sender.take()); + for worker in &mut self.workers { println!("Shutting down worker {}", worker.id); @@ -72,30 +70,21 @@ impl Drop for ThreadPool { } } } +// ANCHOR_END: here struct Worker { id: usize, thread: Option>, } -// ANCHOR: here impl Worker { - fn new(id: usize, receiver: Arc>>) -> Worker { + fn new(id: usize, receiver: Arc>>) -> Worker { let thread = thread::spawn(move || loop { - let message = receiver.lock().unwrap().recv().unwrap(); - - match message { - Message::NewJob(job) => { - println!("Worker {} got a job; executing.", id); + let job = receiver.lock().unwrap().recv().unwrap(); - job(); - } - Message::Terminate => { - println!("Worker {} was told to terminate.", id); + println!("Worker {id} got a job; executing."); - break; - } - } + job(); }); Worker { @@ -104,4 +93,3 @@ impl Worker { } } } -// ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-23/src/main.rs b/listings/ch20-web-server/listing-20-23/src/main.rs new file mode 100755 index 0000000..b6aa046 --- /dev/null +++ b/listings/ch20-web-server/listing-20-23/src/main.rs @@ -0,0 +1,45 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming().take(2) { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } + + println!("Shutting down."); +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-24/src/lib.rs b/listings/ch20-web-server/listing-20-24/src/lib.rs index 747bff2..28c0dea 100755 --- a/listings/ch20-web-server/listing-20-24/src/lib.rs +++ b/listings/ch20-web-server/listing-20-24/src/lib.rs @@ -1,20 +1,15 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, - sender: mpsc::Sender, + sender: Option>, } type Job = Box; -enum Message { - NewJob(Job), - Terminate, -} - impl ThreadPool { /// Create a new ThreadPool. /// @@ -36,7 +31,10 @@ impl ThreadPool { workers.push(Worker::new(id, Arc::clone(&receiver))); } - ThreadPool { workers, sender } + ThreadPool { + workers, + sender: Some(sender), + } } pub fn execute(&self, f: F) @@ -45,20 +43,13 @@ impl ThreadPool { { let job = Box::new(f); - self.sender.send(Message::NewJob(job)).unwrap(); + self.sender.as_ref().unwrap().send(job).unwrap(); } } -// ANCHOR: here impl Drop for ThreadPool { fn drop(&mut self) { - println!("Sending terminate message to all workers."); - - for _ in &self.workers { - self.sender.send(Message::Terminate).unwrap(); - } - - println!("Shutting down all workers."); + drop(self.sender.take()); for worker in &mut self.workers { println!("Shutting down worker {}", worker.id); @@ -69,27 +60,26 @@ impl Drop for ThreadPool { } } } -// ANCHOR_END: here struct Worker { id: usize, thread: Option>, } +// ANCHOR: here impl Worker { - fn new(id: usize, receiver: Arc>>) -> Worker { + fn new(id: usize, receiver: Arc>>) -> Worker { let thread = thread::spawn(move || loop { - let message = receiver.lock().unwrap().recv().unwrap(); + let message = receiver.lock().unwrap().recv(); match message { - Message::NewJob(job) => { - println!("Worker {} got a job; executing.", id); + Ok(job) => { + println!("Worker {id} got a job; executing."); job(); } - Message::Terminate => { - println!("Worker {} was told to terminate.", id); - + Err(_) => { + println!("Worker {id} disconnected; shutting down."); break; } } @@ -101,3 +91,4 @@ impl Worker { } } } +// ANCHOR_END: here diff --git a/listings/ch20-web-server/listing-20-24/src/main.rs b/listings/ch20-web-server/listing-20-24/src/main.rs new file mode 100755 index 0000000..b6aa046 --- /dev/null +++ b/listings/ch20-web-server/listing-20-24/src/main.rs @@ -0,0 +1,45 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming().take(2) { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } + + println!("Shutting down."); +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/listing-20-25/src/lib.rs b/listings/ch20-web-server/listing-20-25/src/lib.rs index 68f4263..54c0489 100755 --- a/listings/ch20-web-server/listing-20-25/src/lib.rs +++ b/listings/ch20-web-server/listing-20-25/src/lib.rs @@ -1,20 +1,15 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, - sender: mpsc::Sender, + sender: Option>, } type Job = Box; -enum Message { - NewJob(Job), - Terminate, -} - impl ThreadPool { /// Create a new ThreadPool. /// @@ -36,7 +31,10 @@ impl ThreadPool { workers.push(Worker::new(id, Arc::clone(&receiver))); } - ThreadPool { workers, sender } + ThreadPool { + workers, + sender: Some(sender), + } } pub fn execute(&self, f: F) @@ -45,19 +43,13 @@ impl ThreadPool { { let job = Box::new(f); - self.sender.send(Message::NewJob(job)).unwrap(); + self.sender.as_ref().unwrap().send(job).unwrap(); } } impl Drop for ThreadPool { fn drop(&mut self) { - println!("Sending terminate message to all workers."); - - for _ in &self.workers { - self.sender.send(Message::Terminate).unwrap(); - } - - println!("Shutting down all workers."); + drop(self.sender.take()); for worker in &mut self.workers { println!("Shutting down worker {}", worker.id); @@ -75,19 +67,18 @@ struct Worker { } impl Worker { - fn new(id: usize, receiver: Arc>>) -> Worker { + fn new(id: usize, receiver: Arc>>) -> Worker { let thread = thread::spawn(move || loop { - let message = receiver.lock().unwrap().recv().unwrap(); + let message = receiver.lock().unwrap().recv(); match message { - Message::NewJob(job) => { - println!("Worker {} got a job; executing.", id); + Ok(job) => { + println!("Worker {id} got a job; executing."); job(); } - Message::Terminate => { - println!("Worker {} was told to terminate.", id); - + Err(_) => { + println!("Worker {id} disconnected; shutting down."); break; } } diff --git a/listings/ch20-web-server/listing-20-25/src/main.rs b/listings/ch20-web-server/listing-20-25/src/main.rs new file mode 100755 index 0000000..a649ff1 --- /dev/null +++ b/listings/ch20-web-server/listing-20-25/src/main.rs @@ -0,0 +1,53 @@ +use hello::ThreadPool; +use std::fs; +use std::io::prelude::*; +use std::net::TcpListener; +use std::net::TcpStream; +use std::thread; +use std::time::Duration; + +// ANCHOR: here +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming().take(2) { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } + + println!("Shutting down."); +} +// ANCHOR_END: here + +fn handle_connection(mut stream: TcpStream) { + let mut buffer = [0; 1024]; + stream.read(&mut buffer).unwrap(); + + let get = b"GET / HTTP/1.1\r\n"; + let sleep = b"GET /sleep HTTP/1.1\r\n"; + + let (status_line, filename) = if buffer.starts_with(get) { + ("HTTP/1.1 200 OK", "hello.html") + } else if buffer.starts_with(sleep) { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } else { + ("HTTP/1.1 404 NOT FOUND", "404.html") + }; + + let contents = fs::read_to_string(filename).unwrap(); + + let response = format!( + "{}\r\nContent-Length: {}\r\n\r\n{}", + status_line, + contents.len(), + contents + ); + + stream.write_all(response.as_bytes()).unwrap(); + stream.flush().unwrap(); +} diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt b/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt index 4cc1d13..fa337b8 100755 --- a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt +++ b/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt @@ -1,9 +1,9 @@ $ cargo check Checking hello v0.1.0 (file:///projects/hello) error[E0599]: no function or associated item named `new` found for struct `ThreadPool` in the current scope - --> src/bin/main.rs:11:28 + --> src/main.rs:12:28 | -11 | let pool = ThreadPool::new(4); +12 | let pool = ThreadPool::new(4); | ^^^ function or associated item not found in `ThreadPool` For more information about this error, try `rustc --explain E0599`. diff --git a/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs b/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs new file mode 100755 index 0000000..f7b4216 --- /dev/null +++ b/listings/ch20-web-server/no-listing-01-define-threadpool-struct/src/main.rs @@ -0,0 +1,45 @@ +// ANCHOR: here +use hello::ThreadPool; +// ANCHOR_END: here +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt b/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt index 72d4cd9..44c8f39 100755 --- a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt +++ b/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt @@ -1,9 +1,9 @@ $ cargo check Checking hello v0.1.0 (file:///projects/hello) error[E0599]: no method named `execute` found for struct `ThreadPool` in the current scope - --> src/bin/main.rs:16:14 + --> src/main.rs:17:14 | -16 | pool.execute(|| { +17 | pool.execute(|| { | ^^^^^^^ method not found in `ThreadPool` For more information about this error, try `rustc --explain E0599`. diff --git a/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs b/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/no-listing-02-impl-threadpool-new/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs b/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/no-listing-03-define-execute/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt b/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt index 21c726c..e4c0eeb 100755 --- a/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt +++ b/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt @@ -5,6 +5,12 @@ error[E0599]: no method named `join` found for enum `Option` in the current scop | 52 | worker.thread.join().unwrap(); | ^^^^ method not found in `Option>` + | +note: the method `join` exists on the type `JoinHandle<()>` +help: consider using `Option::expect` to unwrap the `JoinHandle<()>` value, panicking if the value is an `Option::None` + | +52 | worker.thread.expect("REASON").join().unwrap(); + | +++++++++++++++++ error[E0308]: mismatched types --> src/lib.rs:72:22 @@ -16,8 +22,8 @@ error[E0308]: mismatched types found struct `JoinHandle<_>` help: try wrapping the expression in `Some` | -72 | Worker { id, Some(thread) } - | +++++ + +72 | Worker { id, thread: Some(thread) } + | +++++++++++++ + Some errors have detailed explanations: E0308, E0599. For more information about an error, try `rustc --explain E0308`. diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/src/lib.rs b/listings/ch20-web-server/no-listing-04-update-worker-definition/src/lib.rs index 1098330..6ef710a 100755 --- a/listings/ch20-web-server/no-listing-04-update-worker-definition/src/lib.rs +++ b/listings/ch20-web-server/no-listing-04-update-worker-definition/src/lib.rs @@ -1,7 +1,7 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, @@ -66,7 +66,7 @@ impl Worker { let thread = thread::spawn(move || loop { let job = receiver.lock().unwrap().recv().unwrap(); - println!("Worker {} got a job; executing.", id); + println!("Worker {id} got a job; executing."); job(); }); diff --git a/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs b/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/no-listing-04-update-worker-definition/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/src/lib.rs b/listings/ch20-web-server/no-listing-05-fix-worker-new/src/lib.rs index 6bef23a..ede3750 100755 --- a/listings/ch20-web-server/no-listing-05-fix-worker-new/src/lib.rs +++ b/listings/ch20-web-server/no-listing-05-fix-worker-new/src/lib.rs @@ -1,7 +1,7 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, @@ -68,7 +68,7 @@ impl Worker { let thread = thread::spawn(move || loop { let job = receiver.lock().unwrap().recv().unwrap(); - println!("Worker {} got a job; executing.", id); + println!("Worker {id} got a job; executing."); job(); }); diff --git a/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs b/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs new file mode 100755 index 0000000..79efb28 --- /dev/null +++ b/listings/ch20-web-server/no-listing-05-fix-worker-new/src/main.rs @@ -0,0 +1,43 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming() { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs b/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs index d5b38a6..b795ea5 100755 --- a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs +++ b/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/lib.rs @@ -1,7 +1,7 @@ -use std::sync::mpsc; -use std::sync::Arc; -use std::sync::Mutex; -use std::thread; +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; pub struct ThreadPool { workers: Vec, @@ -68,7 +68,7 @@ impl Worker { let thread = thread::spawn(move || loop { let job = receiver.lock().unwrap().recv().unwrap(); - println!("Worker {} got a job; executing.", id); + println!("Worker {id} got a job; executing."); job(); }); diff --git a/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs b/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs new file mode 100755 index 0000000..b6aa046 --- /dev/null +++ b/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/src/main.rs @@ -0,0 +1,45 @@ +use hello::ThreadPool; +use std::{ + fs, + io::{prelude::*, BufReader}, + net::{TcpListener, TcpStream}, + thread, + time::Duration, +}; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming().take(2) { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } + + println!("Shutting down."); +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&mut stream); + let request_line = buf_reader.lines().next().unwrap().unwrap(); + + let (status_line, filename) = match &request_line[..] { + "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"), + "GET /sleep HTTP/1.1" => { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } + _ => ("HTTP/1.1 404 NOT FOUND", "404.html"), + }; + + let contents = fs::read_to_string(filename).unwrap(); + let length = contents.len(); + + let response = + format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); + + stream.write_all(response.as_bytes()).unwrap(); +} diff --git a/listings/ch20-web-server/no-listing-07-final-code/404.html b/listings/ch20-web-server/no-listing-07-final-code/404.html new file mode 100755 index 0000000..88d8e91 --- /dev/null +++ b/listings/ch20-web-server/no-listing-07-final-code/404.html @@ -0,0 +1,11 @@ + + + + + Hello! + + +

Oops!

+

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

+ + diff --git a/listings/ch20-web-server/no-listing-07-final-code/Cargo.lock b/listings/ch20-web-server/no-listing-07-final-code/Cargo.lock new file mode 100755 index 0000000..f2d069f --- /dev/null +++ b/listings/ch20-web-server/no-listing-07-final-code/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "hello" +version = "0.1.0" + diff --git a/listings/ch20-web-server/no-listing-07-final-code/Cargo.toml b/listings/ch20-web-server/no-listing-07-final-code/Cargo.toml new file mode 100755 index 0000000..fe61947 --- /dev/null +++ b/listings/ch20-web-server/no-listing-07-final-code/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch20-web-server/no-listing-07-final-code/hello.html b/listings/ch20-web-server/no-listing-07-final-code/hello.html new file mode 100755 index 0000000..fe442d6 --- /dev/null +++ b/listings/ch20-web-server/no-listing-07-final-code/hello.html @@ -0,0 +1,11 @@ + + + + + Hello! + + +

Hello!

+

Hi from Rust

+ + diff --git a/listings/ch20-web-server/no-listing-07-final-code/src/lib.rs b/listings/ch20-web-server/no-listing-07-final-code/src/lib.rs new file mode 100755 index 0000000..54c0489 --- /dev/null +++ b/listings/ch20-web-server/no-listing-07-final-code/src/lib.rs @@ -0,0 +1,92 @@ +use std::{ + sync::{mpsc, Arc, Mutex}, + thread, +}; + +pub struct ThreadPool { + workers: Vec, + sender: Option>, +} + +type Job = Box; + +impl ThreadPool { + /// Create a new ThreadPool. + /// + /// The size is the number of threads in the pool. + /// + /// # Panics + /// + /// The `new` function will panic if the size is zero. + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + + let (sender, receiver) = mpsc::channel(); + + let receiver = Arc::new(Mutex::new(receiver)); + + let mut workers = Vec::with_capacity(size); + + for id in 0..size { + workers.push(Worker::new(id, Arc::clone(&receiver))); + } + + ThreadPool { + workers, + sender: Some(sender), + } + } + + pub fn execute(&self, f: F) + where + F: FnOnce() + Send + 'static, + { + let job = Box::new(f); + + self.sender.as_ref().unwrap().send(job).unwrap(); + } +} + +impl Drop for ThreadPool { + fn drop(&mut self) { + drop(self.sender.take()); + + for worker in &mut self.workers { + println!("Shutting down worker {}", worker.id); + + if let Some(thread) = worker.thread.take() { + thread.join().unwrap(); + } + } + } +} + +struct Worker { + id: usize, + thread: Option>, +} + +impl Worker { + fn new(id: usize, receiver: Arc>>) -> Worker { + let thread = thread::spawn(move || loop { + let message = receiver.lock().unwrap().recv(); + + match message { + Ok(job) => { + println!("Worker {id} got a job; executing."); + + job(); + } + Err(_) => { + println!("Worker {id} disconnected; shutting down."); + break; + } + } + }); + + Worker { + id, + thread: Some(thread), + } + } +} diff --git a/listings/ch20-web-server/no-listing-07-final-code/src/main.rs b/listings/ch20-web-server/no-listing-07-final-code/src/main.rs new file mode 100755 index 0000000..3161c2e --- /dev/null +++ b/listings/ch20-web-server/no-listing-07-final-code/src/main.rs @@ -0,0 +1,51 @@ +use hello::ThreadPool; +use std::fs; +use std::io::prelude::*; +use std::net::TcpListener; +use std::net::TcpStream; +use std::thread; +use std::time::Duration; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + let pool = ThreadPool::new(4); + + for stream in listener.incoming().take(2) { + let stream = stream.unwrap(); + + pool.execute(|| { + handle_connection(stream); + }); + } + + println!("Shutting down."); +} + +fn handle_connection(mut stream: TcpStream) { + let mut buffer = [0; 1024]; + stream.read(&mut buffer).unwrap(); + + let get = b"GET / HTTP/1.1\r\n"; + let sleep = b"GET /sleep HTTP/1.1\r\n"; + + let (status_line, filename) = if buffer.starts_with(get) { + ("HTTP/1.1 200 OK", "hello.html") + } else if buffer.starts_with(sleep) { + thread::sleep(Duration::from_secs(5)); + ("HTTP/1.1 200 OK", "hello.html") + } else { + ("HTTP/1.1 404 NOT FOUND", "404.html") + }; + + let contents = fs::read_to_string(filename).unwrap(); + + let response = format!( + "{}\r\nContent-Length: {}\r\n\r\n{}", + status_line, + contents.len(), + contents + ); + + stream.write_all(response.as_bytes()).unwrap(); + stream.flush().unwrap(); +} diff --git a/src/ch00-00-introduction.md b/src/ch00-00-introduction.md index 25227c7..3eac407 100644 --- a/src/ch00-00-introduction.md +++ b/src/ch00-00-introduction.md @@ -2,7 +2,7 @@ > [ch00-00-introduction.md](https://github.com/rust-lang/book/blob/main/src/ch00-00-introduction.md) >
-> commit d036f7f049fb4884f63993901ff14d674c8dfb09 +> commit ace3550ad8c3da7aeab521f2e1f96a85b5c8f17d > 注意:此书的英文原版与 [No Starch Press][nsp] 出版的纸质版和电子版《[The Rust Programming Language][nsprust]》一致。 @@ -17,12 +17,12 @@ Rust 适合很多开发者,其原因多种多样。下面讨论几个最重要 ### 开发团队 -实践证明,对于大规模的开发团队,即使成员的系统编程水平不同,Rust 仍是高效的协作工具。底层代码中容易出现很多不易察觉的 bug。在其他编程语言中想要找到它们,只能设计大量的测试,并且让经验丰富的开发者细心审核代码。在 Rust 中,编译器充当了守门员的角色。如果代码中存在这些难找的 bug,比如并发的 bug,它会拒绝编译。只要与编译器协同工作,团队就可以花更多的时间聚焦在程序逻辑上,无需费心找 bug。 +实践证明,对于大规模的开发团队,即使成员的系统编程水平不同,Rust 仍是高效的协作工具。底层代码中容易出现多种不易察觉的 bug。在其他编程语言中想要找到它们,只能设计大量的测试,并且让经验丰富的开发者细心审核代码。在 Rust 中,编译器充当了守门员的角色。如果代码中存在这些难找的 bug,比如并发的 bug,它会拒绝编译。只要与编译器协同工作,团队就可以花更多的时间聚焦在程序逻辑上,无需费心找 bug。 Rust 也为系统编程世界带来了现代化的开发工具: * Cargo 是内置的依赖管理器和构建工具,它能轻松增加、编译和管理依赖,并使依赖在 Rust 生态系统中保持一致。 -* Rustfmt 确保开发者遵循一致的代码风格。 +* Rustfmt 格式化工具确保开发者遵循一致的代码风格。 * Rust Language Server 为集成开发环境(IDE)提供了强大的代码补全和内联错误信息功能。 通过使用 Rust 生态系统中丰富的工具,开发者可以更高效地编写系统层面代码。 @@ -41,7 +41,7 @@ Rust 适合那些希望构建 Rust 编程语言、社区、开发工具和库的 ### 重视速度和稳定性的开发者 -Rust 适合追求编程语言的速度与稳定性的开发者。使用 Rust,不仅写出来的程序运行速度快,写代码的速度也快。Rust 编译器会检查代码,确保增加功能、重构代码时的稳定性。与之相比,其他的一些语言没有检查功能,导致开发者往往不敢修改脆弱的祖传代码。Rust 力求将高级语言特性编译成底层代码,并且与手写的代码运行速度同样快,这一概念称为零开销抽象(zero-cost abstractions),可以让代码又安全又快速。 +Rust 适合追求编程语言的速度与稳定性的开发者。对于速度来说,既是指 Rust 可以运行的多快,也是指编写 Rust 程序的速度。Rust 编译器会检查代码,确保增加功能、重构代码时的稳定性。与之相比,其他的一些语言没有检查功能,导致开发者往往不敢修改脆弱的祖传代码。Rust 力求将高级语言特性编译成底层代码,并且与手写的代码运行速度同样快,这一概念称为零开销抽象(zero-cost abstractions),可以让代码又安全又快速。 这里提到的只是较大的几个受益群体,Rust 语言也希望能支持更多其他用户。总之,Rust 最重要的目标是消除数十年来程序员习以为常的取舍,让安全和高效、速度和易读易用**可以兼得**。试试看 Rust,说不定它的选择就适合你。 @@ -51,11 +51,11 @@ Rust 适合追求编程语言的速度与稳定性的开发者。使用 Rust, ## 如何阅读本书 -本书推荐从头到尾顺序阅读,因为靠后的章节需要前面章节的概念基础。前面的章节可能不会深入介绍部分主题,而是留待后续章节重新讨论。 +本书大体上假设您按从头到尾的顺序阅读。后面的章节建立于前面章节的基础上。前面的章节可能不会深入介绍部分主题,而是留待后续章节重新讨论。 本书分为两类章节:概念章节和项目章节。在概念章节中,我们学习 Rust 的某个方面。在项目章节中,我们应用目前所学的知识一同构建小型程序。第 2、12、20 章是项目章节;其余都是概念章节。 -第 1 章介绍如何安装 Rust,如何编写 “Hello, world!” 程序,以及如何使用 Rust 的包管理器和构建工具 Cargo。第 2 章是 Rust 语言的实战介绍。我们会站在较高的层次介绍一些概念,而将详细的介绍放在稍后的章节中。如果你希望立刻就动手实践一下,第 2 章正好适合你。第 3 章介绍 Rust 中类似其他编程语言的特性,你可以选择跳过,直接阅读第 4 章学习 Rust 的所有权(ownership)系统。不过,如果你注重细节,可以跳过第 2 章直接看第 3 章,之后想要写项目的时候再回来看第 2 章。 +第 1 章介绍如何安装 Rust,如何编写 “Hello, world!” 程序,以及如何使用 Rust 的包管理器和构建工具 Cargo。第 2 章是一个编写 Rust 语言的实战介绍,我们会构建一个猜猜看游戏。我们会站在较高的层次介绍一些概念,而将详细的介绍放在稍后的章节中。如果你希望立刻就动手实践一下,第 2 章正好适合你。第 3 章介绍 Rust 中类似其他编程语言的特性,你可以选择跳过,直接阅读第 4 章学习 Rust 的所有权(ownership)系统。不过,如果你注重细节,可以跳过第 2 章直接看第 3 章,之后想要写项目的时候再回来看第 2 章。 第 5 章讨论结构体(struct)和方法,第 6 章介绍枚举(enum)、`match` 表达式和 `if let` 控制流结构。在 Rust 中,创建自定义类型需要用到结构体和枚举。 diff --git a/src/ch01-01-installation.md b/src/ch01-01-installation.md index fe146a4..b364313 100644 --- a/src/ch01-01-installation.md +++ b/src/ch01-01-installation.md @@ -1,7 +1,7 @@ ## 安装 > [ch01-01-installation.md](https://github.com/rust-lang/book/blob/main/src/ch01-01-installation.md)
-> commit 1e17bf15b12f6f7b8d1711dbd343ef8993f64baa +> commit 2bd5d42c9956369132228da6409f0e68da56c51a 第一步是安装 Rust。我们会通过 `rustup` 下载 Rust,这是一个管理 Rust 版本和相关工具的命令行工具。下载时需要联网。 @@ -18,7 +18,7 @@ 如果你使用 Linux 或 macOS,打开终端并输入如下命令: ```console -$ curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh +$ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh ``` 此命令下载一个脚本并开始安装 `rustup` 工具,这会安装最新稳定版 Rust。过程中可能会提示你输入密码。如果安装成功,将会出现如下内容: @@ -39,11 +39,13 @@ Linux 用户通常需要根据发行版(distribution)文档安装 GCC 或 Cl ### 在 Windows 上安装 `rustup` -在 Windows 上,前往 [https://www.rust-lang.org/install.html][install] 并按照说明安装 Rust。在安装过程的某个步骤,你会收到一个信息说明为什么需要安装 Visual Studio 2013 或其更新版本的 MSVC 构建工具。要获取构建工具,你需要安装 [Visual Studio 2022][visualstudio]。当被问及需要安装什么工作负载(Workload)的时候,请确保勾选了以下内容: +在 Windows 上,前往 [https://www.rust-lang.org/install.html][install] 并按照说明安装 Rust。在安装过程的某个步骤,你会收到一个信息说明为什么需要安装 Visual Studio 2013 或其更新版本的 MSVC 构建工具。 -- “使用 C++ 的桌面开发”, -- Windows 10 (或 11) SDK, -- 英语语言包,以及其他你所需要的语言包。 +要获取构建工具,你需要安装 [Visual Studio 2022][visualstudio]。当被问及需要安装什么工作负载(Workload)的时候,请确保勾选了以下内容: + +- “使用 C++ 的桌面开发”(“Desktop Development with C++”) +- Windows 10(或 11)SDK +- 英语语言包,以及其他你所需要的语言包 本书的余下部分会使用能同时运行于 *cmd.exe* 和 PowerShell 的命令。如果存在特定差异,我们会解释使用哪一个。 @@ -75,23 +77,21 @@ rustc x.y.z (abcabcabc yyyy-mm-dd) 在 PowerShell 中,请使用命令: -```console +```powershell > echo $env:Path ``` 在 Linux 和 macOS 中,请使用命令: ```console -echo $PATH +$ echo $PATH ``` -如果一切正确但 Rust 仍不能使用,有许多地方可以求助。最简单的是[位于 Rust 官方 Discord][discord] 上的 #beginners 频道。在这里你可以和其他 Rustacean(Rust 用户的称号,有自嘲意味)聊天并寻求帮助。其它给力的资源包括[用户论坛][users]和 [Stack Overflow][stackoverflow]。 - -> 译者注:这些资源的主要语言都是英语。 +如果一切正确但 Rust 仍不能使用,有许多地方可以求助。您可以在[社区页面][community]查看如何与其他 Rustaceans(Rust 用户的称号,有自嘲意味)联系。 ## 更新与卸载 -通过 `rustup` 安装了 Rust 之后,很容易更新到最新版本,只需要在命令行中运行如下更新脚本即可: +通过 `rustup` 安装了 Rust 之后,更新到最新版本就很简单了,只需要在您对应的命令行中运行如下更新脚本: ```console $ rustup update @@ -112,6 +112,4 @@ $ rustup self uninstall [otherinstall]: https://forge.rust-lang.org/infra/other-installation-methods.html [install]: https://www.rust-lang.org/tools/install [visualstudio]: https://visualstudio.microsoft.com/downloads/ -[discord]: https://discord.gg/rust-lang -[users]: https://users.rust-lang.org/ -[stackoverflow]: https://stackoverflow.com/questions/tagged/rust +[community]: https://www.rust-lang.org/community diff --git a/src/ch01-02-hello-world.md b/src/ch01-02-hello-world.md index 0ba7049..4de02e4 100644 --- a/src/ch01-02-hello-world.md +++ b/src/ch01-02-hello-world.md @@ -2,9 +2,9 @@ > [ch01-02-hello-world.md](https://github.com/rust-lang/book/blob/main/src/ch01-02-hello-world.md) >
-> commit 3709acaf30b7e8e520c53e02aa8081f33f4a4c17 +> commit f801008f555e4e94aae826cf45f3a8011a773098 -既然安装好了 Rust,我们来编写第一个 Rust 程序。当学习一门新语言的时候,使用该语言在屏幕上打印 `Hello, world!` 是一项传统,我们将沿用这一传统! +既然安装好了 Rust,是时候来编写第一个 Rust 程序了。当学习一门新语言的时候,使用该语言在屏幕上打印 `Hello, world!` 是一项传统,我们将沿用这一传统! > 注意:本书假设你熟悉基本的命令行操作。Rust 对于你的编辑器、工具,以及代码位于何处并没有特定的要求,如果你更倾向于使用集成开发环境(IDE),而不是命令行,请尽管使用你喜欢的 IDE。目前很多 IDE 都在一定程度上支持 Rust;查看 IDE 文档以了解更多细节。Rust 团队一直致力于借助 `rust-analyzer` 提供强大的 IDE 支持。详见[附录 D][devtools]。 @@ -110,14 +110,14 @@ $ rustc main.rs 如果你有 C 或 C++ 背景,就会发现这与 `gcc` 和 `clang` 类似。编译成功后,Rust 会输出一个二进制的可执行文件。 -在 Linux、macOS 或 Windows 的 PowerShell 上,在 shell 中输入 `ls` 命令可以看见这个可执行文件。在 Linux 和 macOS,你会看到两个文件。在 Windows PowerShell 中,你会看到同使用 CMD 相同的三个文件。 +在 Linux、macOS 或 Windows 的 PowerShell 上,在 shell 中输入 `ls` 命令可以看见这个可执行文件。 ```console $ ls main main.rs ``` -在 Windows 的 CMD 上,则输入如下内容: +在 Linux 和 macOS,你会看到两个文件。在 Windows PowerShell 中,你会看到同使用 CMD 相同的三个文件。在 Windows 的 CMD 上,则输入如下内容: ```doscon > dir /B %= the /B option says to only show the file names =% diff --git a/src/ch01-03-hello-cargo.md b/src/ch01-03-hello-cargo.md index ead58d4..516ace5 100644 --- a/src/ch01-03-hello-cargo.md +++ b/src/ch01-03-hello-cargo.md @@ -2,7 +2,7 @@ > [ch01-03-hello-cargo.md](https://github.com/rust-lang/book/blob/main/src/ch01-03-hello-cargo.md) >
-> commit 0a5421ceb238357b3634fb75234eba4d1dad643c +> commit f801008f555e4e94aae826cf45f3a8011a773098 Cargo 是 Rust 的构建系统和包管理器。大多数 Rustacean 们使用 Cargo 来管理他们的 Rust 项目,因为它可以为你处理很多任务,比如构建代码、下载依赖库并编译这些库。(我们把代码所需要的库叫做 **依赖**(*dependencies*))。 @@ -52,8 +52,6 @@ edition = "2021" 这个文件使用 [*TOML*][toml] (*Tom's Obvious, Minimal Language*) 格式,这是 Cargo 配置文件的格式。 -[toml]: https://toml.io - 第一行,`[package]`,是一个片段(section)标题,表明下面的语句用来配置一个包。随着我们在这个文件增加更多的信息,还将增加其他片段(section)。 接下来的三行设置了 Cargo 编译程序所需的配置:项目的名称、项目的版本以及要使用的 Rust 版本。[附录 E][appendix-e] 会介绍 `edition` 的值。 @@ -152,9 +150,7 @@ $ cd someproject $ cargo build ``` -关于更多 Cargo 的信息,请查阅 [其文档][its documentation]。 - -[its documentation]: https://doc.rust-lang.org/cargo/ +关于更多 Cargo 的信息,请查阅 [其文档][cargo]。 ## 总结 @@ -169,4 +165,6 @@ $ cargo build 是时候通过构建更实质性的程序来熟悉读写 Rust 代码了。所以在第二章我们会构建一个猜猜看游戏程序。如果你更愿意从学习 Rust 常用的编程概念开始,请阅读第三章,接着再回到第二章。 [installation]: ch01-01-installation.html#installation +[toml]: https://toml.io [appendix-e]: appendix-05-editions.html +[cargo]: https://doc.rust-lang.org/cargo/ diff --git a/src/ch02-00-guessing-game-tutorial.md b/src/ch02-00-guessing-game-tutorial.md index 6290a81..e621763 100644 --- a/src/ch02-00-guessing-game-tutorial.md +++ b/src/ch02-00-guessing-game-tutorial.md @@ -4,7 +4,7 @@ >
> commit 6e2fe7c0f085989cc498cec139e717e2af172cb7 -让我们一起动手完成一个项目,来快速上手 Rust!本章将介绍 Rust 中一些常用概念,并通过真实的程序来展示如何运用它们。你将会学到 `let`、`match`、方法(method)、关联函数(associated function)、使用外部 crate 等知识!后续章节会深入探讨这些概念的细节。在这一章,我们将练习基础内容。 +让我们一起动手完成一个项目,来快速上手 Rust!本章将介绍 Rust 中一些常用概念,并通过真实的程序来展示如何运用它们。你将会学到 `let`、`match`、方法(method)、关联函数(associated function)、外部 crate 等知识!后续章节会深入探讨这些概念的细节。在这一章,我们将练习基础内容。 我们会实现一个经典的新手编程问题:猜猜看游戏。它是这么工作的:程序将会随机生成一个 1 到 100 之间的随机整数。接着它会请玩家猜一个数并输入,然后提示猜测是大了还是小了。如果猜对了,它会打印祝贺信息并退出。 @@ -122,7 +122,7 @@ let mut bananas = 5; // 可变 {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}} ``` -如果程序的开头没有使用 `use std::io` 引入 `io` 库,我们仍可以通过把函数调用写成 `std::io::stdin` 来使用函数。`stdin` 函数返回一个 [`std::io::Stdin`][iostdin] 的实例,这代表终端标准输入句柄的类型。 +如果程序的开头没有使用 `use std::io;` 引入 `io` 库,我们仍可以通过把函数调用写成 `std::io::stdin` 来使用函数。`stdin` 函数返回一个 [`std::io::Stdin`][iostdin] 的实例,这代表终端标准输入句柄的类型。 代码的下一部分,`.read_line(&mut guess)`,调用 [`read_line`][read_line] 方法从标准输入句柄获取用户输入。我们还将 `&mut guess` 作为参数传递给 `read_line()` 函数,让其将用户输入储存到这个字符串中。`read_line` 的工作是,无论用户在标准输入中键入什么内容,都将其追加(不会覆盖其原有内容)到一个字符串中,因此它需要字符串作为参数。这个字符串参数应该是可变的,以便 `read_line` 将用户输入附加上去。 @@ -147,7 +147,7 @@ io::stdin().read_line(&mut guess).expect("Failed to read line"); 之前提到了 `read_line` 会将用户输入附加到传递给它的字符串中,不过它也会返回一个类型为 `Result` 的值。 [`Result`][result] 是一种[*枚举类型*][enums],通常也写作 *enum*。枚举类型变量的值可以是多种可能状态中的一个。我们把每种可能的状态称为一种 *枚举成员(variant)*。 -第六章将介绍枚举的更多细节。这里的 `Result` 类型将用来编码错误处理的信息。 +[第六章][enums]将介绍枚举的更多细节。这里的 `Result` 类型将用来编码错误处理的信息。 `Result` 的成员是 `Ok` 和 `Err`,`Ok` 成员表示操作成功,内部包含成功时产生的值。`Err` 成员则意味着操作失败,并且包含失败的前因后果。 @@ -171,16 +171,16 @@ Rust 警告我们没有使用 `read_line` 的返回值 `Result`,说明有一 {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print_guess}} ``` -这行代码现在打印了存储用户输入的字符串。第一个参数是格式化字符串,里面的 `{}` 是预留在特定位置的占位符:把 `{}` 想象成小蟹钳,可以夹住合适的值。使用 `{}` 也可以打印多个值:第一对 `{}` 使用格式化字符串之后的第一个值,第二对则使用第二个值,依此类推。调用一次 `println!` 打印多个值看起来像这样: +这行代码现在打印了存储用户输入的字符串。里面的 `{}` 是预留在特定位置的占位符:把 `{}` 想象成小蟹钳,可以夹住合适的值。当打印变量的值时,变量名可以写进大括号中。当打印表达式的执行结果时,格式化字符串(format string)中大括号中留空,格式化字符串后跟逗号分隔的需要打印的表达式列表,其顺序与每一个空大括号占位符的顺序一致。在一个 `println!` 调用中打印变量和表达式的值看起来像这样: ```rust let x = 5; let y = 10; -println!("x = {} and y = {}", x, y); +println!("x = {x} and y + 2 = {}", y + 2); ``` -这行代码会打印出 `x = 5 and y = 10`。 +这行代码会打印出 `x = 5 and y + 2 = 12`。 ### 测试第一部分代码 @@ -212,32 +212,32 @@ Cargo 对外部 crate 的运用是其真正的亮点所在。在我们使用 `ra 文件名: Cargo.toml ```toml -{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}} +{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:8:}} ``` -在 _Cargo.toml_ 文件中,标题以及之后的内容属同一个片段,直到遇到下一个标题才开始新的片段。`[dependencies]` 片段告诉 Cargo 本项目依赖了哪些外部 crate 及其版本。本例中,我们使用语义化版本 `0.8.3` 来指定 `rand` crate。Cargo 理解 [语义化版本(Semantic Versioning)][semver](有时也称为 _SemVer_),这是一种定义版本号的标准。`0.8.3` 事实上是 `^0.8.3` 的简写,它表示任何至少是 `0.8.3` 但小于 `0.9.0` 的版本。 +在 _Cargo.toml_ 文件中,标题以及之后的内容属同一个片段,直到遇到下一个标题才开始新的片段。`[dependencies]` 片段告诉 Cargo 本项目依赖了哪些外部 crate 及其版本。本例中,我们使用语义化版本 `0.8.5` 来指定 `rand` crate。Cargo 理解 [语义化版本(Semantic Versioning)][semver](有时也称为 _SemVer_),这是一种定义版本号的标准。`0.8.5` 事实上是 `^0.8.5` 的简写,它表示任何至少是 `0.8.5` 但小于 `0.9.0` 的版本。 -Cargo 认为这些版本与 `0.8.3` 版本的公有 API 相兼容,这样的版本指定确保了我们可以获取能使本章代码编译的最新的补丁(patch)版本。任何大于等于 `0.9.0` 的版本不能保证和接下来的示例采用了相同的 API。 +Cargo 认为这些版本与 `0.8.5` 版本的公有 API 相兼容,这样的版本指定确保了我们可以获取能使本章代码编译的最新的补丁(patch)版本。任何大于等于 `0.9.0` 的版本不能保证和接下来的示例采用了相同的 API。 现在,不修改任何代码,构建项目,如示例 2-2 所示: ```console $ cargo build Updating crates.io index - Downloaded rand v0.8.3 - Downloaded libc v0.2.86 - Downloaded getrandom v0.2.2 + Downloaded rand v0.8.5 + Downloaded libc v0.2.127 + Downloaded getrandom v0.2.7 Downloaded cfg-if v1.0.0 - Downloaded ppv-lite86 v0.2.10 - Downloaded rand_chacha v0.3.0 - Downloaded rand_core v0.6.2 - Compiling rand_core v0.6.2 - Compiling libc v0.2.86 - Compiling getrandom v0.2.2 + Downloaded ppv-lite86 v0.2.16 + Downloaded rand_chacha v0.3.1 + Downloaded rand_core v0.6.3 + Compiling libc v0.2.127 + Compiling getrandom v0.2.7 Compiling cfg-if v1.0.0 - Compiling ppv-lite86 v0.2.10 - Compiling rand_chacha v0.3.0 - Compiling rand v0.8.3 + Compiling ppv-lite86 v0.2.16 + Compiling rand_core v0.6.3 + Compiling rand_chacha v0.3.1 + Compiling rand v0.8.5 Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Finished dev [unoptimized + debuginfo] target(s) in 2.53s ``` @@ -264,21 +264,21 @@ $ cargo build #### _Cargo.lock_ 文件确保构建是可重现的 -Cargo 有一个机制来确保任何人在任何时候重新构建代码,都会产生相同的结果:Cargo 只会使用你指定的依赖版本,除非你又手动指定了别的。例如,如果下周 `rand` crate 的 `0.8.4` 版本出来了,它修复了一个重要的 bug,同时也含有一个会破坏代码运行的缺陷。为了处理这个问题,Rust在你第一次运行 `cargo build` 时建立了 *Cargo.lock* 文件,我们现在可以在*guessing_game* 目录找到它。 +Cargo 有一个机制来确保任何人在任何时候重新构建代码,都会产生相同的结果:Cargo 只会使用你指定的依赖版本,除非你又手动指定了别的。例如,如果下周 `rand` crate 的 `0.8.6` 版本出来了,它修复了一个重要的 bug,同时也含有一个会破坏代码运行的缺陷。为了处理这个问题,Rust在你第一次运行 `cargo build` 时建立了 *Cargo.lock* 文件,我们现在可以在*guessing_game* 目录找到它。 -当第一次构建项目时,Cargo 计算出所有符合要求的依赖版本并写入 *Cargo.lock* 文件。当将来构建项目时,Cargo 会发现 *Cargo.lock* 已存在并使用其中指定的版本,而不是再次计算所有的版本。这使得你拥有了一个自动化的可重现的构建。换句话说,项目会持续使用 `0.8.3` 直到你显式升级,多亏有了 *Cargo.lock* 文件。由于 *Cargo.lock* 文件对于“可重复构建”非常重要,因此它通常会和项目中的其余代码一样纳入到版本控制系统中。 +当第一次构建项目时,Cargo 计算出所有符合要求的依赖版本并写入 *Cargo.lock* 文件。当将来构建项目时,Cargo 会发现 *Cargo.lock* 已存在并使用其中指定的版本,而不是再次计算所有的版本。这使得你拥有了一个自动化的可重现的构建。换句话说,项目会持续使用 `0.8.5` 直到你显式升级,多亏有了 *Cargo.lock* 文件。由于 *Cargo.lock* 文件对于“可重复构建”非常重要,因此它通常会和项目中的其余代码一样纳入到版本控制系统中。 #### 更新 crate 到一个新版本 -当你 **确实** 需要升级 crate 时,Cargo 提供了这样一个命令,`update`,它会忽略 *Cargo.lock* 文件,并计算出所有符合 *Cargo.toml* 声明的最新版本。Cargo 接下来会把这些版本写入 *Cargo.lock* 文件。不过,Cargo 默认只会寻找大于 `0.8.3` 而小于 `0.9.0` 的版本。如果 `rand` crate 发布了两个新版本,`0.8.4` 和 `0.9.0`,在运行 `cargo update` 时会出现如下内容: +当你 **确实** 需要升级 crate 时,Cargo 提供了这样一个命令,`update`,它会忽略 *Cargo.lock* 文件,并计算出所有符合 *Cargo.toml* 声明的最新版本。Cargo 接下来会把这些版本写入 *Cargo.lock* 文件。不过,Cargo 默认只会寻找大于 `0.8.5` 而小于 `0.9.0` 的版本。如果 `rand` crate 发布了两个新版本,`0.8.6` 和 `0.9.0`,在运行 `cargo update` 时会出现如下内容: ```console $ cargo update Updating crates.io index - Updating rand v0.8.3 -> v0.8.4 + Updating rand v0.8.5 -> v0.8.6 ``` -Cargo 忽略了 `0.9.0` 版本。这时,你也会注意到的 *Cargo.lock* 文件中的变化无外乎现在使用的 `rand` crate 版本是`0.8.4` 。如果想要使用 `0.9.0` 版本的 `rand` 或是任何 `0.9.x` 系列的版本,必须像这样更新 *Cargo.toml* 文件: +Cargo 忽略了 `0.9.0` 版本。这时,你也会注意到的 *Cargo.lock* 文件中的变化无外乎现在使用的 `rand` crate 版本是`0.8.6` 。如果想要使用 `0.9.0` 版本的 `rand` 或是任何 `0.9.x` 系列的版本,必须像这样更新 *Cargo.toml* 文件: ```toml [dependencies] @@ -302,7 +302,7 @@ rand = "0.9.0" 示例 2-3:添加生成随机数的代码 -首先,我们新增了一行 `use rand::Rng`。`Rng` 是一个 trait,它定义了随机数生成器应实现的方法,想使用这些方法的话,此 trait 必须在作用域中。第十章会详细介绍 trait。 +首先,我们新增了一行 `use rand::Rng;`。`Rng` 是一个 trait,它定义了随机数生成器应实现的方法,想使用这些方法的话,此 trait 必须在作用域中。第十章会详细介绍 trait。 接下来,我们在中间还新增加了两行。第一行调用了 `rand::thread_rng` 函数提供实际使用的随机数生成器:它位于当前执行线程的本地环境中,并从操作系统获取 seed。接着调用随机数生成器的 `gen_range` 方法。这个方法由 `use rand::Rng` 语句引入到作用域的 `Rng` trait 定义。`gen_range` 方法获取一个范围表达式(range expression)作为参数,并生成一个在此范围之间的随机数。这里使用的这类范围表达式使用了 `start..=end` 这样的形式,也就是说包含了上下端点,所以需要指定 `1..=100` 来请求一个 1 和 100 之间的数。 @@ -353,7 +353,9 @@ You guessed: 5 一个 `match` 表达式由 **分支(arms)** 构成。一个分支包含一个 **模式**(*pattern*)和表达式开头的值与分支模式相匹配时应该执行的代码。Rust 获取提供给 `match` 的值并挨个检查每个分支的模式。`match` 结构和模式是 Rust 中强大的功能,它体现了代码可能遇到的多种情形,并帮助你确保没有遗漏处理。这些功能将分别在第六章和第十八章详细介绍。 -让我们看看使用 `match` 表达式的例子。假设用户猜了 50,这时随机生成的秘密数字是 38。比较 50 与 38 时,因为 50 比 38 要大,`cmp` 方法会返回 `Ordering::Greater`。`Ordering::Greater` 是 `match` 表达式得到的值。它检查第一个分支的模式,`Ordering::Less` 与 `Ordering::Greater`并不匹配,所以它忽略了这个分支的代码并来到下一个分支。下一个分支的模式是 `Ordering::Greater`,**正确** 匹配!这个分支关联的代码被执行,在屏幕打印出 `Too big!`。`match` 表达式会在第一次成功匹配后终止,因为该场景下没有检查最后一个分支的必要。 +让我们看看使用 `match` 表达式的例子。假设用户猜了 50,这时随机生成的秘密数字是 38。 + +比较 50 与 38 时,因为 50 比 38 要大,`cmp` 方法会返回 `Ordering::Greater`。`Ordering::Greater` 是 `match` 表达式得到的值。它检查第一个分支的模式,`Ordering::Less` 与 `Ordering::Greater`并不匹配,所以它忽略了这个分支的代码并来到下一个分支。下一个分支的模式是 `Ordering::Greater`,**正确** 匹配!这个分支关联的代码被执行,在屏幕打印出 `Too big!`。`match` 表达式会在第一次成功匹配后终止,因为该场景下没有检查最后一个分支的必要。 然而,示例 2-4 的代码并不能编译,可以尝试一下: @@ -377,11 +379,13 @@ You guessed: 5 let guess: u32 = guess.trim().parse().expect("Please type a number!"); ``` -这里创建了一个叫做 `guess` 的变量。不过等等,不是已经有了一个叫做 `guess` 的变量了吗?确实如此,不过 Rust 允许用一个新值来 **隐藏** (_shadow_) `guess` 之前的值。这个功能常用在需要转换值类型之类的场景。它允许我们复用 `guess` 变量的名字,而不是被迫创建两个不同变量,诸如 `guess_str` 和 `guess` 之类。(第三章会介绍 shadowing 的更多细节。) +这里创建了一个叫做 `guess` 的变量。不过等等,不是已经有了一个叫做 `guess` 的变量了吗?确实如此,不过 Rust 允许用一个新值来 **隐藏** (_Shadowing_) `guess` 之前的值。这个功能常用在需要转换值类型之类的场景。它允许我们复用 `guess` 变量的名字,而不是被迫创建两个不同变量,诸如 `guess_str` 和 `guess` 之类。[第三章][shadowing]会介绍 shadowing 的更多细节,现在只需知道这个功能经常用于将一个类型的值转换为另一个类型的值。 我们将这个新变量绑定到 `guess.trim().parse()` 表达式上。表达式中的 `guess` 指的是包含输入的字符串类型 `guess` 变量。`String` 实例的 `trim` 方法会去除字符串开头和结尾的空白字符,我们必须执行此方法才能将字符串与 `u32` 比较,因为 `u32` 只能包含数值型数据。用户必须输入 enter 键才能让 `read_line` 返回并输入他们的猜想,这将会在字符串中增加一个换行(newline)符。例如,用户输入 5 并按下 enter(在 Windows 上,按下 enter 键会得到一个回车符和一个换行符,`\r\n`),`guess` 看起来像这样:`5\n` 或者 `5\r\n`。`\n` 代表 “换行”,回车键;`\r` 代表 “回车”,回车键。`trim` 方法会消除 `\n` 或者 `\r\n`,只留下 `5`。 -[字符串的 `parse` 方法][parse] 将字符串转换成其他类型。这里用它来把字符串转换为数值。我们需要告诉 Rust 具体的数字类型,这里通过 `let guess: u32` 指定。`guess` 后面的冒号(`:`)告诉 Rust 我们指定了变量的类型。Rust 有一些内建的数字类型;`u32` 是一个无符号的 32 位整型。对于不大的正整数来说,它是不错的默认类型,第三章还会讲到其他数字类型。另外,程序中的 `u32` 注解以及与 `secret_number` 的比较,意味着 Rust 会推断出 `secret_number` 也是 `u32` 类型。现在可以使用相同类型比较两个值了! +[字符串的 `parse` 方法][parse] 将字符串转换成其他类型。这里用它来把字符串转换为数值。我们需要告诉 Rust 具体的数字类型,这里通过 `let guess: u32` 指定。`guess` 后面的冒号(`:`)告诉 Rust 我们指定了变量的类型。Rust 有一些内建的数字类型;`u32` 是一个无符号的 32 位整型。对于不大的正整数来说,它是不错的默认类型,[第三章][integers]还会讲到其他数字类型。 + +另外,程序中的 `u32` 注解以及与 `secret_number` 的比较,意味着 Rust 会推断出 `secret_number` 也是 `u32` 类型。现在可以使用相同类型比较两个值了! `parse` 方法只有在字符逻辑上可以转换为数字的时候才能工作所以非常容易出错。例如,字符串中包含 `A👍%`,就无法将其转换为一个数字。因此,`parse` 方法返回一个 `Result` 类型。像之前 [“使用 `Result` 类型来处理潜在的错误”](#使用-result-类型来处理潜在的错误) 讨论的 `read_line` 方法那样,再次按部就班的用 `expect` 方法处理即可。如果 `parse` 不能从字符串生成一个数字,返回一个 `Result` 的 `Err` 成员时,`expect` 会使游戏崩溃并打印附带的信息。如果 `parse` 成功地将字符串转换为一个数字,它会返回 `Result` 的 `Ok` 成员,然后 `expect` 会返回 `Ok` 值中的数字。 @@ -510,10 +514,10 @@ You win! 示例 2-6:猜猜看游戏的完整代码 -## 总结 - 此时此刻,你顺利完成了猜猜看游戏。恭喜! +## 总结 + 本项目通过动手实践,向你介绍了 Rust 新概念:`let`、`match`、函数、使用外部 crate 等等,接下来的几章,你会继续深入学习这些概念。第三章介绍大部分编程语言都有的概念,比如变量、数据类型和函数,以及如何在 Rust 中使用它们。第四章探索所有权(ownership),这是一个 Rust 同其他语言大不相同的功能。第五章讨论结构体和方法的语法,而第六章侧重解释枚举。 [prelude]: https://doc.rust-lang.org/std/prelude/index.html @@ -532,4 +536,6 @@ You win! [doccargo]: http://doc.crates.io [doccratesio]: http://doc.crates.io/crates-io.html [match]: ch06-02-match.html +[shadowing]: ch03-01-variables-and-mutability.html#shadowing [parse]: https://doc.rust-lang.org/std/primitive.str.html#method.parse +[integers]: ch03-02-data-types.html#integer-types