diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index c80f76d96..000000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,139 +0,0 @@
-name: "CI"
-
-on:
- push:
- branches:
- - main
- pull_request:
- branches:
- - main
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- repository: mainmatter/core-sans-a-fonts
- ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- path: core-sans-a-fonts
- - name: Install Fonts
- run: |
- sudo cp -r core-sans-a-fonts/* /usr/local/share/fonts/
- sudo fc-cache -f -v
- fc-list | grep "Core Sans"
- - uses: actions-rust-lang/setup-rust-toolchain@v1
- - name: Install exercise plugin
- run: cargo install --path helpers/mdbook-exercise-linker
- - name: Install link shortener plugin
- run: cargo install --path helpers/mdbook-link-shortener
- - name: Install mdbook-pandoc, calibre, pdftk and related dependencies
- run: |
- cargo install mdbook-pandoc --locked --version 0.7.1
- sudo apt-get update
- sudo apt-get install -y fonts-noto calibre pdftk
-
- export PANDOC_VERSION=3.3
- curl -LsSf https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-linux-amd64.tar.gz | tar zxf -
- echo "$PWD/pandoc-${PANDOC_VERSION}/bin" >> $GITHUB_PATH
- shell: bash
- - name: Setup TeX Live
- uses: teatimeguest/setup-texlive-action@v3
- with:
- packages:
- scheme-basic
- luatex
- lualatex-math
- luacolor
- luatexbase
- luaotfload
- framed
- unicode-math
- xcolor
- geometry
- longtable
- booktabs
- array
- lua-ul
- etoolbox
- fancyvrb
- footnote
- selnolig
- natbib
- csquotes
- bookmark
- xurl
- amsmath
- setspace
- iftex
- - name: Check `tlmgr` version
- run: tlmgr --version
- - uses: taiki-e/install-action@v2
- with:
- tool: mdbook
- - name: Build book
- env:
- LINK_SHORTENER_VERIFY: "true"
- run: |
- cd book
- mdbook build
- - name: Add cover and back to downloadable PDF
- run: |
- pdftk book/assets/cover.pdf book/book/pandoc/pdf/100-exercises-to-learn-rust.pdf book/assets/back.pdf cat output book/book/pandoc/pdf/100-exercises-to-learn-rust-with-cover.pdf
- mv book/book/pandoc/pdf/100-exercises-to-learn-rust-with-cover.pdf book/book/pandoc/pdf/100-exercises-to-learn-rust.pdf
- - name: Convert HTML to ePUB
- run: |
- cd book/book/pandoc/html
- sed -i 's|\\newpage
{=latex}||g' 100-exercises-to-learn-rust.html
- ebook-convert 100-exercises-to-learn-rust.html 100-exercises-to-learn-rust.epub \
- --embed-all-fonts \
- --subset-embedded-fonts
- - name: Link Checker
- uses: lycheeverse/lychee-action@v1
- with:
- fail: true
- args: |
- --exclude-loopback
- --require-https
- --no-progress
- book/book/html/
- # Upload the HTML book as an artifact
- - uses: actions/upload-artifact@v4
- with:
- name: book
- # When you support multiple formats, the output directory changes
- # to include the format in its path.
- path: book/book/html
- - uses: actions/upload-artifact@v4
- with:
- name: online-pdf
- path: book/book/pandoc/pdf/100-exercises-to-learn-rust.pdf
- - uses: actions/upload-artifact@v4
- with:
- name: paperback
- path: book/book/pandoc/paperback/100-exercises-to-learn-rust.pdf
- - uses: actions/upload-artifact@v4
- with:
- name: ePUB
- path: book/book/pandoc/html/100-exercises-to-learn-rust.epub
-
- is_fresh:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - run: sudo apt-get update && sudo apt-get install -y jq
- - run: |
- ./helpers/json2redirects.sh book/link2alias.json > site/_redirects
- # Verify nothing has changed, meaning that the redirect file is up-to-date
- - run: |
- git diff --exit-code site/_redirects
-
- formatter:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: dprint/check@v2.2
\ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
new file mode 100644
index 000000000..9fd45e090
--- /dev/null
+++ b/.github/workflows/rust.yml
@@ -0,0 +1,22 @@
+name: Rust
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+env:
+ CARGO_TERM_COLOR: always
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Build
+ run: cargo build --verbose
+ - name: Run tests
+ run: cargo test --verbose
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 000000000..13566b81b
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/100-exercises-to-learn-rust.iml b/.idea/100-exercises-to-learn-rust.iml
new file mode 100644
index 000000000..67ffa75fd
--- /dev/null
+++ b/.idea/100-exercises-to-learn-rust.iml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 000000000..c2a79df73
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 000000000..35eb1ddfb
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..6ad06ce71
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "rust-analyzer.diagnostics.useRustcErrorCode": true
+}
\ No newline at end of file
diff --git a/exercises/01_intro/00_welcome/src/lib.rs b/exercises/01_intro/00_welcome/src/lib.rs
index ec95b6ca7..e0f1fc265 100644
--- a/exercises/01_intro/00_welcome/src/lib.rs
+++ b/exercises/01_intro/00_welcome/src/lib.rs
@@ -17,7 +17,7 @@
// You can also find solutions to all exercises in the `solutions` git branch.
fn greeting() -> &'static str {
// TODO: fix me 👇
- "I'm ready to __!"
+ "I'm ready to learn Rust!"
}
// Your solutions will be automatically verified by a set of tests.
diff --git a/exercises/01_intro/01_syntax/src/lib.rs b/exercises/01_intro/01_syntax/src/lib.rs
index 676d81b22..001d56ab5 100644
--- a/exercises/01_intro/01_syntax/src/lib.rs
+++ b/exercises/01_intro/01_syntax/src/lib.rs
@@ -3,7 +3,7 @@
// partner in this course and it'll often guide you in the right direction!
//
// The input parameters should have the same type of the return type.
-fn compute(a, b) -> u32 {
+fn compute(a : u32, b : u32) -> u32 {
// Don't touch the function body.
a + b * 2
}
diff --git a/exercises/02_basic_calculator/00_intro/src/lib.rs b/exercises/02_basic_calculator/00_intro/src/lib.rs
index 03aeb1633..446e06257 100644
--- a/exercises/02_basic_calculator/00_intro/src/lib.rs
+++ b/exercises/02_basic_calculator/00_intro/src/lib.rs
@@ -1,6 +1,5 @@
fn intro() -> &'static str {
- // TODO: fix me 👇
- "I'm ready to __!"
+ "I'm ready to build a calculator in Rust!"
}
#[cfg(test)]
diff --git a/exercises/02_basic_calculator/01_integers/src/lib.rs b/exercises/02_basic_calculator/01_integers/src/lib.rs
index 555db12ab..d01dc7b9e 100644
--- a/exercises/02_basic_calculator/01_integers/src/lib.rs
+++ b/exercises/02_basic_calculator/01_integers/src/lib.rs
@@ -1,6 +1,6 @@
fn compute(a: u32, b: u32) -> u32 {
// TODO: change the line below to fix the compiler error and make the tests pass.
- a + b * 4u8
+ a + b * (4u8 as u32)
}
#[cfg(test)]
diff --git a/exercises/02_basic_calculator/02_variables/src/lib.rs b/exercises/02_basic_calculator/02_variables/src/lib.rs
index e8d116749..c894ac98d 100644
--- a/exercises/02_basic_calculator/02_variables/src/lib.rs
+++ b/exercises/02_basic_calculator/02_variables/src/lib.rs
@@ -8,7 +8,7 @@
pub fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 {
// TODO: define a variable named `distance` with the right value to get tests to pass
// Do you need to annotate the type of `distance`? Why or why not?
-
+ let distance = end - start;
// Don't change the line below
distance / time_elapsed
}
diff --git a/exercises/02_basic_calculator/03_if_else/src/lib.rs b/exercises/02_basic_calculator/03_if_else/src/lib.rs
index 15af33e1d..0f47aee34 100644
--- a/exercises/02_basic_calculator/03_if_else/src/lib.rs
+++ b/exercises/02_basic_calculator/03_if_else/src/lib.rs
@@ -1,6 +1,6 @@
/// Return `true` if `n` is even, `false` otherwise.
fn is_even(n: u32) -> bool {
- todo!()
+ n % 2 == 0
}
#[cfg(test)]
diff --git a/exercises/02_basic_calculator/04_panics/src/lib.rs b/exercises/02_basic_calculator/04_panics/src/lib.rs
index 341a5ef3a..b76c56507 100644
--- a/exercises/02_basic_calculator/04_panics/src/lib.rs
+++ b/exercises/02_basic_calculator/04_panics/src/lib.rs
@@ -2,7 +2,9 @@
/// calculate the average speed of the journey.
fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 {
// TODO: Panic with a custom message if `time_elapsed` is 0
-
+ if time_elapsed == 0 {
+ panic!("The journey took no time at all, that's impossible!");
+ }
(end - start) / time_elapsed
}
diff --git a/exercises/02_basic_calculator/05_factorial/src/lib.rs b/exercises/02_basic_calculator/05_factorial/src/lib.rs
index d2f11a721..ef43562aa 100644
--- a/exercises/02_basic_calculator/05_factorial/src/lib.rs
+++ b/exercises/02_basic_calculator/05_factorial/src/lib.rs
@@ -9,6 +9,13 @@
// `factorial(2)` to return `2`, and so on.
//
// Use only what you learned! No loops yet, so you'll have to use recursion!
+fn factorial(n: u32) -> u32 {
+ if n == 0 {
+ 1
+ } else {
+ n * factorial(n - 1)
+ }
+}
#[cfg(test)]
mod tests {
diff --git a/exercises/02_basic_calculator/06_while/src/lib.rs b/exercises/02_basic_calculator/06_while/src/lib.rs
index dbc30ebb2..6b7bf0403 100644
--- a/exercises/02_basic_calculator/06_while/src/lib.rs
+++ b/exercises/02_basic_calculator/06_while/src/lib.rs
@@ -1,10 +1,16 @@
// Rewrite the factorial function using a `while` loop.
-pub fn factorial(n: u32) -> u32 {
+pub fn factorial(mut n: u32) -> u32 {
// The `todo!()` macro is a placeholder that the compiler
// interprets as "I'll get back to this later", thus
// suppressing type errors.
// It panics at runtime.
- todo!()
+ let mut result = 1;
+
+ while n > 0 {
+ result *= n;
+ n -= 1;
+ }
+ result
}
#[cfg(test)]
diff --git a/exercises/02_basic_calculator/07_for/src/lib.rs b/exercises/02_basic_calculator/07_for/src/lib.rs
index d571d57d9..9df098843 100644
--- a/exercises/02_basic_calculator/07_for/src/lib.rs
+++ b/exercises/02_basic_calculator/07_for/src/lib.rs
@@ -1,6 +1,11 @@
// Rewrite the factorial function using a `for` loop.
pub fn factorial(n: u32) -> u32 {
- todo!()
+
+ let mut result = 1;
+ for i in 1..=n {
+ result *= i;
+ }
+ result
}
#[cfg(test)]
diff --git a/exercises/02_basic_calculator/08_overflow/src/lib.rs b/exercises/02_basic_calculator/08_overflow/src/lib.rs
index f99dd7cf5..7924179fa 100644
--- a/exercises/02_basic_calculator/08_overflow/src/lib.rs
+++ b/exercises/02_basic_calculator/08_overflow/src/lib.rs
@@ -5,12 +5,12 @@
// For reasons that we'll explain later, the customization needs to be done in the `Cargo.toml`
// at the root of the repository, not in the `Cargo.toml` of the exercise.
-pub fn factorial(n: u32) -> u32 {
- let mut result = 1;
+pub fn factorial(n: u32) -> Option {
+ let mut result: u32 = 1;
for i in 1..=n {
- result *= i;
+ result = result.checked_mul(i)?;
}
- result
+ Some(result)
}
#[cfg(test)]
@@ -22,28 +22,29 @@ mod tests {
// 20! is 2432902008176640000, which is too large to fit in a u32
// With the default dev profile, this will panic when you run `cargo test`
// We want it to wrap around instead
- assert_eq!(factorial(20), 2_192_834_560);
+ //assert_eq!(factorial(20), 2_192_834_560);
+ assert_eq!(factorial(20), None);
// ☝️
// A large number literal using underscores to improve readability!
}
#[test]
fn first() {
- assert_eq!(factorial(0), 1);
+ assert_eq!(factorial(0), Some(1));
}
#[test]
fn second() {
- assert_eq!(factorial(1), 1);
+ assert_eq!(factorial(1), Some(1));
}
#[test]
fn third() {
- assert_eq!(factorial(2), 2);
+ assert_eq!(factorial(2), Some(2));
}
#[test]
fn fifth() {
- assert_eq!(factorial(5), 120);
+ assert_eq!(factorial(5), Some(120));
}
}
diff --git a/exercises/02_basic_calculator/09_saturating/src/lib.rs b/exercises/02_basic_calculator/09_saturating/src/lib.rs
index 4b0addec5..a254b434f 100644
--- a/exercises/02_basic_calculator/09_saturating/src/lib.rs
+++ b/exercises/02_basic_calculator/09_saturating/src/lib.rs
@@ -1,9 +1,9 @@
pub fn factorial(n: u32) -> u32 {
- let mut result = 1;
+ let mut result: u32 = 1;
for i in 1..=n {
// Use saturating multiplication to stop at the maximum value of u32
// rather than overflowing and wrapping around
- result *= i;
+ result = result.saturating_mul(i);
}
result
}
diff --git a/exercises/02_basic_calculator/10_as_casting/src/lib.rs b/exercises/02_basic_calculator/10_as_casting/src/lib.rs
index b1921d0a2..109b088f3 100644
--- a/exercises/02_basic_calculator/10_as_casting/src/lib.rs
+++ b/exercises/02_basic_calculator/10_as_casting/src/lib.rs
@@ -6,7 +6,7 @@ mod tests {
#[test]
fn u16_to_u32() {
- let v: u32 = todo!();
+ let v: u32 = 47;
assert_eq!(47u16 as u32, v);
}
@@ -19,19 +19,19 @@ mod tests {
// literal. If we were to use a variable, the compiler wouldn't be able to
// catch this at compile time.
#[allow(overflowing_literals)]
- let x = { 255 as i8 };
+ let x = { -124 as i8 };
// You could solve this by using exactly the same expression as above,
// but that would defeat the purpose of the exercise. Instead, use a genuine
// `i8` value that is equivalent to `255` when converted from `u8`.
- let y: i8 = todo!();
+ let y: i8 = -124 as i8;
assert_eq!(x, y);
}
#[test]
fn bool_to_u8() {
- let v: u8 = todo!();
+ let v: u8 = 1;
assert_eq!(true as u8, v);
}
}
diff --git a/exercises/03_ticket_v1/00_intro/src/lib.rs b/exercises/03_ticket_v1/00_intro/src/lib.rs
index f7afa4701..7c8a4d64d 100644
--- a/exercises/03_ticket_v1/00_intro/src/lib.rs
+++ b/exercises/03_ticket_v1/00_intro/src/lib.rs
@@ -1,6 +1,5 @@
fn intro() -> &'static str {
- // TODO: fix me 👇
- "I'm ready to __!"
+ "I'm ready to start modelling a software ticket!"
}
#[cfg(test)]
diff --git a/exercises/03_ticket_v1/01_struct/src/lib.rs b/exercises/03_ticket_v1/01_struct/src/lib.rs
index 1119e330a..4187073f0 100644
--- a/exercises/03_ticket_v1/01_struct/src/lib.rs
+++ b/exercises/03_ticket_v1/01_struct/src/lib.rs
@@ -5,6 +5,17 @@
// It should also have a method named `is_available` that returns a `true` if the quantity is
// greater than 0, otherwise `false`.
+struct Order {
+ price: u32,
+ quantity: u32,
+}
+
+impl Order {
+ fn is_available(&self) -> bool {
+ self.quantity > 0
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;