Merge remote-tracking branch 'origin/ch13'

This commit is contained in:
Carol (Nichols || Goulding)
2022-04-27 09:00:05 -04:00
108 changed files with 2209 additions and 1724 deletions

View File

@@ -60,6 +60,7 @@ BoxMeUp
BTreeSet
BuildHasher
Cacher
cacher
Cagain
callsite
CamelCase
@@ -429,6 +430,7 @@ SelectBox
semver
SemVer
serde
ShirtColor
ShlAssign
ShrAssign
shouldn

View File

@@ -1,6 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "workout-app"
version = "0.1.0"
version = 3
[[package]]
name = "shirt-company"
version = "0.1.0"

View File

@@ -1,5 +1,5 @@
[package]
name = "workout-app"
name = "shirt-company"
version = "0.1.0"
edition = "2021"

View File

@@ -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

View File

@@ -1,12 +1,52 @@
// ANCHOR: here
use std::thread;
use std::time::Duration;
fn simulated_expensive_calculation(intensity: u32) -> u32 {
println!("calculating slowly...");
thread::sleep(Duration::from_secs(2));
intensity
#[derive(Debug, PartialEq, Copy, Clone)]
enum ShirtColor {
Red,
Blue,
}
// ANCHOR_END: here
fn main() {}
struct Inventory {
shirts: Vec<ShirtColor>,
}
impl Inventory {
fn giveaway(&self, user_preference: Option<ShirtColor>) -> ShirtColor {
user_preference.unwrap_or_else(|| self.most_stocked())
}
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
}
}
}
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
);
}

View File

@@ -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
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 generate_workout(intensity: u32, random_number: u32) {}
// 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

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "workout-app"
name = "closure-example"
version = "0.1.0"
edition = "2021"

View File

@@ -0,0 +1,12 @@
$ 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
For more information about this error, try `rustc --explain E0308`.
error: could not compile `closure-example` due to previous error

View File

@@ -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
}

View File

@@ -1,5 +1,5 @@
[package]
name = "workout-app"
name = "closure-example"
version = "0.1.0"
edition = "2021"

View File

@@ -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]

View File

@@ -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);
generate_workout(simulated_user_specified_value, simulated_random_number);
let only_borrows = || println!("From closure: {:?}", list);
println!("Before calling closure: {:?}", list);
only_borrows();
println!("After calling closure: {:?}", list);
}

View File

@@ -1,5 +1,5 @@
[package]
name = "workout-app"
name = "closure-example"
version = "0.1.0"
edition = "2021"

View File

@@ -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]

View File

@@ -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);
generate_workout(simulated_user_specified_value, simulated_random_number);
let mut borrows_mutably = || list.push(7);
borrows_mutably();
println!("After calling closure: {:?}", list);
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "workout-app"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "workout-app"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,33 +0,0 @@
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;
generate_workout(simulated_user_specified_value, simulated_random_number);
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "workout-app"
version = "0.1.0"

View File

@@ -1,5 +1,5 @@
[package]
name = "workout-app"
name = "rectangles"
version = "0.1.0"
edition = "2021"

View File

@@ -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,
},
]

View File

@@ -1,33 +1,25 @@
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);
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "closure-example"
version = "0.1.0"

View File

@@ -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]

View File

@@ -1,12 +1,18 @@
$ 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:27:30
|
24 | let value = String::from("by key called");
| ----- captured outer variable
25 |
26 | list.sort_by_key(|r| {
| ______________________-
27 | | sort_operations.push(value);
| | ^^^^^ move occurs because `value` has type `String`, which does not implement the `Copy` trait
28 | | r.width
29 | | });
| |_____- captured by this `FnMut` closure
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

View File

@@ -1,8 +1,31 @@
fn main() {
// ANCHOR: here
let example_closure = |x| x;
let s = example_closure(String::from("hello"));
let n = example_closure(5);
// ANCHOR_END: here
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
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");
list.sort_by_key(|r| {
sort_operations.push(value);
r.width
});
println!("{:#?}", list);
}

View File

@@ -1,5 +1,5 @@
[package]
name = "cacher"
name = "rectangles"
version = "0.1.0"
edition = "2021"

View File

@@ -1,11 +1,29 @@
// ANCHOR: here
struct Cacher<T>
where
T: Fn(u32) -> u32,
{
calculation: T,
value: Option<u32>,
#[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);
}

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "cacher"
name = "iterators"
version = "0.1.0"
edition = "2021"

View File

@@ -1,34 +1,7 @@
struct Cacher<T>
where
T: Fn(u32) -> u32,
{
calculation: T,
value: Option<u32>,
fn main() {
// ANCHOR: here
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
// ANCHOR_END: here
}
// ANCHOR: here
impl<T> Cacher<T>
where
T: Fn(u32) -> u32,
{
fn new(calculation: T) -> Cacher<T> {
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
}
}
}
}
// ANCHOR_END: here
fn main() {}

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "workout-app"
name = "iterators"
version = "0.1.0"
edition = "2021"

View File

@@ -1,64 +1,11 @@
use std::thread;
use std::time::Duration;
struct Cacher<T>
where
T: Fn(u32) -> u32,
{
calculation: T,
value: Option<u32>,
}
impl<T> Cacher<T>
where
T: Fn(u32) -> u32,
{
fn new(calculation: T) -> Cacher<T> {
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
}
}
}
}
// 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
});
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)
);
}
}
}
// ANCHOR_END: here
fn main() {
let simulated_user_specified_value = 10;
let simulated_random_number = 7;
// ANCHOR: here
let v1 = vec![1, 2, 3];
generate_workout(simulated_user_specified_value, simulated_random_number);
let v1_iter = v1.iter();
for val in v1_iter {
println!("Got: {}", val);
}
// ANCHOR_END: here
}

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "equal-to-x"
name = "iterators"
version = "0.1.0"
edition = "2021"

View File

@@ -1,9 +0,0 @@
fn main() {
let x = 4;
let equal_to_x = |z| z == x;
let y = 4;
assert!(equal_to_x(y));
}

View File

@@ -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
}

View File

@@ -1,7 +0,0 @@
fn main() {
// ANCHOR: here
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
// ANCHOR_END: here
}

View File

@@ -1,11 +1,7 @@
fn main() {
// ANCHOR: here
let v1 = vec![1, 2, 3];
let v1: Vec<i32> = 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
}

View File

@@ -2,6 +2,8 @@ fn main() {
// ANCHOR: here
let v1: Vec<i32> = vec![1, 2, 3];
v1.iter().map(|x| x + 1);
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
assert_eq!(v2, vec![2, 3, 4]);
// ANCHOR_END: here
}

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "iterators"
name = "shoe_size"
version = "0.1.0"
edition = "2021"

View File

@@ -1,15 +1,48 @@
#[derive(PartialEq, Debug)]
struct Shoe {
size: u32,
style: String,
}
fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
shoes.into_iter().filter(|s| s.size == shoe_size).collect()
}
#[cfg(test)]
mod tests {
// ANCHOR: here
use super::*;
#[test]
fn iterator_sum() {
let v1 = vec![1, 2, 3];
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 v1_iter = v1.iter();
let in_my_size = shoes_in_size(shoes, 10);
let total: i32 = v1_iter.sum();
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
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "iterators"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "iterators"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "iterators"
name = "minigrep"
version = "0.1.0"
edition = "2021"

View File

@@ -1,9 +1,23 @@
use std::env;
use std::process;
use minigrep::Config;
// ANCHOR: here
fn main() {
// ANCHOR: here
let v1: Vec<i32> = vec![1, 2, 3];
let config = Config::new(env::args()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
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

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "shoe_size"
name = "minigrep"
version = "0.1.0"
edition = "2021"

View File

@@ -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 filename: String,
pub case_sensitive: bool,
}
fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
shoes.into_iter().filter(|s| s.size == shoe_size).collect()
// ANCHOR: here
impl Config {
pub fn new(
mut args: impl Iterator<Item = String>,
) -> Result<Config, &'static str> {
// --snip--
// ANCHOR_END: here
if args.len() < 3 {
return Err("not enough arguments");
}
let query = args[1].clone();
let filename = args[2].clone();
let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
Ok(Config {
query,
filename,
case_sensitive,
})
}
}
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(config.filename)?;
let results = if config.case_sensitive {
search(&config.query, &contents)
} else {
search_case_insensitive(&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"),
},
];
fn case_sensitive() {
let query = "duct";
let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct tape.";
let in_my_size = shoes_in_size(shoes, 10);
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)
);
}
}

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "counter"
name = "minigrep"
version = "0.1.0"
edition = "2021"

View File

@@ -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 filename: String,
pub case_sensitive: bool,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
// ANCHOR: here
impl Config {
pub fn new(
mut args: impl Iterator<Item = String>,
) -> Result<Config, &'static str> {
args.next();
let query = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a query string"),
};
let filename = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a file name"),
};
let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
Ok(Config {
query,
filename,
case_sensitive,
})
}
}
// ANCHOR_END: here
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(config.filename)?;
let results = if config.case_sensitive {
search(&config.query, &contents)
} else {
search_case_insensitive(&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)
);
}
}

View File

@@ -1,24 +0,0 @@
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
// ANCHOR: here
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
// ANCHOR_END: here

View File

@@ -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"

View File

@@ -1,5 +1,5 @@
[package]
name = "counter"
name = "minigrep"
version = "0.1.0"
edition = "2021"

View File

@@ -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 filename: String,
pub case_sensitive: bool,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
impl Config {
pub fn new(
mut args: impl Iterator<Item = String>,
) -> Result<Config, &'static str> {
args.next();
let query = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a query string"),
};
let filename = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a file name"),
};
let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
Ok(Config {
query,
filename,
case_sensitive,
})
}
}
impl Iterator for Counter {
type Item = u32;
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(config.filename)?;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
let results = if config.case_sensitive {
search(&config.query, &contents)
} else {
search_case_insensitive(&config.query, &contents)
};
for line in results {
println!("{}", line);
}
Ok(())
}
// 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();
fn case_sensitive() {
let query = "duct";
let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct tape.";
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);
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
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "counter"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "counter"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,51 +0,0 @@
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[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);
}
// ANCHOR: here
#[test]
fn using_other_iterator_trait_methods() {
let sum: u32 = Counter::new()
.zip(Counter::new().skip(1))
.map(|(a, b)| a * b)
.filter(|x| x % 3 == 0)
.sum();
assert_eq!(18, sum);
}
// ANCHOR_END: here
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "minigrep"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "minigrep"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,23 +0,0 @@
use std::env;
use std::process;
use minigrep::Config;
// ANCHOR: here
fn main() {
let config = Config::new(env::args()).unwrap_or_else(|err| {
eprintln!("Problem parsing arguments: {}", err);
process::exit(1);
});
// --snip--
// ANCHOR_END: here
if let Err(e) = minigrep::run(config) {
eprintln!("Application error: {}", e);
process::exit(1);
}
// ANCHOR: here
}
// ANCHOR_END: here

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "minigrep"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "minigrep"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,107 +0,0 @@
use std::env;
use std::error::Error;
use std::fs;
pub struct Config {
pub query: String,
pub filename: String,
pub case_sensitive: bool,
}
// ANCHOR: here
impl Config {
pub fn new(mut args: env::Args) -> Result<Config, &'static str> {
// --snip--
// ANCHOR_END: here
if args.len() < 3 {
return Err("not enough arguments");
}
let query = args[1].clone();
let filename = args[2].clone();
let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
Ok(Config {
query,
filename,
case_sensitive,
})
}
}
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(config.filename)?;
let results = if config.case_sensitive {
search(&config.query, &contents)
} else {
search_case_insensitive(&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)
);
}
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "minigrep"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "minigrep"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,111 +0,0 @@
use std::env;
use std::error::Error;
use std::fs;
pub struct Config {
pub query: String,
pub filename: String,
pub case_sensitive: bool,
}
// ANCHOR: here
impl Config {
pub fn new(mut args: env::Args) -> Result<Config, &'static str> {
args.next();
let query = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a query string"),
};
let filename = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a file name"),
};
let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
Ok(Config {
query,
filename,
case_sensitive,
})
}
}
// ANCHOR_END: here
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(config.filename)?;
let results = if config.case_sensitive {
search(&config.query, &contents)
} else {
search_case_insensitive(&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)
);
}
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "minigrep"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "minigrep"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,106 +0,0 @@
use std::env;
use std::error::Error;
use std::fs;
pub struct Config {
pub query: String,
pub filename: String,
pub case_sensitive: bool,
}
impl Config {
pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
args.next();
let query = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a query string"),
};
let filename = match args.next() {
Some(arg) => arg,
None => return Err("Didn't get a file name"),
};
let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
Ok(Config {
query,
filename,
case_sensitive,
})
}
}
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(config.filename)?;
let results = if config.case_sensitive {
search(&config.query, &contents)
} else {
search_case_insensitive(&config.query, &contents)
};
for line in results {
println!("{}", line);
}
Ok(())
}
// 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::*;
#[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)
);
}
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "cacher"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "cacher"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,23 +0,0 @@
$ cargo test
Compiling cacher v0.1.0 (file:///projects/cacher)
Finished test [unoptimized + debuginfo] target(s) in 0.72s
Running unittests (target/debug/deps/cacher-074d7c200c000afa)
running 1 test
test tests::call_with_different_values ... FAILED
failures:
---- tests::call_with_different_values stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `1`,
right: `2`', src/lib.rs:43:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::call_with_different_values
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'

View File

@@ -1,47 +0,0 @@
struct Cacher<T>
where
T: Fn(u32) -> u32,
{
calculation: T,
value: Option<u32>,
}
impl<T> Cacher<T>
where
T: Fn(u32) -> u32,
{
fn new(calculation: T) -> Cacher<T> {
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
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
// ANCHOR: here
#[test]
fn call_with_different_values() {
let mut c = Cacher::new(|a| a);
let v1 = c.value(1);
let v2 = c.value(2);
assert_eq!(v2, 2);
}
// ANCHOR_END: here
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "equal-to-x"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "equal-to-x"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,12 +0,0 @@
$ cargo run
Compiling equal-to-x v0.1.0 (file:///projects/equal-to-x)
error[E0434]: can't capture dynamic environment in a fn item
--> src/main.rs:5:14
|
5 | z == x
| ^
|
= help: use the `|| { ... }` closure form instead
For more information about this error, try `rustc --explain E0434`.
error: could not compile `equal-to-x` due to previous error

View File

@@ -1,11 +0,0 @@
fn main() {
let x = 4;
fn equal_to_x(z: i32) -> bool {
z == x
}
let y = 4;
assert!(equal_to_x(y));
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "equal-to-x"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "equal-to-x"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@@ -1,20 +0,0 @@
$ cargo run
Compiling equal-to-x v0.1.0 (file:///projects/equal-to-x)
error[E0382]: borrow of moved value: `x`
--> src/main.rs:6:40
|
2 | let x = vec![1, 2, 3];
| - move occurs because `x` has type `Vec<i32>`, which does not implement the `Copy` trait
3 |
4 | let equal_to_x = move |z| z == x;
| -------- - variable moved due to use in closure
| |
| value moved into closure here
5 |
6 | println!("can't use x here: {:?}", x);
| ^ value borrowed here after move
|
= note: this error originates in the macro `$crate::format_args_nl` (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 `equal-to-x` due to previous error

View File

@@ -1,11 +0,0 @@
fn main() {
let x = vec![1, 2, 3];
let equal_to_x = move |z| z == x;
println!("can't use x here: {:?}", x);
let y = vec![1, 2, 3];
assert!(equal_to_x(y));
}

View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "counter"
version = "0.1.0"

View File

@@ -1,6 +0,0 @@
[package]
name = "counter"
version = "0.1.0"
edition = "2021"
[dependencies]

Some files were not shown because too many files have changed in this diff Show More