├── .github └── workflows │ └── mdbook.yml ├── .gitignore ├── LICENSE ├── README.md ├── assets └── lets-get-rusty-learning-guide.png ├── book.toml ├── src ├── SUMMARY.md ├── advanced │ ├── async-await-traits.md │ ├── attribute-like.md │ ├── calling-unsafe-functions.md │ ├── creating-threads.md │ ├── custom-derive.md │ ├── declarative-macros.md │ ├── dereferencing-raw-pointers.md │ ├── ffi-c-from-rust.md │ ├── ffi-rust-from-c.md │ ├── ffi-rust-from-python.md │ ├── function-like.md │ ├── implementing-unsafe-traits.md │ ├── inline-assembly.md │ ├── intro-to-concurrency.md │ ├── intro-to-macros.md │ ├── intro-to-unsafe-rust.md │ ├── moving-values-into-threads.md │ ├── mutable-static-variables.md │ ├── passing-messages-between-threads.md │ ├── procedural-macros.md │ ├── send-and-sync-traits.md │ ├── sharing-states-between-threads.md │ ├── tokio-streams.md │ └── tokio-tasks.md ├── beginner │ ├── basics.md │ ├── benchmark-tests.md │ ├── borrowing.md │ ├── cargo-features.md │ ├── cargo-workspaces.md │ ├── comments.md │ ├── constants-statics-exercises.md │ ├── constants-statics.md │ ├── control-flow.md │ ├── data-types.md │ ├── documentation.md │ ├── enums.md │ ├── external-dependencies.md │ ├── functions.md │ ├── hello-world.md │ ├── implementation-blocks.md │ ├── integration-tests.md │ ├── matching.md │ ├── memory-saftey.md │ ├── modules.md │ ├── option.md │ ├── ownership.md │ ├── project-structure.md │ ├── publishing-your-package.md │ ├── result.md │ ├── setup.md │ ├── slices.md │ ├── strings.md │ ├── structs.md │ ├── tuple-structs.md │ ├── unit-tests.md │ ├── variables.md │ └── vectors.md ├── curriculum │ ├── accelerator.html │ ├── favicon.png │ ├── index.html │ └── lgr_logo.png ├── further-learning │ ├── api-project.md │ ├── building-microservices-in-rust.md │ ├── cli-project.md │ ├── deep-dive-into-string-in-rust.md │ ├── mircoservices-project.md │ ├── rust-based-computer-science.md │ └── systems-programming-in-rust.md ├── index.md ├── intermediate │ ├── anyhow.md │ ├── avoiding-unwrap.md │ ├── box-smart-pointer.md │ ├── closures.md │ ├── combinators.md │ ├── concrete-lifetimes.md │ ├── custom-errors.md │ ├── deref-coercion.md │ ├── deriving-traits.md │ ├── error-stack.md │ ├── function-pointers.md │ ├── generics-lifetimes.md │ ├── generics.md │ ├── iterator-over-collections.md │ ├── iterator-pattern.md │ ├── lifetime-elision.md │ ├── multiple-error-types-exercises.md │ ├── multiple-error-types.md │ ├── orphan-rule.md │ ├── propagating-errors.md │ ├── rc-smart-pointer.md │ ├── recoverable-errors.md │ ├── refcell-smart-pointer.md │ ├── result-and-option.md │ ├── supertraits.md │ ├── thiserror.md │ ├── trait-bounds.md │ ├── trait-objects.md │ ├── traits.md │ └── unrecoverable-errors.md ├── roadmap │ ├── favicon.png │ ├── index.html │ └── lgr_logo.png ├── start-with-tris │ ├── favicon.png │ ├── index.html │ └── lgr_logo.png ├── start │ ├── favicon.png │ ├── index.html │ └── lgr_logo.png └── starter-pack │ ├── curriculum.html │ ├── favicon.png │ ├── index.html │ └── lgr_logo.png └── theme ├── book.js ├── css ├── chrome.css ├── general.css ├── print.css └── variables.css ├── favicon.png ├── favicon.svg ├── fonts ├── OPEN-SANS-LICENSE.txt ├── SOURCE-CODE-PRO-LICENSE.txt ├── fonts.css ├── open-sans-v17-all-charsets-300.woff2 ├── open-sans-v17-all-charsets-300italic.woff2 ├── open-sans-v17-all-charsets-600.woff2 ├── open-sans-v17-all-charsets-600italic.woff2 ├── open-sans-v17-all-charsets-700.woff2 ├── open-sans-v17-all-charsets-700italic.woff2 ├── open-sans-v17-all-charsets-800.woff2 ├── open-sans-v17-all-charsets-800italic.woff2 ├── open-sans-v17-all-charsets-italic.woff2 ├── open-sans-v17-all-charsets-regular.woff2 └── source-code-pro-v11-all-charsets-500.woff2 ├── head.hbs ├── highlight.css ├── highlight.js └── index.hbs /.github/workflows/mdbook.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a mdBook site to GitHub Pages 2 | # 3 | # To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html 4 | # 5 | name: Deploy mdBook site to Pages 6 | 7 | on: 8 | # Runs on pushes targeting the default branch 9 | push: 10 | branches: ["main"] 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 16 | permissions: 17 | contents: read 18 | pages: write 19 | id-token: write 20 | 21 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 22 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 23 | concurrency: 24 | group: "pages" 25 | cancel-in-progress: false 26 | 27 | jobs: 28 | # Build job 29 | build: 30 | runs-on: ubuntu-latest 31 | env: 32 | MDBOOK_VERSION: 0.4.36 33 | steps: 34 | - uses: actions/checkout@v4 35 | - name: Install mdBook 36 | run: | 37 | curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh 38 | rustup update 39 | cargo install --version ${MDBOOK_VERSION} mdbook 40 | - name: Setup Pages 41 | id: pages 42 | uses: actions/configure-pages@v4 43 | - name: Build with mdBook 44 | run: mdbook build 45 | - name: Upload artifact 46 | uses: actions/upload-pages-artifact@v3 47 | with: 48 | path: ./book 49 | 50 | # Deployment job 51 | deploy: 52 | environment: 53 | name: github-pages 54 | url: ${{ steps.deployment.outputs.page_url }} 55 | runs-on: ubuntu-latest 56 | needs: build 57 | steps: 58 | - name: Deploy to GitHub Pages 59 | id: deployment 60 | uses: actions/deploy-pages@v4 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # Generated by mdBook 17 | book 18 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Let's Get Rusty 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Let's Get Rusty Learning Guide 🦀 2 | 3 | ![Let's Get Rusty Learning Guide](assets/lets-get-rusty-learning-guide.png) 4 | 5 | This is a space designed for aspiring Rust developers. 6 | 7 | The curriculum is composed of existing YouTube videos by Let's Get Rusty, organized to guide you step-by-step through your Rust learning journey. 8 | 9 | And to make your learning more interactive, there're exercises covering most of the topics. So, whether you're just starting out or looking to sharpen your skills in Rust, this is the perfect place for you. 10 | 11 | To discuss and/or collaborate with other Rust developers, join our [Discord community](https://discord.com/invite/wTfbkNeZnv)! 12 | 13 | ## Features 14 | 15 | - Tutorial videos by Let's Get Rusty 16 | 17 | - Additional resources 18 | 19 | - Exercises 20 | 21 | - Exercise solutions 22 | 23 | - More user customizations coming soon! 24 | 25 | ## Installation 26 | 27 | ```shell 28 | git clone git@github.com:letsgetrusty/rust-learning-guide.git 29 | 30 | cargo install mdbook 31 | 32 | cd rust-learning-guide && mdbook serve --open 33 | ``` 34 | 35 | ## Credits 36 | 37 | - Bogdan himself :) 38 | 39 | - Talented technical writers @ Let's Get Rusty 40 | 41 | - OP open-source community contributors! 42 | 43 | - [The Rust Book](https://github.com/rust-lang/book), [Rust By Example](https://github.com/rust-lang/rust-by-example), [Rust By Practice](https://github.com/sunface/rust-by-practice) 44 | 45 | ## Licenses 46 | 47 | - MIT License -------------------------------------------------------------------------------- /assets/lets-get-rusty-learning-guide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/assets/lets-get-rusty-learning-guide.png -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["letsgetrusty"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "Let's Get Rusty" 7 | 8 | [output.html] 9 | default-theme = "ayu" 10 | preferred-dark-theme = "ayu" 11 | no-section-label = true 12 | 13 | [output.html.fold] 14 | enable = true 15 | level = 0 16 | 17 | [output.html.playground] 18 | editable = true 19 | 20 | [rust] 21 | edition = "2021" -------------------------------------------------------------------------------- /src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | 4 | [Let's Get Rusty Learning Guide](index.md) 5 | 6 | # Beginner 7 | 8 | ---- 9 | 10 | - [Basics](beginner/setup.md) 11 | - [Setup](beginner/setup.md) 12 | - [Hello World](beginner/hello-world.md) 13 | - [Comments](beginner/comments.md) 14 | - [Variables](beginner/variables.md) 15 | - [Data Types](beginner/data-types.md) 16 | - [Constants & Statics](beginner/constants-statics.md) 17 | - [Functions](beginner/functions.md) 18 | - [Control Flow](beginner/control-flow.md) 19 | - [Memory Safety](beginner/ownership.md) 20 | - [Ownership](beginner/ownership.md) 21 | - [Borrowing](beginner/borrowing.md) 22 | - [Slices](beginner/slices.md) 23 | - [Strings](beginner/strings.md) 24 | - [Custom Data Types](beginner/structs.md) 25 | - [Structs](beginner/structs.md) 26 | - [Implementation Blocks](beginner/implementation-blocks.md) 27 | - [Tuple Structs](beginner/tuple-structs.md) 28 | - [Enums](beginner/enums.md) 29 | - [Matching](beginner/matching.md) 30 | - [Option](beginner/option.md) 31 | - [Result](beginner/result.md) 32 | - [Vectors](beginner/vectors.md) 33 | - [Project Structure](beginner/project-structure.md) 34 | - [Project Structure Overview](beginner/project-structure.md) 35 | - [Modules](beginner/modules.md) 36 | - [External Dependencies](beginner/external-dependencies.md) 37 | - [Publishing Your Package](beginner/publishing-your-package.md) 38 | - [Cargo Features](beginner/cargo-features.md) 39 | - [Cargo Workspaces](beginner/cargo-workspaces.md) 40 | - [Testing](beginner/unit-tests.md) 41 | - [Unit Tests](beginner/unit-tests.md) 42 | - [Integration Tests](beginner/integration-tests.md) 43 | - [Benchmark Tests](beginner/benchmark-tests.md) 44 | - [Documentation](beginner/documentation.md) 45 | 46 | # Intermediate 47 | 48 | ---- 49 | 50 | - [Polymorphism](intermediate/generics.md) 51 | - [Generics](intermediate/generics.md) 52 | - [Traits](intermediate/traits.md) 53 | - [Trait Bounds](intermediate/trait-bounds.md) 54 | - [Supertraits](intermediate/supertraits.md) 55 | - [Trait Objects](intermediate/trait-objects.md) 56 | - [Deriving Traits](intermediate/deriving-traits.md) 57 | - [Orphan Rule](intermediate/orphan-rule.md) 58 | - [Advanced Memory Management](intermediate/concrete-lifetimes.md) 59 | - [Concrete Lifetimes](intermediate/concrete-lifetimes.md) 60 | - [Generic Lifetimes](intermediate/generics-lifetimes.md) 61 | - [Lifetime Elision](intermediate/lifetime-elision.md) 62 | - [Box Smart Pointer](intermediate/box-smart-pointer.md) 63 | - [Rc Smart Pointer](intermediate/rc-smart-pointer.md) 64 | - [RefCell Smart Pointer](intermediate/refcell-smart-pointer.md) 65 | - [Deref Coercion](intermediate/deref-coercion.md) 66 | - [Error Handling](intermediate/unrecoverable-errors.md) 67 | - [Unrecoverable Errors](intermediate/unrecoverable-errors.md) 68 | - [Recoverable Errors](intermediate/recoverable-errors.md) 69 | - [Propagating Errors](intermediate/propagating-errors.md) 70 | - [Result and Option](intermediate/result-and-option.md) 71 | - [Multiple Error Types](intermediate/multiple-error-types.md) 72 | - [Advanced Error Handling](intermediate/avoiding-unwrap.md) 73 | - [Avoiding Unwrap](intermediate/avoiding-unwrap.md) 74 | - [Custom Errors](intermediate/custom-errors.md) 75 | - [thiserror](intermediate/thiserror.md) 76 | - [anyhow](intermediate/anyhow.md) 77 | - [error-stack](intermediate/error-stack.md) 78 | - [Functional Programming](intermediate/closures.md) 79 | - [Closures](intermediate/closures.md) 80 | - [Function Pointers](intermediate/function-pointers.md) 81 | - [Iterator Pattern](intermediate/iterator-pattern.md) 82 | - [Iterator over Collections](intermediate/iterator-over-collections.md) 83 | - [Combinators](intermediate/combinators.md) 84 | 85 | # Advanced 86 | 87 | ---- 88 | 89 | - [Concurrency](advanced/intro-to-concurrency.md) 90 | - [Intro to Concurrency](advanced/intro-to-concurrency.md) 91 | - [Creating Threads](advanced/creating-threads.md) 92 | - [Moving Values into Threads](advanced/moving-values-into-threads.md) 93 | - [Passing Messages between Threads](advanced/passing-messages-between-threads.md) 94 | - [Sharing States between Threads](advanced/sharing-states-between-threads.md) 95 | - [Send and Sync Traits](advanced/send-and-sync-traits.md) 96 | - [async/.await](advanced/async-await-traits.md) 97 | - [Tokio Tasks](advanced/tokio-tasks.md) 98 | - [Tokio Streams](advanced/tokio-streams.md) 99 | - [Macros](advanced/intro-to-macros.md) 100 | - [Intro to Macros](advanced/intro-to-macros.md) 101 | - [Declarative Macros](advanced/declarative-macros.md) 102 | - [Procedural Macros](advanced/procedural-macros.md) 103 | - [Custom Derive](advanced/custom-derive.md) 104 | - [Attribute Like](advanced/attribute-like.md) 105 | - [Function Like](advanced/function-like.md) 106 | - [Unsafe Rust and FFI](advanced/intro-to-unsafe-rust.md) 107 | - [Intro to Unsafe Rust](advanced/intro-to-unsafe-rust.md) 108 | - [Dereferencing Raw Pointers](advanced/dereferencing-raw-pointers.md) 109 | - [Calling Unsafe Functions](advanced/calling-unsafe-functions.md) 110 | - [Mutable Static Variables](advanced/mutable-static-variables.md) 111 | - [Implementing Unsafe Traits](advanced/implementing-unsafe-traits.md) 112 | - [Inline Assembly](advanced/inline-assembly.md) 113 | - [FFI C from Rust](advanced/ffi-c-from-rust.md) 114 | - [FFI Rust from C](advanced/ffi-rust-from-c.md) 115 | - [FFI Rust from Python](advanced/ffi-rust-from-python.md) 116 | 117 | # Further Learning 118 | 119 | ---- 120 | 121 | - [Masterclasses](further-learning/rust-based-computer-science.md) 122 | - [Rust Based Computer Science](further-learning/rust-based-computer-science.md) 123 | - [Deep Dive into Strings in Rust](further-learning/deep-dive-into-string-in-rust.md) 124 | - [Building Microservices in Rust](further-learning/building-microservices-in-rust.md) 125 | - [Systems Programming in Rust](further-learning/systems-programming-in-rust.md) 126 | - [Projects](further-learning/cli-project.md) 127 | - [CLI Project](further-learning/cli-project.md) 128 | - [API Project](further-learning/api-project.md) 129 | - [Microservices Project](further-learning/mircoservices-project.md) 130 | -------------------------------------------------------------------------------- /src/advanced/async-await-traits.md: -------------------------------------------------------------------------------- 1 | # async/.await 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Starter guide to writing async Rust 9 | - Crust of Rust: async/await 10 | 11 | ## Exercises 12 | 13 | #### Awaiting 14 | 15 | ```rust,editable,compile_fail 16 | // When executing the below code nothing is printed to console. Can you guess what is missing? 17 | 18 | #[tokio::main] 19 | async fn main() { 20 | my_function(); 21 | } 22 | 23 | async fn my_function() { 24 | println!("My first asynchronous function in rust!"); 25 | } 26 | ``` 27 | 28 |
29 | Solution 30 | 31 | ```rust 32 | #[tokio::main] 33 | async fn main() { 34 | my_function().await; 35 | } 36 | 37 | async fn my_function() { 38 | println!("My first asynchronous function in rust!"); 39 | } 40 | ``` 41 |
42 | 43 | #### Creating executor 44 | 45 | ```rust,editable,compile_fail 46 | // Fix the code to make it compile. You may only add code, not remove it. 47 | 48 | use std::time::Duration; 49 | use tokio::time::sleep; 50 | 51 | struct Employee { 52 | id: u32, 53 | name: String, 54 | salary: f32, 55 | } 56 | 57 | impl Employee { 58 | fn new(id: u32, name: &str, salary: f32) -> Self { 59 | Self { 60 | id, 61 | name: name.to_string(), 62 | salary, 63 | } 64 | } 65 | } 66 | 67 | fn main() { 68 | let (id1, id2) = (2, 3); 69 | let emp1 = read_details_from_db(id1).await.unwrap(); 70 | let emp2 = read_details_from_db(id2).await.unwrap(); 71 | if emp1.salary > emp2.salary { 72 | println!( 73 | "{} earns ${} more than {}", 74 | emp1.name, 75 | emp1.salary - emp2.salary, 76 | emp2.name 77 | ); 78 | } else if emp2.salary > emp1.salary { 79 | println!( 80 | "{} earns ${} more than {}", 81 | emp2.name, 82 | emp2.salary - emp1.salary, 83 | emp1.name 84 | ); 85 | } else { 86 | println!("Both {} and {} earn same amount", emp1.name, emp2.name); 87 | } 88 | } 89 | 90 | async fn read_details_from_db(id: u32) -> Result { 91 | // dummy read from database 92 | sleep(Duration::from_millis(1000)).await; 93 | let database = [ 94 | Employee::new(1, "Alice", 98000.0), 95 | Employee::new(2, "Bob", 95000.0), 96 | Employee::new(3, "Cindy", 95000.0), 97 | ]; 98 | for emp in database { 99 | if id == emp.id { 100 | return Ok(emp); 101 | } 102 | } 103 | Err("Employee record not present".into()) 104 | } 105 | ``` 106 | 107 |
108 | Solution 109 | 110 | ```rust 111 | use std::time::Duration; 112 | use tokio::time::sleep; 113 | 114 | struct Employee { 115 | id: u32, 116 | name: String, 117 | salary: f32, 118 | } 119 | 120 | impl Employee { 121 | fn new(id: u32, name: &str, salary: f32) -> Self { 122 | Self { 123 | id, 124 | name: name.to_string(), 125 | salary, 126 | } 127 | } 128 | } 129 | 130 | #[tokio::main] 131 | async fn main() { 132 | let (id1, id2) = (2, 3); 133 | let emp1 = read_details_from_db(id1).await.unwrap(); 134 | let emp2 = read_details_from_db(id2).await.unwrap(); 135 | if emp1.salary > emp2.salary { 136 | println!( 137 | "{} earns ${} more than {}", 138 | emp1.name, 139 | emp1.salary - emp2.salary, 140 | emp2.name 141 | ); 142 | } else if emp2.salary > emp1.salary { 143 | println!( 144 | "{} earns ${} more than {}", 145 | emp2.name, 146 | emp2.salary - emp1.salary, 147 | emp1.name 148 | ); 149 | } else { 150 | println!("Both {} and {} earn same amount", emp1.name, emp2.name); 151 | } 152 | } 153 | 154 | async fn read_details_from_db(id: u32) -> Result { 155 | // dummy read from database 156 | sleep(Duration::from_millis(1000)).await; 157 | let database = [ 158 | Employee::new(1, "Alice", 98000.0), 159 | Employee::new(2, "Bob", 95000.0), 160 | Employee::new(3, "Cindy", 95000.0), 161 | ]; 162 | for emp in database { 163 | if id == emp.id { 164 | return Ok(emp); 165 | } 166 | } 167 | Err("Employee record not present".into()) 168 | } 169 | ``` 170 |
171 | -------------------------------------------------------------------------------- /src/advanced/attribute-like.md: -------------------------------------------------------------------------------- 1 | # Attribute Like 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/advanced/calling-unsafe-functions.md: -------------------------------------------------------------------------------- 1 | # Calling Unsafe Functions 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Unsafe functions 10 | 11 | ```rust,editable,compile_fail 12 | // Fix the code to make it compile. You can only add and not remove anything from the code. 13 | 14 | fn increment(a: *mut i32) { 15 | *a += 1; 16 | } 17 | 18 | fn get_val(a: *const i32) -> i32 { 19 | *a 20 | } 21 | 22 | fn main() { 23 | let mut x = 0; 24 | let ptr1 = &mut x as *mut i32; 25 | unsafe { 26 | increment(ptr1); 27 | increment(ptr1); 28 | increment(ptr1); 29 | assert_eq!(get_val(ptr1), 3); 30 | } 31 | } 32 | ``` 33 | 34 |
35 | Solution 36 | 37 | ```rust 38 | unsafe fn increment(a: *mut i32) { 39 | *a += 1; 40 | } 41 | 42 | unsafe fn get_val(a: *const i32) -> i32 { 43 | *a 44 | } 45 | 46 | fn main() { 47 | let mut x = 0; 48 | let ptr1 = &mut x as *mut i32; 49 | unsafe { 50 | increment(ptr1); 51 | increment(ptr1); 52 | increment(ptr1); 53 | assert_eq!(get_val(ptr1), 3); 54 | } 55 | } 56 | ``` 57 |
58 | 59 | #### Unsafe methods 60 | 61 | ```rust,editable,compile_fail 62 | // Something is missing from the method signatures. Complete them wherever required. 63 | 64 | use std::ops::{Add, Mul, Sub}; 65 | 66 | struct VarManipulator(*mut T) 67 | where 68 | T: Copy + Add + Mul + Sub; 69 | 70 | impl VarManipulator 71 | where 72 | T: Copy + Add + Mul + Sub, 73 | { 74 | fn new(ptr: *mut T) -> Self { 75 | Self(ptr) 76 | } 77 | fn add(&self, operand2: T) { 78 | *self.0 = *self.0 + operand2; 79 | } 80 | fn mul(&self, operand2: T) { 81 | *self.0 = *self.0 * operand2; 82 | } 83 | fn sub(&self, operand2: T) { 84 | *self.0 = *self.0 - operand2; 85 | } 86 | fn get_val(&self) -> T { 87 | *self.0 88 | } 89 | } 90 | 91 | fn main() { 92 | let mut x = 20; 93 | let manipulator = VarManipulator::new(&mut x); 94 | unsafe { 95 | manipulator.sub(10); 96 | manipulator.mul(9); 97 | manipulator.add(10); 98 | assert_eq!(manipulator.get_val(), 100); 99 | assert_eq!(x, manipulator.get_val()); 100 | } 101 | } 102 | ``` 103 | 104 |
105 | Solution 106 | 107 | ```rust 108 | use std::ops::{Add, Mul, Sub}; 109 | 110 | struct VarManipulator(*mut T) 111 | where 112 | T: Copy + Add + Mul + Sub; 113 | 114 | impl VarManipulator 115 | where 116 | T: Copy + Add + Mul + Sub, 117 | { 118 | fn new(ptr: *mut T) -> Self { 119 | Self(ptr) 120 | } 121 | unsafe fn add(&self, operand2: T) { 122 | *self.0 = *self.0 + operand2; 123 | } 124 | unsafe fn mul(&self, operand2: T) { 125 | *self.0 = *self.0 * operand2; 126 | } 127 | unsafe fn sub(&self, operand2: T) { 128 | *self.0 = *self.0 - operand2; 129 | } 130 | unsafe fn get_val(&self) -> T { 131 | *self.0 132 | } 133 | } 134 | 135 | fn main() { 136 | let mut x = 20; 137 | let manipulator = VarManipulator::new(&mut x); 138 | unsafe { 139 | manipulator.sub(10); 140 | manipulator.mul(9); 141 | manipulator.add(10); 142 | assert_eq!(manipulator.get_val(), 100); 143 | assert_eq!(x, manipulator.get_val()); 144 | } 145 | } 146 | ``` 147 |
148 | -------------------------------------------------------------------------------- /src/advanced/creating-threads.md: -------------------------------------------------------------------------------- 1 | # Creating Threads 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Joining 1 10 | 11 | ```rust,editable,compile_fail 12 | // Modify the code to ensure that main thread waits for other threads to finish. 13 | 14 | use std::thread; 15 | 16 | fn main() { 17 | // print hello 10 times from spawned thread 18 | let handle = thread::spawn(|| { 19 | for i in 0..10 { 20 | println!("{i} Hello from spawned thread!") 21 | } 22 | }); 23 | 24 | // print hello 10 times from main thread 25 | for i in 0..10 { 26 | println!("{i} Hello from main thread!"); 27 | } 28 | } 29 | ``` 30 | 31 |
32 | Solution 33 | 34 | ```rust 35 | use std::thread; 36 | 37 | fn main() { 38 | // print hello 10 times from spawned thread 39 | let handle = thread::spawn(|| { 40 | for i in 0..10 { 41 | println!("{i} Hello from spawned thread!") 42 | } 43 | }); 44 | 45 | // print hello 10 times from main thread 46 | for i in 0..10 { 47 | println!("{i} Hello from main thread!"); 48 | } 49 | handle.join().unwrap(); 50 | } 51 | ``` 52 |
53 | 54 | #### Joining 2 55 | 56 | ```rust,editable,compile_fail 57 | // Fix the code to make sure that sum is calculated correctly. 58 | 59 | use std::{ 60 | ops::Range, 61 | thread::{self, JoinHandle}, 62 | }; 63 | 64 | fn summation_thread(range: Range) -> JoinHandle { 65 | thread::spawn(|| { 66 | let mut sum = 0; 67 | for num in range { 68 | sum += num; 69 | } 70 | sum 71 | }) 72 | } 73 | 74 | // calculate the sum of numbers 1..=40_00_000 using four threads 75 | fn main() { 76 | let handle1 = summation_thread(1..10_00_000); 77 | let handle2 = summation_thread(10_00_000..20_00_000); 78 | let handle3 = summation_thread(20_00_000..30_00_000); 79 | 80 | let mut sum = 0u64; 81 | for num in 30_00_000..=40_00_000 { 82 | sum += num; 83 | } 84 | println!("Sum of numbers 1..=40_00_000: {sum}"); 85 | assert_eq!(sum, 8000002000000); 86 | } 87 | ``` 88 | 89 |
90 | Solution 91 | 92 | ```rust 93 | use std::{ 94 | ops::Range, 95 | thread::{self, JoinHandle}, 96 | }; 97 | 98 | fn summation_thread(range: Range) -> JoinHandle { 99 | thread::spawn(|| { 100 | let mut sum = 0; 101 | for num in range { 102 | sum += num; 103 | } 104 | sum 105 | }) 106 | } 107 | 108 | // calculate the sum of numbers 1..=40_00_000 using four threads 109 | fn main() { 110 | let handle1 = summation_thread(1..10_00_000); 111 | let handle2 = summation_thread(10_00_000..20_00_000); 112 | let handle3 = summation_thread(20_00_000..30_00_000); 113 | 114 | let mut sum = 0u64; 115 | for num in 30_00_000..=40_00_000 { 116 | sum += num; 117 | } 118 | sum += handle1.join().unwrap(); 119 | sum += handle2.join().unwrap(); 120 | sum += handle3.join().unwrap(); 121 | println!("Sum of numbers 1..=40_00_000: {sum}"); 122 | assert_eq!(sum, 8000002000000); 123 | } 124 | ``` 125 |
126 | 127 | #### Sleeping 128 | 129 | ```rust,editable,compile_fail 130 | // When main thread terminates, all the spawned threads also get terminated. 131 | // Make the main thread sleep for half a second before terminating, to ensure that spawned thread gets enough time to complete. 132 | // Do not join the spawned thread. 133 | 134 | use std::thread; 135 | 136 | fn main() { 137 | thread::spawn(|| { 138 | println!("Count down from 10 to 1 🚀"); 139 | for num in (1..=10).rev() { 140 | println!("Count down: {num}!"); 141 | } 142 | }); 143 | println!("Count up from 1 to 10..."); 144 | for num in 1..=10 { 145 | println!("Count up: {num}"); 146 | } 147 | } 148 | ``` 149 | 150 |
151 | Solution 152 | 153 | ```rust 154 | use std::thread; 155 | use std::time::Duration; 156 | 157 | fn main() { 158 | thread::spawn(|| { 159 | println!("Count down from 10 to 1 🚀"); 160 | for num in (1..=10).rev() { 161 | println!("Count down: {num}!"); 162 | } 163 | }); 164 | println!("Count up from 1 to 10..."); 165 | for num in 1..=10 { 166 | println!("Count up: {num}"); 167 | } 168 | thread::sleep(Duration::from_millis(500)); 169 | } 170 | ``` 171 |
172 | -------------------------------------------------------------------------------- /src/advanced/custom-derive.md: -------------------------------------------------------------------------------- 1 | # Custom Derive 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/advanced/declarative-macros.md: -------------------------------------------------------------------------------- 1 | # Declarative Macros 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - A Practical Introduction to Declarative Macros in Rust 9 | 10 | ## Exercises 11 | 12 | #### Invocation 13 | 14 | ```rust,editable,compile_fail 15 | // Fix the code to make it compile. 16 | 17 | macro_rules! my_macro { 18 | () => { 19 | println!("Check out my macro!"); 20 | }; 21 | } 22 | 23 | fn main() { 24 | my_macro(); 25 | } 26 | ``` 27 | 28 |
29 | Solution 30 | 31 | ```rust 32 | macro_rules! my_macro { 33 | () => { 34 | println!("Check out my macro!"); 35 | }; 36 | } 37 | 38 | fn main() { 39 | my_macro!(); 40 | } 41 | ``` 42 |
43 | 44 | #### Scope 1 45 | 46 | ```rust,editable,compile_fail 47 | // Everything seems correct, but the code does not compile. Maybe it has to do with the position of defining a macro. 48 | 49 | fn main() { 50 | my_macro!(); 51 | } 52 | 53 | macro_rules! my_macro { 54 | () => { 55 | println!("Check out my macro!"); 56 | }; 57 | } 58 | ``` 59 | 60 |
61 | Solution 62 | 63 | ```rust 64 | macro_rules! my_macro { 65 | () => { 66 | println!("Check out my macro!"); 67 | }; 68 | } 69 | 70 | fn main() { 71 | my_macro!(); 72 | } 73 | ``` 74 |
75 | 76 | #### Scope 2 77 | 78 | ```rust,editable,compile_fail 79 | // Fix the code by bringing `my_macros` in scope (You have to mark `macros` module with something). 80 | 81 | mod macros { 82 | macro_rules! my_macro { 83 | () => { 84 | println!("Check out my macro!"); 85 | }; 86 | } 87 | } 88 | 89 | fn main() { 90 | my_macro!(); 91 | } 92 | ``` 93 | 94 |
95 | Solution 96 | 97 | ```rust 98 | #[macro_use] 99 | mod macros { 100 | macro_rules! my_macro { 101 | () => { 102 | println!("Check out my macro!"); 103 | }; 104 | } 105 | } 106 | 107 | fn main() { 108 | my_macro!(); 109 | } 110 | ``` 111 |
112 | 113 | #### Multiple matchers 1 114 | 115 | ```rust,editable,compile_fail 116 | // Fix the code to make it compile. You can not remove anything. 117 | 118 | #[rustfmt::skip] 119 | macro_rules! my_macro { 120 | () => { 121 | println!("Check out my macro!"); 122 | } 123 | ($val:expr) => { 124 | println!("Look at this other macro: {}", $val); 125 | } 126 | } 127 | 128 | fn main() { 129 | my_macro!(); 130 | my_macro!(7777); 131 | } 132 | ``` 133 | 134 |
135 | Solution 136 | 137 | ```rust 138 | #[rustfmt::skip] 139 | macro_rules! my_macro { 140 | () => { 141 | println!("Check out my macro!"); 142 | }; 143 | ($val:expr) => { 144 | println!("Look at this other macro: {}", $val); 145 | }; 146 | } 147 | 148 | fn main() { 149 | my_macro!(); 150 | my_macro!(7777); 151 | } 152 | ``` 153 |
154 | 155 | #### Multiple matchers 2 156 | 157 | ```rust,editable,compile_fail 158 | // We are trying to create a macro called `vec2`, which has the same functionality as the `vec` macro. 159 | // Complete the transcriber for each matcher. 160 | 161 | macro_rules! vec2 { 162 | () => {}; 163 | ($($a:expr),+ $(,)?) => {{}}; 164 | ($m:expr; $n:expr) => {{}}; 165 | } 166 | 167 | #[cfg(test)] 168 | mod tests { 169 | 170 | #[test] 171 | fn creates_empty_vector() { 172 | let first: Vec = vec![]; 173 | let second: Vec = vec2![]; 174 | assert_eq!(first, second); 175 | } 176 | 177 | #[test] 178 | fn creates_vector_from_list() { 179 | assert_eq!(vec![1, 2, 3,], vec2![1, 2, 3,]); 180 | assert_eq!(vec!['a', 'b', 'b', 'a'], vec2!['a', 'b', 'b', 'a']); 181 | } 182 | 183 | #[test] 184 | fn creates_vector_with_repeating_element() { 185 | assert_eq!(vec![5; 10], vec2![5;10]); 186 | } 187 | } 188 | ``` 189 | 190 |
191 | Solution 192 | 193 | ```rust 194 | macro_rules! vec2 { 195 | () => { 196 | Vec::new() 197 | }; 198 | ($($a:expr),+ $(,)?) => { 199 | { 200 | let mut res = Vec::new(); 201 | $( res.push($a); )+ 202 | res 203 | } 204 | }; 205 | ($m:expr; $n:expr) => { 206 | { 207 | let mut res = Vec::new(); 208 | for _ in 0..$n { 209 | res.push($m.clone()); 210 | } 211 | res 212 | } 213 | }; 214 | } 215 | 216 | #[cfg(test)] 217 | mod tests { 218 | 219 | #[test] 220 | fn creates_empty_vector() { 221 | let first: Vec = vec![]; 222 | let second: Vec = vec2![]; 223 | assert_eq!(first, second); 224 | } 225 | 226 | #[test] 227 | fn creates_vector_from_list() { 228 | assert_eq!(vec![1, 2, 3,], vec2![1, 2, 3,]); 229 | assert_eq!(vec!['a', 'b', 'b', 'a'], vec2!['a', 'b', 'b', 'a']); 230 | } 231 | 232 | #[test] 233 | fn creates_vector_with_repeating_element() { 234 | assert_eq!(vec![5; 10], vec2![5;10]); 235 | } 236 | } 237 | ``` 238 |
239 | 240 | #### Repetition 241 | 242 | ```rust,editable,compile_fail 243 | // Complete the definition of `sum`. 244 | 245 | macro_rules! sum { 246 | () => { 247 | { 248 | let mut sum = 0; 249 | $( sum += $a; )+ 250 | } 251 | }; 252 | } 253 | 254 | fn main() { 255 | assert_eq!(sum!(1, 2, 3), 6); 256 | assert_eq!(sum!(10u8, 20u8), 30); 257 | } 258 | ``` 259 | 260 |
261 | Solution 262 | 263 | ```rust 264 | macro_rules! sum { 265 | ($($a:expr),+) => { 266 | { 267 | let mut sum = 0; 268 | $( sum += $a; )+ 269 | sum 270 | } 271 | }; 272 | } 273 | 274 | fn main() { 275 | assert_eq!(sum!(1, 2, 3), 6); 276 | assert_eq!(sum!(10u8, 20u8), 30); 277 | } 278 | ``` 279 |
280 | -------------------------------------------------------------------------------- /src/advanced/dereferencing-raw-pointers.md: -------------------------------------------------------------------------------- 1 | # Dereferencing Raw Pointers 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Immutable raw pointers 10 | 11 | ```rust,editable,compile_fail 12 | // Fix the code to make it compile. You may not modify any statement. 13 | 14 | fn main() { 15 | let num = 123; 16 | let ptr = &num as *const i32; 17 | println!("{} stored at {:p}", *ptr, ptr); 18 | } 19 | ``` 20 | 21 |
22 | Solution 23 | 24 | ```rust 25 | fn main() { 26 | let num = 123; 27 | let ptr = &num as *const i32; 28 | unsafe { 29 | println!("{} stored at {:p}", *ptr, ptr); 30 | } 31 | } 32 | ``` 33 |
34 | 35 | #### Mutable raw pointers 36 | 37 | ```rust,editable,compile_fail 38 | // Fix the code to make it compile. 39 | 40 | fn main() { 41 | // print first 10 fibonacci numbers 42 | let (mut a, mut b) = (1, 0); 43 | let mut c = 0; 44 | let ptr_a = &mut a as *const i32; 45 | let ptr_b = &mut b as *const i32; 46 | let ptr_c = &mut c as *const i32; 47 | for _ in 0..10 { 48 | *ptr_c = *ptr_a + *ptr_b; 49 | println!("{}", *ptr_c); 50 | *ptr_a = *ptr_b; 51 | *ptr_b = *ptr_c; 52 | } 53 | } 54 | ``` 55 | 56 |
57 | Solution 58 | 59 | ```rust 60 | fn main() { 61 | // print first 10 fibonacci numbers 62 | let (mut a, mut b) = (1, 0); 63 | let mut c = 0; 64 | let ptr_a = &mut a as *mut i32; 65 | let ptr_b = &mut b as *mut i32; 66 | let ptr_c = &mut c as *mut i32; 67 | unsafe { 68 | for _ in 0..10 { 69 | *ptr_c = *ptr_a + *ptr_b; 70 | println!("{}", *ptr_c); 71 | *ptr_a = *ptr_b; 72 | *ptr_b = *ptr_c; 73 | } 74 | } 75 | } 76 | ``` 77 |
78 | 79 | #### Multiple pointers 80 | 81 | ```rust,editable,compile_fail 82 | // Fix the code to make it compile. 83 | 84 | macro_rules! ptr { 85 | ($type:ty, $var:ident) => { 86 | &mut $var as *mut $type 87 | }; 88 | } 89 | 90 | fn main() { 91 | let mut x = 20; 92 | let ptr1 = ptr!(i32, x); 93 | let ptr2 = ptr!(i32, x); 94 | println!("x: {x}"); 95 | *ptr1 = *ptr1 * 2; 96 | *ptr2 = *ptr2 * 2; 97 | *ptr2 = *ptr1 * 2; 98 | println!("x * 8 = {x}"); 99 | } 100 | ``` 101 | 102 |
103 | Solution 104 | 105 | ```rust 106 | macro_rules! ptr { 107 | ($type:ty, $var:ident) => { 108 | &mut $var as *mut $type 109 | }; 110 | } 111 | 112 | fn main() { 113 | let mut x = 20; 114 | let ptr1 = ptr!(i32, x); 115 | let ptr2 = ptr!(i32, x); 116 | println!("x: {x}"); 117 | unsafe { 118 | *ptr1 = *ptr1 * 2; 119 | *ptr2 = *ptr2 * 2; 120 | *ptr2 = *ptr1 * 2; 121 | } 122 | println!("x * 8 = {x}"); 123 | } 124 | ``` 125 |
126 | -------------------------------------------------------------------------------- /src/advanced/ffi-c-from-rust.md: -------------------------------------------------------------------------------- 1 | # FFI C from Rust 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/advanced/ffi-rust-from-c.md: -------------------------------------------------------------------------------- 1 | # FFI Rust from C 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/advanced/ffi-rust-from-python.md: -------------------------------------------------------------------------------- 1 | # FFI Rust from Python 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | ## Exercises 10 | 11 | (No exercises yet. Feel free to contribute here!) 12 | -------------------------------------------------------------------------------- /src/advanced/function-like.md: -------------------------------------------------------------------------------- 1 | # Function Like 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/advanced/implementing-unsafe-traits.md: -------------------------------------------------------------------------------- 1 | # Implementing Unsafe Traits 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Unsafe traits 10 | 11 | ```rust,editable,compile_fail 12 | // Fix the code to make it compile. Do not modify trait definition. 13 | 14 | unsafe trait Length { 15 | fn length(&self) -> usize; 16 | } 17 | 18 | impl Length for String { 19 | fn length(&self) -> usize { 20 | self.len() 21 | } 22 | } 23 | 24 | impl Length for i32 { 25 | fn length(&self) -> usize { 26 | match self { 27 | -9..=9 => 1, 28 | _ => 1 + (self / 10).length(), 29 | } 30 | } 31 | } 32 | 33 | fn main() { 34 | let my_str = "Unsafe Traits".to_owned(); 35 | let my_num = 12323; 36 | println!("\"{my_str}\" takes {} bytes", my_str.length()); 37 | println!("{my_num} has {} digits", my_num.length()); 38 | } 39 | 40 | ``` 41 | 42 |
43 | Solution 44 | 45 | ```rust 46 | unsafe trait Length { 47 | fn length(&self) -> usize; 48 | } 49 | 50 | unsafe impl Length for String { 51 | fn length(&self) -> usize { 52 | self.len() 53 | } 54 | } 55 | 56 | unsafe impl Length for i32 { 57 | fn length(&self) -> usize { 58 | match self { 59 | -9..=9 => 1, 60 | _ => 1 + (self / 10).length(), 61 | } 62 | } 63 | } 64 | 65 | fn main() { 66 | let my_str = "Unsafe Traits".to_owned(); 67 | let my_num = 12323; 68 | println!("\"{my_str}\" takes {} bytes", my_str.length()); 69 | println!("{my_num} has {} digits", my_num.length()); 70 | } 71 | ``` 72 |
73 | -------------------------------------------------------------------------------- /src/advanced/inline-assembly.md: -------------------------------------------------------------------------------- 1 | # Inline Assembly 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | #### Additional Resources 10 | - Unlocking the Power of Rust: Use Inline Assembly to make System Calls 11 | 12 | ## Exercises 13 | 14 | (No exercises yet. Feel free to contribute here!) 15 | -------------------------------------------------------------------------------- /src/advanced/intro-to-concurrency.md: -------------------------------------------------------------------------------- 1 | # Intro to Concurrency 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | -------------------------------------------------------------------------------- /src/advanced/intro-to-macros.md: -------------------------------------------------------------------------------- 1 | # Intro to Macros 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | -------------------------------------------------------------------------------- /src/advanced/intro-to-unsafe-rust.md: -------------------------------------------------------------------------------- 1 | # Intro to Unsafe Rust 2 | 3 |
4 | 5 |
-------------------------------------------------------------------------------- /src/advanced/moving-values-into-threads.md: -------------------------------------------------------------------------------- 1 | # Moving Values into Threads 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Moving 10 | 11 | ```rust,editable,compile_fail 12 | // Fix the code to make it compile. 13 | 14 | use std::thread; 15 | 16 | fn main() { 17 | let msg = "Hello from spawned thread".to_owned(); 18 | let handle = thread::spawn(|| { 19 | println!("{msg}"); 20 | }); 21 | handle.join().unwrap(); 22 | } 23 | ``` 24 | 25 |
26 | Solution 27 | 28 | ```rust 29 | use std::thread; 30 | 31 | fn main() { 32 | let msg = "Hello from spawned thread".to_owned(); 33 | let handle = thread::spawn(move || { 34 | println!("{msg}"); 35 | }); 36 | handle.join().unwrap(); 37 | } 38 | ``` 39 |
40 | -------------------------------------------------------------------------------- /src/advanced/mutable-static-variables.md: -------------------------------------------------------------------------------- 1 | # Mutable Static Variables 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Mutating 10 | 11 | ```rust,editable,compile_fail 12 | // Fix the code to make it compile. 13 | 14 | static COUNTER: u32 = 0; 15 | 16 | // return fibonacci number corresponding to specified position 17 | fn fib(num: u32) -> u32 { 18 | unsafe { 19 | COUNTER += 1; 20 | } 21 | if num <= 1 { 22 | num 23 | } else { 24 | fib(num - 1) + fib(num - 2) 25 | } 26 | } 27 | 28 | fn main() { 29 | let num = fib(5); 30 | println!("Fibonacci number at position 5: {num}"); 31 | println!("Number of function calls made to calculate: {COUNTER}"); 32 | } 33 | ``` 34 | 35 |
36 | Solution 37 | 38 | ```rust 39 | static mut COUNTER: u32 = 0; 40 | 41 | // return fibonacci number corresponding to specified position 42 | fn fib(num: u32) -> u32 { 43 | unsafe { 44 | COUNTER += 1; 45 | } 46 | if num <= 1 { 47 | num 48 | } else { 49 | fib(num - 1) + fib(num - 2) 50 | } 51 | } 52 | 53 | fn main() { 54 | let num = fib(5); 55 | println!("Fibonacci number at position 5: {num}"); 56 | unsafe { 57 | println!("Number of function calls made to calculate: {COUNTER}"); 58 | } 59 | } 60 | ``` 61 |
62 | -------------------------------------------------------------------------------- /src/advanced/passing-messages-between-threads.md: -------------------------------------------------------------------------------- 1 | # Passing Messages between Threads 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Message Passing With Rust MPSC Channels 9 | - Threads, Messaging, and MPSC in Rust 10 | 11 | ## Exercises 12 | 13 | #### Passing message 1 14 | 15 | ```rust,editable,compile_fail 16 | // Fix the code to make it compile and produce the correct output. 17 | 18 | use std::sync::mpsc::{self, Sender}; 19 | use std::thread; 20 | 21 | fn main() { 22 | let (tx, rx) = mpsc::channel(); 23 | let nums = [12, 43, 54, 43, 53, 52, 98, 89]; 24 | sum(&nums, 3, tx); 25 | let mut res = 0; 26 | for sum in rx { 27 | res += sum; 28 | } 29 | println!("Sum of numbers: {res}"); 30 | } 31 | 32 | // calculate sum of numbers using specified number of threads 33 | fn sum(nums: &[i32], thread_count: usize, tx) { 34 | let elements_per_thread = nums.len() / thread_count; 35 | let mut start_pos; 36 | let mut partition; 37 | for i in 0..thread_count - 1 { 38 | start_pos = i * elements_per_thread; 39 | partition = Vec::from(&nums[start_pos..start_pos + elements_per_thread]); 40 | let tx_clone = tx.clone(); 41 | thread::spawn(move || { 42 | let mut sum = 0; 43 | for num in partition { 44 | sum += num; 45 | } 46 | }); 47 | } 48 | // sum the remaining elements using last thread 49 | partition = Vec::from(&nums[(thread_count - 1) * elements_per_thread..]); 50 | thread::spawn(move || { 51 | let mut sum = 0; 52 | for num in partition { 53 | sum += num; 54 | } 55 | tx.send(sum).unwrap() 56 | }); 57 | } 58 | ``` 59 | 60 |
61 | Solution 62 | 63 | ```rust 64 | use std::sync::mpsc::{self, Sender}; 65 | use std::thread; 66 | 67 | fn main() { 68 | let (tx, rx) = mpsc::channel(); 69 | let nums = [12, 43, 54, 43, 53, 52, 98, 89]; 70 | sum(&nums, 3, tx); 71 | let mut res = 0; 72 | for sum in rx { 73 | res += sum; 74 | } 75 | println!("Sum of numbers: {res}"); 76 | } 77 | 78 | // calculate sum of numbers using specified number of threads 79 | fn sum(nums: &[i32], thread_count: usize, tx: Sender) { 80 | let elements_per_thread = nums.len() / thread_count; 81 | let mut start_pos; 82 | let mut partition; 83 | for i in 0..thread_count - 1 { 84 | start_pos = i * elements_per_thread; 85 | partition = Vec::from(&nums[start_pos..start_pos + elements_per_thread]); 86 | let tx_clone = tx.clone(); 87 | thread::spawn(move || { 88 | let mut sum = 0; 89 | for num in partition { 90 | sum += num; 91 | } 92 | tx_clone.send(sum).unwrap(); 93 | }); 94 | } 95 | // sum the remaining elements using last thread 96 | partition = Vec::from(&nums[(thread_count - 1) * elements_per_thread..]); 97 | thread::spawn(move || { 98 | let mut sum = 0; 99 | for num in partition { 100 | sum += num; 101 | } 102 | tx.send(sum).unwrap() 103 | }); 104 | } 105 | ``` 106 |
107 | 108 | #### Passing message 2 109 | 110 | ```rust,editable,compile_fail 111 | // Fix the code to make it compile. 112 | 113 | use std::sync::mpsc; 114 | use std::thread; 115 | 116 | fn main() { 117 | let sentences = [ 118 | "!tpircs llehs a eb ot detnaw eh esuaceB ?tsuR nrael barC eht sirreF did yhW".to_owned(), 119 | "!sgel sih fo thgie lla htiw tsuR ni edoc nac eh - reksat-itlum etamitlu eht si barC eht sirreF".to_owned() 120 | ]; 121 | let (tx, rx) = mpsc::channel(); 122 | for sentence in sentences { 123 | let tx_clone = tx.clone(); 124 | thread::spawn(|| { 125 | let reversed = sentence.chars().rev().collect::(); 126 | }); 127 | } 128 | drop(tx); 129 | let printer = thread::spawn(|| { 130 | println!("Reversed sentences:"); 131 | for sentence in rx { 132 | println!("{sentence}"); 133 | } 134 | }); 135 | printer.join().unwrap(); 136 | } 137 | ``` 138 | 139 |
140 | Solution 141 | 142 | ```rust 143 | use std::sync::mpsc; 144 | use std::thread; 145 | 146 | fn main() { 147 | let sentences = [ 148 | "!tpircs llehs a eb ot detnaw eh esuaceB ?tsuR nrael barC eht sirreF did yhW".to_owned(), 149 | "!sgel sih fo thgie lla htiw tsuR ni edoc nac eh - reksat-itlum etamitlu eht si barC eht sirreF".to_owned() 150 | ]; 151 | let (tx, rx) = mpsc::channel(); 152 | for sentence in sentences { 153 | let tx_clone = tx.clone(); 154 | thread::spawn(move || { 155 | let reversed = sentence.chars().rev().collect::(); 156 | tx_clone.send(reversed).unwrap(); 157 | }); 158 | } 159 | drop(tx); 160 | let printer = thread::spawn(|| { 161 | println!("Reversed sentences:"); 162 | for sentence in rx { 163 | println!("{sentence}"); 164 | } 165 | }); 166 | printer.join().unwrap(); 167 | } 168 | ``` 169 |
170 | -------------------------------------------------------------------------------- /src/advanced/procedural-macros.md: -------------------------------------------------------------------------------- 1 | # Procedural Macros 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Learning Rust: Procedural Macros 9 | 10 | ## Exercises 11 | 12 | (No exercises yet. Feel free to contribute here!) 13 | -------------------------------------------------------------------------------- /src/advanced/send-and-sync-traits.md: -------------------------------------------------------------------------------- 1 | # Send and Sync Traits 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | #### Additional Resources 10 | - Send, Sync, and their implementors 11 | 12 | ## Exercises 13 | 14 | (No exercises yet. Feel free to contribute here!) 15 | -------------------------------------------------------------------------------- /src/advanced/sharing-states-between-threads.md: -------------------------------------------------------------------------------- 1 | # Sharing States between Threads 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Rust: Shared-State Concurrency 9 | 10 | ## Exercises 11 | 12 | #### Acquiring locks 13 | 14 | ```rust,editable,compile_fail 15 | // Inorder to access a value wrapped in a mutex, it's lock has to be acquired. 16 | // Fix the code by acquiring the lock at appropriate places. 17 | 18 | use std::sync::{Arc, Mutex}; 19 | use std::thread; 20 | 21 | struct Wrapper { 22 | value: i32, 23 | } 24 | 25 | impl Wrapper { 26 | fn new() -> Self { 27 | Wrapper { value: 0 } 28 | } 29 | fn add(&mut self, to_add: i32) { 30 | self.value += to_add; 31 | } 32 | } 33 | 34 | // calculate sum of range 1..=40000 using four threads 35 | fn main() { 36 | let sum = Arc::new(Mutex::new(Wrapper::new())); 37 | let mut handles = Vec::new(); 38 | for i in 0..4 { 39 | let sum_clone = Arc::clone(&sum); 40 | let handle = thread::spawn(move || { 41 | let mut sum = 0; 42 | let start = i * 10000 + 1; 43 | for num in start..start + 10000 { 44 | sum += num; 45 | } 46 | // TODO: acquire lock and add sum to sum_clone 47 | }); 48 | handles.push(handle); 49 | } 50 | for handle in handles { 51 | handle.join().unwrap(); 52 | } 53 | // TODO: acquire lock and print the sum value 54 | println!("Sum of range 1..=40000 : {}"); 55 | } 56 | ``` 57 | 58 |
59 | Solution 60 | 61 | ```rust 62 | use std::sync::{Arc, Mutex}; 63 | use std::thread; 64 | 65 | struct Wrapper { 66 | value: i32, 67 | } 68 | 69 | impl Wrapper { 70 | fn new() -> Self { 71 | Wrapper { value: 0 } 72 | } 73 | fn add(&mut self, to_add: i32) { 74 | self.value += to_add; 75 | } 76 | } 77 | 78 | // calculate sum of range 1..=40000 using four threads 79 | fn main() { 80 | let sum = Arc::new(Mutex::new(Wrapper::new())); 81 | let mut handles = Vec::new(); 82 | for i in 0..4 { 83 | let sum_clone = Arc::clone(&sum); 84 | let handle = thread::spawn(move || { 85 | let mut sum = 0; 86 | let start = i * 10000 + 1; 87 | for num in start..start + 10000 { 88 | sum += num; 89 | } 90 | let mut lock = sum_clone.lock().unwrap(); 91 | lock.add(sum); 92 | }); 93 | handles.push(handle); 94 | } 95 | for handle in handles { 96 | handle.join().unwrap(); 97 | } 98 | let lock = sum.lock().unwrap(); 99 | println!("Sum of range 1..=40000 : {}", lock.value); 100 | } 101 | ``` 102 |
103 | 104 | #### Atomic ref count 105 | 106 | ```rust,editable,compile_fail 107 | // Fix the code to make it compile. 108 | 109 | use std::rc::Rc; 110 | use std::sync::Mutex; 111 | use std::thread; 112 | 113 | fn is_prime(num: u32) -> bool { 114 | for i in 2..=num / 2 { 115 | if num % i == 0 { 116 | return false; 117 | } 118 | } 119 | if num <= 1 { 120 | false 121 | } else { 122 | true 123 | } 124 | } 125 | 126 | // list of all prime numbers less than 10000 using four threads 127 | fn main() { 128 | let mut primes = Rc::new(Mutex::new(Vec::new())); 129 | let thread_count = 4; 130 | let elemets_per_thread = 10000 / thread_count; 131 | let mut handles = Vec::new(); 132 | for i in 0..thread_count { 133 | let start = i * elemets_per_thread; 134 | let list_clone = Rc::clone(&primes); 135 | let handle = thread::spawn(|| { 136 | for num in start..start + elemets_per_thread { 137 | if is_prime(num) { 138 | let mut lock = list_clone.lock().unwrap(); 139 | lock.push(num); 140 | } 141 | } 142 | }); 143 | handles.push(handle); 144 | } 145 | for handle in handles { 146 | handle.join().unwrap(); 147 | } 148 | let lock = primes.lock().unwrap(); 149 | println!("Prime numbers:"); 150 | println!("{:?}", lock); 151 | assert_eq!(lock.len(), 1229); 152 | } 153 | ``` 154 | 155 |
156 | Solution 157 | 158 | ```rust 159 | use std::sync::{Mutex, Arc}; 160 | use std::thread; 161 | 162 | fn is_prime(num: u32) -> bool { 163 | for i in 2..=num / 2 { 164 | if num % i == 0 { 165 | return false; 166 | } 167 | } 168 | if num <= 1 { 169 | false 170 | } else { 171 | true 172 | } 173 | } 174 | 175 | // list of all prime numbers less than 10000 using four threads 176 | fn main() { 177 | let primes = Arc::new(Mutex::new(Vec::new())); 178 | let thread_count = 4; 179 | let elemets_per_thread = 10000 / thread_count; 180 | let mut handles = Vec::new(); 181 | for i in 0..thread_count { 182 | let start = i * elemets_per_thread; 183 | let list_clone = Arc::clone(&primes); 184 | let handle = thread::spawn(move || { 185 | for num in start..start + elemets_per_thread { 186 | if is_prime(num) { 187 | let mut lock = list_clone.lock().unwrap(); 188 | lock.push(num); 189 | } 190 | } 191 | }); 192 | handles.push(handle); 193 | } 194 | for handle in handles { 195 | handle.join().unwrap(); 196 | } 197 | let lock = primes.lock().unwrap(); 198 | println!("Prime numbers:"); 199 | println!("{:?}", lock); 200 | assert_eq!(lock.len(), 1229); 201 | } 202 | ``` 203 |
204 | -------------------------------------------------------------------------------- /src/advanced/tokio-streams.md: -------------------------------------------------------------------------------- 1 | # Tokio Streams 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | ## Exercises 10 | 11 | (No exercises yet. Feel free to contribute here!) 12 | -------------------------------------------------------------------------------- /src/advanced/tokio-tasks.md: -------------------------------------------------------------------------------- 1 | # Tokio Tasks 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | ## Exercises 10 | 11 | #### Awaiting tasks 12 | 13 | ```rust,editable,compile_fail 14 | // Fix the code to make it compile. 15 | 16 | use std::time::Duration; 17 | use tokio::time::sleep; 18 | 19 | struct Employee { 20 | id: u32, 21 | name: String, 22 | salary: f32, 23 | } 24 | 25 | impl Employee { 26 | fn new(id: u32, name: &str, salary: f32) -> Self { 27 | Self { 28 | id, 29 | name: name.to_string(), 30 | salary, 31 | } 32 | } 33 | } 34 | 35 | #[tokio::main] 36 | async fn main() { 37 | let ids = [1, 2, 4, 5, 9, 10]; 38 | let mut handles = Vec::new(); 39 | for id in ids { 40 | let handle = tokio::spawn(async move { 41 | let res = print_details(id).await; 42 | if let Err(e) = res { 43 | println!("{e}"); 44 | } 45 | }); 46 | handles.push(handle); 47 | } 48 | for handle in handles { 49 | handle.join().unwrap(); 50 | } 51 | } 52 | 53 | async fn print_details(id: u32) -> Result<(), String> { 54 | let emp = read_details_from_db(id).await?; 55 | println!("Id: {}, Name: {}, Salary: {}", emp.id, emp.name, emp.salary); 56 | Ok(()) 57 | } 58 | 59 | async fn read_details_from_db(id: u32) -> Result { 60 | // dummy read from database 61 | sleep(Duration::from_millis(1000)).await; 62 | let database = [ 63 | Employee::new(1, "Alice", 98000.0), 64 | Employee::new(2, "Bob", 95000.0), 65 | Employee::new(3, "Cindy", 95000.0), 66 | Employee::new(4, "Daniel", 88000.0), 67 | ]; 68 | for emp in database { 69 | if id == emp.id { 70 | return Ok(emp); 71 | } 72 | } 73 | Err(format!("Employee record for id {} not present", id)) 74 | } 75 | ``` 76 | 77 |
78 | Solution 79 | 80 | ```rust 81 | // Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=270cc37d8222f963cedfb137f0472584 82 | 83 | // Fix the code to make it compile. 84 | 85 | use std::time::Duration; 86 | use tokio::time::sleep; 87 | 88 | struct Employee { 89 | id: u32, 90 | name: String, 91 | salary: f32, 92 | } 93 | 94 | impl Employee { 95 | fn new(id: u32, name: &str, salary: f32) -> Self { 96 | Self { 97 | id, 98 | name: name.to_string(), 99 | salary, 100 | } 101 | } 102 | } 103 | 104 | #[tokio::main] 105 | async fn main() { 106 | let ids = [1, 2, 4, 5, 9, 10]; 107 | let mut handles = Vec::new(); 108 | for id in ids { 109 | let handle = tokio::spawn(async move { 110 | let res = print_details(id).await; 111 | if let Err(e) = res { 112 | println!("{e}"); 113 | } 114 | }); 115 | handles.push(handle); 116 | } 117 | for handle in handles { 118 | handle.await.unwrap(); // use await here instead of join() 119 | } 120 | } 121 | 122 | async fn print_details(id: u32) -> Result<(), String> { 123 | let emp = read_details_from_db(id).await?; 124 | println!("Id: {}, Name: {}, Salary: {}", emp.id, emp.name, emp.salary); 125 | Ok(()) 126 | } 127 | 128 | async fn read_details_from_db(id: u32) -> Result { 129 | // dummy read from database 130 | sleep(Duration::from_millis(1000)).await; 131 | let database = [ 132 | Employee::new(1, "Alice", 98000.0), 133 | Employee::new(2, "Bob", 95000.0), 134 | Employee::new(3, "Cindy", 95000.0), 135 | Employee::new(4, "Daniel", 88000.0), 136 | ]; 137 | for emp in database { 138 | if id == emp.id { 139 | return Ok(emp); 140 | } 141 | } 142 | Err(format!("Employee record for id {} not present", id)) 143 | } 144 | ``` 145 |
146 | -------------------------------------------------------------------------------- /src/beginner/basics.md: -------------------------------------------------------------------------------- 1 | # Basics 2 | -------------------------------------------------------------------------------- /src/beginner/benchmark-tests.md: -------------------------------------------------------------------------------- 1 | # Benchmark Tests 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/beginner/borrowing.md: -------------------------------------------------------------------------------- 1 | # Borrowing 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - How to fight Rust's borrow checker... and win. 9 | 10 | ## Exercises 11 | 12 | #### Immutable references 13 | 14 | ```rust,editable,compile_fail 15 | // Fix the code so that it compiles. 16 | 17 | fn main() { 18 | let mut str1 = String::from("modifiable"); 19 | let str2 = String::from("fixed string"); 20 | let mut str_ptr: &String; 21 | str_ptr = str1; 22 | println!("ptr currently points to {str_ptr}"); 23 | str_ptr = str2; 24 | println!("ptr currently points to {str_ptr}"); 25 | str1.push_str(" string"); 26 | str_ptr = str1; 27 | println!("ptr currently points to {str_ptr}"); 28 | } 29 | ``` 30 | 31 |
32 | Solution 33 | 34 | ```rust 35 | fn main() { 36 | let mut str1 = String::from("modifiable"); 37 | let str2 = String::from("fixed string"); 38 | let mut str_ptr: &String; 39 | str_ptr = &str1; 40 | println!("ptr currently points to {str_ptr}"); 41 | str_ptr = &str2; 42 | println!("ptr currently points to {str_ptr}"); 43 | str1.push_str(" string"); 44 | str_ptr = &str1; 45 | println!("ptr currently points to {str_ptr}"); 46 | } 47 | ``` 48 |
49 | 50 | #### Mutable references 1 51 | 52 | ```rust,editable,compile_fail 53 | // Fix the code so that it compiles. 54 | 55 | fn main() { 56 | let mut s = String::from("Hello, "); 57 | let s_ref = &s; 58 | change_string(s_ref); 59 | println!("{s_ref}"); 60 | } 61 | 62 | fn change_string(s: &String) { 63 | s.push_str(" world!"); 64 | } 65 | ``` 66 | 67 |
68 | Solution 69 | 70 | ```rust 71 | fn main() { 72 | let mut s = String::from("Hello, "); 73 | let s_ref = &mut s; 74 | change_string(s_ref); 75 | println!("{s_ref}"); 76 | } 77 | 78 | fn change_string(s: &mut String) { 79 | s.push_str(" world!"); 80 | } 81 | ``` 82 |
83 | 84 | #### Mutable references 2 85 | 86 | ```rust,editable,compile_fail 87 | // Fix the code so that it compiles. 88 | 89 | fn main() { 90 | let str1 = String::from("Rust"); 91 | let str2 = String::from("Golang"); 92 | let ref1 = &mut str1; 93 | let mut ref2 = &mut str2; 94 | 95 | println!("First string: {ref1}"); 96 | println!("Second string: {ref2}"); 97 | ref1.push('🦀'); 98 | ref2.push('🦫'); 99 | println!("Modified first string: {ref1}"); 100 | println!("Modified second string: {ref2}"); 101 | // only one mutable reference allowed at a time, ref1 is no longer valid 102 | ref2 = &mut str1; 103 | ref2.pop(); 104 | println!("Original first string: {ref2}"); 105 | } 106 | ``` 107 | 108 |
109 | Solution 110 | 111 | ```rust 112 | fn main() { 113 | let mut str1 = String::from("Rust"); 114 | let mut str2 = String::from("Golang"); 115 | let ref1 = &mut str1; 116 | let mut ref2 = &mut str2; 117 | 118 | println!("First string: {ref1}"); 119 | println!("Second string: {ref2}"); 120 | ref1.push('🦀'); 121 | ref2.push('🦫'); 122 | println!("Modified first string: {ref1}"); 123 | println!("Modified second string: {ref2}"); 124 | // only one mutable reference allowed at a time, ref1 is no longer valid 125 | ref2 = &mut str1; 126 | ref2.pop(); 127 | println!("Original first string: {ref2}"); 128 | } 129 | ``` 130 |
131 | 132 | #### Passing by reference 133 | 134 | ```rust,editable,compile_fail 135 | // Complete the function signature to make the code compile. 136 | 137 | fn main() { 138 | let mut s1 = String::from("this is "); 139 | let s2 = String::from("an example sentence"); 140 | concat(&mut s1, &s2); 141 | println!("{s1}") 142 | } 143 | 144 | fn concat(s1, s2) { 145 | for ch in s2.chars() { 146 | s1.push(ch); 147 | } 148 | } 149 | ``` 150 | 151 |
152 | Solution 153 | 154 | ```rust 155 | fn main() { 156 | let mut s1 = String::from("this is "); 157 | let s2 = String::from("an example sentence"); 158 | concat(&mut s1, &s2); 159 | println!("{s1}") 160 | } 161 | 162 | fn concat(s1: &mut String, s2: &str) { 163 | for ch in s2.chars() { 164 | s1.push(ch); 165 | } 166 | } 167 | ``` 168 |
169 | -------------------------------------------------------------------------------- /src/beginner/cargo-features.md: -------------------------------------------------------------------------------- 1 | # Cargo Features 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/beginner/cargo-workspaces.md: -------------------------------------------------------------------------------- 1 | # Cargo Workspaces 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/beginner/comments.md: -------------------------------------------------------------------------------- 1 | # Comments 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/beginner/constants-statics-exercises.md: -------------------------------------------------------------------------------- 1 | # Constants & Statics 2 | 3 | ## Constants 4 | 5 |
6 | Description 7 | 8 | This is a helpful description. Read me to understand what to do! 9 | 10 |
11 | 12 | ```rust,editable,compile_fail 13 | // Fix the code so it compiles! 14 | 15 | const NUMBER = 3; 16 | 17 | fn main() { 18 | println!("Number {}", NUMBER); 19 | } 20 | ``` 21 | 22 |
23 | Hint 1 24 | 25 | This is a helpful hint! Read me to understand what to do! 26 | 27 |
28 |
29 | Hint 2 30 | 31 | This is a helpful hint! Read me to understand what to do! 32 | 33 |
34 |
35 | Hint 3 36 | 37 | This is a helpful hint! Read me to understand what to do! 38 | 39 |
40 |
41 | Solution 42 | 43 | ```rust 44 | const NUMBER: i32 = 3; 45 | 46 | fn main() { 47 | println!("Number {}", NUMBER); 48 | } 49 | ``` 50 |
51 | 52 | ## Statics 53 | 54 |
55 | Description 56 | 57 | This is a helpful description. Read me to understand what to do! 58 | 59 |
60 | 61 | ```rust,editable,compile_fail 62 | // Fix the code so it compiles! 63 | 64 | static LANGUAGE = "Go"; 65 | 66 | fn main() { 67 | // These two initializations perform a string copy from same memory location 68 | let lang1 = LANGUAGE; 69 | let mut lang2 = LANGUAGE; 70 | 71 | lang2 = "Rust"; 72 | println!("I like {} more than {}!", lang2, lang1); 73 | } 74 | ``` 75 | 76 |
77 | Hint 1 78 | 79 | This is a helpful hint! Read me to understand what to do! 80 | 81 |
82 |
83 | Hint 2 84 | 85 | This is a helpful hint! Read me to understand what to do! 86 | 87 |
88 |
89 | Hint 3 90 | 91 | This is a helpful hint! Read me to understand what to do! 92 | 93 |
94 |
95 | Solution 96 | 97 | ```rust 98 | static LANGUAGE: &str = "Go"; 99 | 100 | fn main() { 101 | // These two initializations perform a string copy from same memory location 102 | let lang1 = LANGUAGE; 103 | let mut lang2 = LANGUAGE; 104 | 105 | lang2 = "Rust"; 106 | println!("I like {} more than {}!", lang2, lang1); 107 | } 108 | 109 | ``` 110 |
111 | 112 | 113 | -------------------------------------------------------------------------------- /src/beginner/constants-statics.md: -------------------------------------------------------------------------------- 1 | # Constants & Statics 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Static variables in Rust 9 | 10 | ## Exercises 11 | 12 | #### Constants 13 | 14 | ```rust,editable,compile_fail 15 | // Fix the code so it compiles! 16 | 17 | const NUMBER = 3; 18 | 19 | fn main() { 20 | println!("Number {}", NUMBER); 21 | } 22 | ``` 23 | 24 |
25 | Solution 26 | 27 | ```rust 28 | const NUMBER: i32 = 3; 29 | 30 | fn main() { 31 | println!("Number {}", NUMBER); 32 | } 33 | ``` 34 |
35 | 36 | #### Statics 37 | 38 | ```rust,editable,compile_fail 39 | // Fix the code so it compiles! 40 | 41 | static LANGUAGE = "Go"; 42 | 43 | fn main() { 44 | // These two initializations perform a string copy from same memory location 45 | let lang1 = LANGUAGE; 46 | let mut lang2 = LANGUAGE; 47 | 48 | lang2 = "Rust"; 49 | println!("I like {} more than {}!", lang2, lang1); 50 | } 51 | ``` 52 | 53 |
54 | Solution 55 | 56 | ```rust 57 | static LANGUAGE: &str = "Go"; 58 | 59 | fn main() { 60 | // These two initializations perform a string copy from same memory location 61 | let lang1 = LANGUAGE; 62 | let mut lang2 = LANGUAGE; 63 | 64 | lang2 = "Rust"; 65 | println!("I like {} more than {}!", lang2, lang1); 66 | } 67 | 68 | ``` 69 |
-------------------------------------------------------------------------------- /src/beginner/control-flow.md: -------------------------------------------------------------------------------- 1 | # Control Flow 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### If/else 10 | 11 | ```rust,editable,compile_fail 12 | pub fn bigger(a: i32, b: i32) -> i32 { 13 | // Complete this function to return the bigger number! 14 | // Do not use: 15 | // - another function call 16 | // - additional variables 17 | } 18 | 19 | // Don't mind this for now :) 20 | #[cfg(test)] 21 | mod tests { 22 | use super::*; 23 | 24 | #[test] 25 | fn ten_is_bigger_than_eight() { 26 | assert_eq!(10, bigger(10, 8)); 27 | } 28 | 29 | #[test] 30 | fn fortytwo_is_bigger_than_thirtytwo() { 31 | assert_eq!(42, bigger(32, 42)); 32 | } 33 | } 34 | ``` 35 | 36 |
37 | Solution 38 | 39 | ```rust 40 | pub fn bigger(a: i32, b: i32) -> i32 { 41 | if a > b { 42 | a 43 | } else { 44 | b 45 | } 46 | } 47 | 48 | // Don't mind this for now :) 49 | #[cfg(test)] 50 | mod tests { 51 | use super::*; 52 | 53 | #[test] 54 | fn ten_is_bigger_than_eight() { 55 | assert_eq!(10, bigger(10, 8)); 56 | } 57 | 58 | #[test] 59 | fn fortytwo_is_bigger_than_thirtytwo() { 60 | assert_eq!(42, bigger(32, 42)); 61 | } 62 | } 63 | ``` 64 |
65 | 66 | 67 | #### Loop 68 | 69 | ```rust,editable,compile_fail 70 | use num::integer::sqrt; 71 | 72 | // There's a prime number hiding in our array of integers! 73 | // The function below tries to find the prime number by checking each element, 74 | // and finding its divisor. If none is found, then it's a prime number and 75 | // its search ends! 76 | 77 | // But it seems that its search never does end, when there's clearly a 78 | // prime number there. Fix the function so that it returns the prime number. 79 | 80 | fn main() { 81 | let numbers = [36, 25, 49, 3, 64, 16, 9]; 82 | let prime = get_prime(numbers); 83 | } 84 | 85 | fn get_prime(arr: [i32; 7]) -> i32 { 86 | 87 | // Loop through every element in the array 88 | let mut i = 0; 89 | 'outer: loop { 90 | 91 | // Find a divisor. 92 | let mut n = 2; 93 | 'inner: loop { 94 | 95 | // If a number can be evenly divided by another number except 1 and itself, 96 | // then it's not a prime. 97 | // Break out here to move on to the next element. 98 | if arr[i] % n == 0 { 99 | if arr[i] == 2 { 100 | break 'outer; 101 | } 102 | i += 1; 103 | break; 104 | } 105 | 106 | // If no divisors are found, then we've found a prime! 107 | // Break out of the loop here. 108 | if n >= sqrt(arr[i]) { 109 | break; 110 | } 111 | 112 | // Otherwise, move to the next element. 113 | n += 1; 114 | } 115 | } 116 | println!("The first prime number in the array is {}.", arr[i]); 117 | arr[i] 118 | } 119 | ``` 120 | 121 |
122 | Solution 123 | 124 | ```rust 125 | use num::integer::sqrt; 126 | 127 | fn main() { 128 | let numbers = [36, 25, 49, 3, 64, 16, 9]; 129 | let prime = get_prime(numbers); 130 | } 131 | 132 | fn get_prime(arr: [i32; 7]) -> i32 { 133 | 134 | let mut i = 0; 135 | 'outer: loop { 136 | 137 | let mut n = 2; 138 | 'inner: loop { 139 | 140 | if arr[i] % n == 0 { 141 | if arr[i] == 2 { 142 | break 'outer; 143 | } 144 | i += 1; 145 | break; 146 | } 147 | 148 | if n >= sqrt(arr[i]) { 149 | break 'outer; 150 | } 151 | 152 | n += 1; 153 | } 154 | } 155 | println!("The first prime number in the array is {}.", arr[i]); 156 | arr[i] 157 | } 158 | ``` 159 |
160 | 161 | #### While 162 | 163 | ```rust,editable,compile_fail 164 | // Below is the classic FizzBuzz program. It prints every number from 1 to 100, 165 | // except for multiples of 3 it prints "fizz" instead of the number, and for 166 | // multiples of 5 it prints "buzz" instead of the number. If the number is 167 | // both a multiple of 3 and 5, it prints "fizzbuzz". 168 | 169 | // Fix the compile time error so that the program runs successfully. 170 | 171 | fn main() { 172 | let mut n = 1; 173 | while { 174 | if n % 15 == 0 { 175 | println!("fizzbuzz"); 176 | } else if n % 3 == 0 { 177 | println!("fizz"); 178 | } else if n % 5 == 0 { 179 | println!("buzz"); 180 | } else { 181 | println!("{}", n); 182 | } 183 | n += 1; 184 | } 185 | } 186 | ``` 187 | 188 |
189 | Solution 190 | 191 | ```rust 192 | fn main() { 193 | let mut n = 1; 194 | while n <= 100 { 195 | if n % 15 == 0 { 196 | println!("fizzbuzz"); 197 | } else if n % 3 == 0 { 198 | println!("fizz"); 199 | } else if n % 5 == 0 { 200 | println!("buzz"); 201 | } else { 202 | println!("{}", n); 203 | } 204 | n += 1; 205 | } 206 | } 207 | ``` 208 |
209 | 210 | #### For 211 | 212 | ```rust,editable,compile_fail 213 | // Here's a bucket list of cities I'd like to visit one day, and I'd like to 214 | // share it with the world. Fix the loop so it announces the cities I'd like to visit. 215 | 216 | fn main() { 217 | let cities = ["Perth", "Qingdao", "Rome"]; 218 | for cities { 219 | println!("I'd like to visit {} someday!", city); 220 | } 221 | } 222 | ``` 223 | 224 |
225 | Solution 226 | 227 | ```rust 228 | fn main() { 229 | let cities = ["Perth", "Qingdao", "Rome"]; 230 | for city in cities { 231 | println!("I'd like to visit {} someday!", city); 232 | } 233 | } 234 | ``` 235 |
-------------------------------------------------------------------------------- /src/beginner/documentation.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | #### Additional Resources 10 | - Intro Guide to Rust Documentation With Rustdoc 11 | 12 | ## Exercises 13 | 14 | (No exercises yet. Feel free to contribute here!) 15 | -------------------------------------------------------------------------------- /src/beginner/enums.md: -------------------------------------------------------------------------------- 1 | # Enums 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Definition 1 10 | 11 | ```rust,editable,compile_fail 12 | // Complete the code by addressing the TODO. 13 | 14 | #[derive(Debug)] // this line makes the enum variants printable! 15 | enum Message { 16 | // TODO: define a few types of messages as used below 17 | } 18 | 19 | fn main() { 20 | println!("{:?}", Message::Quit); 21 | println!("{:?}", Message::Echo); 22 | println!("{:?}", Message::Move); 23 | println!("{:?}", Message::ChangeColor); 24 | } 25 | ``` 26 | 27 |
28 | Solution 29 | 30 | ```rust 31 | #[derive(Debug)] 32 | enum Message { 33 | Quit, 34 | Echo, 35 | Move, 36 | ChangeColor, 37 | } 38 | 39 | fn main() { 40 | println!("{:?}", Message::Quit); 41 | println!("{:?}", Message::Echo); 42 | println!("{:?}", Message::Move); 43 | println!("{:?}", Message::ChangeColor); 44 | } 45 | ``` 46 |
47 | 48 | #### Definition 2 49 | 50 | ```rust,editable,compile_fail 51 | // Complete the code by addressing the TODO. 52 | 53 | #[derive(Debug)] // this line makes the enum variants printable! 54 | enum Message { 55 | // TODO: define the different variants used below 56 | } 57 | 58 | impl Message { 59 | fn call(&self) { 60 | println!("{:?}", self); 61 | } 62 | } 63 | 64 | fn main() { 65 | let messages = [ 66 | Message::Move { x: 10, y: 30 }, 67 | Message::Echo(String::from("hello world")), 68 | Message::ChangeColor(200, 255, 255), 69 | Message::Quit, 70 | ]; 71 | 72 | for message in &messages { 73 | message.call(); 74 | } 75 | } 76 | ``` 77 | 78 |
79 | Solution 80 | 81 | ```rust 82 | #[derive(Debug)] 83 | enum Message { 84 | Move { x: i32, y: i32 }, 85 | Echo(String), 86 | ChangeColor(u8, u8, u8), 87 | Quit, 88 | } 89 | 90 | impl Message { 91 | fn call(&self) { 92 | println!("{:?}", self); 93 | } 94 | } 95 | 96 | fn main() { 97 | let messages = [ 98 | Message::Move { x: 10, y: 30 }, 99 | Message::Echo(String::from("hello world")), 100 | Message::ChangeColor(200, 255, 255), 101 | Message::Quit, 102 | ]; 103 | 104 | for message in &messages { 105 | message.call(); 106 | } 107 | } 108 | ``` 109 |
110 | -------------------------------------------------------------------------------- /src/beginner/external-dependencies.md: -------------------------------------------------------------------------------- 1 | # External Dependencies 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | 10 | #### Additional Resources 11 | - How to Add a Crate/Dependency to Rust using Cargo -------------------------------------------------------------------------------- /src/beginner/functions.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Definition 10 | 11 | ```rust,editable,compile_fail 12 | // Something's missing from the function definition. Fix it so it compiles! 13 | 14 | fn main() { 15 | call_me(9395550113); 16 | } 17 | 18 | fn call_me(num:) { 19 | println!("Ring! Call number {}", num); 20 | } 21 | ``` 22 | 23 |
24 | Solution 25 | 26 | ```rust 27 | fn main() { 28 | call_me(9395550113); 29 | } 30 | 31 | fn call_me(num: i64) { 32 | println!("Ring! Call number {}", num); 33 | } 34 | ``` 35 |
36 | 37 | #### Return types 38 | 39 | ```rust,editable,compile_fail 40 | // This store is having a sale where if the price is an even number, you get 41 | // 10 Rustbucks off, but if it's an odd number, it's 3 Rustbucks off. 42 | // But it won't compile--fix it 43 | // (Don't worry about the function bodies themselves, we're only interested 44 | // in the signatures for now) 45 | 46 | fn main() { 47 | let original_price = 51; 48 | println!("Your sale price is {}", sale_price(original_price)); 49 | } 50 | 51 | fn sale_price(price: i32) -> { 52 | if is_even(price) { 53 | price - 10 54 | } else { 55 | price - 3 56 | } 57 | } 58 | 59 | fn is_even(num: i32) -> bool { 60 | num % 2 == 0 61 | } 62 | ``` 63 | 64 |
65 | Solution 66 | 67 | ```rust 68 | fn main() { 69 | let original_price = 51; 70 | println!("Your sale price is {}", sale_price(original_price)); 71 | } 72 | 73 | fn sale_price(price: i32) -> i32 { 74 | if is_even(price) { 75 | price - 10 76 | } else { 77 | price - 3 78 | } 79 | } 80 | 81 | fn is_even(num: i32) -> bool { 82 | num % 2 == 0 83 | } 84 | ``` 85 |
86 | 87 | #### Return keyword 88 | 89 | ```rust,editable,compile_fail 90 | // This function describes a morning in the life of a Rust programmer. 91 | // She has a few morning rituals, but she skips all that if she wakes up late! 92 | // Fix the morning_routine function to return early when the Rust programmer wakes up late. 93 | 94 | fn main() { 95 | let i_woke_up_late = true; 96 | morning_routine(i_woke_up_late); 97 | } 98 | 99 | fn morning_routine(i_am_late: bool) { 100 | println!("This morning, I..."); 101 | if i_am_late { 102 | go_to_work(); 103 | } 104 | exercise(); 105 | eat_breakfast(); 106 | make_coffee(); 107 | go_to_work(); 108 | } 109 | 110 | fn exercise() { 111 | println!("I went to the gym."); 112 | } 113 | 114 | fn eat_breakfast() { 115 | println!("I had a healthy breakfast!"); 116 | } 117 | 118 | fn make_coffee() { 119 | println!("I made myself coffee. Now that I'm ready..."); 120 | } 121 | 122 | fn go_to_work() { 123 | println!("I went straight to work!"); 124 | } 125 | ``` 126 | 127 |
128 | Solution 129 | 130 | ```rust 131 | fn main() { 132 | let i_woke_up_late = true; 133 | morning_routine(i_woke_up_late); 134 | } 135 | 136 | fn morning_routine(i_am_late: bool) { 137 | println!("This morning, I..."); 138 | if i_am_late { 139 | go_to_work(); 140 | return; 141 | } 142 | exercise(); 143 | eat_breakfast(); 144 | make_coffee(); 145 | go_to_work(); 146 | } 147 | 148 | fn exercise() { 149 | println!("I went to the gym."); 150 | } 151 | 152 | fn eat_breakfast() { 153 | println!("I had a healthy breakfast!"); 154 | } 155 | 156 | fn make_coffee() { 157 | println!("I made myself coffee. Now that I'm ready..."); 158 | } 159 | 160 | fn go_to_work() { 161 | println!("I went straight to work!"); 162 | } 163 | 164 | ``` 165 |
166 | -------------------------------------------------------------------------------- /src/beginner/hello-world.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 |
4 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/beginner/implementation-blocks.md: -------------------------------------------------------------------------------- 1 | # Implementation Blocks 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Methods 10 | 11 | ```rust,editable,compile_fail 12 | // Complete the method signatures by providing appropriate arguments. 13 | 14 | struct Student { 15 | first_name: String, 16 | last_name: String, 17 | roll_no: u16, 18 | } 19 | 20 | impl Student { 21 | fn get_name() -> String { 22 | format!("{} {}", self.first_name, self.last_name) 23 | } 24 | fn set_roll_no(, new_roll_no: u16) { 25 | self.roll_no = new_roll_no; 26 | } 27 | fn convert_to_string() -> String { // should take ownership 28 | format!( 29 | "Name: {} {}, Roll no: {}", 30 | self.first_name, self.last_name, self.roll_no 31 | ) 32 | } 33 | } 34 | 35 | fn main() { 36 | let mut student = Student { 37 | first_name: "Harry".to_string(), 38 | last_name: "Potter".to_string(), 39 | roll_no: 42, 40 | }; 41 | println!("Student is: {}", student.get_name()); 42 | student.set_roll_no(50); 43 | let student_details = student.convert_to_string(); 44 | println!("{student_details}"); 45 | } 46 | 47 | ``` 48 | 49 |
50 | Solution 51 | 52 | ```rust 53 | struct Student { 54 | first_name: String, 55 | last_name: String, 56 | roll_no: u16, 57 | } 58 | 59 | impl Student { 60 | fn get_name(&self) -> String { 61 | format!("{} {}", self.first_name, self.last_name) 62 | } 63 | fn set_roll_no(&mut self, new_roll_no: u16) { 64 | self.roll_no = new_roll_no; 65 | } 66 | fn convert_to_string(self) -> String { 67 | format!( 68 | "Name: {} {}, Roll no: {}", 69 | self.first_name, self.last_name, self.roll_no 70 | ) 71 | } 72 | } 73 | 74 | fn main() { 75 | let mut student = Student { 76 | first_name: "Harry".to_string(), 77 | last_name: "Potter".to_string(), 78 | roll_no: 42, 79 | }; 80 | println!("Student is: {}", student.get_name()); 81 | student.set_roll_no(50); 82 | let student_details = student.convert_to_string(); 83 | println!("{student_details}"); 84 | } 85 | ``` 86 |
87 | 88 | #### Associated functions 89 | 90 | ```rust,editable,compile_fail 91 | // Fix the code so that it compiles. 92 | 93 | struct ShopItem { 94 | name: String, 95 | quantity: u32, 96 | } 97 | 98 | impl ShopItem { 99 | fn new(name: String, quantity: u32) -> ShopItem { 100 | ShopItem { name, quantity } 101 | } 102 | fn in_stock(&self) -> bool { 103 | self.quantity > 0 104 | } 105 | } 106 | 107 | fn main() { 108 | let item = ShopItem.new("Pants".to_string(), 450); 109 | if item.in_stock() { 110 | println!("{} remaining: {}", item.name, item.quantity); 111 | } else { 112 | println!("{} not in stock", item.name); 113 | } 114 | } 115 | ``` 116 | 117 |
118 | Solution 119 | 120 | ```rust 121 | struct ShopItem { 122 | name: String, 123 | quantity: u32, 124 | } 125 | 126 | impl ShopItem { 127 | fn new(name: String, quantity: u32) -> ShopItem { 128 | ShopItem { name, quantity } 129 | } 130 | fn in_stock(&self) -> bool { 131 | self.quantity > 0 132 | } 133 | } 134 | 135 | fn main() { 136 | let item = ShopItem::new("Pants".to_string(), 450); 137 | if item.in_stock() { 138 | println!("{} remaining: {}", item.name, item.quantity); 139 | } else { 140 | println!("{} not in stock", item.name); 141 | } 142 | } 143 | ``` 144 |
145 | -------------------------------------------------------------------------------- /src/beginner/integration-tests.md: -------------------------------------------------------------------------------- 1 | # Integration Tests 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/beginner/matching.md: -------------------------------------------------------------------------------- 1 | # Matching 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Exhaustive requirement 10 | 11 | ```rust,editable,compile_fail 12 | // Make the following code compile. 13 | // If you score 50 or less, you fail. 14 | 15 | fn main() { 16 | // marks scored out of 100 17 | let marks = 75u8; 18 | match marks { 19 | 91..=100 => println!("You performed excellent!"), 20 | 71..=90 => println!("You performed good :)"), 21 | 51..=70 => println!("Your performance was average..."), 22 | 0..=30 => println!("You failed. Better luck next time."), 23 | 101..=u8::MAX => println!("Invalid marks!!!"), 24 | } 25 | } 26 | ``` 27 | 28 |
29 | Solution 30 | 31 | ```rust 32 | fn main() { 33 | let side_count = 5; 34 | let message = match side_count { 35 | 0 | 1 | 2 => "invalid shape", 36 | 3 => "it's a triangle", 37 | 4 => "it's a quadrilateral", 38 | 5 => "it's a pentagon", 39 | 6 => "it's a hexagon", 40 | _ => "i don't know the name, lol", 41 | }; 42 | println!("{message}"); 43 | } 44 | ``` 45 |
46 | 47 | #### Enum matching 1 48 | 49 | ```rust,editable,compile_fail 50 | // Fix the code so that it compiles. 51 | 52 | // USD coin types 53 | // cent values: penny:1, nickel:5, dime: 10, quarter:25 54 | enum Coin { 55 | Penny, 56 | Nickel, 57 | Dime, 58 | Quarter, 59 | } 60 | 61 | fn value_in_cents(coin: Coin) -> u8 { 62 | match coin { 63 | Coin::Penny => 1, 64 | Coin::Nickel => 5, 65 | Coin::Quarter => 25, 66 | } 67 | } 68 | 69 | fn main() { 70 | let piggy_bank = [Coin::Nickel, Coin::Penny, Coin::Dime, Coin::Penny]; 71 | let mut my_savings = 0; 72 | for coin in piggy_bank { 73 | my_savings += value_in_cents(coin); 74 | } 75 | println!("My savings: {my_savings} cents"); 76 | } 77 | ``` 78 | 79 |
80 | Solution 81 | 82 | ```rust 83 | enum Coin { 84 | Penny, 85 | Nickel, 86 | Dime, 87 | Quarter, 88 | } 89 | 90 | fn value_in_cents(coin: Coin) -> u8 { 91 | match coin { 92 | Coin::Penny => 1, 93 | Coin::Nickel => 5, 94 | Coin::Dime => 10, 95 | Coin::Quarter => 25, 96 | } 97 | } 98 | 99 | fn main() { 100 | let piggy_bank = [Coin::Nickel, Coin::Penny, Coin::Dime, Coin::Penny]; 101 | let mut my_savings = 0; 102 | for coin in piggy_bank { 103 | my_savings += value_in_cents(coin); 104 | } 105 | println!("My savings: {my_savings} cents"); 106 | } 107 | ``` 108 |
109 | 110 | #### Enum matching 2 111 | 112 | 113 | ```rust,editable,compile_fail 114 | // Fix the code so that it compiles. 115 | 116 | enum Operation { 117 | Add(u8, u8), 118 | Mul(u8, u8), 119 | Subtract { first: u8, second: u8 }, 120 | Divide { divident: u8, divisor: u8 }, 121 | } 122 | 123 | impl Operation { 124 | fn result(&self) -> u8 { 125 | match self { 126 | Self::Add(a, b) => a + b, // notice Self can be used instead of Operation 127 | Self::Subtract { first, second } => first - second, 128 | Self::Divide { divident, divisor } => divident / divisor, 129 | } 130 | } 131 | } 132 | 133 | fn main() { 134 | let user_operation = Operation::Subtract { 135 | first: 75, 136 | second: 20, 137 | }; 138 | println!("Result: {}", user_operation::result()); 139 | } 140 | ``` 141 | 142 |
143 | Solution 144 | 145 | ```rust 146 | enum Operation { 147 | Add(u8, u8), 148 | Mul(u8, u8), 149 | Subtract { first: u8, second: u8 }, 150 | Divide { divident: u8, divisor: u8 }, 151 | } 152 | 153 | impl Operation { 154 | fn result(&self) -> u8 { 155 | match self { 156 | Self::Add(a, b) => a + b, 157 | Self::Mul(x, y) => x * y, 158 | Self::Subtract { first, second } => first - second, 159 | Self::Divide { divident, divisor } => divident / divisor, 160 | } 161 | } 162 | } 163 | 164 | fn main() { 165 | let user_operation = Operation::Subtract { 166 | first: 75, 167 | second: 20, 168 | }; 169 | println!("Result: {}", user_operation.result()); 170 | } 171 | ``` 172 |
173 | -------------------------------------------------------------------------------- /src/beginner/memory-saftey.md: -------------------------------------------------------------------------------- 1 | # Memory Safety 2 | -------------------------------------------------------------------------------- /src/beginner/option.md: -------------------------------------------------------------------------------- 1 | # Option 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Matching option 1 10 | 11 | 12 | ```rust,editable,compile_fail 13 | // Fix the code so that it compiles. 14 | 15 | struct Point { 16 | x: i32, 17 | y: i32, 18 | } 19 | 20 | fn main() { 21 | let y: Option = Some(Point { x: 100, y: 200 }); 22 | 23 | match y { 24 | Some(p) => println!("Co-ordinates are {},{} ", p.x, p.y), 25 | _ => println!("no match"), 26 | } 27 | y; // Fix without deleting this line. 28 | } 29 | ``` 30 |
31 | Solution 32 | 33 | ```rust 34 | struct Point { 35 | x: i32, 36 | y: i32, 37 | } 38 | 39 | fn main() { 40 | let y: Option = Some(Point { x: 100, y: 200 }); 41 | 42 | match &y { 43 | Some(p) => println!("Co-ordinates are {},{} ", p.x, p.y), 44 | _ => println!("no match"), 45 | } 46 | y; // Fix without deleting this line. 47 | } 48 | ``` 49 |
50 | 51 | #### Matching option 2 52 | 53 | 54 | ```rust,editable,compile_fail 55 | // Fix the code so that it compiles. 56 | 57 | fn last_element(nums: &[i32]) -> Option { 58 | if nums.len() > 0 { 59 | Some(nums[nums.len() - 1]) 60 | } else { 61 | None 62 | } 63 | } 64 | 65 | fn main() { 66 | let my_nums = [1, 1, 2, 3, 5, 8, 13]; 67 | match last_element(&my_nums) { 68 | Some => println!("Last element: {ele}"), 69 | None => println!("Empty array"), 70 | } 71 | } 72 | ``` 73 | 74 |
75 | Solution 76 | 77 | ```rust 78 | fn last_element(nums: &[i32]) -> Option { 79 | if nums.len() > 0 { 80 | Some(nums[nums.len() - 1]) 81 | } else { 82 | None 83 | } 84 | } 85 | 86 | fn main() { 87 | let my_nums = [1, 1, 2, 3, 5, 8, 13]; 88 | match last_element(&my_nums) { 89 | Some(ele) => println!("Last element: {ele}"), 90 | None => println!("Empty array"), 91 | } 92 | } 93 | ``` 94 |
95 | 96 | #### If let 97 | 98 | ```rust,editable,compile_fail 99 | // Fix the code so that it compiles. 100 | 101 | struct User { 102 | id: u32, 103 | name: String, 104 | } 105 | 106 | fn get_user_name(id: u32) -> Option { 107 | let database = [ 108 | User {id: 1, name: String::from("Alice")}, 109 | User {id: 2, name: String::from("Bob")}, 110 | User {id: 3, name: String::from("Cindy")} 111 | ]; 112 | for user in database { 113 | if user.id == id { 114 | return Some(user.name) 115 | } 116 | } 117 | None 118 | } 119 | 120 | fn main() { 121 | let user_id = 3; 122 | if Some(name) == get_user_name(user_id) { 123 | println!("User's name: {name}"); 124 | } 125 | } 126 | ``` 127 |
128 | Solution 129 | 130 | ```rust 131 | struct User { 132 | id: u32, 133 | name: String, 134 | } 135 | 136 | fn get_user_name(id: u32) -> Option { 137 | let database = [ 138 | User {id: 1, name: String::from("Alice")}, 139 | User {id: 2, name: String::from("Bob")}, 140 | User {id: 3, name: String::from("Cindy")} 141 | ]; 142 | for user in database { 143 | if user.id == id { 144 | return Some(user.name) 145 | } 146 | } 147 | None 148 | } 149 | 150 | fn main() { 151 | let user_id = 3; 152 | if let Some(name) = get_user_name(user_id) { 153 | println!("User's name: {name}"); 154 | } 155 | } 156 | ``` 157 |
158 | -------------------------------------------------------------------------------- /src/beginner/ownership.md: -------------------------------------------------------------------------------- 1 | # Ownership 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - 5. Rust ownership system 9 | 10 | ## Exercises 11 | 12 | #### Moving on assignment 13 | 14 | ```rust,editable,compile_fail 15 | // Something's missing. Fix the code so that it compiles. 16 | 17 | fn main() { 18 | let s1 = String::from("Rust"); 19 | let mut s2 = s1; 20 | s2.push_str(" is an awesome language"); 21 | println!("String:\"{s1}\" is a substring of \"{s2}\""); 22 | } 23 | ``` 24 | 25 |
26 | Solution 27 | 28 | ```rust 29 | fn main() { 30 | let s1 = String::from("Rust"); 31 | let mut s2 = s1.clone(); 32 | s2.push_str(" is an awesome language"); 33 | println!("String:\"{s1}\" is a substring of \"{s2}\""); 34 | } 35 | ``` 36 |
37 | 38 | #### Moving on assignment 2 39 | 40 | ```rust,editable,compile_fail 41 | // Fix the code so that it compiles. Modify only one statement. 42 | 43 | fn main() { 44 | let mut my_str = String::from("Example"); 45 | let mut temp; 46 | while my_str.len() > 0 { 47 | temp = my_str; 48 | println!("Length of temporary string is: {}", temp.len()); 49 | my_str.pop(); 50 | } 51 | } 52 | ``` 53 | 54 |
55 | Solution 56 | 57 |
58 | Description 59 | 60 | The ownership of a value is assigned upon the assignment of the value itself. We need to be aware of the ownership of a value every time an assignment of a value occurs. 61 | 62 |
63 | 64 | ```rust 65 | fn main() { 66 | let mut my_str = String::from("Example"); 67 | let mut temp; 68 | while my_str.len() > 0 { 69 | temp = my_str.clone(); 70 | println!("Length of temporary string is: {}", temp.len()); 71 | my_str.pop(); 72 | } 73 | } 74 | ``` 75 |
76 | 77 | #### Moving into function 78 | 79 | ```rust,editable,compile_fail 80 | // Fix the code so that it compiles. 81 | 82 | fn main() { 83 | let my_string = String::from("I love rust bootcamp 💕"); 84 | let occurence_count = count_occurences(my_string, 'o'); 85 | println!("The number of times 'o' apprears in \"{my_string}\" = {occurence_count}"); 86 | } 87 | 88 | // this function counts the number of times a letter appears in a text 89 | fn count_occurences(text: String, letter: char) -> u32 { 90 | let mut res = 0; 91 | for ch in text.chars() { 92 | if ch == letter { 93 | res += 1; 94 | } 95 | } 96 | res 97 | } 98 | ``` 99 | 100 |
101 | Solution 102 | 103 | ```rust 104 | fn main() { 105 | let my_string = String::from("I love rust bootcamp 💕"); 106 | let occurence_count = count_occurences(&my_string, 'o'); 107 | println!("The number of times 'o' apprears in \"{my_string}\" = {occurence_count}"); 108 | } 109 | 110 | // this function counts the number of times a letter appears in a text 111 | fn count_occurences(text: &String, letter: char) -> u32 { 112 | let mut res = 0; 113 | for ch in text.chars() { 114 | if ch == letter { 115 | res += 1; 116 | } 117 | } 118 | res 119 | } 120 | ``` 121 |
122 | 123 | #### Moving out of function 124 | 125 | ```rust,editable,compile_fail 126 | // Make the following code compile by modifying only one statement. 127 | 128 | fn main() { 129 | let mut str1 = get_new_string(); 130 | println!("Printing through str1: {}", str1); 131 | let mut str2 = str1; 132 | println!("Printing through str2: {}", str2); 133 | str1 = str2; 134 | println!("Again printing through str1: {}", str1); 135 | str2 = str1; 136 | println!("Again printing through str2: {}", str2); 137 | println!("Printing thourgh both: {}, {}", str1, str2); 138 | } 139 | 140 | fn get_new_string() -> String { 141 | let new_string = String::from("I will master rust 🦀 🦀"); 142 | new_string 143 | } // string ownership is transferred to the calling function 144 | ``` 145 |
146 | Solution 147 | 148 | ```rust 149 | fn main() { 150 | let mut str1 = get_new_string(); 151 | println!("Printing through str1: {}", str1); 152 | let mut str2 = str1; 153 | println!("Printing through str2: {}", str2); 154 | str1 = str2; 155 | println!("Again printing through str1: {}", str1); 156 | str2 = str1.clone(); 157 | println!("Again printing through str2: {}", str2); 158 | println!("Printing thourgh both: {}, {}", str1, str2); 159 | } 160 | 161 | fn get_new_string() -> String { 162 | let new_string = String::from("I will master rust 🦀 🦀"); 163 | new_string 164 | } // string ownership is transferred to the calling function 165 | ``` 166 |
-------------------------------------------------------------------------------- /src/beginner/project-structure.md: -------------------------------------------------------------------------------- 1 | # Project Structure Overview 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | -------------------------------------------------------------------------------- /src/beginner/publishing-your-package.md: -------------------------------------------------------------------------------- 1 | # Publishing your Package 2 | 3 |
4 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/beginner/result.md: -------------------------------------------------------------------------------- 1 | # Result 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | 10 | #### Additional Resources 11 | - A Simpler Way to See Results 12 | 13 | 14 | ## Exercises 15 | 16 | #### Mathing result 17 | 18 | ```rust,editable,compile_fail 19 | // Complete the match statement to check whether operation succeeded or not. 20 | 21 | enum Operation { 22 | Add(i32, i32), 23 | Mul(i32, i32), 24 | Sub { first: i32, second: i32 }, 25 | Div { divident: i32, divisor: i32 }, 26 | } 27 | 28 | impl Operation { 29 | fn execute(self) -> Result { 30 | match self { 31 | Self::Add(a, b) => Ok(a + b), 32 | Self::Mul(a, b) => Ok(a * b), 33 | Self::Sub { first, second } => Ok(first - second), 34 | Self::Div { divident, divisor } => { 35 | if divisor == 0 { 36 | Err(String::from("Can not divide by zero")) 37 | } else { 38 | Ok(divident / divisor) 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | fn main() { 46 | let user_input = Operation::Div { 47 | divident: 20, 48 | divisor: 0, 49 | }; 50 | match user_input.execute() { 51 | => println!("Result: {res}"), 52 | => println!("Error: {e}"), 53 | } 54 | } 55 | ``` 56 | 57 |
58 | Solution 59 | 60 | ```rust 61 | enum Operation { 62 | Add(i32, i32), 63 | Mul(i32, i32), 64 | Sub { first: i32, second: i32 }, 65 | Div { divident: i32, divisor: i32 }, 66 | } 67 | 68 | impl Operation { 69 | fn execute(self) -> Result { 70 | match self { 71 | Self::Add(a, b) => Ok(a + b), 72 | Self::Mul(a, b) => Ok(a * b), 73 | Self::Sub { first, second } => Ok(first - second), 74 | Self::Div { divident, divisor } => { 75 | if divisor == 0 { 76 | Err(String::from("Can not divide by zero")) 77 | } else { 78 | Ok(divident / divisor) 79 | } 80 | } 81 | } 82 | } 83 | } 84 | 85 | fn main() { 86 | let user_input = Operation::Div { 87 | divident: 20, 88 | divisor: 0, 89 | }; 90 | match user_input.execute() { 91 | Ok(res) => println!("Result: {res}"), 92 | Err(e) => println!("Error: {e}"), 93 | } 94 | } 95 | ``` 96 |
97 | 98 | #### Returning result 99 | 100 | ```rust,editable,compile_fail 101 | // Complete the function signature. 102 | 103 | fn greet(name: &str) -> { 104 | if name.len() > 0 { 105 | println!("Hello {name}!"); 106 | Ok(()) 107 | } else { 108 | Err("Empty name provided".to_string()) 109 | } 110 | } 111 | 112 | fn main() { 113 | let name = "Tom"; 114 | if let Err(e) = greet(name) { 115 | println!("Error: {e}"); 116 | } 117 | } 118 | ``` 119 | 120 |
121 | Solution 122 | 123 | ```rust 124 | fn greet(name: &str) -> Result<(), String> { 125 | if name.len() > 0 { 126 | println!("Hello {name}!"); 127 | Ok(()) 128 | } else { 129 | Err("Empty name provided".to_string()) 130 | } 131 | } 132 | 133 | fn main() { 134 | let name = "Tom"; 135 | if let Err(e) = greet(name) { 136 | println!("Error: {e}"); 137 | } 138 | } 139 | ``` 140 |
141 | -------------------------------------------------------------------------------- /src/beginner/setup.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | > Note: To install Rust, head over to https://rustup.rs. 4 | 5 |
6 | 7 |
8 | 9 | #### Additional Resources 10 | - The ultimate Rust IDE is here 11 | 12 | -------------------------------------------------------------------------------- /src/beginner/slices.md: -------------------------------------------------------------------------------- 1 | # Slices 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### String slice 10 | 11 | ```rust,editable,compile_fail 12 | // Complete the function definition to make the code compile. 13 | // The output of the code should be logically correct. 14 | 15 | fn main() { 16 | let text = String::from("Today is a very warm and sunny day."); 17 | let words = ["very", "arm", "say", "sun", "dew"]; 18 | let mut pos; 19 | 20 | println!("Text: {text}"); 21 | for word in words { 22 | pos = find_substr_pos(&text, word); 23 | if pos == text.len() { 24 | println!("{word} is not present in text"); 25 | } else { 26 | println!("{word} present at index {pos}"); 27 | } 28 | } 29 | } 30 | 31 | // this function tries to search for substr in text from left to right 32 | // if it finds substr, it returns the index where it starts 33 | // otherwise it returns length of text (which is an invalid index) 34 | fn find_substr_pos(text, substr) -> usize { // both parameters should have same data type 35 | if text.len() < substr.len() { 36 | return text.len(); 37 | } 38 | let len = substr.len(); 39 | for start in 0..text.len() - len + 1 { 40 | if substr == &text[] { // what will be the correct range? 41 | return start; 42 | } 43 | } 44 | text.len() 45 | } 46 | ``` 47 | 48 |
49 | Solution 50 | 51 | ```rust 52 | fn main() { 53 | let text = String::from("Today is a very warm and sunny day."); 54 | let words = ["very", "arm", "say", "sun", "dew"]; 55 | let mut pos; 56 | 57 | println!("Text: {text}"); 58 | for word in words { 59 | pos = find_substr_pos(&text, word); 60 | if pos == text.len() { 61 | println!("{word} is not present in text"); 62 | } else { 63 | println!("{word} present at index {pos}"); 64 | } 65 | } 66 | } 67 | 68 | fn find_substr_pos(text: &str, substr: &str) -> usize { 69 | if text.len() < substr.len() { 70 | return text.len(); 71 | } 72 | let len = substr.len(); 73 | for start in 0..text.len() - len + 1 { 74 | if substr == &text[start..start+len] { 75 | return start; 76 | } 77 | } 78 | text.len() 79 | } 80 | ``` 81 |
82 | 83 | #### Array slice 84 | 85 | ```rust,editable,compile_fail 86 | // Fix the program so that it compiles successfully and produces the desired output. 87 | 88 | fn main() { 89 | let nums = [1, 1, 2, 3, 5, 8, 13]; 90 | let res = find_subarray(&nums[..], 16); 91 | if res.0 == nums.len() { 92 | println!("No subarray found"); 93 | } else { 94 | println!("Subarray found: {:?}", &nums[res.0..res.0 + res.1]); 95 | } 96 | } 97 | 98 | // this function searches an array to find a subarray with the given sum 99 | // it returns the index where the subarray starts along with the length of the subarray 100 | // if the array does not include any subarray with the sum, it returns a tuple with length or array 101 | fn find_subarray(nums: &[i32], sum: i32) -> (usize, usize) { 102 | for len in (1..nums.len() + 1).rev() { 103 | for start in 0..nums.len() - len + 1 { 104 | if array_sum(&nums[]) == sum { 105 | return (start, len); 106 | } 107 | } 108 | } 109 | (nums.len(), nums.len()) 110 | } 111 | fn array_sum(nums) -> i32 { 112 | let mut res = 0; 113 | for num in nums { 114 | res += num; 115 | } 116 | res 117 | } 118 | 119 | ``` 120 | 121 |
122 | Solution 123 | 124 | ```rust 125 | fn main() { 126 | let nums = [1, 1, 2, 3, 5, 8, 13]; 127 | let res = find_subarray(&nums[..], 16); 128 | if res.0 == nums.len() { 129 | println!("No subarray found"); 130 | } else { 131 | println!("Subarray found: {:?}", &nums[res.0..res.0 + res.1]); 132 | } 133 | } 134 | 135 | fn find_subarray(nums: &[i32], sum: i32) -> (usize, usize) { 136 | for len in (1..nums.len() + 1).rev() { 137 | for start in 0..nums.len() - len + 1 { 138 | if array_sum(&nums[start..start+len]) == sum { 139 | return (start, len); 140 | } 141 | } 142 | } 143 | (nums.len(), nums.len()) 144 | } 145 | fn array_sum(nums: &[i32]) -> i32 { 146 | let mut res = 0; 147 | for num in nums { 148 | res += num; 149 | } 150 | res 151 | } 152 | ``` 153 |
154 | -------------------------------------------------------------------------------- /src/beginner/strings.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/beginner/structs.md: -------------------------------------------------------------------------------- 1 | # Structs 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Struct definition 10 | 11 | ```rust,editable,compile_fail 12 | // Complete the code by addressing the TODO. 13 | 14 | struct User { 15 | // TODO: Something goes here 16 | } 17 | 18 | fn main() { 19 | let user = User { 20 | name: String::from("Tom Riddle"), 21 | age: 17u8, 22 | }; 23 | println!("User's name: {}", user.name); 24 | println!("User's age: {}", user.age); 25 | } 26 | ``` 27 | 28 |
29 | Solution 30 | 31 | ```rust 32 | struct User { 33 | name: String, 34 | age: u8, 35 | } 36 | 37 | fn main() { 38 | let user = User { 39 | name: String::from("Tom Riddle"), 40 | age: 17u8, 41 | }; 42 | println!("User's name: {}", user.name); 43 | println!("User's age: {}", user.age); 44 | } 45 | ``` 46 |
47 | 48 | #### Mutating structs 49 | 50 | ```rust,editable,compile_fail 51 | // Make the following code compile. 52 | 53 | struct ShopItem { 54 | name: String, 55 | quantity: u32, 56 | in_stock: bool, 57 | } 58 | 59 | fn main() { 60 | let item = ShopItem { 61 | name: String::from("Socks"), 62 | quantity: 200, 63 | in_stock: true, 64 | }; 65 | // 50 pairs of socks were sold 66 | item.quantity -= 50; 67 | if item.quantity == 0 { 68 | item.in_stock = false; 69 | } 70 | println!("{} is in stock: {}", item.name, item.in_stock); 71 | } 72 | ``` 73 | 74 |
75 | Solution 76 | 77 | ```rust 78 | struct ShopItem { 79 | name: String, 80 | quantity: u32, 81 | in_stock: bool, 82 | } 83 | 84 | fn main() { 85 | let mut item = ShopItem { 86 | name: String::from("Socks"), 87 | quantity: 200, 88 | in_stock: true, 89 | }; 90 | // 50 pairs of socks were sold 91 | item.quantity -= 50; 92 | if item.quantity == 0 { 93 | item.in_stock = false; 94 | } 95 | println!("{} is in stock: {}", item.name, item.in_stock); 96 | } 97 | ``` 98 |
99 | 100 | #### Structs and Functions 101 | 102 | 103 | ```rust,editable,compile_fail 104 | // Complete the function signatures and make the code compile. 105 | 106 | struct ShopItem { 107 | name: String, 108 | quantity: u32, 109 | } 110 | 111 | fn main() { 112 | let item = create_item("Socks", 200); 113 | let in_stock = is_in_stock(&item); 114 | println!("{} is in stock: {in_stock}", item.name); 115 | } 116 | 117 | fn create_item(name: &str, quantity: u32) -> { 118 | ShopItem { 119 | name: name.to_string(), 120 | quantity, // notice how struct initializations can be shortened when variable and field have same name 121 | } 122 | } 123 | 124 | fn is_in_stock(item) -> bool { 125 | item.quantity > 0 126 | } 127 | ``` 128 | 129 |
130 | Solution 131 | 132 | ```rust 133 | struct ShopItem { 134 | name: String, 135 | quantity: u32, 136 | } 137 | 138 | fn main() { 139 | let item = create_item("Socks", 200); 140 | let in_stock = is_in_stock(&item); 141 | println!("{} is in stock: {in_stock}", item.name); 142 | } 143 | 144 | fn create_item(name: &str, quantity: u32) -> ShopItem { 145 | ShopItem { 146 | name: name.to_string(), 147 | quantity, 148 | } 149 | } 150 | 151 | fn is_in_stock(item: &ShopItem) -> bool { 152 | item.quantity > 0 153 | } 154 | ``` 155 |
156 | -------------------------------------------------------------------------------- /src/beginner/tuple-structs.md: -------------------------------------------------------------------------------- 1 | # Tuple Structs 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Definition 10 | 11 |
12 | Description 13 | 14 | This is a helpful description. Read me to understand what to do! 15 | 16 |
17 | 18 | ```rust,editable,compile_fail 19 | // Complete the structure definition. 20 | 21 | struct Point 22 | 23 | impl Point { 24 | fn on_x_axis(&self) -> bool { 25 | self.1 == 0.0 26 | } 27 | fn on_y_axis(&self) -> bool { 28 | self.0 == 0.0 29 | } 30 | } 31 | 32 | fn main() { 33 | let point = Point(0.0, 0.0); 34 | if point.on_x_axis() && point.on_y_axis() { 35 | println!("Point is origin"); 36 | } 37 | } 38 | ``` 39 | 40 |
41 | Hint 1 42 | 43 | This is a helpful hint! Read me to understand what to do! 44 | 45 |
46 |
47 | Hint 2 48 | 49 | This is a helpful hint! Read me to understand what to do! 50 | 51 |
52 |
53 | Hint 3 54 | 55 | This is a helpful hint! Read me to understand what to do! 56 | 57 |
58 |
59 | Solution 60 | 61 | ```rust 62 | struct Point(f32, f32); 63 | 64 | impl Point { 65 | fn on_x_axis(&self) -> bool { 66 | self.1 == 0.0 67 | } 68 | fn on_y_axis(&self) -> bool { 69 | self.0 == 0.0 70 | } 71 | } 72 | 73 | fn main() { 74 | let point = Point(0.0, 0.0); 75 | if point.on_x_axis() && point.on_y_axis() { 76 | println!("Point is origin"); 77 | } 78 | } 79 | ``` 80 |
81 | -------------------------------------------------------------------------------- /src/beginner/unit-tests.md: -------------------------------------------------------------------------------- 1 | # Unit Tests 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Testing in Rust - Part 2 9 | 10 | ## Exercises 11 | 12 | 13 | #### Asserting 1 14 | 15 | ```rust,editable,compile_fail 16 | // Make the test compile and pass successfully. 17 | 18 | #[cfg(test)] 19 | mod tests { 20 | #[test] 21 | fn you_can_assert() { 22 | assert!(); 23 | } 24 | } 25 | 26 | ``` 27 |
28 | Solution 29 | 30 | ```rust 31 | #[cfg(test)] 32 | mod tests { 33 | #[test] 34 | fn you_can_assert() { 35 | assert!(1 == 1); // use any expression that evaluates to true 36 | } 37 | } 38 | ``` 39 |
40 | 41 | #### Asserting 2 42 | 43 | ```rust,editable,compile_fail 44 | // Make the test compile and pass successfully. 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | #[test] 49 | fn you_can_assert_eq() { 50 | assert_eq!(); 51 | } 52 | } 53 | ``` 54 |
55 | Solution 56 | 57 | ```rust 58 | #[cfg(test)] 59 | mod tests { 60 | #[test] 61 | fn you_can_assert_eq() { 62 | assert_eq!(7+2, 9); // can use any two expressions that are equal 63 | } 64 | } 65 | ``` 66 |
67 | 68 | #### Asserting 3 69 | 70 | ```rust,editable,compile_fail 71 | // Make the tests compile and pass successfully. 72 | 73 | pub fn is_even(num: i32) -> bool { 74 | num % 2 == 0 75 | } 76 | 77 | #[cfg(test)] 78 | mod tests { 79 | use super::*; 80 | 81 | #[test] 82 | fn is_true_when_even() { 83 | assert!(); 84 | } 85 | 86 | #[test] 87 | fn is_false_when_odd() { 88 | assert!(); 89 | } 90 | } 91 | ``` 92 |
93 | Solution 94 | 95 | ```rust 96 | pub fn is_even(num: i32) -> bool { 97 | num % 2 == 0 98 | } 99 | 100 | #[cfg(test)] 101 | mod tests { 102 | use super::*; 103 | 104 | #[test] 105 | fn is_true_when_even() { 106 | assert!(is_even(10)); 107 | } 108 | 109 | #[test] 110 | fn is_false_when_odd() { 111 | assert!(!is_even(9)); 112 | } 113 | } 114 | ``` 115 |
116 | 117 | #### Returning result 118 | 119 | ```rust,editable,compile_fail 120 | // Complete the test function's signature. 121 | 122 | fn calculate_sum(nums: &[i32]) -> Result { 123 | if nums.len() == 0 { 124 | return Err("Number list is empty".to_string()); 125 | } 126 | let mut sum = 0; 127 | for num in nums { 128 | sum += num; 129 | } 130 | Ok(sum) 131 | } 132 | 133 | #[cfg(test)] 134 | mod tests { 135 | use super::*; 136 | 137 | #[test] 138 | fn calculates_sum_correctly() -> { 139 | let nums = [1, 2, 3, 4, 5]; 140 | let sum = calculate_sum(&nums)?; 141 | assert_eq!(sum, 5 * (5 + 1) / 2); 142 | Ok(()) 143 | } 144 | } 145 | ``` 146 |
147 | Solution 148 | 149 | ```rust 150 | fn calculate_sum(nums: &[i32]) -> Result { 151 | if nums.len() == 0 { 152 | return Err("Number list is empty".to_string()); 153 | } 154 | let mut sum = 0; 155 | for num in nums { 156 | sum += num; 157 | } 158 | Ok(sum) 159 | } 160 | 161 | #[cfg(test)] 162 | mod tests { 163 | use super::*; 164 | 165 | #[test] 166 | fn calculates_sum_correctly() -> Result<(), String> { 167 | let nums = [1, 2, 3, 4, 5]; 168 | let sum = calculate_sum(&nums)?; 169 | assert_eq!(sum, 5 * (5 + 1) / 2); 170 | Ok(()) 171 | } 172 | } 173 | ``` 174 |
175 | 176 | #### Testing panics 177 | 178 | ```rust,editable,compile_fail 179 | // Add a macro to make the test pass. 180 | 181 | fn average(nums: &[i32]) -> i32 { 182 | if nums.len() == 0 { 183 | panic!("Empty number list"); 184 | } 185 | let mut sum = 0; 186 | for num in nums { 187 | sum += num; 188 | } 189 | sum / nums.len() as i32 190 | } 191 | 192 | #[cfg(test)] 193 | mod tests { 194 | use super::*; 195 | 196 | #[test] 197 | fn it_panics() { 198 | let nums = []; 199 | let _avg = average(&nums); 200 | } 201 | } 202 | ``` 203 |
204 | Solution 205 | 206 | ```rust 207 | fn average(nums: &[i32]) -> i32 { 208 | if nums.len() == 0 { 209 | panic!("Empty number list"); 210 | } 211 | let mut sum = 0; 212 | for num in nums { 213 | sum += num; 214 | } 215 | sum / nums.len() as i32 216 | } 217 | 218 | #[cfg(test)] 219 | mod tests { 220 | use super::*; 221 | 222 | #[test] 223 | #[should_panic] 224 | fn it_panics() { 225 | let nums = []; 226 | let _avg = average(&nums); 227 | } 228 | } 229 | ``` 230 |
231 | -------------------------------------------------------------------------------- /src/beginner/variables.md: -------------------------------------------------------------------------------- 1 | # Variables 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Shadowing in Rust 9 | 10 | ## Exercises 11 | 12 | #### Declaration 13 | 14 | ```rust,editable,compile_fail 15 | // Fix the variable definition of 'x' 16 | 17 | fn main() { 18 | x = 5; 19 | println!("x has the value {}", x); 20 | } 21 | ``` 22 | 23 |
24 | Solution 25 | 26 | ```rust 27 | fn main() { 28 | let x = 5; 29 | println!("x has the value {}", x); 30 | } 31 | ``` 32 |
33 | 34 | 35 | #### Declaration with reassignment 36 | 37 | ```rust,editable,compile_fail 38 | // Fix the variable definition of 'x' 39 | 40 | fn main() { 41 | let x = 3; 42 | println!("Number {}", x); 43 | x = 5; // don't change this line 44 | println!("Number {}", x); 45 | } 46 | ``` 47 | 48 |
49 | Solution 50 | 51 | ```rust 52 | fn main() { 53 | let mut x = 3; 54 | println!("Number {}", x); 55 | x = 5; // don't change this line 56 | println!("Number {}", x); 57 | } 58 | ``` 59 |
60 | 61 | 62 | #### Declaration with shadowing 63 | 64 | ```rust,editable,compile_fail 65 | // Fix this code with shadowing 66 | 67 | fn main() { 68 | let x = "three"; // don't change this line 69 | println!("Spell a Number : {}", x); 70 | x = 3; // don't rename this variable 71 | println!("Number plus two is : {}", x + 2); 72 | } 73 | ``` 74 | 75 |
76 | Solution 77 | 78 | ```rust 79 | fn main() { 80 | let x = "three"; // don't change this line 81 | println!("Spell a Number : {}", x); 82 | let x = 3; // don't rename this variable 83 | println!("Number plus two is : {}", x + 2); 84 | } 85 | ``` 86 |
-------------------------------------------------------------------------------- /src/curriculum/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/curriculum/favicon.png -------------------------------------------------------------------------------- /src/curriculum/lgr_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/curriculum/lgr_logo.png -------------------------------------------------------------------------------- /src/further-learning/api-project.md: -------------------------------------------------------------------------------- 1 | # API Project 2 | 3 | > Note: This is an exclusive of our Rust Developer Bootcamp! 4 | -------------------------------------------------------------------------------- /src/further-learning/building-microservices-in-rust.md: -------------------------------------------------------------------------------- 1 | # Building Microservices in Rust 2 | 3 | > Note: This is an exclusive of our Rust Developer Bootcamp! 4 | -------------------------------------------------------------------------------- /src/further-learning/cli-project.md: -------------------------------------------------------------------------------- 1 | # CLI Project 2 | 3 | > Note: This is an exclusive of our Rust Developer Bootcamp! 4 | -------------------------------------------------------------------------------- /src/further-learning/deep-dive-into-string-in-rust.md: -------------------------------------------------------------------------------- 1 | # Deep Dive into Strings in Rust 2 | 3 | > Note: This is an exclusive of our Rust Developer Bootcamp! 4 | -------------------------------------------------------------------------------- /src/further-learning/mircoservices-project.md: -------------------------------------------------------------------------------- 1 | # Microservices Project 2 | 3 | > Note: This is an exclusive of our Rust Developer Bootcamp! 4 | -------------------------------------------------------------------------------- /src/further-learning/rust-based-computer-science.md: -------------------------------------------------------------------------------- 1 | # Rust Based Computer Science 2 | 3 | > Note: This is an exclusive of our Rust Developer Bootcamp! 4 | -------------------------------------------------------------------------------- /src/further-learning/systems-programming-in-rust.md: -------------------------------------------------------------------------------- 1 | # Systems Programming in Rust 2 | 3 | > Note: This is an exclusive of our Rust Developer Bootcamp! 4 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | # Let's Get Rusty Learning Guide 🦀 2 | 3 |
4 | 5 |
6 | 7 | This is a space designed for aspiring Rust developers. 8 | 9 | The curriculum is composed of existing YouTube videos by Let's Get Rusty, organized to guide you step-by-step through your Rust learning journey. 10 | 11 | And to make your learning more interactive, there are exercises covering most of the topics. So, whether you're just starting out or looking to sharpen your skills in Rust, this is the perfect place for you. 12 | 13 | To discuss and/or collaborate with other Rust developers, join our [Discord community](https://discord.com/invite/wTfbkNeZnv)! 14 | 15 | 16 | ## Features 17 | 18 | - Tutorial videos by Let's Get Rusty 19 | 20 | - Additional resources 21 | 22 | - Exercises 23 | 24 | - Exercise solutions 25 | 26 | - More user customizations coming soon! 27 | 28 | ## Installation 29 | 30 | ```shell 31 | git clone git@github.com:letsgetrusty/rust-learning-guide.git 32 | 33 | cargo install mdbook 34 | 35 | cd rust-learning-guide && mdbook serve --open 36 | ``` 37 | 38 | 39 | ## Credits 40 | 41 | - Bogdan :) 42 | 43 | - OP open-source community contributors! 44 | 45 | - [The Rust Book](https://github.com/rust-lang/book), [Rust By Example](https://github.com/rust-lang/rust-by-example), [Rust By Practice](https://github.com/sunface/rust-by-practice) 46 | 47 | 48 | ## Licenses 49 | 50 | - MIT License -------------------------------------------------------------------------------- /src/intermediate/anyhow.md: -------------------------------------------------------------------------------- 1 | # anyhow 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | #### Additional Resources 10 | - Error Handling In Rust - A Deep Dive 11 | 12 | ## Exercises 13 | 14 | (No exercises yet. Feel free to contribute here!) 15 | -------------------------------------------------------------------------------- /src/intermediate/avoiding-unwrap.md: -------------------------------------------------------------------------------- 1 | # Avoiding Unwrap 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | ## Exercises 10 | 11 | #### Avoiding unwrap 12 | 13 | ```rust,editable,compile_fail 14 | // Modify `get_last` to handle all cases and make the program execute successfully. 15 | 16 | fn get_last(nums: &mut Vec) -> i32 { 17 | nums.pop().unwrap() 18 | } 19 | 20 | fn main() { 21 | let mut vec1 = vec![1, 2, 3]; 22 | let mut vec2 = vec![]; 23 | assert!(matches!(get_last(&mut vec1), Ok(3))); 24 | assert!(matches!(get_last(&mut vec2), Err("Empty vector"))); 25 | } 26 | ``` 27 | 28 |
29 | Solution 30 | 31 | ```rust 32 | fn get_last(nums: &mut Vec) -> Result { 33 | if nums.len() == 0 { 34 | return Err("Empty vector"); 35 | } 36 | Ok(nums.pop().unwrap()) 37 | } 38 | 39 | fn main() { 40 | let mut vec1 = vec![1, 2, 3]; 41 | let mut vec2 = vec![]; 42 | assert!(matches!(get_last(&mut vec1), Ok(3))); 43 | assert!(matches!(get_last(&mut vec2), Err("Empty vector"))); 44 | } 45 | ``` 46 |
47 | -------------------------------------------------------------------------------- /src/intermediate/box-smart-pointer.md: -------------------------------------------------------------------------------- 1 | # Box Smart Pointer 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Creation 10 | 11 | ```rust,editable,compile_fail 12 | // Initialize heap_var to store value 4 on the heap & make the code execute successfully. 13 | 14 | fn main() { 15 | let stack_var = 5; 16 | // TODO: initialize this variable 17 | let heap_var 18 | let res = stack_var + *heap_var; 19 | assert_eq!(res, 9); 20 | } 21 | ``` 22 | 23 |
24 | Solution 25 | 26 | ```rust 27 | fn main() { 28 | let stack_var = 5; 29 | let heap_var = Box::new(4); 30 | let res = stack_var + *heap_var; 31 | assert_eq!(res, 9); 32 | } 33 | ``` 34 |
35 | 36 | #### Recursive types 37 | 38 |
39 | Description 40 | 41 | This is a helpful description. Read me to understand what to do! 42 | 43 |
44 | 45 | ```rust,editable,compile_fail 46 | // The recursive type we're implementing in this exercise is the `cons list` - a data structure 47 | // frequently found in functional programming languages. Each item in a cons list contains two 48 | // elements: the value of the current item and the next item. The last item is a value called `Nil`. 49 | // 50 | // Step 1: use a `Box` in the enum definition to make the code compile 51 | // Step 2: create both empty and non-empty cons lists by replacing `todo!()` 52 | 53 | 54 | #[derive(PartialEq, Debug)] 55 | pub enum List { 56 | Cons(i32, List), 57 | Nil, 58 | } 59 | 60 | fn main() { 61 | println!("This is an empty cons list: {:?}", create_empty_list()); 62 | println!( 63 | "This is a non-empty cons list: {:?}", 64 | create_non_empty_list() 65 | ); 66 | } 67 | 68 | pub fn create_empty_list() -> List { 69 | todo!() 70 | } 71 | 72 | pub fn create_non_empty_list() -> List { 73 | todo!() 74 | } 75 | 76 | #[cfg(test)] 77 | mod tests { 78 | use super::*; 79 | 80 | #[test] 81 | fn test_create_empty_list() { 82 | assert_eq!(List::Nil, create_empty_list()) 83 | } 84 | 85 | #[test] 86 | fn test_create_non_empty_list() { 87 | assert_ne!(create_empty_list(), create_non_empty_list()) 88 | } 89 | } 90 | ``` 91 | 92 |
93 | Solution 94 | 95 | ```rust 96 | #[derive(PartialEq, Debug)] 97 | pub enum List { 98 | Cons(i32, Box), 99 | Nil, 100 | } 101 | 102 | fn main() { 103 | println!("This is an empty cons list: {:?}", create_empty_list()); 104 | println!( 105 | "This is a non-empty cons list: {:?}", 106 | create_non_empty_list() 107 | ); 108 | } 109 | 110 | pub fn create_empty_list() -> List { 111 | List::Nil 112 | } 113 | 114 | pub fn create_non_empty_list() -> List { 115 | List::Cons(1, Box::new(List::Cons(1, Box::new(List::Nil)))) 116 | } 117 | 118 | #[cfg(test)] 119 | mod tests { 120 | use super::*; 121 | 122 | #[test] 123 | fn test_create_empty_list() { 124 | assert_eq!(List::Nil, create_empty_list()) 125 | } 126 | 127 | #[test] 128 | fn test_create_non_empty_list() { 129 | assert_ne!(create_empty_list(), create_non_empty_list()) 130 | } 131 | } 132 | ``` 133 |
134 | -------------------------------------------------------------------------------- /src/intermediate/concrete-lifetimes.md: -------------------------------------------------------------------------------- 1 | # Concret Lifetimes 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Lifetimes of owned values 10 | 11 | ```rust,editable,compile_fail 12 | // Fix the code by shifting only one statement. 13 | 14 | fn main() { 15 | let str1 = "🦀".to_string(); 16 | let bytes = str1.into_bytes(); 17 | println!("A crab: {str1}"); 18 | println!("A crab represented in unicode: {bytes:?}"); 19 | } 20 | ``` 21 | 22 |
23 | Solution 24 | 25 | ```rust 26 | fn main() { 27 | let str1 = "🦀".to_string(); 28 | println!("A crab: {str1}"); 29 | let bytes = str1.into_bytes(); 30 | println!("A crab represented in unicode: {bytes:?}"); 31 | } 32 | ``` 33 |
34 | 35 | #### Dangling references 36 | 37 | ```rust,editable,compile_fail 38 | // Fix the code by addressing the TODO. 39 | 40 | fn main() { 41 | let num_ref; 42 | { 43 | // TODO: shift below statement to appropriate location 44 | let num = 23; 45 | num_ref = # 46 | } 47 | println!("Reference points to {}", num_ref); 48 | } 49 | ``` 50 | 51 |
52 | Solution 53 | 54 | ```rust 55 | fn main() { 56 | let num_ref; 57 | let num = 23; 58 | { 59 | num_ref = # 60 | } 61 | println!("Reference points to {}", num_ref); 62 | } 63 | ``` 64 |
65 | 66 | #### Non-lexical lifetimes 67 | 68 | 69 | ```rust,editable,compile_fail 70 | // Fix the code by shifting only one statement. 71 | 72 | fn main() { 73 | let mut my_str = "Old String".to_owned(); 74 | let ref1 = &my_str; 75 | let ref2 = &mut my_str; 76 | ref2.replace_range(0..3, "New"); 77 | println!("{ref1}"); 78 | println!("{ref2}"); 79 | } 80 | ``` 81 | 82 |
83 | Solution 84 | 85 | ```rust 86 | fn main() { 87 | let mut my_str = "Old String".to_owned(); 88 | let ref1 = &my_str; 89 | println!("{ref1}"); 90 | let ref2 = &mut my_str; 91 | ref2.replace_range(0..3, "New"); 92 | println!("{ref2}"); 93 | } 94 | ``` 95 |
96 | -------------------------------------------------------------------------------- /src/intermediate/deref-coercion.md: -------------------------------------------------------------------------------- 1 | # Deref Coercion 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Deref coercion with Box 10 | 11 | ```rust,editable,compile_fail 12 | // Complete the code by addressing the TODOs. 13 | 14 | use std::rc::Rc; 15 | 16 | struct Employee { 17 | name: String, 18 | id: u32, 19 | } 20 | 21 | impl Employee { 22 | fn new(name: &str, id: u32) -> Self { 23 | Employee { 24 | name: name.to_string(), 25 | id, 26 | } 27 | } 28 | fn print_details(&self) { 29 | println!("Name: {}, ID: {}", self.name, self.id); 30 | } 31 | } 32 | 33 | fn main() { 34 | let emp1 = Box::new(Employee::new("Alice", 1234)); 35 | // TODO: call print_details on emp1 36 | let emp2 = Box::new(emp1); 37 | // TODO: call print_details on emp2 38 | let emp3 = Rc::new(emp2); 39 | // TODO: call print_details on emp3 40 | } 41 | ``` 42 | 43 |
44 | Solution 45 | 46 | ```rust 47 | use std::rc::Rc; 48 | 49 | struct Employee { 50 | name: String, 51 | id: u32, 52 | } 53 | 54 | impl Employee { 55 | fn new(name: &str, id: u32) -> Self { 56 | Employee { 57 | name: name.to_string(), 58 | id, 59 | } 60 | } 61 | fn print_details(&self) { 62 | println!("Name: {}, ID: {}", self.name, self.id); 63 | } 64 | } 65 | 66 | fn main() { 67 | let emp1 = Box::new(Employee::new("Alice", 1234)); 68 | emp1.print_details(); 69 | let emp2 = Box::new(emp1); 70 | emp2.print_details(); 71 | let emp3 = Rc::new(emp2); 72 | emp3.print_details(); 73 | } 74 | ``` 75 |
76 | 77 | #### Deref & deref mut 78 | 79 | ```rust,editable,compile_fail 80 | // Make the code compile by implementing Deref & DerefMut for Wrapper. 81 | 82 | use std::ops::{Deref, DerefMut}; 83 | 84 | struct Wrapper(T); 85 | 86 | impl Deref for Wrapper { 87 | type Target; 88 | fn deref(&self) -> &Self::Target {} 89 | } 90 | 91 | impl DerefMut for Wrapper { 92 | fn deref_mut(&mut self) -> &mut Self::Target {} 93 | } 94 | 95 | fn main() { 96 | let mut my_str = Wrapper(String::from("Ferris")); 97 | my_str.push_str(" the crab!!"); 98 | my_str.pop(); 99 | assert!(are_equal(&my_str, "Ferris the crab!")); 100 | } 101 | 102 | fn are_equal(a: &str, b: &str) -> bool { 103 | a == b 104 | } 105 | ``` 106 | 107 |
108 | Solution 109 | 110 | ```rust 111 | use std::ops::{Deref, DerefMut}; 112 | 113 | struct Wrapper(T); 114 | 115 | impl Deref for Wrapper { 116 | type Target = T; 117 | fn deref(&self) -> &Self::Target { 118 | &self.0 119 | } 120 | } 121 | 122 | impl DerefMut for Wrapper { 123 | fn deref_mut(&mut self) -> &mut Self::Target { 124 | &mut self.0 125 | } 126 | } 127 | 128 | fn main() { 129 | let mut my_str = Wrapper(String::from("Ferris")); 130 | my_str.push_str(" the crab!!"); 131 | my_str.pop(); 132 | assert!(are_equal(&my_str, "Ferris the crab!")); 133 | } 134 | 135 | fn are_equal(a: &str, b: &str) -> bool { 136 | a == b 137 | } 138 | ``` 139 |
140 | 141 | #### Shared ownership with mutability 142 | 143 | ```rust,editable,compile_fail 144 | // Complete the update_value function. 145 | 146 | use core::fmt::Debug; 147 | use std::cell::RefCell; 148 | use std::rc::Rc; 149 | 150 | fn main() { 151 | let owner1 = Rc::new(RefCell::new("Harry")); 152 | print_value(&owner1); 153 | let owner2 = Rc::clone(&owner1); 154 | update_value(&owner2, "Ron"); 155 | print_value(&owner1); 156 | print_value(&owner2); 157 | } 158 | 159 | fn update_value(owner: &Rc>, value: T) {} 160 | 161 | fn print_value(owner: &Rc>) { 162 | println!("{:?}", owner.borrow()); 163 | } 164 | ``` 165 | 166 |
167 | Solution 168 | 169 | ```rust 170 | use core::fmt::Debug; 171 | use std::cell::RefCell; 172 | use std::rc::Rc; 173 | 174 | fn main() { 175 | let owner1 = Rc::new(RefCell::new("Harry")); 176 | print_value(&owner1); 177 | let owner2 = Rc::clone(&owner1); 178 | update_value(&owner2, "Ron"); 179 | print_value(&owner1); 180 | print_value(&owner2); 181 | } 182 | 183 | fn update_value(owner: &Rc>, value: T) { 184 | *owner.borrow_mut() = value; 185 | } 186 | 187 | fn print_value(owner: &Rc>) { 188 | println!("{:?}", owner.borrow()); 189 | } 190 | ``` 191 |
192 | -------------------------------------------------------------------------------- /src/intermediate/deriving-traits.md: -------------------------------------------------------------------------------- 1 | # Deriving Traits 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - 5 traits your Rust types must implement 9 | 10 | ## Exercises 11 | 12 | #### Deriving on structs 13 | 14 | ```rust,editable,compile_fail 15 | // Complete the code by deriving the required traits. 16 | 17 | struct Point { 18 | x: i32, 19 | y: i32, 20 | } 21 | 22 | fn main() { 23 | let my_point = Point { x: 20, y: 10 }; 24 | let origin = Point::default(); 25 | println!("Origin: {origin:?}"); 26 | if my_point == origin { 27 | println!("Selected point is origin!"); 28 | } else { 29 | println!("Selected point: {my_point:?}"); 30 | } 31 | } 32 | ``` 33 | 34 |
35 | Solution 36 | 37 | ```rust 38 | #[derive(Default, Debug, PartialEq)] 39 | struct Point { 40 | x: i32, 41 | y: i32, 42 | } 43 | 44 | fn main() { 45 | let my_point = Point { x: 20, y: 10 }; 46 | let origin = Point::default(); 47 | println!("Origin: {origin:?}"); 48 | if my_point == origin { 49 | println!("Selected point is origin!"); 50 | } else { 51 | println!("Selected point: {my_point:?}"); 52 | } 53 | } 54 | ``` 55 |
56 | 57 | #### Deriving on enums 58 | 59 | 60 | ```rust,editable,compile_fail 61 | // Only one trait needs to be derived. Can you figure out which? 62 | 63 | enum Size { 64 | Small, 65 | Medium, 66 | Large, 67 | } 68 | 69 | fn main() { 70 | let my_size = Size::Small; 71 | if my_size == Size::Small { 72 | println!("I can fit in any size!"); 73 | } 74 | } 75 | ``` 76 | 77 |
78 | Solution 79 | 80 | ```rust 81 | #[derive(PartialEq)] 82 | enum Size { 83 | Small, 84 | Medium, 85 | Large, 86 | } 87 | 88 | fn main() { 89 | let my_size = Size::Small; 90 | if my_size == Size::Small { 91 | println!("I can fit in any size!"); 92 | } 93 | } 94 | ``` 95 |
96 | -------------------------------------------------------------------------------- /src/intermediate/error-stack.md: -------------------------------------------------------------------------------- 1 | # error-stack 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | (No exercises yet. Feel free to contribute here!) 10 | -------------------------------------------------------------------------------- /src/intermediate/function-pointers.md: -------------------------------------------------------------------------------- 1 | # Function Pointers 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### As parameters 10 | 11 | ```rust,editable,compile_fail 12 | // Complete the function signature for `factorial`. It must not contain any generics/traits. 13 | 14 | fn decrement(x: u32) -> u32 { 15 | x - 1 16 | } 17 | 18 | fn multiply(x: u32, y: u32) -> u32 { 19 | x * y 20 | } 21 | 22 | fn factorial(num, dec, mul) { 23 | let mut res = 1; 24 | let mut temp = num; 25 | while temp > 1 { 26 | res = mul(res, temp); 27 | temp = dec(temp); 28 | } 29 | res 30 | } 31 | 32 | fn main() { 33 | let num = 6; 34 | let fact = factorial(num, decrement, multiply); 35 | println!("{num}! = {fact}"); 36 | } 37 | ``` 38 | 39 |
40 | Solution 41 | 42 | ```rust 43 | fn decrement(x: u32) -> u32 { 44 | x - 1 45 | } 46 | 47 | fn multiply(x: u32, y: u32) -> u32 { 48 | x * y 49 | } 50 | 51 | fn factorial(num: u32, dec: fn(u32)->u32, mul: fn(u32, u32)->u32) -> u32 { 52 | let mut res = 1; 53 | let mut temp = num; 54 | while temp > 1 { 55 | res = mul(res, temp); 56 | temp = dec(temp); 57 | } 58 | res 59 | } 60 | 61 | fn main() { 62 | let num = 6; 63 | let fact = factorial(num, decrement, multiply); 64 | println!("{num}! = {fact}"); 65 | } 66 | ``` 67 |
68 | 69 | #### Coercing from closures 70 | 71 | ```rust,editable,compile_fail 72 | // Fix the code by addressing the TODO. 73 | 74 | fn invoker(logic: fn(T), arg: T) { 75 | logic(arg); 76 | } 77 | 78 | fn main() { 79 | // TODO: shift below declaration to somewhere else 80 | let greeting = String::from("Nice to meet you"); 81 | let greet = |name| { 82 | println!("{greeting} {name}!"); 83 | }; 84 | invoker(greet, "Jenny"); 85 | } 86 | ``` 87 | 88 |
89 | Solution 90 | 91 | ```rust 92 | fn invoker(logic: fn(T), arg: T) { 93 | logic(arg); 94 | } 95 | 96 | fn main() { 97 | let greet = |name| { 98 | let greeting = String::from("Nice to meet you"); 99 | println!("{greeting} {name}!"); 100 | }; 101 | invoker(greet, "Jenny"); 102 | } 103 | ``` 104 |
105 | -------------------------------------------------------------------------------- /src/intermediate/generics-lifetimes.md: -------------------------------------------------------------------------------- 1 | # Generic Lifetimes 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Concrete vs Generic Lifetimes 9 | 10 | ## Exercises 11 | 12 | #### Helping the borrow checker 13 | 14 | ```rust,editable,compile_fail 15 | // Make the code compile by completing the function signature. 16 | 17 | fn longest(x: &str, y: &str) -> &str { 18 | if x.len() > y.len() { 19 | x 20 | } else { 21 | y 22 | } 23 | } 24 | 25 | fn main() { 26 | let string1 = String::from("abcd"); 27 | let string2 = "xyz"; 28 | 29 | let result = longest(string1.as_str(), string2); 30 | println!("The longest string is '{}'", result); 31 | } 32 | ``` 33 | 34 |
35 | Solution 36 | 37 | ```rust 38 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 39 | if x.len() > y.len() { 40 | x 41 | } else { 42 | y 43 | } 44 | } 45 | 46 | fn main() { 47 | let string1 = String::from("abcd"); 48 | let string2 = "xyz"; 49 | 50 | let result = longest(string1.as_str(), string2); 51 | println!("The longest string is '{}'", result); 52 | } 53 | ``` 54 |
55 | 56 | #### Complying with the borrow checker 57 | 58 | ```rust,editable,compile_fail 59 | // Make the code compile. You can only shift one statement. 60 | // You can not shift variable declarations. 61 | 62 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 63 | if x.len() > y.len() { 64 | x 65 | } else { 66 | y 67 | } 68 | } 69 | 70 | fn main() { 71 | let string1 = String::from("long string is long"); 72 | let result; 73 | { 74 | let string2 = String::from("xyz"); 75 | result = longest(string1.as_str(), string2.as_str()); 76 | } 77 | println!("The longest string is '{}'", result); 78 | } 79 | ``` 80 | 81 |
82 | Solution 83 | 84 | ```rust 85 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 86 | if x.len() > y.len() { 87 | x 88 | } else { 89 | y 90 | } 91 | } 92 | 93 | fn main() { 94 | let string1 = String::from("long string is long"); 95 | let result; 96 | { 97 | let string2 = String::from("xyz"); 98 | result = longest(string1.as_str(), string2.as_str()); 99 | println!("The longest string is '{}'", result); 100 | } 101 | } 102 | ``` 103 |
104 | 105 | #### Struct lifetimes 106 | 107 | ```rust,editable,compile_fail 108 | // Something is missing from our struct definition. Can you fix it? 109 | 110 | struct Book { 111 | author: &str, 112 | title: &str, 113 | } 114 | 115 | fn main() { 116 | let name = String::from("Jill Smith"); 117 | let title = String::from("Fish Flying"); 118 | let book = Book { 119 | author: &name, 120 | title: &title, 121 | }; 122 | 123 | println!("{} by {}", book.title, book.author); 124 | } 125 | ``` 126 | 127 |
128 | Solution 129 | 130 | ```rust 131 | struct Book<'a> { 132 | author: &'a str, 133 | title: &'a str, 134 | } 135 | 136 | fn main() { 137 | let name = String::from("Jill Smith"); 138 | let title = String::from("Fish Flying"); 139 | let book = Book { 140 | author: &name, 141 | title: &title, 142 | }; 143 | 144 | println!("{} by {}", book.title, book.author); 145 | } 146 | ``` 147 |
148 | -------------------------------------------------------------------------------- /src/intermediate/generics.md: -------------------------------------------------------------------------------- 1 | # Generics 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Rust: Generics, Traits, Lifetimes 9 | 10 | 11 | ## Exercises 12 | 13 | #### Defining generics types 1 14 | 15 | ```rust,editable,compile_fail 16 | // Fix the code by annotating variable with the correct type. 17 | 18 | fn main() { 19 | let mut shopping_list: Vec = Vec::new(); 20 | shopping_list.push("milk"); 21 | } 22 | ``` 23 | 24 |
25 | Solution 26 | 27 | ```rust 28 | fn main() { 29 | let mut shopping_list: Vec<&str> = Vec::new(); 30 | shopping_list.push("milk"); 31 | } 32 | ``` 33 |
34 | 35 | #### Defining generics types 2 36 | 37 | 38 | ```rust,editable,compile_fail 39 | // Define the generic struct Point. 40 | 41 | fn main() { 42 | let p1 = Point { x: 20, y: 10 }; 43 | let p2 = Point { x: 22.3, y: 3.14 }; 44 | println!("Point1: ({}, {})", p1.x, p1.y); 45 | println!("Point2: ({}, {})", p2.x, p2.y); 46 | } 47 | ``` 48 | 49 |
50 | Solution 51 | 52 | ```rust 53 | struct Point { 54 | x: T, 55 | y: T, 56 | } 57 | 58 | fn main() { 59 | let p1 = Point { x: 20, y: 10 }; 60 | let p2 = Point { x: 22.3, y: 3.14 }; 61 | println!("Point1: ({}, {})", p1.x, p1.y); 62 | println!("Point2: ({}, {})", p2.x, p2.y); 63 | } 64 | ``` 65 |
66 | 67 | #### Defining generic types 3 68 | 69 | 70 | ```rust,editable,compile_fail 71 | // Make the code compile by defining Operation enum with a single generic type. 72 | 73 | fn main() { 74 | let _op1 = Operation::Add(15u8, 10u8); 75 | let _op2 = Operation::Mul(150, 23); 76 | let _op3 = Operation::Sub { 77 | left: 120, 78 | right: 50, 79 | }; 80 | let _op4 = Operation::Div { 81 | dividend: 10.23, 82 | divisor: 2.43, 83 | }; 84 | } 85 | ``` 86 | 87 |
88 | Solution 89 | 90 | ```rust 91 | enum Operation { 92 | Add(T, T), 93 | Mul(T, T), 94 | Sub { left: T, right: T }, 95 | Div { dividend: T, divisor: T }, 96 | } 97 | 98 | fn main() { 99 | let _op1 = Operation::Add(15u8, 10u8); 100 | let _op2 = Operation::Mul(150, 23); 101 | let _op3 = Operation::Sub { 102 | left: 120, 103 | right: 50, 104 | }; 105 | let _op4 = Operation::Div { 106 | dividend: 10.23, 107 | divisor: 2.43, 108 | }; 109 | } 110 | ``` 111 |
112 | 113 | #### Implementation block 1 114 | 115 | 116 | ```rust,editable,compile_fail 117 | // Implement the add method for Pair type. 118 | 119 | struct Pair(T, T); 120 | 121 | fn main() { 122 | let p1 = Pair(10, 23); 123 | let addition = p1.add(); 124 | assert_eq!(addition, 33); 125 | } 126 | ``` 127 | 128 |
129 | Solution 130 | 131 | ```rust 132 | use std::ops::Add; 133 | 134 | struct Pair(T, T); 135 | impl Pair 136 | where T: Add + Copy 137 | { 138 | fn add(&self) -> T { 139 | self.0 + self.1 140 | } 141 | } 142 | 143 | fn main() { 144 | let p1 = Pair(10, 23); 145 | let addition = p1.add(); 146 | assert_eq!(addition, 33); 147 | } 148 | ``` 149 |
150 | 151 | #### Implementation block 2 152 | 153 | 154 | ```rust,editable,compile_fail 155 | // Rewrite Wrapper struct so that it supports wrapping ANY type. 156 | 157 | struct Wrapper { 158 | value: u32, 159 | } 160 | 161 | impl Wrapper { 162 | pub fn new(value: u32) -> Self { 163 | Wrapper { value } 164 | } 165 | } 166 | 167 | #[cfg(test)] 168 | mod tests { 169 | use super::*; 170 | 171 | #[test] 172 | fn store_u32_in_wrapper() { 173 | assert_eq!(Wrapper::new(42).value, 42); 174 | } 175 | 176 | #[test] 177 | fn store_str_in_wrapper() { 178 | assert_eq!(Wrapper::new("Foo").value, "Foo"); 179 | } 180 | } 181 | ``` 182 | 183 |
184 | Solution 185 | 186 | ```rust 187 | struct Wrapper { 188 | value: T, 189 | } 190 | 191 | impl Wrapper { 192 | pub fn new(value: T) -> Self { 193 | Wrapper { value } 194 | } 195 | } 196 | 197 | #[cfg(test)] 198 | mod tests { 199 | use super::*; 200 | 201 | #[test] 202 | fn store_u32_in_wrapper() { 203 | assert_eq!(Wrapper::new(42).value, 42); 204 | } 205 | 206 | #[test] 207 | fn store_str_in_wrapper() { 208 | assert_eq!(Wrapper::new("Foo").value, "Foo"); 209 | } 210 | } 211 | ``` 212 |
213 | 214 | #### Generic functions 215 | 216 | 217 | ```rust,editable,compile_fail 218 | // Fix the code so that it compiles. 219 | 220 | fn take_and_give_ownership(input: T) -> { 221 | input 222 | } 223 | 224 | struct User { 225 | name: String, 226 | id: u32, 227 | } 228 | 229 | fn main() { 230 | let str1 = String::from("Ferris the 🦀!"); 231 | let user1 = User { 232 | name: "Alice".to_string(), 233 | id: 199, 234 | }; 235 | let _str2 = take_and_give_ownership(str1); 236 | let _user2 = take_and_give_ownership(user1); 237 | } 238 | ``` 239 | 240 |
241 | Solution 242 | 243 | ```rust 244 | fn take_and_give_ownership(input: T) -> T { 245 | input 246 | } 247 | 248 | struct User { 249 | name: String, 250 | id: u32, 251 | } 252 | 253 | fn main() { 254 | let str1 = String::from("Ferris the 🦀!"); 255 | let user1 = User { 256 | name: "Alice".to_string(), 257 | id: 199, 258 | }; 259 | let _str2 = take_and_give_ownership(str1); 260 | let _user2 = take_and_give_ownership(user1); 261 | } 262 | ``` 263 |
264 | -------------------------------------------------------------------------------- /src/intermediate/iterator-over-collections.md: -------------------------------------------------------------------------------- 1 | # Iterator Over Collections 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | #### Additional Resources 10 | - Make iterators 10X better with itertools 11 | 12 | ## Exercises 13 | 14 | #### Iterating immutably 15 | 16 | ```rust,editable,compile_fail 17 | // Make the code compile by filling in the `???`s 18 | 19 | fn main() { 20 | let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"]; 21 | 22 | let mut my_iterable_fav_fruits = ???; // TODO: Step 1 23 | 24 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"banana")); 25 | assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 2 26 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"avocado")); 27 | assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 3 28 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry")); 29 | assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 4 30 | } 31 | ``` 32 | 33 |
34 | Solution 35 | 36 | ```rust 37 | fn main() { 38 | let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"]; 39 | 40 | let mut my_iterable_fav_fruits = my_fav_fruits.iter(); 41 | 42 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"banana")); 43 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"custard apple")); 44 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"avocado")); 45 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"peach")); 46 | assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry")); 47 | assert_eq!(my_iterable_fav_fruits.next(), None); 48 | } 49 | ``` 50 |
51 | 52 | #### Iterating mutably 53 | 54 | ```rust,editable,compile_fail 55 | // Make the code compile by only modifying the loop. 56 | 57 | fn main() { 58 | let mut nums = [0, 1, 2, 3, 4]; 59 | let odd_nums = [1, 3, 5, 7, 9]; 60 | for num in nums.iter() { 61 | *num = 2 * *num + 1; 62 | } 63 | assert_eq!(nums, odd_nums) 64 | } 65 | ``` 66 | 67 |
68 | Solution 69 | 70 | ```rust 71 | fn main() { 72 | let mut nums = [0, 1, 2, 3, 4]; 73 | let odd_nums = [1, 3, 5, 7, 9]; 74 | for num in nums.iter_mut() { 75 | *num = 2 * *num + 1; 76 | } 77 | assert_eq!(nums, odd_nums) 78 | } 79 | ``` 80 |
81 | 82 | #### Hashmaps 83 | 84 | ```rust,editable,compile_fail 85 | // Fix the code to make it compile. 86 | 87 | use std::collections::HashMap; 88 | 89 | fn main() { 90 | // marks scored out of 50 91 | let mut marks = HashMap::from([("Harry", 40.0), ("Hermoine", 50.0), ("Ron", 35.5)]); 92 | // convert marks into percentage 93 | for (_, marks) in marks { 94 | *marks = (*marks * 100.0) / 50.0; 95 | } 96 | marks.for_each(|(student, marks)| println!("{student} scored {marks}%")); 97 | } 98 | ``` 99 | 100 |
101 | Solution 102 | 103 | ```rust 104 | use std::collections::HashMap; 105 | 106 | fn main() { 107 | // marks scored out of 50 108 | let mut marks = HashMap::from([("Harry", 40.0), ("Hermoine", 50.0), ("Ron", 35.5)]); 109 | // convert marks into percentage 110 | for (_, marks) in marks.iter_mut() { 111 | *marks = (*marks * 100.0) / 50.0; 112 | } 113 | marks.iter().for_each(|(student, marks)| println!("{student} scored {marks}%")); 114 | } 115 | ``` 116 |
117 | -------------------------------------------------------------------------------- /src/intermediate/lifetime-elision.md: -------------------------------------------------------------------------------- 1 | # Lifetime Elision 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Lifetime elision 10 | 11 | ```rust,editable,compile_fail 12 | // The code below executes successfully. However, remove the lifetimes from wherever they can be inferred implicitly. 13 | 14 | struct NameStack<'a> { 15 | names: Vec<&'a str>, 16 | } 17 | 18 | impl<'a> NameStack<'a> { 19 | fn new() -> Self { 20 | NameStack { names: Vec::new() } 21 | } 22 | fn add_name(&mut self, name: &'a str) { 23 | self.names.push(name); 24 | } 25 | fn remove_name_with_substr<'b>(&mut self, sub_str: &'b str) -> &'a str { 26 | for i in 0..self.names.len() { 27 | if self.names[i].contains(sub_str) { 28 | let removed = self.names.remove(i); 29 | return removed; 30 | } 31 | } 32 | panic!("Name with substring not found"); 33 | } 34 | } 35 | 36 | fn main() { 37 | let mut my_names = NameStack::new(); 38 | my_names.add_name("Alice"); 39 | my_names.add_name("Bob"); 40 | my_names.add_name("Cindy"); 41 | my_names.add_name("Emily"); 42 | let removed = my_names.remove_name_with_substr("ice"); 43 | println!("Removed: {removed}"); 44 | assert_eq!(my_names.names.len(), 3); 45 | } 46 | 47 | ``` 48 | 49 |
50 | Solution 51 | 52 | ```rust 53 | struct NameStack<'a> { 54 | names: Vec<&'a str>, 55 | } 56 | 57 | impl<'a> NameStack<'a> { 58 | fn new() -> Self { 59 | NameStack { names: Vec::new() } 60 | } 61 | fn add_name(&mut self, name: &'a str) { 62 | self.names.push(name); 63 | } 64 | fn remove_name_with_substr(&mut self, sub_str: &str) -> &str { 65 | for i in 0..self.names.len() { 66 | if self.names[i].contains(sub_str) { 67 | let removed = self.names.remove(i); 68 | return removed; 69 | } 70 | } 71 | panic!("Name with substring not found"); 72 | } 73 | } 74 | 75 | fn main() { 76 | let mut my_names = NameStack::new(); 77 | my_names.add_name("Alice"); 78 | my_names.add_name("Bob"); 79 | my_names.add_name("Cindy"); 80 | my_names.add_name("Emily"); 81 | let removed = my_names.remove_name_with_substr("ice"); 82 | println!("Removed: {removed}"); 83 | assert_eq!(my_names.names.len(), 3); 84 | } 85 | ``` 86 |
87 | -------------------------------------------------------------------------------- /src/intermediate/orphan-rule.md: -------------------------------------------------------------------------------- 1 | # Orphan Rule 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | #### Additional Resources 10 | - The Orphan Rule in Rust 11 | 12 | ## Exercises 13 | 14 | (No exercises yet. Feel free to contribute here!) 15 | -------------------------------------------------------------------------------- /src/intermediate/refcell-smart-pointer.md: -------------------------------------------------------------------------------- 1 | # RefCell Smart Pointer 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Borrowing 10 | 11 | ```rust,editable,compile_fail 12 | // Complete the following code. 13 | 14 | use std::cell::RefCell; 15 | 16 | fn main() { 17 | // storing value 5 on heap 18 | let ptr = RefCell::new(5); 19 | // get an immutable reference to the stored value 20 | let ref1 = ; 21 | println!("Stored value: {}", ref1); 22 | drop(ref1); 23 | // get a mutable reference to the stored value 24 | let mut ref2 = ; 25 | *ref2 = 6; // Note: we can mutate the value associated with ptr, even though it is not marked as mut 26 | println!("Stored value: {}", ref2); 27 | } 28 | ``` 29 | 30 |
31 | Solution 32 | 33 | ```rust 34 | use std::cell::RefCell; 35 | 36 | fn main() { 37 | // storing value 5 on heap 38 | let ptr = RefCell::new(5); 39 | // get an immutable reference to the stored value 40 | let ref1 = ptr.borrow(); 41 | println!("Stored value: {}", ref1); 42 | drop(ref1); 43 | // get a mutable reference to the stored value 44 | let mut ref2 = ptr.borrow_mut(); 45 | *ref2 = 6; // Note: we can mutate the value associated with ptr, even though it is not marked as mut 46 | println!("Stored value: {}", ref2); 47 | } 48 | ``` 49 |
50 | 51 | #### Interior mutability 52 | 53 |
54 | Description 55 | 56 | This is a helpful description. Read me to understand what to do! 57 | 58 |
59 | 60 | ```rust,editable,compile_fail 61 | // Fix the print_details method. You can only modify the method body. 62 | 63 | use std::cell::RefCell; 64 | 65 | struct Student { 66 | name: String, 67 | marks: u8, 68 | grade: RefCell, 69 | } 70 | 71 | impl Student { 72 | fn new(name: &str, marks: u8) -> Self { 73 | Student { 74 | name: name.to_owned(), 75 | marks, 76 | grade: RefCell::new('X'), 77 | } 78 | } 79 | 80 | fn print_details(&self) { 81 | let grade = match self.marks { 82 | 0..=33 => 'C', 83 | 34..=60 => 'B', 84 | _ => 'A', 85 | }; 86 | self.grade = grade; 87 | println!( 88 | "name: {}, marks: {}, grade: {}", 89 | self.name, 90 | self.marks, 91 | self.grade.borrow() 92 | ); 93 | } 94 | } 95 | 96 | fn main() { 97 | let student = Student::new("Harry", 70); 98 | student.print_details(); 99 | } 100 | ``` 101 | 102 |
103 | Solution 104 | 105 | ```rust 106 | use std::cell::RefCell; 107 | 108 | struct Student { 109 | name: String, 110 | marks: u8, 111 | grade: RefCell, 112 | } 113 | 114 | impl Student { 115 | fn new(name: &str, marks: u8) -> Self { 116 | Student { 117 | name: name.to_owned(), 118 | marks, 119 | grade: RefCell::new('X'), 120 | } 121 | } 122 | 123 | fn print_details(&self) { 124 | let grade = match self.marks { 125 | 0..=33 => 'C', 126 | 34..=60 => 'B', 127 | _ => 'A', 128 | }; 129 | *self.grade.borrow_mut() = grade; 130 | println!( 131 | "name: {}, marks: {}, grade: {}", 132 | self.name, 133 | self.marks, 134 | self.grade.borrow() 135 | ); 136 | } 137 | } 138 | 139 | fn main() { 140 | let student = Student::new("Harry", 70); 141 | student.print_details(); 142 | } 143 | ``` 144 |
145 | -------------------------------------------------------------------------------- /src/intermediate/result-and-option.md: -------------------------------------------------------------------------------- 1 | # Result and Option 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | ## Exercises 10 | 11 | #### Option to Result 12 | 13 | ```rust,editable,compile_fail 14 | // Fix the `fetch_last` function. Do not add any other statement. 15 | 16 | fn fetch_last(list: &mut Vec) -> Option { 17 | list.pop().ok_or() 18 | } 19 | 20 | fn main() { 21 | let mut my_nums = Vec::::new(); 22 | match fetch_last(&mut my_nums) { 23 | Ok(ele) => println!("Last element: {ele}"), 24 | Err(error) => { 25 | println!("Error: {error}"); 26 | assert_eq!(error, "Empty list".to_owned()); 27 | } 28 | } 29 | } 30 | ``` 31 | 32 |
33 | Solution 34 | 35 | ```rust 36 | fn fetch_last(list: &mut Vec) -> Result { 37 | list.pop().ok_or("Empty list".to_owned()) 38 | } 39 | 40 | fn main() { 41 | let mut my_nums = Vec::::new(); 42 | match fetch_last(&mut my_nums) { 43 | Ok(ele) => println!("Last element: {ele}"), 44 | Err(error) => { 45 | println!("Error: {error}"); 46 | assert_eq!(error, "Empty list".to_owned()); 47 | } 48 | } 49 | } 50 | ``` 51 |
52 | 53 | #### Result to Option 54 | 55 | ```rust,editable,compile_fail 56 | // Use `ok` combinator to convert Result to Option. 57 | // Do not add any statements anywhere. 58 | 59 | fn add(num1: &str, num2: &str) -> Option { 60 | // TODO: only modify the 2 statements below 61 | let num1 = num1.parse::(); 62 | let num2 = num2.parse::(); 63 | num1.checked_add(num2) 64 | } 65 | 66 | fn main() { 67 | let (num1, num2) = ("4", "5"); 68 | if let Some(sum) = add("4", "5") { 69 | println!("{num1} + {num2} = {sum}"); 70 | } 71 | } 72 | ``` 73 | 74 |
75 | Solution 76 | 77 | ```rust 78 | fn add(num1: &str, num2: &str) -> Option { 79 | let num1 = num1.parse::().ok()?; 80 | let num2 = num2.parse::().ok()?; 81 | num1.checked_add(num2) 82 | } 83 | 84 | fn main() { 85 | let (num1, num2) = ("4", "5"); 86 | if let Some(sum) = add("4", "5") { 87 | println!("{num1} + {num2} = {sum}"); 88 | } 89 | } 90 | ``` 91 |
92 | -------------------------------------------------------------------------------- /src/intermediate/supertraits.md: -------------------------------------------------------------------------------- 1 | # Supertraits 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Implementing supertraits 10 | 11 | ```rust,editable,compile_fail 12 | // Make the code compile. Large should be the default size. 13 | 14 | /* 15 | Default trait is provided by standard library. 16 | Has one associated function: default() -> Self 17 | */ 18 | 19 | trait Bounded: Default { 20 | fn get_max() -> Self; 21 | fn get_min() -> Self; 22 | } 23 | 24 | enum Size { 25 | Small, 26 | Medium, 27 | Large, 28 | } 29 | 30 | impl Bounded for Size { 31 | fn get_max() -> Self { 32 | Self::Large 33 | } 34 | fn get_min() -> Self { 35 | Self::Small 36 | } 37 | } 38 | 39 | fn get_size_num(size: &Size) -> u8 { 40 | match size { 41 | Size::Small => 0, 42 | Size::Medium => 1, 43 | Size::Large => 2, 44 | } 45 | } 46 | 47 | fn main() { 48 | let my_size = Size::Large; 49 | let min_size_num = get_size_num(&Size::get_min()); 50 | let default_size_num = get_size_num(&Size::default()); 51 | let my_size_num = get_size_num(&my_size); 52 | if my_size_num == min_size_num { 53 | println!("I have the shortest size!"); 54 | } 55 | if my_size_num == default_size_num { 56 | println!("Default size suits me!") 57 | } 58 | } 59 | ``` 60 | 61 |
62 | Solution 63 | 64 | ```rust 65 | trait Bounded: Default { 66 | fn get_max() -> Self; 67 | fn get_min() -> Self; 68 | } 69 | 70 | #[derive(Default)] 71 | enum Size { 72 | Small, 73 | Medium, 74 | #[default] 75 | Large, 76 | } 77 | 78 | impl Bounded for Size { 79 | fn get_max() -> Self { 80 | Self::Large 81 | } 82 | fn get_min() -> Self { 83 | Self::Small 84 | } 85 | } 86 | 87 | fn get_size_num(size: &Size) -> u8 { 88 | match size { 89 | Size::Small => 0, 90 | Size::Medium => 1, 91 | Size::Large => 2, 92 | } 93 | } 94 | 95 | fn main() { 96 | let my_size = Size::Large; 97 | let min_size_num = get_size_num(&Size::get_min()); 98 | let default_size_num = get_size_num(&Size::default()); 99 | let my_size_num = get_size_num(&my_size); 100 | if my_size_num == min_size_num { 101 | println!("I have the shortest size!"); 102 | } 103 | if my_size_num == default_size_num { 104 | println!("Default size suits me!") 105 | } 106 | } 107 | ``` 108 |
109 | 110 | #### Multiple supertraits 111 | 112 | 113 | ```rust,editable,compile_fail 114 | // Something is missing with the definition of Comparable trait. Fix it. 115 | 116 | trait Numeric { 117 | fn convert_to_num(&self) -> u8; 118 | } 119 | 120 | trait Printable { 121 | fn convert_to_str(&self) -> String; 122 | } 123 | 124 | trait Comparable { 125 | fn print_greater(a: &Self, b: &Self) { 126 | let num1 = a.convert_to_num(); 127 | let num2 = b.convert_to_num(); 128 | if num1 > num2 { 129 | println!( 130 | "{} is greater than {}", 131 | a.convert_to_str(), 132 | b.convert_to_str() 133 | ); 134 | } else if num2 > num1 { 135 | println!( 136 | "{} is greater than {}", 137 | b.convert_to_str(), 138 | a.convert_to_str() 139 | ); 140 | } else { 141 | println!("Both sizes are {}", a.convert_to_str()); 142 | } 143 | } 144 | } 145 | 146 | enum Size { 147 | Small, 148 | Medium, 149 | Large, 150 | } 151 | 152 | impl Numeric for Size { 153 | fn convert_to_num(&self) -> u8 { 154 | match self { 155 | Self::Small => 0, 156 | Self::Medium => 1, 157 | Self::Large => 2, 158 | } 159 | } 160 | } 161 | 162 | impl Printable for Size { 163 | fn convert_to_str(&self) -> String { 164 | match self { 165 | Self::Small => "Small size".to_string(), 166 | Self::Medium => "Medium size".to_string(), 167 | Self::Large => "Large size".to_string(), 168 | } 169 | } 170 | } 171 | 172 | impl Comparable for Size {} 173 | 174 | fn main() { 175 | let (size1, size2) = (Size::Small, Size::Medium); 176 | Comparable::print_greater(&size1, &size2); 177 | } 178 | ``` 179 | 180 |
181 | Solution 182 | 183 | ```rust 184 | trait Numeric { 185 | fn convert_to_num(&self) -> u8; 186 | } 187 | 188 | trait Printable { 189 | fn convert_to_str(&self) -> String; 190 | } 191 | 192 | trait Comparable: Numeric + Printable { 193 | fn print_greater(a: &Self, b: &Self) { 194 | let num1 = a.convert_to_num(); 195 | let num2 = b.convert_to_num(); 196 | if num1 > num2 { 197 | println!( 198 | "{} is greater than {}", 199 | a.convert_to_str(), 200 | b.convert_to_str() 201 | ); 202 | } else if num2 > num1 { 203 | println!( 204 | "{} is greater than {}", 205 | b.convert_to_str(), 206 | a.convert_to_str() 207 | ); 208 | } else { 209 | println!("Both sizes are {}", a.convert_to_str()); 210 | } 211 | } 212 | } 213 | 214 | enum Size { 215 | Small, 216 | Medium, 217 | Large, 218 | } 219 | 220 | impl Numeric for Size { 221 | fn convert_to_num(&self) -> u8 { 222 | match self { 223 | Self::Small => 0, 224 | Self::Medium => 1, 225 | Self::Large => 2, 226 | } 227 | } 228 | } 229 | 230 | impl Printable for Size { 231 | fn convert_to_str(&self) -> String { 232 | match self { 233 | Self::Small => "Small size".to_string(), 234 | Self::Medium => "Medium size".to_string(), 235 | Self::Large => "Large size".to_string(), 236 | } 237 | } 238 | } 239 | 240 | impl Comparable for Size {} 241 | 242 | fn main() { 243 | let (size1, size2) = (Size::Small, Size::Medium); 244 | Comparable::print_greater(&size1, &size2); 245 | } 246 | ``` 247 |
248 | -------------------------------------------------------------------------------- /src/intermediate/thiserror.md: -------------------------------------------------------------------------------- 1 | # thiserror 2 | 3 | > Note: No official YouTube video yet, but our Rust Developer Bootcamp covers this topic! 4 | 5 | 6 | No video yet... 7 | 8 | 9 | #### Additional Resources 10 | - Error Handling In Rust - A Deep Dive 11 | 12 | ## Exercises 13 | 14 | (No exercises yet. Feel free to contribute here!) 15 | -------------------------------------------------------------------------------- /src/intermediate/trait-objects.md: -------------------------------------------------------------------------------- 1 | # Trait Objects 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Returning and passing to functions 10 | 11 | ```rust,editable,compile_fail 12 | // Make the code compile by completing the function signatures. 13 | 14 | trait Shape { 15 | fn shape(&self) -> String; 16 | } 17 | 18 | struct Triangle; 19 | 20 | struct Square; 21 | 22 | impl Shape for Triangle { 23 | fn shape(&self) -> String { 24 | "🔺".to_string() 25 | } 26 | } 27 | 28 | impl Shape for Square { 29 | fn shape(&self) -> String { 30 | "🟥".to_string() 31 | } 32 | } 33 | 34 | fn get_shape(side_count: u8) -> { 35 | match side_count { 36 | 3 => Box::new(Triangle), 37 | 4 => Box::new(Square), 38 | _ => panic!("No shape with side count available"), 39 | } 40 | } 41 | 42 | fn draw_shape(to_draw: &) { 43 | println!("{}", to_draw.shape()) 44 | } 45 | 46 | fn main() { 47 | let my_shape = get_shape(4); 48 | draw_shape(my_shape.as_ref()); 49 | } 50 | ``` 51 | 52 |
53 | Solution 54 | 55 | ```rust 56 | trait Shape { 57 | fn shape(&self) -> String; 58 | } 59 | 60 | struct Triangle; 61 | 62 | struct Square; 63 | 64 | impl Shape for Triangle { 65 | fn shape(&self) -> String { 66 | "🔺".to_string() 67 | } 68 | } 69 | 70 | impl Shape for Square { 71 | fn shape(&self) -> String { 72 | "🟥".to_string() 73 | } 74 | } 75 | 76 | fn get_shape(side_count: u8) -> Box { 77 | match side_count { 78 | 3 => Box::new(Triangle), 79 | 4 => Box::new(Square), 80 | _ => panic!("No shape with side count available"), 81 | } 82 | } 83 | 84 | fn draw_shape(to_draw: &dyn Shape) { 85 | println!("{}", to_draw.shape()) 86 | } 87 | 88 | fn main() { 89 | let my_shape = get_shape(4); 90 | draw_shape(my_shape.as_ref()); 91 | } 92 | ``` 93 |
94 | 95 | #### Trait objects vectors 96 | 97 | 98 | ```rust,editable,compile_fail 99 | // Make the code compile by annotating the type for the vector. 100 | 101 | trait Shape { 102 | fn shape(&self) -> String; 103 | fn side_count(&self) -> u8; 104 | } 105 | 106 | struct Triangle; 107 | 108 | struct Square; 109 | 110 | impl Shape for Triangle { 111 | fn shape(&self) -> String { 112 | "🔺".to_string() 113 | } 114 | fn side_count(&self) -> u8 { 115 | 3 116 | } 117 | } 118 | 119 | impl Shape for Square { 120 | fn shape(&self) -> String { 121 | "🟥".to_string() 122 | } 123 | fn side_count(&self) -> u8 { 124 | 4 125 | } 126 | } 127 | 128 | fn main() { 129 | let shape1 = Square; 130 | let shape2 = Square; 131 | let shape3 = Triangle; 132 | let shapes = vec![&shape1, &shape2, &shape3]; 133 | 134 | // fetch the first triangle and print it 135 | for shape in shapes { 136 | if shape.side_count() == 3 { 137 | println!("{}", shape.shape()); 138 | break; 139 | } 140 | } 141 | } 142 | ``` 143 | 144 |
145 | Solution 146 | 147 | ```rust 148 | trait Shape { 149 | fn shape(&self) -> String; 150 | fn side_count(&self) -> u8; 151 | } 152 | 153 | struct Triangle; 154 | 155 | struct Square; 156 | 157 | impl Shape for Triangle { 158 | fn shape(&self) -> String { 159 | "🔺".to_string() 160 | } 161 | fn side_count(&self) -> u8 { 162 | 3 163 | } 164 | } 165 | 166 | impl Shape for Square { 167 | fn shape(&self) -> String { 168 | "🟥".to_string() 169 | } 170 | fn side_count(&self) -> u8 { 171 | 4 172 | } 173 | } 174 | 175 | fn main() { 176 | let shape1 = Square; 177 | let shape2 = Square; 178 | let shape3 = Triangle; 179 | let shapes: Vec<&dyn Shape> = vec![&shape1, &shape2, &shape3]; 180 | 181 | // fetch the first triangle and print it 182 | for shape in shapes { 183 | if shape.side_count() == 3 { 184 | println!("{}", shape.shape()); 185 | break; 186 | } 187 | } 188 | } 189 | ``` 190 |
191 | -------------------------------------------------------------------------------- /src/intermediate/traits.md: -------------------------------------------------------------------------------- 1 | # Traits 2 | 3 |
4 | 5 |
6 | 7 | #### Additional Resources 8 | - Class Based OOP vs Traits 9 | 10 | 11 | ## Exercises 12 | 13 | #### Implementing traits 1 14 | 15 | ```rust,editable,compile_fail 16 | // Complete the code by addressing the TODO. 17 | 18 | trait AppendBar { 19 | fn append_bar(self) -> Self; 20 | } 21 | 22 | impl AppendBar for String { 23 | // TODO: Implement `AppendBar` for type `String`. 24 | } 25 | 26 | fn main() { 27 | let s = String::from("Foo"); 28 | let s = s.append_bar(); 29 | println!("s: {}", s); 30 | } 31 | 32 | #[cfg(test)] 33 | mod tests { 34 | use super::*; 35 | 36 | #[test] 37 | fn is_foo_bar() { 38 | assert_eq!(String::from("Foo").append_bar(), String::from("FooBar")); 39 | } 40 | 41 | #[test] 42 | fn is_bar_bar() { 43 | assert_eq!( 44 | String::from("").append_bar().append_bar(), 45 | String::from("BarBar") 46 | ); 47 | } 48 | } 49 | ``` 50 | 51 |
52 | Solution 53 | 54 | ```rust 55 | trait AppendBar { 56 | fn append_bar(self) -> Self; 57 | } 58 | 59 | impl AppendBar for String { 60 | fn append_bar(self) -> Self { 61 | format!("{self}Bar") 62 | } 63 | } 64 | 65 | fn main() { 66 | let s = String::from("Foo"); 67 | let s = s.append_bar(); 68 | println!("s: {}", s); 69 | } 70 | 71 | #[cfg(test)] 72 | mod tests { 73 | use super::*; 74 | 75 | #[test] 76 | fn is_foo_bar() { 77 | assert_eq!(String::from("Foo").append_bar(), String::from("FooBar")); 78 | } 79 | 80 | #[test] 81 | fn is_bar_bar() { 82 | assert_eq!( 83 | String::from("").append_bar().append_bar(), 84 | String::from("BarBar") 85 | ); 86 | } 87 | } 88 | ``` 89 |
90 | 91 | #### Implementing traits 2 92 | 93 | 94 | ```rust,editable,compile_fail 95 | // Complete the code by addressing the TODO. 96 | 97 | trait AppendBar { 98 | fn append_bar(self) -> Self; 99 | } 100 | 101 | // TODO: Implement trait `AppendBar` for a vector of strings. 102 | 103 | #[cfg(test)] 104 | mod tests { 105 | use super::*; 106 | 107 | #[test] 108 | fn is_vec_pop_eq_bar() { 109 | let mut foo = vec![String::from("Foo")].append_bar(); 110 | assert_eq!(foo.pop().unwrap(), String::from("Bar")); 111 | assert_eq!(foo.pop().unwrap(), String::from("Foo")); 112 | } 113 | } 114 | ``` 115 | 116 |
117 | Solution 118 | 119 | ```rust 120 | trait AppendBar { 121 | fn append_bar(self) -> Self; 122 | } 123 | 124 | impl AppendBar for Vec { 125 | fn append_bar(self) -> Self { 126 | let mut res = self; 127 | res.push(String::from("Bar")); 128 | res 129 | } 130 | } 131 | 132 | #[cfg(test)] 133 | mod tests { 134 | use super::*; 135 | 136 | #[test] 137 | fn is_vec_pop_eq_bar() { 138 | let mut foo = vec![String::from("Foo")].append_bar(); 139 | assert_eq!(foo.pop().unwrap(), String::from("Bar")); 140 | assert_eq!(foo.pop().unwrap(), String::from("Foo")); 141 | } 142 | } 143 | ``` 144 |
145 | 146 | #### Default implementations 147 | 148 | 149 | ```rust,editable,compile_fail 150 | // Fix this code by updating the Licensed trait. 151 | 152 | pub trait Licensed { 153 | fn licensing_info(&self) -> String; 154 | } 155 | 156 | struct SomeSoftware { 157 | version_number: i32, 158 | } 159 | 160 | struct OtherSoftware { 161 | version_number: String, 162 | } 163 | 164 | impl Licensed for SomeSoftware {} // Don't edit this line 165 | impl Licensed for OtherSoftware {} // Don't edit this line 166 | 167 | #[cfg(test)] 168 | mod tests { 169 | use super::*; 170 | 171 | #[test] 172 | fn is_licensing_info_the_same() { 173 | let licensing_info = String::from("Some information"); 174 | let some_software = SomeSoftware { version_number: 1 }; 175 | let other_software = OtherSoftware { 176 | version_number: "v2.0.0".to_string(), 177 | }; 178 | assert_eq!(some_software.licensing_info(), licensing_info); 179 | assert_eq!(other_software.licensing_info(), licensing_info); 180 | } 181 | } 182 | ``` 183 | 184 |
185 | Solution 186 | 187 | ```rust 188 | pub trait Licensed { 189 | fn licensing_info(&self) -> String { 190 | format!("Some information") 191 | } 192 | } 193 | 194 | struct SomeSoftware { 195 | version_number: i32, 196 | } 197 | 198 | struct OtherSoftware { 199 | version_number: String, 200 | } 201 | 202 | impl Licensed for SomeSoftware {} 203 | impl Licensed for OtherSoftware {} 204 | 205 | #[cfg(test)] 206 | mod tests { 207 | use super::*; 208 | 209 | #[test] 210 | fn is_licensing_info_the_same() { 211 | let licensing_info = String::from("Some information"); 212 | let some_software = SomeSoftware { version_number: 1 }; 213 | let other_software = OtherSoftware { 214 | version_number: "v2.0.0".to_string(), 215 | }; 216 | assert_eq!(some_software.licensing_info(), licensing_info); 217 | assert_eq!(other_software.licensing_info(), licensing_info); 218 | } 219 | } 220 | ``` 221 |
222 | 223 | #### Overriding 224 | 225 | 226 | ```rust,editable,compile_fail 227 | // Make the code execute successfully by correctly implementing Message trait for Cat type. 228 | 229 | trait Message { 230 | fn message(&self) -> String { 231 | "Default Message!".to_string() 232 | } 233 | } 234 | 235 | struct Fish; 236 | struct Cat; 237 | impl Message for Fish {} 238 | impl Message for Cat {} 239 | 240 | fn main() { 241 | let fish = Fish; 242 | let cat = Cat; 243 | assert_eq!(String::from("Default Message!"), fish.message()); 244 | assert_eq!(String::from("Meow 🐱"), cat.message()); 245 | } 246 | ``` 247 | 248 |
249 | Solution 250 | 251 | ```rust 252 | trait Message { 253 | fn message(&self) -> String { 254 | "Default Message!".to_string() 255 | } 256 | } 257 | 258 | struct Fish; 259 | struct Cat; 260 | impl Message for Fish {} 261 | impl Message for Cat { 262 | fn message(&self) -> String { 263 | "Meow 🐱".to_string() 264 | } 265 | } 266 | 267 | fn main() { 268 | let fish = Fish; 269 | let cat = Cat; 270 | assert_eq!(String::from("Default Message!"), fish.message()); 271 | assert_eq!(String::from("Meow 🐱"), cat.message()); 272 | } 273 | ``` 274 |
275 | -------------------------------------------------------------------------------- /src/intermediate/unrecoverable-errors.md: -------------------------------------------------------------------------------- 1 | # Unrecoverable Errors 2 | 3 |
4 | 5 |
6 | 7 | ## Exercises 8 | 9 | #### Panicking 10 | 11 | ```rust,editable,compile_fail 12 | // Make the program error out with appropriate message where required. 13 | 14 | fn div(a: i32, b: i32) -> i32 { 15 | if b == 0 { 16 | // TODO: panic with msg `divide by zero error` 17 | } 18 | a / b 19 | } 20 | 21 | fn main() { 22 | let _res = div(23, 0); 23 | } 24 | ``` 25 | 26 |
27 | Solution 28 | 29 | ```rust 30 | fn div(a: i32, b: i32) -> i32 { 31 | if b == 0 { 32 | panic!("divide by zero error"); 33 | } 34 | a / b 35 | } 36 | 37 | fn main() { 38 | let _res = div(23, 0); 39 | } 40 | ``` 41 |
42 | -------------------------------------------------------------------------------- /src/roadmap/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/roadmap/favicon.png -------------------------------------------------------------------------------- /src/roadmap/lgr_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/roadmap/lgr_logo.png -------------------------------------------------------------------------------- /src/start-with-tris/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/start-with-tris/favicon.png -------------------------------------------------------------------------------- /src/start-with-tris/lgr_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/start-with-tris/lgr_logo.png -------------------------------------------------------------------------------- /src/start/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/start/favicon.png -------------------------------------------------------------------------------- /src/start/lgr_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/start/lgr_logo.png -------------------------------------------------------------------------------- /src/starter-pack/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/starter-pack/favicon.png -------------------------------------------------------------------------------- /src/starter-pack/lgr_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/src/starter-pack/lgr_logo.png -------------------------------------------------------------------------------- /theme/css/general.css: -------------------------------------------------------------------------------- 1 | /* Base styles and content styles */ 2 | 3 | @import 'variables.css'; 4 | 5 | :root { 6 | /* Browser default font-size is 16px, this way 1 rem = 10px */ 7 | font-size: 62.5%; 8 | color-scheme: var(--color-scheme); 9 | } 10 | 11 | html { 12 | font-family: "Open Sans", sans-serif; 13 | color: var(--fg); 14 | background-color: var(--bg); 15 | text-size-adjust: none; 16 | -webkit-text-size-adjust: none; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | font-size: 1.6rem; 22 | overflow-x: hidden; 23 | } 24 | 25 | code { 26 | font-family: var(--mono-font) !important; 27 | font-size: var(--code-font-size); 28 | } 29 | 30 | /* make long words/inline code not x overflow */ 31 | main { 32 | overflow-wrap: break-word; 33 | } 34 | 35 | /* make wide tables scroll if they overflow */ 36 | .table-wrapper { 37 | overflow-x: auto; 38 | } 39 | 40 | /* Don't change font size in headers. */ 41 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 42 | font-size: unset; 43 | } 44 | 45 | .left { float: left; } 46 | .right { float: right; } 47 | .boring { opacity: 0.6; } 48 | .hide-boring .boring { display: none; } 49 | .hidden { display: none !important; } 50 | 51 | h2, h3 { margin-top: 2.5em; } 52 | h4, h5 { margin-top: 2em; } 53 | 54 | .header + .header h3, 55 | .header + .header h4, 56 | .header + .header h5 { 57 | margin-top: 1em; 58 | } 59 | 60 | h1:target::before, 61 | h2:target::before, 62 | h3:target::before, 63 | h4:target::before, 64 | h5:target::before, 65 | h6:target::before { 66 | display: inline-block; 67 | content: "»"; 68 | margin-left: -30px; 69 | width: 30px; 70 | } 71 | 72 | /* This is broken on Safari as of version 14, but is fixed 73 | in Safari Technology Preview 117 which I think will be Safari 14.2. 74 | https://bugs.webkit.org/show_bug.cgi?id=218076 75 | */ 76 | :target { 77 | scroll-margin-top: calc(var(--menu-bar-height) + 0.5em); 78 | } 79 | 80 | .page { 81 | outline: 0; 82 | padding: 0 var(--page-padding); 83 | margin-top: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */ 84 | } 85 | .page-wrapper { 86 | box-sizing: border-box; 87 | } 88 | .js:not(.sidebar-resizing) .page-wrapper { 89 | transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */ 90 | } 91 | 92 | .content { 93 | overflow-y: auto; 94 | padding: 0 5px 50px 5px; 95 | } 96 | .content main { 97 | margin-left: auto; 98 | margin-right: auto; 99 | max-width: var(--content-max-width); 100 | } 101 | .content p { line-height: 1.45em; } 102 | .content ol { line-height: 1.45em; } 103 | .content ul { line-height: 1.45em; } 104 | .content a { text-decoration: none; } 105 | .content a:hover { text-decoration: underline; } 106 | .content img, .content video { max-width: 100%; } 107 | .content .header:link, 108 | .content .header:visited { 109 | color: var(--fg); 110 | } 111 | .content .header:link, 112 | .content .header:visited:hover { 113 | text-decoration: none; 114 | } 115 | 116 | table { 117 | margin: 0 auto; 118 | border-collapse: collapse; 119 | } 120 | table td { 121 | padding: 3px 20px; 122 | border: 1px var(--table-border-color) solid; 123 | } 124 | table thead { 125 | background: var(--table-header-bg); 126 | } 127 | table thead td { 128 | font-weight: 700; 129 | border: none; 130 | } 131 | table thead th { 132 | padding: 3px 20px; 133 | } 134 | table thead tr { 135 | border: 1px var(--table-header-bg) solid; 136 | } 137 | /* Alternate background colors for rows */ 138 | table tbody tr:nth-child(2n) { 139 | background: var(--table-alternate-bg); 140 | } 141 | 142 | 143 | blockquote { 144 | margin: 20px 0; 145 | padding: 0 20px; 146 | color: var(--fg); 147 | background-color: var(--quote-bg); 148 | border-top: .1em solid var(--quote-border); 149 | border-bottom: .1em solid var(--quote-border); 150 | } 151 | 152 | kbd { 153 | background-color: var(--table-border-color); 154 | border-radius: 4px; 155 | border: solid 1px var(--theme-popup-border); 156 | box-shadow: inset 0 -1px 0 var(--theme-hover); 157 | display: inline-block; 158 | font-size: var(--code-font-size); 159 | font-family: var(--mono-font); 160 | line-height: 10px; 161 | padding: 4px 5px; 162 | vertical-align: middle; 163 | } 164 | 165 | :not(.footnote-definition) + .footnote-definition, 166 | .footnote-definition + :not(.footnote-definition) { 167 | margin-top: 2em; 168 | } 169 | .footnote-definition { 170 | font-size: 0.9em; 171 | margin: 0.5em 0; 172 | } 173 | .footnote-definition p { 174 | display: inline; 175 | } 176 | 177 | .tooltiptext { 178 | position: absolute; 179 | visibility: hidden; 180 | color: #fff; 181 | background-color: #333; 182 | transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */ 183 | left: -8px; /* Half of the width of the icon */ 184 | top: -35px; 185 | font-size: 0.8em; 186 | text-align: center; 187 | border-radius: 6px; 188 | padding: 5px 8px; 189 | margin: 5px; 190 | z-index: 1000; 191 | } 192 | .tooltipped .tooltiptext { 193 | visibility: visible; 194 | } 195 | 196 | .chapter li.part-title { 197 | color: var(--sidebar-fg); 198 | margin: 5px 0px; 199 | font-weight: bold; 200 | } 201 | 202 | .result-no-output { 203 | font-style: italic; 204 | } 205 | 206 | .youtube-video { 207 | aspect-ratio: 16 / 9; 208 | width: 100%; 209 | } -------------------------------------------------------------------------------- /theme/css/print.css: -------------------------------------------------------------------------------- 1 | 2 | #sidebar, 3 | #menu-bar, 4 | .nav-chapters, 5 | .mobile-nav-chapters { 6 | display: none; 7 | } 8 | 9 | #page-wrapper.page-wrapper { 10 | transform: none; 11 | margin-left: 0px; 12 | overflow-y: initial; 13 | } 14 | 15 | #content { 16 | max-width: none; 17 | margin: 0; 18 | padding: 0; 19 | } 20 | 21 | .page { 22 | overflow-y: initial; 23 | } 24 | 25 | pre > .buttons { 26 | z-index: 2; 27 | } 28 | 29 | a, a:visited, a:active, a:hover { 30 | color: #4183c4; 31 | text-decoration: none; 32 | } 33 | 34 | h1, h2, h3, h4, h5, h6 { 35 | page-break-inside: avoid; 36 | page-break-after: avoid; 37 | } 38 | 39 | pre, code { 40 | page-break-inside: avoid; 41 | white-space: pre-wrap; 42 | } 43 | 44 | .fa { 45 | display: none !important; 46 | } 47 | -------------------------------------------------------------------------------- /theme/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/favicon.png -------------------------------------------------------------------------------- /theme/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /theme/fonts/SOURCE-CODE-PRO-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /theme/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | /* Open Sans is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 */ 2 | /* Source Code Pro is under the Open Font License. See https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL */ 3 | 4 | /* open-sans-300 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 5 | @font-face { 6 | font-family: 'Open Sans'; 7 | font-style: normal; 8 | font-weight: 300; 9 | src: local('Open Sans Light'), local('OpenSans-Light'), 10 | url('open-sans-v17-all-charsets-300.woff2') format('woff2'); 11 | } 12 | 13 | /* open-sans-300italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 14 | @font-face { 15 | font-family: 'Open Sans'; 16 | font-style: italic; 17 | font-weight: 300; 18 | src: local('Open Sans Light Italic'), local('OpenSans-LightItalic'), 19 | url('open-sans-v17-all-charsets-300italic.woff2') format('woff2'); 20 | } 21 | 22 | /* open-sans-regular - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 23 | @font-face { 24 | font-family: 'Open Sans'; 25 | font-style: normal; 26 | font-weight: 400; 27 | src: local('Open Sans Regular'), local('OpenSans-Regular'), 28 | url('open-sans-v17-all-charsets-regular.woff2') format('woff2'); 29 | } 30 | 31 | /* open-sans-italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 32 | @font-face { 33 | font-family: 'Open Sans'; 34 | font-style: italic; 35 | font-weight: 400; 36 | src: local('Open Sans Italic'), local('OpenSans-Italic'), 37 | url('open-sans-v17-all-charsets-italic.woff2') format('woff2'); 38 | } 39 | 40 | /* open-sans-600 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 41 | @font-face { 42 | font-family: 'Open Sans'; 43 | font-style: normal; 44 | font-weight: 600; 45 | src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), 46 | url('open-sans-v17-all-charsets-600.woff2') format('woff2'); 47 | } 48 | 49 | /* open-sans-600italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 50 | @font-face { 51 | font-family: 'Open Sans'; 52 | font-style: italic; 53 | font-weight: 600; 54 | src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), 55 | url('open-sans-v17-all-charsets-600italic.woff2') format('woff2'); 56 | } 57 | 58 | /* open-sans-700 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 59 | @font-face { 60 | font-family: 'Open Sans'; 61 | font-style: normal; 62 | font-weight: 700; 63 | src: local('Open Sans Bold'), local('OpenSans-Bold'), 64 | url('open-sans-v17-all-charsets-700.woff2') format('woff2'); 65 | } 66 | 67 | /* open-sans-700italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 68 | @font-face { 69 | font-family: 'Open Sans'; 70 | font-style: italic; 71 | font-weight: 700; 72 | src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), 73 | url('open-sans-v17-all-charsets-700italic.woff2') format('woff2'); 74 | } 75 | 76 | /* open-sans-800 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 77 | @font-face { 78 | font-family: 'Open Sans'; 79 | font-style: normal; 80 | font-weight: 800; 81 | src: local('Open Sans ExtraBold'), local('OpenSans-ExtraBold'), 82 | url('open-sans-v17-all-charsets-800.woff2') format('woff2'); 83 | } 84 | 85 | /* open-sans-800italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 86 | @font-face { 87 | font-family: 'Open Sans'; 88 | font-style: italic; 89 | font-weight: 800; 90 | src: local('Open Sans ExtraBold Italic'), local('OpenSans-ExtraBoldItalic'), 91 | url('open-sans-v17-all-charsets-800italic.woff2') format('woff2'); 92 | } 93 | 94 | /* source-code-pro-500 - latin_vietnamese_latin-ext_greek_cyrillic-ext_cyrillic */ 95 | @font-face { 96 | font-family: 'Source Code Pro'; 97 | font-style: normal; 98 | font-weight: 500; 99 | src: url('source-code-pro-v11-all-charsets-500.woff2') format('woff2'); 100 | } 101 | -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-300.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-300italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-600.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-600italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-600italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-700.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-700italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-800.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-800italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-800italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-italic.woff2 -------------------------------------------------------------------------------- /theme/fonts/open-sans-v17-all-charsets-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/open-sans-v17-all-charsets-regular.woff2 -------------------------------------------------------------------------------- /theme/fonts/source-code-pro-v11-all-charsets-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letsgetrusty/learn/8159c9f0eccbd2be97a2ec541266e99b1c3b3cec/theme/fonts/source-code-pro-v11-all-charsets-500.woff2 -------------------------------------------------------------------------------- /theme/head.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /theme/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | * An increased contrast highlighting scheme loosely based on the 3 | * "Base16 Atelier Dune Light" theme by Bram de Haan 4 | * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) 5 | * Original Base16 color scheme by Chris Kempson 6 | * (https://github.com/chriskempson/base16) 7 | */ 8 | 9 | /* Comment */ 10 | .hljs-comment, 11 | .hljs-quote { 12 | color: #575757; 13 | } 14 | 15 | /* Red */ 16 | .hljs-variable, 17 | .hljs-template-variable, 18 | .hljs-attribute, 19 | .hljs-tag, 20 | .hljs-name, 21 | .hljs-regexp, 22 | .hljs-link, 23 | .hljs-name, 24 | .hljs-selector-id, 25 | .hljs-selector-class { 26 | color: #d70025; 27 | } 28 | 29 | /* Orange */ 30 | .hljs-number, 31 | .hljs-meta, 32 | .hljs-built_in, 33 | .hljs-builtin-name, 34 | .hljs-literal, 35 | .hljs-type, 36 | .hljs-params { 37 | color: #b21e00; 38 | } 39 | 40 | /* Green */ 41 | .hljs-string, 42 | .hljs-symbol, 43 | .hljs-bullet { 44 | color: #008200; 45 | } 46 | 47 | /* Blue */ 48 | .hljs-title, 49 | .hljs-section { 50 | color: #0030f2; 51 | } 52 | 53 | /* Purple */ 54 | .hljs-keyword, 55 | .hljs-selector-tag { 56 | color: #9d00ec; 57 | } 58 | 59 | .hljs { 60 | display: block; 61 | overflow-x: auto; 62 | background: #f6f7f6; 63 | color: #000; 64 | } 65 | 66 | .hljs-emphasis { 67 | font-style: italic; 68 | } 69 | 70 | .hljs-strong { 71 | font-weight: bold; 72 | } 73 | 74 | .hljs-addition { 75 | color: #22863a; 76 | background-color: #f0fff4; 77 | } 78 | 79 | .hljs-deletion { 80 | color: #b31d28; 81 | background-color: #ffeef0; 82 | } 83 | --------------------------------------------------------------------------------