Compare commits

..

No commits in common. "3d540ed946ee9fd522ba9ec26f68055f5c498317" and "d768353806f905989b4cc29cd7a97891cbbf8ec3" have entirely different histories.

27 changed files with 132 additions and 593 deletions

View file

@ -1,12 +1,13 @@
struct ColorRegularStruct { // Address all the TODOs to make the tests pass!
// TODO: Add the fields that the test `regular_structs` expects.
// What types should the fields have? What are the minimum and maximum values for RGB colors? struct ColorClassicStruct {
// TODO: Something goes here
} }
struct ColorTupleStruct(/* TODO: Add the fields that the test `tuple_structs` expects */); struct ColorTupleStruct(/* TODO: Something goes here */);
#[derive(Debug)] #[derive(Debug)]
struct UnitStruct; struct UnitLikeStruct;
fn main() { fn main() {
// You can optionally experiment here. // You can optionally experiment here.
@ -17,8 +18,8 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn regular_structs() { fn classic_c_structs() {
// TODO: Instantiate a regular struct. // TODO: Instantiate a classic c struct!
// let green = // let green =
assert_eq!(green.red, 0); assert_eq!(green.red, 0);
@ -28,7 +29,7 @@ mod tests {
#[test] #[test]
fn tuple_structs() { fn tuple_structs() {
// TODO: Instantiate a tuple struct. // TODO: Instantiate a tuple struct!
// let green = // let green =
assert_eq!(green.0, 0); assert_eq!(green.0, 0);
@ -38,10 +39,10 @@ mod tests {
#[test] #[test]
fn unit_structs() { fn unit_structs() {
// TODO: Instantiate a unit struct. // TODO: Instantiate a unit-like struct!
// let unit_struct = // let unit_like_struct =
let message = format!("{unit_struct:?}s are fun!"); let message = format!("{:?}s are fun!", unit_like_struct);
assert_eq!(message, "UnitStructs are fun!"); assert_eq!(message, "UnitLikeStructs are fun!");
} }
} }

View file

@ -1,3 +1,5 @@
// Address all the TODOs to make the tests pass!
#[derive(Debug)] #[derive(Debug)]
struct Order { struct Order {
name: String, name: String,
@ -32,10 +34,8 @@ mod tests {
#[test] #[test]
fn your_order() { fn your_order() {
let order_template = create_order_template(); let order_template = create_order_template();
// TODO: Create your own order using the update syntax and template above! // TODO: Create your own order using the update syntax and template above!
// let your_order = // let your_order =
assert_eq!(your_order.name, "Hacker in Rust"); assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year); assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone); assert_eq!(your_order.made_by_phone, order_template.made_by_phone);

View file

@ -1,5 +1,6 @@
// Structs contain data, but can also have logic. In this exercise we have // Structs contain data, but can also have logic. In this exercise we have
// defined the `Package` struct and we want to test some logic attached to it. // defined the Package struct and we want to test some logic attached to it.
// Make the code compile and the tests pass!
#[derive(Debug)] #[derive(Debug)]
struct Package { struct Package {
@ -9,28 +10,26 @@ struct Package {
} }
impl Package { impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self { fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Package {
if weight_in_grams < 10 { if weight_in_grams < 10 {
// This isn't how you should handle errors in Rust, but we will // This is not how you should handle errors in Rust,
// learn about error handling later. // but we will learn about error handling later.
panic!("Can't ship a package with weight below 10 grams"); panic!("Can not ship a package with weight below 10 grams.")
} } else {
Package {
Self { sender_country,
sender_country, recipient_country,
recipient_country, weight_in_grams,
weight_in_grams, }
} }
} }
// TODO: Add the correct return type to the function signature. fn is_international(&self) -> ??? {
fn is_international(&self) { // Something goes here...
// TODO: Read the tests that use this method to find out when a package is concidered international.
} }
// TODO: Add the correct return type to the function signature. fn get_fees(&self, cents_per_gram: u32) -> ??? {
fn get_fees(&self, cents_per_gram: u32) { // Something goes here...
// TODO: Calculate the package's fees.
} }
} }

View file

@ -1,6 +1,6 @@
#[derive(Debug)] #[derive(Debug)]
enum Message { enum Message {
// TODO: Define a few types of messages as used below. // TODO: define a few types of messages as used below
} }
fn main() { fn main() {

View file

@ -1,6 +1,6 @@
#[derive(Debug)] #[derive(Debug)]
enum Message { enum Message {
// TODO: Define the different variants used below. // TODO: define the different variants used below
} }
impl Message { impl Message {

View file

@ -1,5 +1,7 @@
// Address all the TODOs to make the tests pass!
enum Message { enum Message {
// TODO: Implement the message variant types based on their usage below. // TODO: implement the message variant types based on their usage below
} }
struct Point { struct Point {
@ -24,17 +26,17 @@ impl State {
} }
fn echo(&mut self, s: String) { fn echo(&mut self, s: String) {
self.message = s; self.message = s
} }
fn move_position(&mut self, point: Point) { fn move_position(&mut self, p: Point) {
self.position = point; self.position = p;
} }
fn process(&mut self, message: Message) { fn process(&mut self, message: Message) {
// TODO: Create a match expression to process the different message variants. // TODO: create a match expression to process the different message variants
// Remember: When passing a tuple as a function argument, you'll need extra parentheses: // Remember: When passing a tuple as a function argument, you'll need extra parentheses:
// e.g. `foo((t, u, p, l, e))` // fn function((t, u, p, l, e))
} }
} }
@ -52,9 +54,8 @@ mod tests {
quit: false, quit: false,
position: Point { x: 0, y: 0 }, position: Point { x: 0, y: 0 },
color: (0, 0, 0), color: (0, 0, 0),
message: String::from("hello world"), message: "hello world".to_string(),
}; };
state.process(Message::ChangeColor(255, 0, 255)); state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::Echo(String::from("Hello world!"))); state.process(Message::Echo(String::from("Hello world!")));
state.process(Message::Move(Point { x: 10, y: 15 })); state.process(Message::Move(Point { x: 10, y: 15 }));
@ -63,7 +64,7 @@ mod tests {
assert_eq!(state.color, (255, 0, 255)); assert_eq!(state.color, (255, 0, 255));
assert_eq!(state.position.x, 10); assert_eq!(state.position.x, 10);
assert_eq!(state.position.y, 15); assert_eq!(state.position.y, 15);
assert!(state.quit); assert_eq!(state.quit, true);
assert_eq!(state.message, "Hello world!"); assert_eq!(state.message, "Hello world!");
} }
} }

View file

@ -1,9 +1,10 @@
// TODO: Fix the compiler error without changing the function signature. // Make me compile without changing the function signature!
fn current_favorite_color() -> String {
"blue"
}
fn main() { fn main() {
let answer = current_favorite_color(); let answer = current_favorite_color();
println!("My current favorite color is {answer}"); println!("My current favorite color is {}", answer);
}
fn current_favorite_color() -> String {
"blue"
} }

View file

@ -1,14 +1,14 @@
// TODO: Fix the compiler error in the `main` function without changing this function. // Make me compile without changing the function signature!
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}
fn main() { fn main() {
let word = String::from("green"); // Don't change this line. let word = String::from("green"); // Try not changing this line :)
if is_a_color_word(word) { if is_a_color_word(word) {
println!("That is a color word I know!"); println!("That is a color word I know!");
} else { } else {
println!("That is not a color word I know."); println!("That is not a color word I know.");
} }
} }
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}

View file

@ -1,13 +1,16 @@
fn trim_me(input: &str) -> &str { fn trim_me(input: &str) -> String {
// TODO: Remove whitespace from both ends of a string. // TODO: Remove whitespace from both ends of a string!
???
} }
fn compose_me(input: &str) -> String { fn compose_me(input: &str) -> String {
// TODO: Add " world!" to the string! There are multiple ways to do this. // TODO: Add " world!" to the string! There are multiple ways to do this!
???
} }
fn replace_me(input: &str) -> String { fn replace_me(input: &str) -> String {
// TODO: Replace "cars" in the string with "balloons". // TODO: Replace "cars" in the string with "balloons"!
???
} }
fn main() { fn main() {
@ -33,13 +36,7 @@ mod tests {
#[test] #[test]
fn replace_a_string() { fn replace_a_string() {
assert_eq!( assert_eq!(replace_me("I think cars are cool"), "I think balloons are cool");
replace_me("I think cars are cool"), assert_eq!(replace_me("I love to look at cars"), "I love to look at balloons");
"I think balloons are cool",
);
assert_eq!(
replace_me("I love to look at cars"),
"I love to look at balloons",
);
} }
} }

View file

@ -1,36 +1,24 @@
// Calls of this function should be replaced with calls of `string_slice` or `string`. // Ok, here are a bunch of values - some are `String`s, some are `&str`s. Your
fn placeholder() {} // task is to call one of these two functions on each value depending on what
// you think each value is. That is, add either `string_slice` or `string`
// before the parentheses on each line. If you're right, it will compile!
fn string_slice(arg: &str) { fn string_slice(arg: &str) {
println!("{arg}"); println!("{}", arg);
} }
fn string(arg: String) { fn string(arg: String) {
println!("{arg}"); println!("{}", arg);
} }
// TODO: Here are a bunch of values - some are `String`, some are `&str`.
// Your task is to replace `placeholder(…)` with either `string_slice(…)`
// or `string(…)` depending on what you think each value is.
fn main() { fn main() {
placeholder("blue"); ???("blue");
???("red".to_string());
placeholder("red".to_string()); ???(String::from("hi"));
???("rust is fun!".to_owned());
placeholder(String::from("hi")); ???("nice weather".into());
???(format!("Interpolation {}", "Station"));
placeholder("rust is fun!".to_owned()); ???(&String::from("abc")[0..1]);
???(" hello there ".trim());
placeholder("nice weather".into()); ???("Happy Monday!".to_string().replace("Mon", "Tues"));
???("mY sHiFt KeY iS sTiCkY".to_lowercase());
placeholder(format!("Interpolation {}", "Station"));
// WARNING: This is byte indexing, not character indexing.
// Character indexing can be done using `s.chars().nth(INDEX)`.
placeholder(&String::from("abc")[0..1]);
placeholder(" hello there ".trim());
placeholder("Happy Monday!".replace("Mon", "Tues"));
placeholder("mY sHiFt KeY iS sTiCkY".to_lowercase());
} }

View file

@ -1,4 +1,3 @@
// TODO: Fix the compiler error about calling a private function.
mod sausage_factory { mod sausage_factory {
// Don't let anybody outside of this module see this! // Don't let anybody outside of this module see this!
fn get_secret_recipe() -> String { fn get_secret_recipe() -> String {

View file

@ -1,19 +1,20 @@
// You can bring module paths into scopes and provide new names for them with // You can bring module paths into scopes and provide new names for them with
// the `use` and `as` keywords. // the 'use' and 'as' keywords. Fix these 'use' statements to make the code
// compile.
mod delicious_snacks { mod delicious_snacks {
// TODO: Add the follwing two `use` statements after fixing them. // TODO: Fix these use statements
// use self::fruits::PEAR as ???; use self::fruits::PEAR as ???
// use self::veggies::CUCUMBER as ???; use self::veggies::CUCUMBER as ???
mod fruits { mod fruits {
pub const PEAR: &str = "Pear"; pub const PEAR: &'static str = "Pear";
pub const APPLE: &str = "Apple"; pub const APPLE: &'static str = "Apple";
} }
mod veggies { mod veggies {
pub const CUCUMBER: &str = "Cucumber"; pub const CUCUMBER: &'static str = "Cucumber";
pub const CARROT: &str = "Carrot"; pub const CARROT: &'static str = "Carrot";
} }
} }
@ -21,6 +22,6 @@ fn main() {
println!( println!(
"favorite snacks: {} and {}", "favorite snacks: {} and {}",
delicious_snacks::fruit, delicious_snacks::fruit,
delicious_snacks::veggie, delicious_snacks::veggie
); );
} }

View file

@ -1,9 +1,10 @@
// You can use the `use` keyword to bring module paths from modules from // You can use the 'use' keyword to bring module paths from modules from
// anywhere and especially from the standard library into your scope. // anywhere and especially from the Rust standard library into your scope. Bring
// SystemTime and UNIX_EPOCH from the std::time module. Bonus style points if
// you can do it with one line!
// TODO: Bring `SystemTime` and `UNIX_EPOCH` from the `std::time` module into // TODO: Complete this use statement
// your scope. Bonus style points if you can do it with one line! use ???
// use ???;
fn main() { fn main() {
match SystemTime::now().duration_since(UNIX_EPOCH) { match SystemTime::now().duration_since(UNIX_EPOCH) {

View file

@ -402,14 +402,15 @@ hint = """
Rust has more than one type of struct. Three actually, all variants are used to Rust has more than one type of struct. Three actually, all variants are used to
package related data together. package related data together.
There are regular structs. These are named collections of related data stored in There are normal (or classic) structs. These are named collections of related
fields. data stored in fields.
Tuple structs are basically just named tuples. Tuple structs are basically just named tuples.
Finally, unit structs. These don't have any fields and are useful for generics. Finally, Unit-like structs. These don't have any fields and are useful for
generics.
In this exercise, you need to complete and implement one of each kind. In this exercise you need to complete and implement one of each kind.
Read more about structs in The Book: Read more about structs in The Book:
https://doc.rust-lang.org/book/ch05-01-defining-structs.html""" https://doc.rust-lang.org/book/ch05-01-defining-structs.html"""
@ -421,7 +422,7 @@ Creating instances of structs is easy, all you need to do is assign some values
to its fields. to its fields.
There are however some shortcuts that can be taken when instantiating structs. There are however some shortcuts that can be taken when instantiating structs.
Have a look in The Book to find out more: Have a look in The Book, to find out more:
https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax""" https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax"""
[[exercises]] [[exercises]]
@ -434,7 +435,7 @@ the places it goes through right?
For `get_fees`: This method takes an additional argument, is there a field in For `get_fees`: This method takes an additional argument, is there a field in
the `Package` struct that this relates to? the `Package` struct that this relates to?
Have a look in The Book to find out more about method implementations: Have a look in The Book, to find out more about method implementations:
https://doc.rust-lang.org/book/ch05-03-method-syntax.html""" https://doc.rust-lang.org/book/ch05-03-method-syntax.html"""
# ENUMS # ENUMS
@ -451,18 +452,18 @@ dir = "08_enums"
test = false test = false
hint = """ hint = """
You can create enumerations that have different variants with different types You can create enumerations that have different variants with different types
such as no data, anonymous structs, a single string, tuples, etc.""" such as no data, anonymous structs, a single string, tuples, ...etc"""
[[exercises]] [[exercises]]
name = "enums3" name = "enums3"
dir = "08_enums" dir = "08_enums"
hint = """ hint = """
As a first step, define enums to compile the code without errors. As a first step, you can define enums to compile this code without errors.
Then, create a match expression in `process()`. And then create a match expression in `process()`.
Note that you need to deconstruct some message variants in the match expression Note that you need to deconstruct some message variants in the match expression
to get the variant's values.""" to get value in the variant."""
# STRINGS # STRINGS
@ -486,7 +487,7 @@ dir = "09_strings"
test = false test = false
hint = """ hint = """
Yes, it would be really easy to fix this by just changing the value bound to Yes, it would be really easy to fix this by just changing the value bound to
`word` to be a string slice instead of a `String`, wouldn't it? There is a way `word` to be a string slice instead of a `String`, wouldn't it?? There is a way
to add one character to the `if` statement, though, that will coerce the to add one character to the `if` statement, though, that will coerce the
`String` into a string slice. `String` into a string slice.
@ -499,8 +500,7 @@ https://doc.rust-lang.org/stable/book/ch15-02-deref.html#implicit-deref-coercion
name = "strings3" name = "strings3"
dir = "09_strings" dir = "09_strings"
hint = """ hint = """
There are many useful standard library functions for strings. Let's try and use There's tons of useful standard library functions for strings. Let's try and use some of them:
some of them:
https://doc.rust-lang.org/std/string/struct.String.html#method.trim https://doc.rust-lang.org/std/string/struct.String.html#method.trim
For the `compose_me` method: You can either use the `format!` macro, or convert For the `compose_me` method: You can either use the `format!` macro, or convert
@ -510,15 +510,7 @@ the string slice into an owned string, which you can then freely extend."""
name = "strings4" name = "strings4"
dir = "09_strings" dir = "09_strings"
test = false test = false
hint = """ hint = "No hints this time ;)"
Replace `placeholder` with either `string` or `string_slice` in the `main` function.
Example:
`placeholder("blue");`
should become
`string_slice("blue");`
because "blue" is `&str`, not `String`.
"""
# MODULES # MODULES
@ -527,21 +519,21 @@ name = "modules1"
dir = "10_modules" dir = "10_modules"
test = false test = false
hint = """ hint = """
Everything is private in Rust by default. But there's a keyword we can use Everything is private in Rust by default-- but there's a keyword we can use
to make something public!""" to make something public! The compiler error should point to the thing that
needs to be public."""
[[exercises]] [[exercises]]
name = "modules2" name = "modules2"
dir = "10_modules" dir = "10_modules"
test = false test = false
hint = """ hint = """
The `delicious_snacks` module is trying to present an external interface that The delicious_snacks module is trying to present an external interface that is
is different than its internal structure (the `fruits` and `veggies` modules different than its internal structure (the `fruits` and `veggies` modules and
and associated constants). Complete the `use` statements to fit the uses in associated constants). Complete the `use` statements to fit the uses in main and
`main` and find the one keyword missing for both constants. find the one keyword missing for both constants.
Learn more in The Book: Learn more at https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#re-exporting-names-with-pub-use"""
https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#re-exporting-names-with-pub-use"""
[[exercises]] [[exercises]]
name = "modules3" name = "modules3"
@ -550,7 +542,7 @@ test = false
hint = """ hint = """
`UNIX_EPOCH` and `SystemTime` are declared in the `std::time` module. Add a `UNIX_EPOCH` and `SystemTime` are declared in the `std::time` module. Add a
`use` statement for these two to bring them into scope. You can use nested `use` statement for these two to bring them into scope. You can use nested
paths to bring these two in using only one line.""" paths or the glob operator to bring these two in using only one line."""
# HASHMAPS # HASHMAPS

View file

@ -1,49 +1 @@
struct ColorRegularStruct { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
red: u8,
green: u8,
blue: u8,
}
struct ColorTupleStruct(u8, u8, u8);
#[derive(Debug)]
struct UnitStruct;
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn regular_structs() {
let green = ColorRegularStruct {
red: 0,
green: 255,
blue: 0,
};
assert_eq!(green.red, 0);
assert_eq!(green.green, 255);
assert_eq!(green.blue, 0);
}
#[test]
fn tuple_structs() {
let green = ColorTupleStruct(0, 255, 0);
assert_eq!(green.0, 0);
assert_eq!(green.1, 255);
assert_eq!(green.2, 0);
}
#[test]
fn unit_structs() {
let unit_struct = UnitStruct;
let message = format!("{unit_struct:?}s are fun!");
assert_eq!(message, "UnitStructs are fun!");
}
}

View file

@ -1,51 +1 @@
#[derive(Debug)] // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
struct Order {
name: String,
year: u32,
made_by_phone: bool,
made_by_mobile: bool,
made_by_email: bool,
item_number: u32,
count: u32,
}
fn create_order_template() -> Order {
Order {
name: String::from("Bob"),
year: 2019,
made_by_phone: false,
made_by_mobile: false,
made_by_email: true,
item_number: 123,
count: 0,
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn your_order() {
let order_template = create_order_template();
let your_order = Order {
name: String::from("Hacker in Rust"),
count: 1,
// Struct update syntax
..order_template
};
assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone);
assert_eq!(your_order.made_by_mobile, order_template.made_by_mobile);
assert_eq!(your_order.made_by_email, order_template.made_by_email);
assert_eq!(your_order.item_number, order_template.item_number);
assert_eq!(your_order.count, 1);
}
}

View file

@ -1,83 +1 @@
#[derive(Debug)] // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
struct Package {
sender_country: String,
recipient_country: String,
weight_in_grams: u32,
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self {
if weight_in_grams < 10 {
// This isn't how you should handle errors in Rust, but we will
// learn about error handling later.
panic!("Can't ship a package with weight below 10 grams");
}
Self {
sender_country,
recipient_country,
weight_in_grams,
}
}
fn is_international(&self) -> bool {
// ^^^^^^^ added
self.sender_country != self.recipient_country
}
fn get_fees(&self, cents_per_gram: u32) -> u32 {
// ^^^^^^ added
self.weight_in_grams * cents_per_gram
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn fail_creating_weightless_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Austria");
Package::new(sender_country, recipient_country, 5);
}
#[test]
fn create_international_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Russia");
let package = Package::new(sender_country, recipient_country, 1200);
assert!(package.is_international());
}
#[test]
fn create_local_package() {
let sender_country = String::from("Canada");
let recipient_country = sender_country.clone();
let package = Package::new(sender_country, recipient_country, 1200);
assert!(!package.is_international());
}
#[test]
fn calculate_transport_fees() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Spain");
let cents_per_gram = 3;
let package = Package::new(sender_country, recipient_country, 1500);
assert_eq!(package.get_fees(cents_per_gram), 4500);
assert_eq!(package.get_fees(cents_per_gram * 2), 9000);
}
}

View file

@ -1,14 +1 @@
#[derive(Debug)] // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
enum Message {
Quit,
Echo,
Move,
ChangeColor,
}
fn main() {
println!("{:?}", Message::Quit);
println!("{:?}", Message::Echo);
println!("{:?}", Message::Move);
println!("{:?}", Message::ChangeColor);
}

View file

@ -1,26 +1 @@
#[derive(Debug)] // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
enum Message {
Move { x: i64, y: i64 },
Echo(String),
ChangeColor(u8, u8, u8),
Quit,
}
impl Message {
fn call(&self) {
println!("{:?}", self);
}
}
fn main() {
let messages = [
Message::Move { x: 10, y: 30 },
Message::Echo(String::from("hello world")),
Message::ChangeColor(200, 255, 255),
Message::Quit,
];
for message in &messages {
message.call();
}
}

View file

@ -1,75 +1 @@
enum Message { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
ChangeColor(u8, u8, u8),
Echo(String),
Move(Point),
Quit,
}
struct Point {
x: u8,
y: u8,
}
struct State {
color: (u8, u8, u8),
position: Point,
quit: bool,
message: String,
}
impl State {
fn change_color(&mut self, color: (u8, u8, u8)) {
self.color = color;
}
fn quit(&mut self) {
self.quit = true;
}
fn echo(&mut self, s: String) {
self.message = s;
}
fn move_position(&mut self, point: Point) {
self.position = point;
}
fn process(&mut self, message: Message) {
match message {
Message::ChangeColor(r, g, b) => self.change_color((r, g, b)),
Message::Echo(s) => self.echo(s),
Message::Move(point) => self.move_position(point),
Message::Quit => self.quit(),
}
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_match_message_call() {
let mut state = State {
quit: false,
position: Point { x: 0, y: 0 },
color: (0, 0, 0),
message: String::from("hello world"),
};
state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::Echo(String::from("Hello world!")));
state.process(Message::Move(Point { x: 10, y: 15 }));
state.process(Message::Quit);
assert_eq!(state.color, (255, 0, 255));
assert_eq!(state.position.x, 10);
assert_eq!(state.position.y, 15);
assert!(state.quit);
assert_eq!(state.message, "Hello world!");
}
}

View file

@ -1,9 +1 @@
fn current_favorite_color() -> String { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
// Equivalent to `String::from("blue")`
"blue".to_string()
}
fn main() {
let answer = current_favorite_color();
println!("My current favorite color is {answer}");
}

View file

@ -1,15 +1 @@
fn is_a_color_word(attempt: &str) -> bool { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
attempt == "green" || attempt == "blue" || attempt == "red"
}
fn main() {
let word = String::from("green");
if is_a_color_word(&word) {
// ^ added to have `&String` which is automatically
// coerced to `&str` by the compiler.
println!("That is a color word I know!");
} else {
println!("That is not a color word I know.");
}
}

View file

@ -1,48 +1 @@
fn trim_me(input: &str) -> &str { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
input.trim()
}
fn compose_me(input: &str) -> String {
// The macro `format!` has the same syntax as `println!`, but it returns a
// string instead of printing it to the terminal.
// Equivalent to `input.to_string() + " world!"`
format!("{input} world!")
}
fn replace_me(input: &str) -> String {
input.replace("cars", "balloons")
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn trim_a_string() {
assert_eq!(trim_me("Hello! "), "Hello!");
assert_eq!(trim_me(" What's up!"), "What's up!");
assert_eq!(trim_me(" Hola! "), "Hola!");
}
#[test]
fn compose_a_string() {
assert_eq!(compose_me("Hello"), "Hello world!");
assert_eq!(compose_me("Goodbye"), "Goodbye world!");
}
#[test]
fn replace_a_string() {
assert_eq!(
replace_me("I think cars are cool"),
"I think balloons are cool",
);
assert_eq!(
replace_me("I love to look at cars"),
"I love to look at balloons",
);
}
}

View file

@ -1,38 +1 @@
fn string_slice(arg: &str) { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
println!("{arg}");
}
fn string(arg: String) {
println!("{arg}");
}
fn main() {
string_slice("blue");
string("red".to_string());
string(String::from("hi"));
string("rust is fun!".to_owned());
// Here, both answers work.
// `.into()` converts a type into an expected type.
// If it is called where `String` is expected, it will convert `&str` to `String`.
// But if is called where `&str` is expected, then `&str` is kept `&str` since no
// conversion is needed.
string("nice weather".into());
string_slice("nice weather".into());
// ^^^^^^^ the compiler recommends removing the `.into()`
// call because it is a useless conversion.
string(format!("Interpolation {}", "Station"));
// WARNING: This is byte indexing, not character indexing.
// Character indexing can be done using `s.chars().nth(INDEX)`.
string_slice(&String::from("abc")[0..1]);
string_slice(" hello there ".trim());
string("Happy Monday!".replace("Mon", "Tues"));
string("mY sHiFt KeY iS sTiCkY".to_lowercase());
}

View file

@ -1,15 +1 @@
mod sausage_factory { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
fn get_secret_recipe() -> String {
String::from("Ginger")
}
// Added `pub` before `fn` to make the function accessible outside the module.
pub fn make_sausage() {
get_secret_recipe();
println!("sausage!");
}
}
fn main() {
sausage_factory::make_sausage();
}

View file

@ -1,23 +1 @@
mod delicious_snacks { // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
// Added `pub` and used the expected alias after `as`.
pub use self::fruits::PEAR as fruit;
pub use self::veggies::CUCUMBER as veggie;
mod fruits {
pub const PEAR: &str = "Pear";
pub const APPLE: &str = "Apple";
}
mod veggies {
pub const CUCUMBER: &str = "Cucumber";
pub const CARROT: &str = "Carrot";
}
}
fn main() {
println!(
"favorite snacks: {} and {}",
delicious_snacks::fruit,
delicious_snacks::veggie,
);
}

View file

@ -1,8 +1 @@
use std::time::{SystemTime, UNIX_EPOCH}; // Solutions will be available before the stable release. Thank you for testing the beta version 🥰
fn main() {
match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
}
}