mirror of
https://github.com/rust-lang/rustlings.git
synced 2025-01-09 20:03:24 +03:00
Compare commits
No commits in common. "3d540ed946ee9fd522ba9ec26f68055f5c498317" and "d768353806f905989b4cc29cd7a97891cbbf8ec3" have entirely different histories.
3d540ed946
...
d768353806
|
@ -1,12 +1,13 @@
|
|||
struct ColorRegularStruct {
|
||||
// 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?
|
||||
// Address all the TODOs to make the tests pass!
|
||||
|
||||
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)]
|
||||
struct UnitStruct;
|
||||
struct UnitLikeStruct;
|
||||
|
||||
fn main() {
|
||||
// You can optionally experiment here.
|
||||
|
@ -17,8 +18,8 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn regular_structs() {
|
||||
// TODO: Instantiate a regular struct.
|
||||
fn classic_c_structs() {
|
||||
// TODO: Instantiate a classic c struct!
|
||||
// let green =
|
||||
|
||||
assert_eq!(green.red, 0);
|
||||
|
@ -28,7 +29,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn tuple_structs() {
|
||||
// TODO: Instantiate a tuple struct.
|
||||
// TODO: Instantiate a tuple struct!
|
||||
// let green =
|
||||
|
||||
assert_eq!(green.0, 0);
|
||||
|
@ -38,10 +39,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn unit_structs() {
|
||||
// TODO: Instantiate a unit struct.
|
||||
// let unit_struct =
|
||||
let message = format!("{unit_struct:?}s are fun!");
|
||||
// TODO: Instantiate a unit-like struct!
|
||||
// let unit_like_struct =
|
||||
let message = format!("{:?}s are fun!", unit_like_struct);
|
||||
|
||||
assert_eq!(message, "UnitStructs are fun!");
|
||||
assert_eq!(message, "UnitLikeStructs are fun!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Address all the TODOs to make the tests pass!
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Order {
|
||||
name: String,
|
||||
|
@ -32,10 +34,8 @@ mod tests {
|
|||
#[test]
|
||||
fn your_order() {
|
||||
let order_template = create_order_template();
|
||||
|
||||
// TODO: Create your own order using the update syntax and template above!
|
||||
// let your_order =
|
||||
|
||||
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);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// 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)]
|
||||
struct Package {
|
||||
|
@ -9,28 +10,26 @@ struct 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 {
|
||||
// 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,
|
||||
// This is not how you should handle errors in Rust,
|
||||
// but we will learn about error handling later.
|
||||
panic!("Can not ship a package with weight below 10 grams.")
|
||||
} else {
|
||||
Package {
|
||||
sender_country,
|
||||
recipient_country,
|
||||
weight_in_grams,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add the correct return type to the function signature.
|
||||
fn is_international(&self) {
|
||||
// TODO: Read the tests that use this method to find out when a package is concidered international.
|
||||
fn is_international(&self) -> ??? {
|
||||
// Something goes here...
|
||||
}
|
||||
|
||||
// TODO: Add the correct return type to the function signature.
|
||||
fn get_fees(&self, cents_per_gram: u32) {
|
||||
// TODO: Calculate the package's fees.
|
||||
fn get_fees(&self, cents_per_gram: u32) -> ??? {
|
||||
// Something goes here...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[derive(Debug)]
|
||||
enum Message {
|
||||
// TODO: Define a few types of messages as used below.
|
||||
// TODO: define a few types of messages as used below
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[derive(Debug)]
|
||||
enum Message {
|
||||
// TODO: Define the different variants used below.
|
||||
// TODO: define the different variants used below
|
||||
}
|
||||
|
||||
impl Message {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Address all the TODOs to make the tests pass!
|
||||
|
||||
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 {
|
||||
|
@ -24,17 +26,17 @@ impl State {
|
|||
}
|
||||
|
||||
fn echo(&mut self, s: String) {
|
||||
self.message = s;
|
||||
self.message = s
|
||||
}
|
||||
|
||||
fn move_position(&mut self, point: Point) {
|
||||
self.position = point;
|
||||
fn move_position(&mut self, p: Point) {
|
||||
self.position = p;
|
||||
}
|
||||
|
||||
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:
|
||||
// e.g. `foo((t, u, p, l, e))`
|
||||
// fn function((t, u, p, l, e))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,9 +54,8 @@ mod tests {
|
|||
quit: false,
|
||||
position: Point { x: 0, y: 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::Echo(String::from("Hello world!")));
|
||||
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.position.x, 10);
|
||||
assert_eq!(state.position.y, 15);
|
||||
assert!(state.quit);
|
||||
assert_eq!(state.quit, true);
|
||||
assert_eq!(state.message, "Hello world!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// TODO: Fix the compiler error without changing the function signature.
|
||||
fn current_favorite_color() -> String {
|
||||
"blue"
|
||||
}
|
||||
// Make me compile without changing the function signature!
|
||||
|
||||
fn main() {
|
||||
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"
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// TODO: Fix the compiler error in the `main` function without changing this function.
|
||||
fn is_a_color_word(attempt: &str) -> bool {
|
||||
attempt == "green" || attempt == "blue" || attempt == "red"
|
||||
}
|
||||
// Make me compile without changing the function signature!
|
||||
|
||||
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) {
|
||||
println!("That is a color word I know!");
|
||||
} else {
|
||||
println!("That is not a color word I know.");
|
||||
}
|
||||
}
|
||||
|
||||
fn is_a_color_word(attempt: &str) -> bool {
|
||||
attempt == "green" || attempt == "blue" || attempt == "red"
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
fn trim_me(input: &str) -> &str {
|
||||
// TODO: Remove whitespace from both ends of a string.
|
||||
fn trim_me(input: &str) -> String {
|
||||
// TODO: Remove whitespace from both ends of a 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 {
|
||||
// TODO: Replace "cars" in the string with "balloons".
|
||||
// TODO: Replace "cars" in the string with "balloons"!
|
||||
???
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -33,13 +36,7 @@ mod tests {
|
|||
|
||||
#[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",
|
||||
);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,36 +1,24 @@
|
|||
// Calls of this function should be replaced with calls of `string_slice` or `string`.
|
||||
fn placeholder() {}
|
||||
// Ok, here are a bunch of values - some are `String`s, some are `&str`s. Your
|
||||
// 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) {
|
||||
println!("{arg}");
|
||||
println!("{}", arg);
|
||||
}
|
||||
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() {
|
||||
placeholder("blue");
|
||||
|
||||
placeholder("red".to_string());
|
||||
|
||||
placeholder(String::from("hi"));
|
||||
|
||||
placeholder("rust is fun!".to_owned());
|
||||
|
||||
placeholder("nice weather".into());
|
||||
|
||||
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());
|
||||
???("blue");
|
||||
???("red".to_string());
|
||||
???(String::from("hi"));
|
||||
???("rust is fun!".to_owned());
|
||||
???("nice weather".into());
|
||||
???(format!("Interpolation {}", "Station"));
|
||||
???(&String::from("abc")[0..1]);
|
||||
???(" hello there ".trim());
|
||||
???("Happy Monday!".to_string().replace("Mon", "Tues"));
|
||||
???("mY sHiFt KeY iS sTiCkY".to_lowercase());
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
// TODO: Fix the compiler error about calling a private function.
|
||||
mod sausage_factory {
|
||||
// Don't let anybody outside of this module see this!
|
||||
fn get_secret_recipe() -> String {
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
// 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 {
|
||||
// TODO: Add the follwing two `use` statements after fixing them.
|
||||
// use self::fruits::PEAR as ???;
|
||||
// use self::veggies::CUCUMBER as ???;
|
||||
// TODO: Fix these use statements
|
||||
use self::fruits::PEAR as ???
|
||||
use self::veggies::CUCUMBER as ???
|
||||
|
||||
mod fruits {
|
||||
pub const PEAR: &str = "Pear";
|
||||
pub const APPLE: &str = "Apple";
|
||||
pub const PEAR: &'static str = "Pear";
|
||||
pub const APPLE: &'static str = "Apple";
|
||||
}
|
||||
|
||||
mod veggies {
|
||||
pub const CUCUMBER: &str = "Cucumber";
|
||||
pub const CARROT: &str = "Carrot";
|
||||
pub const CUCUMBER: &'static str = "Cucumber";
|
||||
pub const CARROT: &'static str = "Carrot";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +22,6 @@ fn main() {
|
|||
println!(
|
||||
"favorite snacks: {} and {}",
|
||||
delicious_snacks::fruit,
|
||||
delicious_snacks::veggie,
|
||||
delicious_snacks::veggie
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// You can use the `use` keyword to bring module paths from modules from
|
||||
// anywhere and especially from the standard library into your scope.
|
||||
// You can use the 'use' keyword to bring module paths from modules from
|
||||
// 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
|
||||
// your scope. Bonus style points if you can do it with one line!
|
||||
// use ???;
|
||||
// TODO: Complete this use statement
|
||||
use ???
|
||||
|
||||
fn main() {
|
||||
match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
|
|
|
@ -402,14 +402,15 @@ hint = """
|
|||
Rust has more than one type of struct. Three actually, all variants are used to
|
||||
package related data together.
|
||||
|
||||
There are regular structs. These are named collections of related data stored in
|
||||
fields.
|
||||
There are normal (or classic) structs. These are named collections of related
|
||||
data stored in fields.
|
||||
|
||||
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:
|
||||
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.
|
||||
|
||||
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"""
|
||||
|
||||
[[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
|
||||
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"""
|
||||
|
||||
# ENUMS
|
||||
|
@ -451,18 +452,18 @@ dir = "08_enums"
|
|||
test = false
|
||||
hint = """
|
||||
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]]
|
||||
name = "enums3"
|
||||
dir = "08_enums"
|
||||
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
|
||||
to get the variant's values."""
|
||||
to get value in the variant."""
|
||||
|
||||
# STRINGS
|
||||
|
||||
|
@ -486,7 +487,7 @@ dir = "09_strings"
|
|||
test = false
|
||||
hint = """
|
||||
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
|
||||
`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"
|
||||
dir = "09_strings"
|
||||
hint = """
|
||||
There are many useful standard library functions for strings. Let's try and use
|
||||
some of them:
|
||||
There's tons of useful standard library functions for strings. Let's try and use some of them:
|
||||
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
|
||||
|
@ -510,15 +510,7 @@ the string slice into an owned string, which you can then freely extend."""
|
|||
name = "strings4"
|
||||
dir = "09_strings"
|
||||
test = false
|
||||
hint = """
|
||||
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`.
|
||||
"""
|
||||
hint = "No hints this time ;)"
|
||||
|
||||
# MODULES
|
||||
|
||||
|
@ -527,21 +519,21 @@ name = "modules1"
|
|||
dir = "10_modules"
|
||||
test = false
|
||||
hint = """
|
||||
Everything is private in Rust by default. But there's a keyword we can use
|
||||
to make something public!"""
|
||||
Everything is private in Rust by default-- but there's a keyword we can use
|
||||
to make something public! The compiler error should point to the thing that
|
||||
needs to be public."""
|
||||
|
||||
[[exercises]]
|
||||
name = "modules2"
|
||||
dir = "10_modules"
|
||||
test = false
|
||||
hint = """
|
||||
The `delicious_snacks` module is trying to present an external interface that
|
||||
is different than its internal structure (the `fruits` and `veggies` modules
|
||||
and associated constants). Complete the `use` statements to fit the uses in
|
||||
`main` and find the one keyword missing for both constants.
|
||||
The delicious_snacks module is trying to present an external interface that is
|
||||
different than its internal structure (the `fruits` and `veggies` modules and
|
||||
associated constants). Complete the `use` statements to fit the uses in main and
|
||||
find the one keyword missing for both constants.
|
||||
|
||||
Learn more in The Book:
|
||||
https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#re-exporting-names-with-pub-use"""
|
||||
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"""
|
||||
|
||||
[[exercises]]
|
||||
name = "modules3"
|
||||
|
@ -550,7 +542,7 @@ test = false
|
|||
hint = """
|
||||
`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
|
||||
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
|
||||
|
||||
|
|
|
@ -1,49 +1 @@
|
|||
struct ColorRegularStruct {
|
||||
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!");
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,51 +1 @@
|
|||
#[derive(Debug)]
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,83 +1 @@
|
|||
#[derive(Debug)]
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,14 +1 @@
|
|||
#[derive(Debug)]
|
||||
enum Message {
|
||||
Quit,
|
||||
Echo,
|
||||
Move,
|
||||
ChangeColor,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", Message::Quit);
|
||||
println!("{:?}", Message::Echo);
|
||||
println!("{:?}", Message::Move);
|
||||
println!("{:?}", Message::ChangeColor);
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,26 +1 @@
|
|||
#[derive(Debug)]
|
||||
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();
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,75 +1 @@
|
|||
enum Message {
|
||||
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!");
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,9 +1 @@
|
|||
fn current_favorite_color() -> String {
|
||||
// Equivalent to `String::from("blue")`
|
||||
"blue".to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let answer = current_favorite_color();
|
||||
println!("My current favorite color is {answer}");
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,15 +1 @@
|
|||
fn is_a_color_word(attempt: &str) -> bool {
|
||||
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.");
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,48 +1 @@
|
|||
fn trim_me(input: &str) -> &str {
|
||||
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",
|
||||
);
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,38 +1 @@
|
|||
fn string_slice(arg: &str) {
|
||||
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());
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,15 +1 @@
|
|||
mod sausage_factory {
|
||||
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();
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,23 +1 @@
|
|||
mod delicious_snacks {
|
||||
// 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,
|
||||
);
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
|
@ -1,8 +1 @@
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
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!"),
|
||||
}
|
||||
}
|
||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
||||
|
|
Loading…
Reference in a new issue