├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── feature_request.md └── workflows │ └── CI.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Module00 ├── Cargo.toml ├── Readme.md └── src │ ├── cli.rs │ └── main.rs ├── Module01 ├── Todo │ ├── Cargo.toml │ ├── Readme.md │ └── src │ │ └── main.rs ├── error │ ├── Cargo.toml │ ├── Readme.md │ └── src │ │ └── main.rs └── simple_calc │ ├── Cargo.toml │ ├── EdgeCaseFix.md │ ├── Readme.md │ └── src │ └── main.rs ├── Module02 ├── Auth │ ├── .env │ ├── Cargo.toml │ └── src │ │ ├── auth.rs │ │ ├── errors.rs │ │ ├── jwt.rs │ │ ├── main.rs │ │ ├── model.rs │ │ └── routes.rs ├── Chatbot │ ├── .idea │ │ ├── Chatbot.iml │ │ ├── modules.xml │ │ └── vcs.xml │ ├── Cargo.toml │ ├── Readme.md │ ├── chatbot_responses.json │ └── src │ │ └── main.rs ├── Web1 │ ├── Cargo.toml │ ├── Readme.md │ └── src │ │ ├── 404.html │ │ ├── main.rs │ │ └── test.html ├── Web2 │ ├── 404.html │ ├── Cargo.toml │ ├── Readme.md │ ├── hello.html │ ├── image.png │ └── src │ │ └── main.rs ├── auth_server │ ├── Cargo.toml │ ├── Readme │ ├── image.png │ └── src │ │ ├── handlers.rs │ │ ├── jwt.rs │ │ └── main.rs └── gitCheck │ ├── .idea │ └── gitCheck.iml │ ├── Cargo.toml │ ├── Readme.md │ └── src │ ├── handlers.rs │ ├── main.rs │ └── model.rs ├── Module03 ├── data_vault │ ├── Cargo.toml │ └── src │ │ ├── colors.rs │ │ └── main.rs └── data_vault_exx │ ├── Cargo.toml │ ├── Explanations.md │ └── src │ └── main.rs ├── Module05 ├── Readme.md ├── cachecomponent │ ├── Cargo.toml │ ├── Readme.md │ └── src │ │ ├── cache_component.rs │ │ └── main.rs └── consolelog │ ├── Cargo.toml │ ├── Readme.md │ └── src │ ├── main.rs │ └── utility.rs ├── Module07 ├── btreemap │ └── src │ │ ├── btree.rs │ │ ├── config.rs │ │ ├── lib.rs │ │ ├── main.rs │ │ ├── node.rs │ │ ├── tests │ │ └── mod.rs │ │ └── util.rs └── valuetree │ ├── Cargo.toml │ ├── Readme.md │ └── src │ ├── ast.rs │ ├── btree.rs │ ├── config.rs │ ├── lib.rs │ ├── main.rs │ ├── node.rs │ └── util.rs ├── Module08 └── banking │ ├── .env │ ├── Cargo.toml │ └── src │ ├── config.rs │ ├── db │ ├── account.rs │ ├── mod.rs │ └── transaction.rs │ ├── errors.rs │ ├── main.rs │ ├── models │ ├── account.rs │ └── transaction.rs │ ├── routes │ ├── account.rs │ └── mod.rs │ └── services │ └── account_service.rs ├── Module09 ├── .env ├── AmortizedCostAdvanced.mp4 ├── Dockerfile ├── media │ ├── texts │ │ ├── 02b8865db121f075.svg │ │ ├── 067e47c63ddd3127.svg │ │ ├── 0e365c31373d440d.svg │ │ ├── 38a2fbd3333e2b51.svg │ │ ├── 49d193e5ee8199d0.svg │ │ ├── 64cb41458ffa7112.svg │ │ ├── 662e9dce0637f2d9.svg │ │ ├── 7050901ea9077f94.svg │ │ ├── 7d27bc5c721153fd.svg │ │ ├── 7f33a0ccd2a76713.svg │ │ ├── 93e42542bc1afd94.svg │ │ ├── 9f7a0ce90cc7ac5d.svg │ │ ├── a4b94c96deb9ef21.svg │ │ ├── b220958df00f031f.svg │ │ ├── ba31d1ef370d0d29.svg │ │ ├── c8f3937063f8cac9.svg │ │ ├── cf9e771d6fd9ce3d.svg │ │ ├── d8db5015a5ea3018.svg │ │ ├── de46eb1ab737a73e.svg │ │ ├── e320fd24d02cc31d.svg │ │ └── e8497c8cd8465f40.svg │ └── videos │ │ └── a │ │ └── 1080p60 │ │ ├── AmortizedCostAdvanced.mp4 │ │ ├── AmortizedCostRefined.mp4 │ │ └── partial_movie_files │ │ ├── AmortizedCostAdvanced │ │ ├── 3040924799_1000529315_2516712950.mp4 │ │ ├── 3040924799_1342615424_1257065805.mp4 │ │ ├── 3040924799_1570874046_2323842036.mp4 │ │ ├── 3040924799_1600594787_3800533162.mp4 │ │ ├── 3040924799_1644675564_718189330.mp4 │ │ ├── 3040924799_189541869_3613570100.mp4 │ │ ├── 3040924799_2215745579_163205416.mp4 │ │ ├── 3040924799_2595125285_1304643872.mp4 │ │ ├── 3040924799_2646125366_258853677.mp4 │ │ ├── 3040924799_2793458955_1425216704.mp4 │ │ ├── 3040924799_2876327323_2864915012.mp4 │ │ ├── 3040924799_2894392248_1180209270.mp4 │ │ ├── 3040924799_2919340033_3490668070.mp4 │ │ ├── 3040924799_3068668600_921797842.mp4 │ │ ├── 3040924799_320231996_1535447459.mp4 │ │ ├── 3040924799_3891874688_4099317236.mp4 │ │ ├── 3040924799_4129878736_1584757070.mp4 │ │ ├── 3040924799_4150750034_2345848816.mp4 │ │ ├── 3040924799_533474223_1796147278.mp4 │ │ ├── 3040924799_556781075_2280001411.mp4 │ │ ├── 3040924799_66812978_1041101844.mp4 │ │ ├── 3040924799_737070546_2881160873.mp4 │ │ ├── 3040924799_784179552_1872585525.mp4 │ │ ├── 3040924799_800706528_1010095989.mp4 │ │ ├── 3529212410_1760247645_2142691362.mp4 │ │ └── partial_movie_file_list.txt │ │ └── AmortizedCostRefined │ │ ├── 3040924799_1047548945_2225697842.mp4 │ │ ├── 3040924799_1115191695_1609054424.mp4 │ │ ├── 3040924799_1178597654_3936940076.mp4 │ │ ├── 3040924799_1187074030_921797842.mp4 │ │ ├── 3040924799_163472557_3934050777.mp4 │ │ ├── 3040924799_1840646158_4000590238.mp4 │ │ ├── 3040924799_1912175879_1803578682.mp4 │ │ ├── 3040924799_1976618423_1455043070.mp4 │ │ ├── 3040924799_2023230840_3095364569.mp4 │ │ ├── 3040924799_213720279_742841984.mp4 │ │ ├── 3040924799_2158552800_2215161034.mp4 │ │ ├── 3040924799_2215745579_902315314.mp4 │ │ ├── 3040924799_2876327323_2864915012.mp4 │ │ ├── 3040924799_2919340033_612882166.mp4 │ │ ├── 3040924799_3054095095_567640343.mp4 │ │ ├── 3040924799_3388956070_3416479938.mp4 │ │ ├── 3040924799_348530885_3153408772.mp4 │ │ ├── 3040924799_3574089711_658649037.mp4 │ │ ├── 3040924799_3795840722_1437417951.mp4 │ │ ├── 3040924799_3891874688_1846330621.mp4 │ │ ├── 3040924799_4259308663_658649037.mp4 │ │ ├── 3040924799_737070546_1068583945.mp4 │ │ ├── 3040924799_784179552_2918718511.mp4 │ │ ├── 3040924799_831676087_897214138.mp4 │ │ ├── 3040924799_933458367_4063910195.mp4 │ │ ├── 3040924799_998441320_2982120678.mp4 │ │ ├── 3529212410_3514323760_2142691362.mp4 │ │ └── partial_movie_file_list.txt ├── rust_backend │ ├── Cargo.toml │ ├── src │ │ ├── 'db │ │ │ └── create_users_table.sql │ │ ├── config.rs │ │ ├── errors.rs │ │ ├── handlers │ │ │ └── auth.rs │ │ ├── main.rs │ │ ├── middleware │ │ │ └── auth.rs │ │ ├── models │ │ │ └── user.rs │ │ └── nginx │ │ │ └── backend.conf │ └── tests │ │ ├── auth.rs │ │ └── healthcheck.rs └── tokenize │ ├── Cargo.toml │ └── src │ └── main.rs ├── Module10 ├── generic │ ├── Cargo.toml │ └── src │ │ ├── advanced_trait.rs │ │ ├── associated_types.rs │ │ ├── higher_kind.rs │ │ ├── main.rs │ │ ├── operator_overloading.rs │ │ ├── sized_and_unsized.rs │ │ └── where_syntax.rs └── performanceCheck │ ├── Cargo.toml │ ├── Readme.md │ ├── benches │ ├── fibonacci_benchmark.rs │ └── sort_bench.rs │ └── src │ └── lib.rs ├── README.md ├── SECURITY.md ├── clean.sh └── colors.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: mdabir1203 # Replace with your GitHub username 2 | patreon: uknowWhoAb1r 3 | medium: md.abir1203 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - Main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | clean: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | 18 | - name: Set up Rust 19 | uses: actions-rs/toolchain@v1 20 | with: 21 | toolchain: stable 22 | 23 | - name: Make clean script executable 24 | run: chmod +x clean.sh 25 | 26 | - name: Run clean script 27 | run: ./clean.sh 28 | 29 | build-and-test: 30 | needs: clean 31 | runs-on: ubuntu-latest 32 | strategy: 33 | matrix: 34 | module: 35 | - Module00 36 | - Module01/error 37 | - Module01/simple_calc 38 | - Module01/Todo 39 | # - Module02 40 | - Module02/Chatbot 41 | - Module02/gitCheck 42 | - Module02/Web1 43 | - Module02/Web2 44 | - Module02/Auth 45 | - Module02/auth_server 46 | # - Module03 47 | - Module03/data_vault 48 | - Module03/data_vault_exx 49 | # - Module05 50 | - Module03/cachecomponent 51 | - Module03/consolelog 52 | # Module 07 53 | - Module07/btreemap/src 54 | - Module07/valuetree 55 | # Module08 56 | - Module08/banking 57 | # Module09 58 | - Module09/rust_backend 59 | - Module09/tokenize 60 | # Module10 61 | - Module10/generic 62 | - Module10/performanceCheck 63 | 64 | 65 | steps: 66 | - name: Checkout code 67 | uses: actions/checkout@v2 68 | 69 | - name: Set up Rust 70 | uses: actions-rs/toolchain@v1 71 | with: 72 | toolchain: stable 73 | 74 | - name: Build and test 75 | working-directory: ${{ matrix.module }} 76 | run: | 77 | cargo build --verbose 78 | cargo test --verbose 79 | 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore build artifacts 2 | target/ 3 | 4 | # Ignore IDE-specific files 5 | .idea/ 6 | 7 | # Ignore generated files 8 | Cargo.lock 9 | 10 | # Ignore editor-specific files 11 | *.iml 12 | 13 | # Ignore editor-specific files 14 | .vscode/ 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Mohammad Abir Abbas 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 | -------------------------------------------------------------------------------- /Module00/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "Rust_Principles" 3 | version = "0.1.0" 4 | edition = "2021" 5 | -------------------------------------------------------------------------------- /Module00/Readme.md: -------------------------------------------------------------------------------- 1 | Standard Cli Program in Rust -------------------------------------------------------------------------------- /Module00/src/cli.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Write}; 2 | 3 | /// Greets the user with a friendly message. 4 | /// 5 | /// This function prints a "Welcome to the CLI app" message to the standard output (typically the console). 6 | /// It's designed to demonstrate a simple greeting, potentially as part of a larger CLI application. 7 | /// The function returns a `Result` type, which is a common Rust pattern for error handling. 8 | /// 9 | /// # Returns 10 | /// 11 | /// - `Ok(())`: Indicates the greeting was displayed successfully without any errors. 12 | /// - `Err(e)`: An error occurred during the operation. The error is wrapped in the `Result` type, 13 | /// allowing the caller to handle it appropriately. This is typically due to issues with I/O operations, 14 | /// such as problems writing to the standard output. 15 | pub fn greet_user() -> io::Result<()> { 16 | println!("Welcome to the CLI app"); 17 | io::stdout().flush()?; 18 | Ok(()) 19 | } 20 | 21 | #[cfg(test)] 22 | /// Test suite for the `greet_user` function. 23 | mod tests { 24 | use super::*; 25 | 26 | /// Test case to verify that the `greet_user` function returns a result without any errors. 27 | #[test] 28 | fn test_greet_user() { 29 | assert!(greet_user().is_ok()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Module00/src/main.rs: -------------------------------------------------------------------------------- 1 | mod cli; 2 | 3 | /// Greets the user with a friendly message. 4 | /// 5 | /// This function prints a "Hello, user!" message to the standard output (typically the console). 6 | /// It's designed to demonstrate a simple greeting, potentially as part of a larger CLI application. 7 | /// The function returns a `Result` type, which is a common Rust pattern for error handling. 8 | /// 9 | /// # Returns 10 | /// 11 | /// - `Ok(())`: Indicates the greeting was displayed successfully without any errors. 12 | /// - `Err(e)`: An error occurred during the operation. The error is wrapped in the `Result` type, 13 | /// allowing the caller to handle it appropriately. This is typically due to issues with I/O operations, 14 | /// such as problems writing to the standard output. 15 | 16 | fn greet_user() -> std::io::Result<()> { 17 | // Hypothetical greeting logic, possibly involving I/O operations 18 | println!("Hello, misfits and crooks!"); 19 | // If an I/O operation was involved, handle potential errors 20 | // For demonstration, assume success: 21 | Ok(()) 22 | } 23 | 24 | 25 | fn main() { 26 | match cli::greet_user() { 27 | Ok(_) => println!("Greeting displayed successfully."), 28 | Err(e) => eprintln!("Failed to display greeting: {}", e), 29 | } 30 | 31 | match greet_user() { 32 | Ok(_) => println!("Greeting displayed successfully."), 33 | Err(e) => eprintln!("Failed to display greeting: {}", e), 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | 41 | #[test] 42 | fn test_greet_user() { 43 | assert!(greet_user().is_ok()); 44 | } 45 | } -------------------------------------------------------------------------------- /Module01/Todo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "Todo" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /Module01/Todo/Readme.md: -------------------------------------------------------------------------------- 1 | # Simple Todo CLI Application 2 | 3 | This Rust application is a straightforward command-line interface (CLI) for managing a todo list. It allows users to add todo items, display all todo items, mark items as completed, and exit the program. This README provides an overview of the application's functionality, including a breakdown of its syntax and core principles. 4 | 5 | ## Features 6 | 7 | Add todo items with a title. 8 | Display all todo items with their status (completed or not). 9 | Mark todo items as completed. 10 | Exit the application. 11 | 12 | ## How It Works 13 | 14 | ### Main Components 15 | 16 | Structs: Defines the structure of a todo item. 17 | Functions: Implements the logic for adding, displaying, and marking todo items as completed. 18 | Loop: Keeps the application running until the user decides to exit. 19 | Syntax Breakdown 20 | Struct Definition 21 | 22 | ### struct TodoItem: Defines a new structure named TodoItem with three fields: id, title, and completed 23 | 24 | `id:` A unique identifier for each todo item (u32). 25 | `title:` The title or description of the todo item (String). 26 | `completed:` A boolean flag indicating whether the item is completed (bool). 27 | Function to Add Todo Items 28 | `fn add_todo_item:` A function that takes an id and title as arguments and returns a new TodoItem. 29 | `TodoItem { id, title, completed: false }:` Creates a new TodoItem instance with the specified id and title, and sets completed to false. 30 | 31 | ### Function to Display Todo Items 32 | 33 | Iterates over each TodoItem in the provided vector and prints its details. 34 | 35 | ### Function to Mark Todo Items as Completed 36 | 37 | Iterates over the vector of TodoItems and marks the item with the specified id as completed. 38 | 39 | ## Reading User Input 40 | 41 | Prompts the user for input, flushes the standard output to ensure the prompt is displayed, then reads a line of input from the user. 42 | 43 | ### Main Loop 44 | 45 | The main loop of the application displays a menu of options, reads the user's choice, and performs the corresponding action. 46 | Running the Application 47 | To run this application, you need Rust and Cargo installed on your machine. Clone the repository, navigate to the project directory in your terminal, and run cargo run. 48 | 49 | ## Conclusion 50 | 51 | This simple Rust CLI application demonstrates basic Rust syntax and principles, including struct definitions, loops, user input handling, and vector manipulation. It serves as a practical introduction to building CLI applications with Rust. 52 | -------------------------------------------------------------------------------- /Module01/Todo/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Write}; 2 | use std::num::ParseIntError; 3 | 4 | #[derive(Debug)] 5 | struct TodoItem { 6 | id: u32, 7 | title: String, 8 | completed: bool, 9 | } 10 | 11 | impl TodoItem { 12 | fn new(id: u32, title: String) -> Self { 13 | TodoItem { 14 | id, 15 | title, 16 | completed: false, 17 | } 18 | } 19 | 20 | fn mark_as_completed(&mut self) { 21 | self.completed = true; 22 | } 23 | } 24 | 25 | fn display_todo_items(items: &[TodoItem]) { 26 | for item in items { 27 | let completed_status = if item.completed { "x" } else { " " }; 28 | println!("{}: {} [{}]", item.id, item.title, completed_status); 29 | } 30 | } 31 | 32 | fn read_input(prompt: &str) -> io::Result { 33 | print!("{}", prompt); 34 | io::stdout().flush()?; 35 | let mut input = String::new(); 36 | io::stdin().read_line(&mut input)?; 37 | Ok(input.trim().to_string()) 38 | } 39 | 40 | fn parse_u32(input: &str) -> Result { 41 | input.parse::() 42 | } 43 | 44 | /// Handles the "Add Todo Item" functionality. 45 | fn add_todo_item(todo_items: &mut Vec) -> io::Result<()> { 46 | let title = read_input("Enter the title: ")?; 47 | let id = todo_items.len() as u32 + 1; 48 | todo_items.push(TodoItem::new(id, title)); 49 | println!("Todo item added successfully!"); 50 | Ok(()) 51 | } 52 | 53 | /// Handles the "Display Todo Items" functionality. 54 | fn display_todo_items_handler(todo_items: &Vec) { 55 | if todo_items.is_empty() { 56 | println!("No todo items to display."); 57 | } else { 58 | display_todo_items(todo_items); 59 | } 60 | } 61 | 62 | /// Handles the "Mark Item as Completed" functionality. 63 | fn mark_item_as_completed(todo_items: &mut Vec) -> io::Result<()> { 64 | if todo_items.is_empty() { 65 | println!("No todo items to mark as completed."); 66 | return Ok(()); 67 | } 68 | 69 | let id_input = read_input("Enter the ID of the item to mark as completed: ")?; 70 | match parse_u32(&id_input) { 71 | Ok(id) => { 72 | if let Some(item) = todo_items.iter_mut().find(|item| item.id == id) { 73 | item.mark_as_completed(); 74 | println!("Item marked as completed successfully!"); 75 | } else { 76 | println!("Item with ID {} not found", id); 77 | } 78 | } 79 | Err(_) => println!("Invalid ID. Please enter a valid number."), 80 | } 81 | Ok(()) 82 | } 83 | 84 | fn main() -> io::Result<()> { 85 | let mut todo_items = Vec::new(); 86 | 87 | loop { 88 | println!("\n1. Add Todo Item"); 89 | println!("2. Display Todo Items"); 90 | println!("3. Mark Item as Completed"); 91 | println!("4. Exit"); 92 | 93 | let choice = read_input("Enter your choice: ")?; 94 | 95 | match choice.as_str() { 96 | "1" => add_todo_item(&mut todo_items)?, 97 | "2" => display_todo_items_handler(&todo_items), 98 | "3" => mark_item_as_completed(&mut todo_items)?, 99 | "4" => { 100 | println!("Exiting the program. Goodbye!"); 101 | break; 102 | } 103 | _ => println!("Invalid choice! Please enter a number between 1 and 4."), 104 | } 105 | } 106 | 107 | Ok(()) 108 | } 109 | 110 | #[cfg(test)] 111 | mod tests { 112 | use super::*; 113 | 114 | #[test] 115 | fn test_todo_item_new() { 116 | let item = TodoItem::new(1, "Buy groceries".to_string()); 117 | assert_eq!(item.id, 1); 118 | assert_eq!(item.title, "Buy groceries"); 119 | assert_eq!(item.completed, false); 120 | } 121 | 122 | #[test] 123 | fn test_todo_item_mark_as_completed() { 124 | let mut item = TodoItem::new(1, "Buy groceries".to_string()); 125 | item.mark_as_completed(); 126 | assert_eq!(item.completed, true); 127 | } 128 | 129 | #[test] 130 | fn test_display_todo_items_empty() { 131 | let items: Vec = Vec::new(); 132 | display_todo_items(&items); 133 | } 134 | 135 | #[test] 136 | fn test_display_todo_items() { 137 | let items = vec![ 138 | TodoItem::new(1, "Buy groceries".to_string()), 139 | TodoItem::new(2, "Walk the dog".to_string()), 140 | ]; 141 | display_todo_items(&items); 142 | } 143 | 144 | #[test] 145 | fn test_parse_u32() { 146 | assert_eq!(parse_u32("42").unwrap(), 42); 147 | assert!(parse_u32("abc").is_err()); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Module01/error/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "error" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.8.0" 8 | colored = "2.1.0" -------------------------------------------------------------------------------- /Module01/error/Readme.md: -------------------------------------------------------------------------------- 1 | # Number Guessing Game 2 | 3 | This is a simple number guessing game written in Rust. The program generates a random number between 1 and 100, and the user has to guess the number. The program provides feedback on whether the guess is too high, too low, or correct. 4 | 5 | ## Installation 6 | 7 | 1. Ensure you have [Rust](https://www.rust-lang.org/tools/install) installed on your machine. 8 | 9 | 2. Clone this repository: 10 | 11 | ```sh 12 | git clone https://github.com/yourusername/number-guessing-game.git 13 | ``` 14 | 15 | 3. Navigate to the project directory: 16 | 17 | ```sh 18 | cd number-guessing-game 19 | ``` 20 | 21 | 4. Build the project: 22 | 23 | ```sh 24 | cargo build 25 | ``` 26 | 27 | ## Usage 28 | 29 | To run the game, use the following command: 30 | 31 | ```sh 32 | cargo run 33 | ``` 34 | 35 | Follow the on-screen prompts to guess the number and receive feedback. 36 | 37 | ## Features 38 | 39 | - Random number generation: The program generates a random number between 1 and 100. 40 | - User input: Prompts the user to enter a guess. 41 | - Feedback: Provides feedback on whether the guess is too high, too low, or correct. 42 | - Loop: Continues until the user guesses the correct number. 43 | 44 | ## How It Works 45 | 46 | ### Random Number Generation 47 | 48 | The program uses the `rand` crate to generate a random number between 1 and 100. 49 | 50 | ### User Input 51 | 52 | The program reads user input from the command line using the `std::io` library. 53 | 54 | ### Feedback 55 | 56 | After the user enters a guess, the program compares it to the randomly generated number and provides feedback on whether the guess is too high, too low, or correct. 57 | 58 | ### Main Loop 59 | 60 | The game continues in a loop until the user guesses the correct number. It prompts the user for input, checks the guess, and provides feedback accordingly. 61 | 62 | ## Conclusion 63 | 64 | The Number Guessing Game is a fun and interactive way to practice Rust programming. It demonstrates basic concepts such as random number generation, user input handling, conditional logic, and loops. Feel free to modify and extend the game to add new features or improve the user experience. Happy guessing! 65 | 66 | ## License 67 | 68 | This project is licensed under the terms of the MIT license. See the [MIT](https://opensource.org/licenses/MIT) license for more information. 69 | -------------------------------------------------------------------------------- /Module01/error/src/main.rs: -------------------------------------------------------------------------------- 1 | use colored::*; // Import the colored crate 2 | use rand::Rng; 3 | use std::io::{self}; 4 | 5 | /// Represents the possible outcomes of a guess in the number guessing game. 6 | #[derive(Debug, PartialEq)] 7 | enum GuessResult { 8 | TooSmall, 9 | TooBig, 10 | Correct, 11 | } 12 | 13 | /// Gets a guess from the user and returns it as a `u32`. 14 | /// 15 | /// # Returns 16 | /// 17 | /// A `u32` representing the user's guess if the input is valid, otherwise an error is returned. 18 | fn get_guess() -> Result { 19 | println!("{}", "Enter your guess: ".blue().bold()); 20 | let mut guess = String::new(); 21 | io::stdin() 22 | .read_line(&mut guess) 23 | .map_err(|_| "Failed to read line".to_string())?; 24 | guess 25 | .trim() 26 | .parse::() 27 | .map_err(|_| "Please enter a number".to_string()) 28 | } 29 | 30 | /// Compares the user's guess to the secret number and returns the result. 31 | /// 32 | /// # Arguments 33 | /// 34 | /// * `guess` - The user's guess. 35 | /// * `secret_number` - The secret number to be guessed. 36 | /// 37 | /// # Returns 38 | /// 39 | /// A `GuessResult` enum indicating the outcome of the comparison. 40 | fn compare_guess(guess: u32, secret_number: u32) -> GuessResult { 41 | if guess < secret_number { 42 | GuessResult::TooSmall 43 | } else if guess > secret_number { 44 | GuessResult::TooBig 45 | } else { 46 | GuessResult::Correct 47 | } 48 | } 49 | 50 | /// Prints a message based on the result of the guess. 51 | /// 52 | /// # Arguments 53 | /// 54 | /// * `result` - The result of the guess comparison. 55 | fn print_guess_result(result: &GuessResult) { 56 | match result { 57 | GuessResult::TooSmall => println!("{}", "Too small!".red().bold()), 58 | GuessResult::TooBig => println!("{}", "Too big!".red().bold()), 59 | GuessResult::Correct => println!("{}", "You win!".green().bold()), 60 | } 61 | } 62 | 63 | fn main() { 64 | let secret_number = rand::thread_rng().gen_range(1..101); 65 | 66 | loop { 67 | match get_guess() { 68 | Ok(guess) => { 69 | println!("You guessed: {}", guess.to_string().green().bold()); 70 | let result = compare_guess(guess, secret_number); 71 | print_guess_result(&result); 72 | if result == GuessResult::Correct { 73 | break; 74 | } 75 | } 76 | Err(e) => { 77 | println!("{}", e.red().bold()); 78 | } 79 | } 80 | } 81 | } 82 | 83 | #[cfg(test)] 84 | mod tests { 85 | use super::*; 86 | 87 | #[test] 88 | fn test_compare_guess() { 89 | assert_eq!(compare_guess(50, 50), GuessResult::Correct); 90 | assert_eq!(compare_guess(50, 40), GuessResult::TooBig); 91 | assert_eq!(compare_guess(50, 60), GuessResult::TooSmall); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Module01/simple_calc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "SimpleCalc" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /Module01/simple_calc/EdgeCaseFix.md: -------------------------------------------------------------------------------- 1 | - numbers input validation (only digit) 2 | - -------------------------------------------------------------------------------- /Module01/simple_calc/Readme.md: -------------------------------------------------------------------------------- 1 | # Simple Calculator 2 | 3 | The Crazy Cure Calculator is a simple, interactive command-line application written in Rust. It enables users to perform basic arithmetic operations, including addition, subtraction, multiplication, and division, on two input numbers. This document provides a technical and user-friendly overview of the application's functionality. 4 | 5 | ## Features 6 | 7 | - User Interaction: Prompts users for input through the command line. 8 | - Supports Basic Arithmetic Operations: Users can perform addition (+), subtraction (-), multiplication (*), and division (/) on two numbers. 9 | - Error Handling: The application gracefully handles invalid inputs by prompting the user to enter a valid number. 10 | 11 | ## Getting Started 12 | 13 | ### Prerequisites 14 | 15 | - Rust programming language setup on your machine. Visit [The Rust Programming Language](https://www.rust-lang.org/) website for installation instructions. 16 | 17 | ### Running the Application 18 | 19 | 1. Clone the Repository: First, clone the repository to your local machine using Git. 20 | 2. Navigate to the Application Directory: Change into the directory containing the application. 21 | 3. Run the Application: Use Cargo, Rust's package manager and build system, to compile and run the application. 22 | 4. Follow the On-Screen Prompts: The application will guide you through entering two numbers and selecting an operation to perform. 23 | 24 | ## How It Works 25 | 26 | ### Technical Details 27 | 28 | - Reading Input: The application uses Rust's `std::io` library to read user input from the command line. 29 | - Parsing Input: Input numbers are initially read as strings and then parsed into 64-bit floating-point numbers (`f64`) for arithmetic operations. 30 | - Selecting Operations: A `match` statement is used to determine the operation based on the user's choice, performing the corresponding arithmetic operation on the input numbers. 31 | - Error Handling: The application checks for valid numerical input and responds with appropriate error messages if the input is invalid. 32 | 33 | ### User Interaction Flow 34 | 35 | 1. Welcome Message: Upon starting, the application displays a welcome message. 36 | 2. Input Numbers: Users are prompted to enter two numbers, one at a time. 37 | 3. Select Operation: Users choose an arithmetic operation to perform on the entered numbers. 38 | 4. Display Result: The application calculates and displays the result of the chosen operation. 39 | 40 | ## Conclusion 41 | 42 | The Simple Calculator is a straightforward yet powerful example of how Rust can be used to create interactive command-line applications. It demonstrates basic programming concepts such as input/output operations, parsing strings to numbers, conditional logic with `match` statements, and error handling. 43 | 44 | For further exploration, users can extend the application to include more complex operations, improve error handling, or enhance the user interface. 45 | -------------------------------------------------------------------------------- /Module01/simple_calc/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | /// Reads a number from the user's input. 4 | /// 5 | /// # Returns 6 | /// 7 | /// A `f64` representing the number entered by the user. 8 | /// 9 | /// # Panics 10 | /// 11 | /// Panics if the user input is not a valid number. 12 | fn read_number() -> f64 { 13 | let mut input = String::new(); 14 | io::stdin() 15 | .read_line(&mut input) 16 | .expect("Failed to read line"); 17 | input.trim().parse().expect("Please type a number!") 18 | } 19 | 20 | /// Performs a calculation based on the given operator and numbers. 21 | /// 22 | /// # Arguments 23 | /// 24 | /// * `operator` - The operator to use for the calculation. 25 | /// * `num1` - The first number. 26 | /// * `num2` - The second number. 27 | /// 28 | /// # Returns 29 | /// 30 | /// A `String` containing the result of the calculation or an error message. 31 | fn calculate(operator: &str, num1: f64, num2: f64) -> String { 32 | match operator { 33 | "+" => format!("Result: {}", num1 + num2), 34 | "-" => format!("Result: {}", num1 - num2), 35 | "*" => format!("Result: {}", num1 * num2), 36 | "/" => { 37 | if num2 != 0.0 { 38 | format!("Result: {}", num1 / num2) 39 | } else { 40 | "Cannot divide by zero".to_string() 41 | } 42 | } 43 | _ => "Invalid operation".to_string(), 44 | } 45 | } 46 | 47 | fn main() { 48 | println!("Welcome to crazy cure\n"); 49 | 50 | println!("Enter the first number :"); 51 | let num1 = read_number(); 52 | 53 | println!("Enter the second number :"); 54 | let num2 = read_number(); 55 | 56 | println!("Choose an operation: +, -, *, /"); 57 | let mut operator = String::new(); 58 | io::stdin() 59 | .read_line(&mut operator) 60 | .expect("Failed to read line"); 61 | 62 | let result = calculate(operator.trim(), num1, num2); 63 | println!("{}", result); 64 | } 65 | 66 | #[cfg(test)] 67 | mod tests { 68 | use super::*; 69 | 70 | // #[test] 71 | // fn test_read_number() { 72 | // let _input = "42\n"; 73 | // let expected = 42.0; 74 | // let result = read_number(); 75 | // assert_eq!(result, expected); 76 | // } 77 | 78 | #[test] 79 | fn test_calculate_addition() { 80 | let operator = "+"; 81 | let num1 = 10.0; 82 | let num2 = 5.0; 83 | let expected = "Result: 15".to_string(); 84 | let result = calculate(operator, num1, num2); 85 | assert_eq!(result, expected); 86 | } 87 | 88 | #[test] 89 | fn test_calculate_subtraction() { 90 | let operator = "-"; 91 | let num1 = 10.0; 92 | let num2 = 5.0; 93 | let expected = "Result: 5".to_string(); 94 | let result = calculate(operator, num1, num2); 95 | assert_eq!(result, expected); 96 | } 97 | 98 | #[test] 99 | fn test_calculate_multiplication() { 100 | let operator = "*"; 101 | let num1 = 10.0; 102 | let num2 = 5.0; 103 | let expected = "Result: 50".to_string(); 104 | let result = calculate(operator, num1, num2); 105 | assert_eq!(result, expected); 106 | } 107 | 108 | #[test] 109 | fn test_calculate_division() { 110 | let operator = "/"; 111 | let num1 = 10.0; 112 | let num2 = 5.0; 113 | let expected = "Result: 2".to_string(); 114 | let result = calculate(operator, num1, num2); 115 | assert_eq!(result, expected); 116 | } 117 | 118 | #[test] 119 | fn test_calculate_division_by_zero() { 120 | let operator = "/"; 121 | let num1 = 10.0; 122 | let num2 = 0.0; 123 | let expected = "Cannot divide by zero".to_string(); 124 | let result = calculate(operator, num1, num2); 125 | assert_eq!(result, expected); 126 | } 127 | 128 | #[test] 129 | fn test_calculate_invalid_operation() { 130 | let operator = "%"; 131 | let num1 = 10.0; 132 | let num2 = 5.0; 133 | let expected = "Invalid operation".to_string(); 134 | let result = calculate(operator, num1, num2); 135 | assert_eq!(result, expected); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Module02/Auth/.env: -------------------------------------------------------------------------------- 1 | JWT_SECRET="kickmyass" -------------------------------------------------------------------------------- /Module02/Auth/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "Auth" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | warp = "0.3" 8 | serde = { version = "1.0", features = ["derive"] } 9 | serde_json = "1.0" 10 | jsonwebtoken = "7.2" 11 | tokio = { version = "1", features = ["full"] } 12 | thiserror = "1.0" 13 | log = "0.4.22" 14 | dotenv = "0.15.0" 15 | env_logger = "0.11.5" 16 | pretty_env_logger = "0.5.0" 17 | chrono = "0.4.38" 18 | -------------------------------------------------------------------------------- /Module02/Auth/src/auth.rs: -------------------------------------------------------------------------------- 1 | use warp::{http::StatusCode, reject, reply, Rejection, Reply}; 2 | use crate::model::User; 3 | use crate::jwt::{generate_jwt, validate_jwt}; 4 | use crate::errors::{AuthError, CustomError}; 5 | use warp::reply::html; 6 | use warp::filter::FilterBase; 7 | 8 | use serde::Deserialize; 9 | use log::error; 10 | use std::env; 11 | use std::convert::Infallible; 12 | 13 | pub async fn login(user: User) -> Result { 14 | let expected_username = env::var("USERNAME").expect("USERNAME must be set"); 15 | let expected_password = env::var("PASSWORD").expect("PASSWORD must be set"); 16 | 17 | if user.username == expected_username && user.password == expected_password { 18 | let token = generate_jwt(&user.username); 19 | Ok(reply::json(&token)) 20 | } else { 21 | Err(reject::custom(AuthError::InvalidCredentials)) 22 | } 23 | } 24 | 25 | pub async fn protected(token: String) -> Result { 26 | match validate_jwt(&token) { 27 | Ok(_) => Ok(reply::with_status("Access granted", StatusCode::OK)), 28 | Err(_) => Err(reject::custom(AuthError::InvalidToken)), 29 | } 30 | } 31 | 32 | #[derive(Deserialize)] 33 | struct AuthForm { 34 | token: String, 35 | } 36 | 37 | pub async fn serve_form() -> Result { 38 | let html_form = r#" 39 | 40 | 41 |
42 | 43 | 44 | 45 |
46 | 47 | 48 | "#; 49 | Ok(html(html_form)) 50 | } 51 | 52 | pub async fn authenticate(form: AuthForm) -> Result { 53 | match validate_jwt(&form.token) { 54 | Ok(_) => Ok(warp::reply::with_status("Authentication successful", StatusCode::OK)), 55 | Err(_) => { 56 | error!("Authentication failed for token: {}", form.token); 57 | Err(reject::custom(CustomError::Unauthorized)) 58 | }, 59 | } 60 | } 61 | 62 | pub async fn generate_token(body: serde_json::Value) -> Result { 63 | let username = body.get("username").and_then(|v| v.as_str()).unwrap_or(""); 64 | let token = generate_jwt(username); 65 | Ok(warp::reply::json(&token)) 66 | } -------------------------------------------------------------------------------- /Module02/Auth/src/errors.rs: -------------------------------------------------------------------------------- 1 | use warp::{http::StatusCode, reject, Rejection, Reply}; 2 | use std::convert::Infallible; 3 | use thiserror::Error; 4 | use log::error; 5 | 6 | #[derive(Error, Debug)] 7 | pub enum AuthError { 8 | #[error("Invalid credentials")] 9 | InvalidCredentials, 10 | #[error("Invalid token")] 11 | InvalidToken, 12 | #[error("Token has expired")] 13 | ExpiredToken, 14 | } 15 | 16 | impl reject::Reject for AuthError {} 17 | 18 | #[derive(Debug)] 19 | pub enum CustomError { 20 | NotFound, 21 | Unauthorized, 22 | InternalError, 23 | } 24 | 25 | impl reject::Reject for CustomError {} 26 | 27 | pub async fn handle_rejection(err: Rejection) -> Result { 28 | if let Some(auth_error) = err.find::() { 29 | let (code, message) = match auth_error { 30 | AuthError::InvalidCredentials => (StatusCode::UNAUTHORIZED, "Invalid credentials"), 31 | AuthError::InvalidToken => (StatusCode::UNAUTHORIZED, "Invalid token"), 32 | AuthError::ExpiredToken => (StatusCode::UNAUTHORIZED, "Token has expired"), 33 | }; 34 | error!("Auth error occurred: {} - {}", code, message); 35 | return Ok(warp::reply::with_status(message, code)); 36 | } 37 | 38 | if let Some(custom_error) = err.find::() { 39 | let (code, message) = match custom_error { 40 | CustomError::NotFound => (StatusCode::NOT_FOUND, "Not Found"), 41 | CustomError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized"), 42 | CustomError::InternalError => (StatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error"), 43 | }; 44 | error!("Custom error occurred: {} - {}", code, message); 45 | return Ok(warp::reply::with_status(message, code)); 46 | } 47 | 48 | if err.is_not_found() { 49 | return Ok(warp::reply::with_status("Route not found", StatusCode::NOT_FOUND)); 50 | } 51 | 52 | if let Some(_) = err.find::() { 53 | return Ok(warp::reply::with_status("Invalid body", StatusCode::BAD_REQUEST)); 54 | } 55 | 56 | if let Some(_) = err.find::() { 57 | return Ok(warp::reply::with_status("Method not allowed", StatusCode::METHOD_NOT_ALLOWED)); 58 | } 59 | 60 | error!("Unhandled rejection: {:?}", err); 61 | Ok(warp::reply::with_status( 62 | "Unhandled rejection", 63 | StatusCode::INTERNAL_SERVER_ERROR, 64 | )) 65 | } -------------------------------------------------------------------------------- /Module02/Auth/src/jwt.rs: -------------------------------------------------------------------------------- 1 | use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey, TokenData}; 2 | use serde::{Serialize, Deserialize}; 3 | use std::env; 4 | use chrono::{Utc, Duration}; 5 | 6 | #[derive(Debug, Serialize, Deserialize)] 7 | struct Claims { 8 | sub: String, 9 | exp: usize, 10 | } 11 | 12 | pub fn generate_jwt(username: &str) -> String { 13 | let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); 14 | let expiration = Utc::now() 15 | .checked_add_signed(Duration::minutes(60)) 16 | .expect("valid timestamp") 17 | .timestamp(); 18 | 19 | let claims = Claims { 20 | sub: username.to_owned(), 21 | exp: expiration as usize, 22 | }; 23 | 24 | encode(&Header::default(), &claims, &EncodingKey::from_secret(secret.as_ref())).unwrap() 25 | } 26 | 27 | pub fn validate_jwt(token: &str) -> Result, jsonwebtoken::errors::Error> { 28 | let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); 29 | decode::(token, &DecodingKey::from_secret(secret.as_ref()), &Validation::default()) 30 | } -------------------------------------------------------------------------------- /Module02/Auth/src/main.rs: -------------------------------------------------------------------------------- 1 | mod auth; 2 | mod errors; 3 | mod routes; 4 | mod jwt; 5 | mod model; 6 | 7 | use std::env; 8 | use warp::Filter; 9 | use tokio::signal; 10 | 11 | #[tokio::main] 12 | async fn main() { 13 | dotenv().ok(); 14 | 15 | // Load configuration from environment variables 16 | let host = env::var("HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); 17 | let port: u16 = env::var("PORT").unwrap_or_else(|_| "3030".to_string()).parse().expect("PORT must be a number"); 18 | 19 | let routes = routes::routes(); 20 | 21 | // Log server startup 22 | println!("Starting server at {}:{}", host, port); 23 | 24 | // Run the server with graceful shutdown 25 | let (_, server) = warp::serve(routes) 26 | .bind_with_graceful_shutdown(([host.parse().unwrap(), port]), async { 27 | signal::ctrl_c().await.expect("Failed to listen for ctrl_c signal"); 28 | }); 29 | 30 | server.await; 31 | } -------------------------------------------------------------------------------- /Module02/Auth/src/model.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Deserialize)] 4 | pub struct User { 5 | pub username: String, 6 | pub password: String, 7 | } 8 | 9 | #[derive(Serialize, Deserialize)] 10 | pub struct Claims { 11 | sub: String, 12 | exp: usize, 13 | } 14 | 15 | impl Claims { 16 | pub fn new(sub: String, exp: usize) -> Self { 17 | Claims { sub, exp } 18 | } 19 | 20 | pub fn exp(&self) -> usize { 21 | self.exp 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /Module02/Auth/src/routes.rs: -------------------------------------------------------------------------------- 1 | use warp::Filter; 2 | use warp::filter::FilterBase; 3 | use crate::auth::{serve_form, authenticate, generate_token}; 4 | use crate::errors::handle_rejection; 5 | 6 | pub fn routes() -> impl Filter + Clone { 7 | let form_route = warp::path::end() 8 | .and_then(serve_form) 9 | .map_err(|err: std::convert::Infallible| warp::reject::custom(err)); 10 | 11 | let auth_route = warp::path("authenticate") 12 | .and(warp::post()) 13 | .and(warp::body::form()) 14 | .and_then(authenticate) 15 | .map_err(|err: warp::Rejection| err); 16 | 17 | let token_route = warp::path("token") 18 | .and(warp::post()) 19 | .and(warp::body::json()) 20 | .and_then(generate_token) 21 | .map_err(|err: warp::Rejection| err); 22 | 23 | form_route.or(auth_route).or(token_route).recover(handle_rejection) 24 | } -------------------------------------------------------------------------------- /Module02/Chatbot/.idea/Chatbot.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Module02/Chatbot/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Module02/Chatbot/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Module02/Chatbot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "Chatbot" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | regex = "1.5" 8 | serde = { version = "1.0", features = ["derive"] } 9 | serde_json = "1.0" 10 | -------------------------------------------------------------------------------- /Module02/Chatbot/Readme.md: -------------------------------------------------------------------------------- 1 | # 🤖 Rusty the Chatbot 2 | 3 | Welcome to **Rusty the Chatbot**, your friendly command-line companion built with Rust! Whether you're a seasoned Rustacean, a curious beginner, or just someone looking for a fun project, Rusty is here to teach, entertain, and keep you company. 4 | 5 | ## 🚀 Overview 6 | 7 | Rusty is a simple yet powerful chatbot that reads predefined responses from a JSON file and interacts with users via the command line. This project is a fantastic way to dive into some fundamental principles of Rust while building something tangible and fun. 8 | 9 | ## 🎯 Learning Objectives 10 | 11 | By working on Rusty the Chatbot, you'll master: 12 | 13 | 1. **Ownership and Borrowing:** 14 | - Get a grip on Rust’s ownership model, ensuring memory safety without the need for a garbage collector. No leaks here, just pure Rustacean magic! 15 | - Learn the ins and outs of borrowing (`&self`) and mutable borrowing (`&mut self`). Sharing is caring! 16 | 17 | 2. **Error Handling:** 18 | - Embrace Rust’s robust error handling with the `Result` and `Option` types. 19 | - Handle errors gracefully with pattern matching and the trusty `?` operator. No more unexpected panics! 20 | 21 | 3. **Trait Implementation:** 22 | - Implement methods for structs (`impl Chatbot`). Traits are like interfaces, but cooler. 23 | 24 | 4. **File I/O:** 25 | - Read from and write to files using Rust’s standard library. Efficient and safe, just like Rust. 26 | 27 | 5. **Serialization and Deserialization:** 28 | - Use the `serde` library to seamlessly serialize and deserialize data structures to and from JSON. Because who wants to write a parser from scratch? 29 | 30 | 6. **HashMap:** 31 | - Utilize `HashMap` for efficient key-value storage and retrieval. Fast lookups, no sweat. 32 | 33 | 7. **Loops and Conditional Logic:** 34 | - Implement infinite loops (`loop`) and conditional logic to control program flow. Keep Rusty chatting until you say “exit”. 35 | 36 | 8. **User Input and Output:** 37 | - Handle user input and output using `stdin` and `stdout`. Smooth conversations guaranteed. 38 | 39 | ## 🛠️ Getting Started 40 | 41 | ### Prerequisites 42 | 43 | - Rust and Cargo installed. If you haven’t joined the Rustacean club yet, head over to [rust-lang.org](https://www.rust-lang.org/tools/install) to get started. 44 | 45 | ### Project Structure 46 | 47 | Your project directory should look like this: 48 | 49 | rusty_chatbot/ 50 | ├── Cargo.toml 51 | ├── src/ 52 | │ └── main.rs 53 | └── chatbot_responses.json 54 | 55 | ### chatbot_responses.json 56 | 57 | Create a `chatbot_responses.json` file in the root directory of your project with content like this: 58 | 59 | ```json 60 | [ 61 | {"key": "hello", "value": "Hi there! How can I help you?"}, 62 | {"key": "bye", "value": "Goodbye! Have a great day!"}, 63 | {"key": "how are you", "value": "I'm a bot, so I don't have feelings, but thanks for asking!"} 64 | ] 65 | Feel free to add more responses to make Rusty even more engaging! 66 | 67 | Building and Running 68 | Clone the repository: 69 | 70 | git clone 71 | cd rusty_chatbot 72 | Build the project: 73 | 74 | cargo build 75 | Run the project: 76 | 77 | cargo run 78 | Interacting with Rusty: Type your messages and press Enter to chat with Rusty. Type exit to bid Rusty farewell. 79 | 🔍 Code Overview 80 | Chatbot Struct and Implementation 81 | The Chatbot struct holds the responses in a HashMap and provides methods to load responses from a JSON file and respond to user input. Rusty’s brain, if you will. 82 | 83 | UserInput Struct 84 | The UserInput struct is used to deserialize JSON data into Rust structs. It’s like a translator for Rusty. 85 | 86 | Main Function 87 | The main function initializes Rusty, loads responses from the JSON file, and starts the chatbot loop. It’s the heart that keeps Rusty alive and chatting. 88 | 89 | 🙌 Contributing 90 | Contributions are welcome! If you have suggestions or improvements, feel free to open an issue or submit a pull request. Let’s make Rusty smarter together! 91 | 92 | 📜 License 93 | This project is licensed under the MIT License. See the LICENSE file for details. 94 | 95 | Happy coding, and may the Rust be with you! 🦀✨ 96 | -------------------------------------------------------------------------------- /Module02/Chatbot/chatbot_responses.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"key": "hello", "value": "Hi there! How can I help you?"}, 3 | {"key": "bye", "value": "Goodbye! Have a great day!"}, 4 | {"key": "how are you", "value": "I'm a bot, so I don't have feelings, but thanks for asking!"}, 5 | {"key": "Who are you", "value": "I'm YOU, you MOFO!!"} 6 | ] -------------------------------------------------------------------------------- /Module02/Chatbot/src/main.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::HashMap; 3 | use std::fs::File; 4 | use std::io::{self, BufReader, Write}; 5 | 6 | /** 7 | * @file main.rs 8 | * @brief Rusty: A simple chatbot implemented in Rust. 9 | */ 10 | 11 | pub struct Chatbot { 12 | responses: HashMap, 13 | } 14 | 15 | impl Chatbot { 16 | pub fn new() -> Self { 17 | Chatbot { 18 | responses: HashMap::new(), 19 | } 20 | } 21 | 22 | pub fn respond(&self, input: &str) -> String { 23 | let input = input.trim().to_lowercase(); 24 | 25 | for (key, value) in &self.responses { 26 | if input.contains(&key.to_lowercase()) { 27 | return value.clone(); 28 | } 29 | } 30 | 31 | String::from("I'm not sure how to respond to that. Could you please rephrase?") 32 | } 33 | 34 | pub fn load_responses(&mut self, filename: &str) -> Result<(), io::Error> { 35 | let file = File::open(filename)?; 36 | let reader = BufReader::new(file); 37 | let responses: Vec = serde_json::from_reader(reader)?; 38 | 39 | for response in responses { 40 | self.responses.insert(response.key, response.value); 41 | } 42 | Ok(()) 43 | } 44 | } 45 | 46 | #[derive(Debug, Serialize, Deserialize)] 47 | pub struct UserInput { 48 | key: String, 49 | value: String, 50 | } 51 | 52 | fn main() -> io::Result<()> { 53 | let mut chatbot = Chatbot::new(); 54 | 55 | if let Err(e) = chatbot.load_responses("chatbot_responses.json") { 56 | eprintln!("Error loading responses: {}", e); 57 | return Err(e); 58 | } 59 | 60 | println!("Chatbot initialized. Type 'exit' to quit."); 61 | 62 | loop { 63 | print!("You: "); 64 | io::stdout().flush()?; 65 | 66 | let mut input = String::new(); 67 | io::stdin().read_line(&mut input)?; 68 | 69 | let input = input.trim(); 70 | 71 | if input.eq_ignore_ascii_case("exit") { 72 | println!("Goodbye!"); 73 | break; 74 | } 75 | 76 | let response = chatbot.respond(input); 77 | println!("Bot: {}", response); 78 | } 79 | 80 | Ok(()) 81 | } 82 | 83 | #[cfg(test)] 84 | mod tests { 85 | use super::*; 86 | 87 | #[test] 88 | fn test_chatbot_respond() { 89 | let mut chatbot = Chatbot::new(); 90 | chatbot 91 | .responses 92 | .insert("hello".to_string(), "Hi there!".to_string()); 93 | chatbot 94 | .responses 95 | .insert("bye".to_string(), "Goodbye!".to_string()); 96 | 97 | assert_eq!(chatbot.respond("Hello"), "Hi there!"); 98 | assert_eq!(chatbot.respond("Goodbye"), "Goodbye!"); 99 | assert_eq!( 100 | chatbot.respond("How are you?"), 101 | "I'm not sure how to respond to that. Could you please rephrase?" 102 | ); 103 | } 104 | 105 | #[test] 106 | fn test_chatbot_load_responses() { 107 | let mut chatbot = Chatbot::new(); 108 | chatbot.load_responses("chatbot_responses.json").unwrap(); 109 | 110 | assert_eq!(chatbot.responses.len(), 4); 111 | assert_eq!( 112 | chatbot.responses.get("hello").unwrap(), 113 | "Hi there! How can I help you?" 114 | ); 115 | assert_eq!( 116 | chatbot.responses.get("bye").unwrap(), 117 | "Goodbye! Have a great day!" 118 | ); 119 | assert_eq!( 120 | chatbot.responses.get("how are you").unwrap(), 121 | "I'm a bot, so I don't have feelings, but thanks for asking!" 122 | ); 123 | assert_eq!( 124 | chatbot.responses.get("Who are you").unwrap(), 125 | "I'm YOU, you MOFO!!" 126 | ); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Module02/Web1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple_web_server" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | actix-web = "4" 8 | 9 | [dev-dependencies] 10 | actix-rt = "2.5" -------------------------------------------------------------------------------- /Module02/Web1/Readme.md: -------------------------------------------------------------------------------- 1 | # Actix Web Server 2 | 3 | This project is a simple web server built with Actix Web that serves static HTML files and provides a basic route. 4 | 5 | ## Installation 6 | 7 | 1. Ensure you have [Rust](https://www.rust-lang.org/tools/install) installed on your machine. 8 | 2. Clone this repository: 9 | 10 | ```sh 11 | git clone https://github.com/yourusername/actix-web-server.git 12 | ``` 13 | 14 | 3. Navigate to the project directory: 15 | 16 | ```sh 17 | cd actix-web-server 18 | ``` 19 | 20 | 4. Build the project: 21 | 22 | ```sh 23 | cargo build 24 | ``` 25 | 26 | ## Usage 27 | 28 | To run the server, use the following command: 29 | 30 | ```sh 31 | cargo run 32 | ``` 33 | 34 | The server will start and listen on `http://localhost:8080`. You can access the following endpoints: 35 | 36 | - `/`: Serves a static HTML file. 37 | 38 | ## Static Files 39 | 40 | The server serves the following static HTML files: 41 | 42 | - `404.html`: Custom 404 error page. 43 | - `test.html`: A test HTML file. 44 | 45 | ## Testing 46 | 47 | To run the tests, use the following command: 48 | 49 | ```sh 50 | cargo test 51 | ``` 52 | 53 | The tests cover the server routes and error handling. 54 | 55 | ## Features 56 | 57 | - Actix Web: Utilizes the Actix Web framework to build a lightweight web server. 58 | - Static File Serving: Serves static HTML files using Actix Web's `fs` module. 59 | - Error Handling: Demonstrates error handling in Actix Web applications. 60 | 61 | ## License 62 | 63 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 64 | -------------------------------------------------------------------------------- /Module02/Web1/src/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 404 Not Found 7 | 17 | 18 | 19 |

404 Not Found

20 |

Sorry, the page you are looking for does not exist.

21 | 22 | 23 | -------------------------------------------------------------------------------- /Module02/Web1/src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{get, App, HttpResponse, HttpServer, Responder}; 2 | 3 | #[get("/")] // route handler for root 4 | async fn intro() -> impl Responder { 5 | HttpResponse::Ok().body("Welcome to Rusty server") 6 | } 7 | 8 | #[actix_web::main] 9 | async fn main() -> std::io::Result<()> { 10 | HttpServer::new(|| App::new().service(intro)) 11 | .bind("127.0.0.1:8080")? 12 | .run() 13 | .await 14 | } 15 | 16 | #[cfg(test)] 17 | mod tests { 18 | use super::*; 19 | use actix_web::{http::StatusCode, test}; 20 | 21 | #[actix_rt::test] 22 | async fn test_intro() { 23 | let mut app = test::init_service(App::new().service(intro)).await; 24 | println!("server running"); 25 | let req = test::TestRequest::get().uri("/").to_request(); 26 | let resp = test::call_service(&mut app, req).await; 27 | 28 | assert_eq!(resp.status(), StatusCode::OK); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Module02/Web1/src/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebSocket Test 7 | 8 | 9 |

WebSocket Test

10 |
Connecting...
11 |
12 | 13 | 14 |
15 |
16 | 17 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Module02/Web2/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello! 6 | 7 | 8 |

Oops!

9 |

Sorry, I don't know what you're asking for.

10 | 11 | -------------------------------------------------------------------------------- /Module02/Web2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple_web_server2" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | actix-web = "4" 8 | actix-rt = "2.5" 9 | serde = { version = "1.0", features = ["derive"]} 10 | serde_json = "1.0" -------------------------------------------------------------------------------- /Module02/Web2/Readme.md: -------------------------------------------------------------------------------- 1 | # Actix Web Server 2 | 3 | This project is a simple web server built with Actix Web that serves static HTML files and provides basic routes. 4 | 5 | ## Installation 6 | 7 | 1. Ensure you have [Rust](https://www.rust-lang.org/tools/install) installed on your machine. 8 | 2. Clone this repository: 9 | 10 | ```sh 11 | git clone https://github.com/yourusername/actix-web-server.git 12 | ``` 13 | 14 | 3. Navigate to the project directory: 15 | 16 | ```sh 17 | cd actix-web-server 18 | ``` 19 | 20 | 4. Build the project: 21 | 22 | ```sh 23 | cargo build 24 | ``` 25 | 26 | ## Usage 27 | 28 | To run the server, use the following command: 29 | 30 | ```sh 31 | cargo run 32 | ``` 33 | 34 | The server will start and listen on `http://localhost:8080`. You can access the following endpoints: 35 | 36 | ## Endpoints 37 | 38 | - GET /: Returns a welcome message. 39 | - GET /intro/{name}: Greets the user with the specified name. 40 | - POST /echo: Echoes back the JSON payload. 41 | 42 | ## Static Files 43 | 44 | The server serves the following static HTML files: 45 | 46 | - `404.html`: Custom 404 error page. 47 | - `hello.html`: A simple HTML file with a greeting message. 48 | 49 | ## Testing 50 | 51 | To run the tests, use the following command: 52 | 53 | ```sh 54 | cargo test 55 | ``` 56 | 57 | The tests cover the server routes and error handling. 58 | 59 | ## Siege Test Result 60 | 61 | ![alt text](image.png) 62 | 63 | 64 | ## License 65 | 66 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 67 | -------------------------------------------------------------------------------- /Module02/Web2/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module02/Web2/image.png -------------------------------------------------------------------------------- /Module02/Web2/src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[get("/")] 5 | async fn intro() -> impl Responder { 6 | HttpResponse::Ok().body("

Welcome to Rusty server

") 7 | } 8 | 9 | #[get("/intro/{name}")] 10 | async fn greet(name: web::Path) -> impl Responder { 11 | format!("Welcome, my little peers {}!", name) 12 | } 13 | 14 | #[derive(Serialize, Deserialize)] 15 | struct Info { 16 | username: String, 17 | } 18 | 19 | #[post("/echo")] 20 | async fn echo(info: web::Json) -> impl Responder { 21 | HttpResponse::Ok().json(info.0) 22 | } 23 | 24 | #[actix_web::main] 25 | async fn main() -> std::io::Result<()> { 26 | println!("Server starts running .... "); 27 | HttpServer::new(|| App::new().service(intro).service(greet).service(echo)) 28 | .bind("127.0.0.1:5500")? 29 | .run() 30 | .await 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | use actix_web::{http::StatusCode, test}; 37 | 38 | #[actix_rt::test] 39 | async fn test_intro() { 40 | let mut app = test::init_service(App::new().service(intro)).await; 41 | 42 | let req = test::TestRequest::get().uri("/").to_request(); 43 | let resp = test::call_service(&mut app, req).await; 44 | 45 | assert_eq!(resp.status(), StatusCode::OK); 46 | } 47 | 48 | #[actix_rt::test] 49 | async fn test_greet() { 50 | let mut app = test::init_service(App::new().service(greet)).await; 51 | 52 | let req = test::TestRequest::get().uri("/intro/World").to_request(); 53 | let resp = test::call_service(&mut app, req).await; 54 | 55 | assert_eq!(resp.status(), StatusCode::OK); 56 | } 57 | 58 | #[actix_rt::test] 59 | async fn test_echo() { 60 | let mut app = test::init_service(App::new().service(echo)).await; 61 | 62 | let req = test::TestRequest::post() 63 | .uri("/echo") 64 | .set_json(&Info { 65 | username: "World".to_string(), 66 | }) 67 | .to_request(); 68 | let resp = test::call_service(&mut app, req).await; 69 | 70 | assert_eq!(resp.status(), StatusCode::OK); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Module02/auth_server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "auth_server" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | warp = "0.3.7" 8 | jsonwebtoken = "7.2" 9 | serde = { version = "1.0", features = ["derive"]} 10 | serde_json = "1.0" 11 | tokio = { version = "1.0", features = ["full"] } 12 | chrono = "0.4.38" 13 | -------------------------------------------------------------------------------- /Module02/auth_server/Readme: -------------------------------------------------------------------------------- 1 | # Modular Rust Learning: Authentication Server 2 | 3 | This repository contains the code for an authentication server implemented in Rust. The server is built using the Warp web framework and utilizes JSON Web Tokens (JWT) for authentication. 4 | 5 | ## Table of Contents 6 | 7 | - [Architecture](#architecture) 8 | - [Getting Started](#getting-started) 9 | - [Testing the Endpoints](#testing-the-endpoints) 10 | - [Conclusion](#conclusion) 11 | 12 | ## Architecture 13 | 14 | The application is divided into three modules: 15 | 16 | 1. `jwt`: Contains JWT related logic such as token generation, validation, and claims extraction. 17 | 2. `auth`: Handles authentication logic including user login and registration. 18 | 3. `server`: Runs the web server and handles routing. 19 | 20 | The modules are designed to minimize dependencies and promote reusability. Dependency injection is used to pass dependencies between modules. 21 | 22 | ## Getting Started 23 | 24 | To get started with the authentication server, follow these steps: 25 | 26 | 1. Clone the repository: 27 | 28 | ```sh 29 | git clone 30 | cd 31 | ``` 32 | 33 | 2. Install dependencies: 34 | 35 | ```sh 36 | cargo build 37 | ``` 38 | 39 | 3. Run the server: 40 | 41 | ```sh 42 | cargo run 43 | ``` 44 | 45 | ## Testing the Endpoints 46 | 47 | To test the authentication server endpoints, you can use `curl` or any other HTTP client. 48 | 49 | ### Login Endpoint 50 | 51 | Send a POST request to the login endpoint with a JSON body containing the username and password: 52 | 53 | ```bash 54 | curl -X POST -H "Content-Type: application/json" -d '{"username": "admin", "password": "password"}' http://127.0.0.1:3030/login 55 | ``` 56 | 57 | If the credentials are correct, you will receive a JSON response with a JWT token. 58 | 59 | ### Protected Endpoint 60 | 61 | Send a GET request to the protected endpoint with the Authorization header containing the JWT token received from the login endpoint: 62 | 63 | ```bash 64 | TOKEN="your_jwt_token" # Replace with the actual token 65 | curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:3030/protected 66 | ``` 67 | 68 | If the token is valid, you will receive the response "Access granted". If the token is invalid or missing, you will receive the response "Forbidden". 69 | 70 | ## Conclusion 71 | 72 | By completing this project, you will gain a solid understanding of building web servers in Rust using the Warp framework and JWT for authentication. This project will also reinforce your knowledge of Rust's syntax and fundamental principles, preparing you for more advanced Rust programming tasks. 73 | -------------------------------------------------------------------------------- /Module02/auth_server/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module02/auth_server/image.png -------------------------------------------------------------------------------- /Module02/auth_server/src/handlers.rs: -------------------------------------------------------------------------------- 1 | use crate::jwt::{generate_jwt, jwt_validation}; 2 | use serde::Deserialize; 3 | use serde_json::json; 4 | use warp::{reject, Rejection, Reply}; 5 | 6 | // Define the User struct 7 | #[derive(Deserialize)] 8 | pub struct User { 9 | username: String, 10 | password: String, 11 | } 12 | 13 | // Handle login requests 14 | pub async fn login(user: User) -> Result { 15 | match (user.username.as_str(), user.password.as_str()) { 16 | ("DragonBall", "Vegeta") => { 17 | let token = generate_jwt(&user.username); 18 | Ok(warp::reply::json(&json!({ "token": token }))) 19 | } 20 | _ => Ok(warp::reply::json(&json!("\nInvalid credentials"))), 21 | } 22 | } 23 | 24 | // Handle protected route requests 25 | pub async fn protected(token: String) -> Result { 26 | if jwt_validation(&token) { 27 | Ok(warp::reply::json(&json!("\nProtected route accessed"))) 28 | } else { 29 | Ok(warp::reply::json(&json!("\nInvalid token"))) 30 | } 31 | } 32 | 33 | // Define your custom error type 34 | #[derive(Debug)] 35 | pub enum CustomError { 36 | InvalidToken, 37 | } 38 | 39 | impl reject::CombineRejection for CustomError {} 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::*; 44 | use warp::http::StatusCode; 45 | use warp::test::{request, Response}; 46 | 47 | #[tokio::test] 48 | async fn test_login() { 49 | let user = User { 50 | username: "DragonBall".to_string(), 51 | password: "Vegeta".to_string(), 52 | }; 53 | 54 | let res = login(user).await.unwrap(); 55 | assert_eq!(Response::status(&res), StatusCode::OK); 56 | } 57 | 58 | #[tokio::test] 59 | async fn test_protected() { 60 | let token = generate_jwt("DragonBall"); 61 | let res = protected(token).await.unwrap(); 62 | assert_eq!(Response::status(&res), StatusCode::OK); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Module02/auth_server/src/jwt.rs: -------------------------------------------------------------------------------- 1 | use chrono::{Duration, Utc}; 2 | use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation}; 3 | use serde::{Deserialize, Serialize}; 4 | 5 | // Define the Claims struct for JWT 6 | #[derive(Serialize, Deserialize)] 7 | struct Claims { 8 | sub: String, 9 | exp: usize, 10 | } 11 | 12 | // Generate a JWT token 13 | pub fn generate_jwt(username: &str) -> String { 14 | let expiration = Utc::now() 15 | .checked_add_signed(Duration::seconds(60)) 16 | .expect("valid timestamp") 17 | .timestamp(); 18 | 19 | let claims = Claims { 20 | sub: username.to_owned(), 21 | exp: expiration as usize, 22 | }; 23 | 24 | encode( 25 | &Header::default(), 26 | &claims, 27 | &EncodingKey::from_secret("secret".as_ref()), 28 | ) 29 | .unwrap() 30 | } 31 | 32 | // Validate the JWT token 33 | pub fn jwt_validation(token: &str) -> bool { 34 | let validation = Validation::new(Algorithm::HS256); 35 | let token_data = decode::( 36 | token, 37 | &DecodingKey::from_secret("secret".as_ref()), 38 | &validation, 39 | ); 40 | token_data.is_ok() 41 | } 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use super::*; 46 | 47 | #[test] 48 | fn test_generate_jwt() { 49 | let token = generate_jwt("DragonBall"); 50 | assert!(jwt_validation(&token)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Module02/auth_server/src/main.rs: -------------------------------------------------------------------------------- 1 | use warp::Filter; 2 | use warp::Reply; 3 | 4 | mod handlers; 5 | mod jwt; 6 | 7 | use handlers::{login, protected, User}; 8 | use jwt::{generate_jwt, jwt_validation}; 9 | 10 | #[tokio::main] 11 | async fn main() { 12 | // Define the protected route 13 | let protected_route = warp::get() 14 | .and(warp::path("protected")) 15 | .and(warp::header::("authorization")) 16 | .and_then(protected); 17 | 18 | // Define the login route 19 | let login_route = warp::post() 20 | .and(warp::path("login")) 21 | .and(warp::body::json()) 22 | .and_then(login); 23 | 24 | // Combine routes 25 | let routes = login_route.or(protected_route); 26 | 27 | // Start the Warp server 28 | warp::serve(routes).run(([127, 0, 0, 1], 5500)).await; 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | use warp::http::StatusCode; 35 | use warp::test::request; 36 | use warp::Reply; 37 | 38 | #[tokio::test] 39 | async fn test_login() { 40 | let user = User { 41 | username: "DragonBall".to_string(), 42 | password: "Vegeta".to_string(), 43 | }; 44 | 45 | let res = login(user).await.unwrap(); 46 | use warp::reply::json; 47 | 48 | let body = json(&res); 49 | assert_eq!(body.status(), StatusCode::OK); 50 | } 51 | 52 | #[tokio::test] 53 | async fn test_protected() { 54 | let token = generate_jwt("DragonBall"); 55 | let res = protected(token).await.unwrap(); 56 | let body = warp::test::Reply::json::(&res).await; 57 | assert_eq!(body.status(), StatusCode::OK); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Module02/gitCheck/.idea/gitCheck.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Module02/gitCheck/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gitMap" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | 7 | [dependencies] 8 | actix-web = "3.3.2" 9 | reqwest = "0.11.4" 10 | serde = "1.0.130" 11 | serde_json = "1.0.64" 12 | actix-rt = "2.4.1" 13 | tokio = { version = "1", features = ["full"] } 14 | -------------------------------------------------------------------------------- /Module02/gitCheck/Readme.md: -------------------------------------------------------------------------------- 1 | # Actix Web GitHub Repo Info 2 | 3 | This project is a simple web service built with Actix Web that fetches information about GitHub repositories. 4 | 5 | ## Installation 6 | 7 | 1. Ensure you have [Rust](https://www.rust-lang.org/tools/install) installed on your machine. 8 | 2. Clone this repository: 9 | 10 | ```sh 11 | git clone https://github.com/yourusername/actix-web-github-repo-info.git 12 | ``` 13 | 14 | 3. Navigate to the project directory: 15 | 16 | ```sh 17 | cd actix-web-github-repo-info 18 | ``` 19 | 20 | 4. Build the project: 21 | 22 | ```sh 23 | cargo build 24 | ``` 25 | 26 | ## Usage 27 | 28 | To run the server, use the following command: 29 | 30 | ```sh 31 | cargo run 32 | ``` 33 | 34 | The server will start and listen on `http://localhost:8080`. You can access the following endpoints: 35 | 36 | - `/repo/{owner}/{repo}`: Fetches information about the specified GitHub repository. 37 | 38 | ## Testing 39 | 40 | To run the tests, use the following command: 41 | 42 | ```sh 43 | cargo test 44 | ``` 45 | 46 | The tests cover the server routes and error handling. 47 | 48 | ## Features 49 | 50 | - Actix Web: Utilizes the Actix Web framework to build a lightweight web service. 51 | - GitHub API: Fetches repository information using the GitHub API. 52 | - Error Handling: Demonstrates error handling in Actix Web applications. 53 | 54 | ## How It Works 55 | 56 | ### Actix Web Server 57 | 58 | The Actix Web server is configured to listen on `http://localhost:8080`. It defines a single route that accepts two path parameters: `{owner}` and `{repo}`. When a request is made to this route, the server fetches information about the specified GitHub repository using the GitHub API. 59 | 60 | ### GitHub API Integration 61 | 62 | The server makes a request to the GitHub API to retrieve information about the specified repository. It parses the JSON response and returns relevant details such as the repository name, description, stars, forks, and the URL. 63 | 64 | ### Error Handling 65 | 66 | The application handles errors gracefully by returning appropriate HTTP status codes and error messages when encountering issues such as invalid repository names or failed API requests. 67 | 68 | ## Contributing 69 | 70 | Contributions to this project are welcome! Whether it's submitting bug reports, suggesting enhancements, or contributing code, all forms of collaboration are appreciated. 71 | 72 | ## License 73 | 74 | This project is licensed under the MIT License. See the [MIT License](https://opensource.org/licenses/MIT) for details. 75 | 76 | Happy coding, and may the Actix be with you! 🦀✨ 77 | -------------------------------------------------------------------------------- /Module02/gitCheck/src/handlers.rs: -------------------------------------------------------------------------------- 1 | use crate::model::RepoInfo; 2 | use actix_web::{web, HttpResponse, Responder}; 3 | use reqwest; 4 | use serde_json::from_str; 5 | 6 | pub async fn get_repo_info(path: web::Path<(String, String)>) -> impl Responder { 7 | let (owner, repo) = path.into_inner(); 8 | let url = format!("https://api.github.com/repos/{}/{}", owner, repo); 9 | let client = reqwest::Client::new(); 10 | 11 | let response = client 12 | .get(&url) 13 | .header("User-Agent", "request") 14 | .send() 15 | .await; 16 | 17 | match response { 18 | Ok(res) => { 19 | if res.status().is_success() { 20 | let body = res.text().await.unwrap(); 21 | let repo_info: RepoInfo = from_str(&body).unwrap(); 22 | HttpResponse::Ok().json(repo_info) 23 | } else { 24 | HttpResponse::NotFound().body("Repository not Found") 25 | } 26 | } 27 | Err(_) => HttpResponse::InternalServerError().finish(), 28 | } 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | use actix_web::http::StatusCode; 35 | use actix_web::{test, App}; 36 | 37 | #[actix_rt::test] 38 | async fn test_get_repo_info() { 39 | let mut app = 40 | test::init_service(App::new().route("/{owner}/{repo}", web::get().to(get_repo_info))) 41 | .await; 42 | 43 | let req = test::TestRequest::get().uri("/rust-lang/rust").to_request(); 44 | let resp = test::call_service(&mut app, req).await; 45 | 46 | assert_eq!(resp.status(), StatusCode::OK); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Module02/gitCheck/src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{web, App, HttpServer}; 2 | 3 | mod handlers; 4 | mod model; 5 | 6 | #[actix_web::main] 7 | async fn main() -> std::io::Result<()> { 8 | HttpServer::new(|| { 9 | App::new().service( 10 | web::scope("/repo").route("/{owner}/{repo}", web::get().to(handlers::get_repo_info)), 11 | ) 12 | }) 13 | .bind("127.0.0.1:5500")? 14 | .run() 15 | .await 16 | } 17 | 18 | #[cfg(test)] 19 | mod tests { 20 | use super::*; 21 | use actix_web::{http::StatusCode, test}; 22 | 23 | #[actix_rt::test] 24 | async fn test_get_repo_info() { 25 | let mut app = test::init_service(App::new().service( 26 | web::scope("/repo").route("/{owner}/{repo}", web::get().to(handlers::get_repo_info)), 27 | )) 28 | .await; 29 | 30 | let req = test::TestRequest::get() 31 | .uri("/repo/rust-lang/rust") 32 | .to_request(); 33 | let resp = test::call_service(&mut app, req).await; 34 | 35 | assert_eq!(resp.status(), StatusCode::OK); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Module02/gitCheck/src/model.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | #[derive(Serialize, Deserialize)] 5 | pub struct RepoInfo { 6 | pub name: String, 7 | pub description: Option, 8 | pub html_url: String, 9 | pub stargazers_count: u32, 10 | pub forks_count: u32, 11 | } 12 | -------------------------------------------------------------------------------- /Module03/data_vault/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "data_vault" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | serde = { version = "1.0", features = ["derive"] } 8 | serde_json = "1.0" 9 | 10 | -------------------------------------------------------------------------------- /Module03/data_vault/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | pub mod colors; 3 | 4 | // A structure to represent our key-value store 5 | struct SearchEngineKV { 6 | store: HashMap>, 7 | } 8 | 9 | impl SearchEngineKV { 10 | // Create a new empty store 11 | fn new() -> SearchEngineKV { 12 | SearchEngineKV { 13 | store: HashMap::new(), 14 | } 15 | } 16 | 17 | // Insert a URL for a given keyword 18 | fn insert(&mut self, key: String, value: String) { 19 | self.store.entry(key).or_insert_with(Vec::new).push(value); 20 | } 21 | 22 | // Retrieve URLs for a given keyword 23 | fn get(&self, key: &str) -> Option<&Vec> { 24 | self.store.get(key) 25 | } 26 | 27 | // Remove a URL from a keyword entry 28 | fn remove_url(&mut self, key: &str, url: &str) { 29 | if let Some(urls) = self.store.get_mut(key) { 30 | urls.retain(|u| u != url); 31 | if urls.is_empty() { 32 | self.store.remove(key); 33 | } 34 | } 35 | } 36 | } 37 | 38 | fn main() { 39 | let mut engine = SearchEngineKV::new(); 40 | 41 | // Adding some sample data 42 | engine.insert("Cplusplus".to_string(), "https://cplusplus.com/".to_string()); 43 | engine.insert("rust programming".to_string(), "https://doc.rust-lang.org".to_string()); 44 | engine.insert("web development".to_string(), "https://developer.mozilla.org".to_string()); 45 | engine.insert("web development".to_string(), "https://google.com".to_string()); 46 | 47 | 48 | // Retrieving data 49 | if let Some(urls) = engine.get("rust programming") { 50 | println!("URLs for 'rust programming': {:?}", urls); 51 | } 52 | 53 | // Removing a URL 54 | engine.remove_url("web development", "https://developer.mozilla.org"); 55 | 56 | // Check if URL was removed // fix the line below 57 | if let Some(urls) = engine.get("web development") { 58 | println!("URLs for 'web development' after removal: {:?}", urls); 59 | } else { 60 | println!("No URLs found for 'web development' after removal"); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /Module03/data_vault_exx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "data_vault_exx" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | argon2 = "0.5.3" 8 | indicatif = "0.17.8" 9 | rand = { version = "0.8.5", features = ["getrandom"] } 10 | serde = { version = "1.0.209", features = ["derive"] } 11 | serde_json = "1.0.127" 12 | termion = "4.0.2" 13 | 14 | -------------------------------------------------------------------------------- /Module03/data_vault_exx/Explanations.md: -------------------------------------------------------------------------------- 1 | # Rust Vault Application Documentation 2 | 3 | ## Overview 4 | This Rust application provides a secure vault system for storing key-value pairs, protected by a hashed password. It includes features for password hashing, serialization, error handling, file I/O, command-line argument parsing, progress bar display, and terminal input handling. 5 | 6 | ## Features 7 | 8 | ### Password Hashing and Verification 9 | - **Crate**: `argon2` 10 | - **Usage**: 11 | - `PasswordHash` 12 | - `PasswordHasher` 13 | - `PasswordVerifier` 14 | - `SaltString` 15 | - **Description**: Provides functionality for hashing and verifying passwords using the Argon2 algorithm. 16 | 17 | ### Serialization and Deserialization 18 | - **Crate**: `serde` 19 | - **Usage**: 20 | - `Serialize` 21 | - `Deserialize` 22 | - **Description**: Enables serialization and deserialization of the `Vault` struct to and from JSON format. 23 | 24 | ### Error Handling 25 | - **Crate**: `thiserror` 26 | - **Usage**: 27 | - Custom error type `VaultError` 28 | - Implements `std::error::Error` for `PasswordHashError` 29 | - **Description**: Defines custom error types for handling various error scenarios in the application. 30 | 31 | ### File I/O 32 | - **Module**: `std::fs::File` 33 | - **Usage**: 34 | - Reading from and writing to files 35 | - `std::io::{self, Read, Write}` 36 | - **Description**: Manages file operations for saving and loading the vault data. 37 | 38 | ### Command Line Arguments 39 | - **Module**: `std::env::args` 40 | - **Description**: Handles command-line arguments to determine whether to save or load the vault. 41 | 42 | ### Progress Bar 43 | - **Crate**: `indicatif` 44 | - **Usage**: 45 | - `ProgressBar` 46 | - `ProgressStyle` 47 | - **Description**: Displays a progress bar during save and load operations to indicate progress. 48 | 49 | ### Terminal Input Handling 50 | - **Crate**: `termion` 51 | - **Usage**: 52 | - `termion::input::TermRead` 53 | - `termion::raw::IntoRawMode` 54 | - **Description**: Manages terminal input, including hiding password input for security. 55 | 56 | ## Data Structures 57 | 58 | ### Vault 59 | - **Type**: `struct` 60 | - **Fields**: 61 | - `data: HashMap` 62 | - **Methods**: 63 | - `new() -> Self`: Creates a new `Vault`. 64 | - `add_entry(&mut self, key: String, value: String)`: Adds a key-value pair to the vault. 65 | - `get_entry(&self, key: &str) -> Option<&String>`: Retrieves a value by key. 66 | - `save_to_file(&self, filename: &str, password: &str) -> Result<()>`: Serializes the vault and saves it to a file with a hashed password. 67 | - `load_from_file(filename: &str, password: &str) -> Result`: Loads and deserializes the vault from a file after verifying the password. 68 | 69 | ### PasswordHashError 70 | - **Type**: `struct` 71 | - **Fields**: 72 | - `0: argon2::password_hash::Error` 73 | - **Implements**: 74 | - `fmt::Display` 75 | - `std::error::Error` 76 | 77 | ### VaultError 78 | - **Type**: `enum` 79 | - **Variants**: 80 | - `Io(#[from] std::io::Error)`: For I/O errors. 81 | - `Serialization(#[from] serde_json::Error)`: For serialization errors. 82 | - `Argon2(String)`: For Argon2-specific errors. 83 | - `PasswordHash(#[from] PasswordHashError)`: For password hash errors. 84 | - `InvalidPassword`: For invalid password errors. 85 | - `InvalidFileFormat`: For invalid file format errors. 86 | 87 | ## Functions 88 | 89 | ### is_password_strong(password: &str) -> bool 90 | - **Description**: Checks if a password meets certain strength criteria (length, digit, uppercase letter, special character). 91 | - **Parameters**: 92 | - `password: &str`: The password to check. 93 | - **Returns**: `bool` indicating whether the password is strong. 94 | 95 | ### main() -> std::result::Result<(), Box> 96 | - **Description**: The entry point of the program. Handles command-line arguments to either save or load the vault. Manages user input for passwords and displays progress bars. 97 | - **Returns**: `std::result::Result<(), Box>` -------------------------------------------------------------------------------- /Module05/Readme.md: -------------------------------------------------------------------------------- 1 | # Reusable Modular Rust Components to be used in various use cases -------------------------------------------------------------------------------- /Module05/cachecomponent/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cachecomponent" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /Module05/cachecomponent/Readme.md: -------------------------------------------------------------------------------- 1 | The `GetCache` trait and its implementations for `InMemoryCache` and ``Cache`` structs provide a flexible and modular caching system. 2 | 3 | Here are some scenarios where such reusable modular components can be useful: 4 | 5 | ### 1. Web Applications 6 | In web development, caching is often used to improve performance by reducing the number of database queries or computationally expensive operations. Your caching system can be used in web frameworks like Rocket or actix-web to cache frequently accessed data, such as user sessions, configuration data, or intermediate computation results. 7 | 8 | ### 2. Distributed Systems 9 | In distributed systems, caching can help reduce the load on shared resources and improve overall system performance. Your caching system can be used in distributed systems built with frameworks like Tokio or async-std to cache data that's frequently accessed across multiple nodes. 10 | 11 | ### 3. Machine Learning and Data Science 12 | In machine learning and data science applications, caching can be used to store intermediate results of computationally expensive operations, such as data preprocessing or model training. Your caching system can be used in Rust libraries like rusty-machine or rusty-nn to cache intermediate results and improve performance. 13 | 14 | ### 4. Embedded Systems 15 | In embedded systems, caching can be used to improve performance and reduce memory usage. Your caching system can be used in embedded systems built with Rust to cache frequently accessed data, such as sensor readings or configuration data. 16 | 17 | ### 5. Game Development 18 | In game development, caching can be used to improve performance by reducing the number of computations required for game logic or physics simulations. Your caching system can be used in game engines like Piston or ggez to cache intermediate results and improve performance. -------------------------------------------------------------------------------- /Module05/cachecomponent/src/cache_component.rs: -------------------------------------------------------------------------------- 1 | // Import the necessary modules from the standard library 2 | use std::collections::HashMap; 3 | use std::hash::Hash; 4 | use std::marker::PhantomData; 5 | 6 | 7 | // Defined a trait (interface) for a cache that can get and set values 8 | pub trait GetCache { 9 | // Getting a value from the cache by its key 10 | fn get(&self, key: &K) -> Option<&V>; 11 | // Setting a value in the cache with a given key 12 | fn set(&mut self, key: K, value: V); 13 | } 14 | 15 | // Defined a struct for an in-memory cache 16 | pub struct InMemoryCache { 17 | // The underlying data storage is a HashMap 18 | data: HashMap, 19 | } 20 | 21 | // Implemented methods for the InMemoryCache struct 22 | impl InMemoryCache { 23 | // Creating a new, empty in-memory cache 24 | pub fn new() -> Self { 25 | InMemoryCache { data: HashMap::new() } 26 | } 27 | } 28 | 29 | // Implemented the GetCache trait for InMemoryCache 30 | impl GetCache for InMemoryCache { 31 | // Getting a value from the cache by its key 32 | fn get(&self, key: &K) -> Option<&V> { 33 | // Delegated to the underlying HashMap 34 | self.data.get(key) 35 | } 36 | // Setting a value in the cache with a given key 37 | fn set(&mut self, key: K, value: V) { 38 | // Delegated to the underlying HashMap 39 | self.data.insert(key, value); 40 | } 41 | } 42 | 43 | // Defined a struct for a cache that can use different strategies 44 | pub struct Cache> { 45 | // The underlying cache strategy 46 | strategy: T, 47 | _marker: PhantomData<(K, V)>, 48 | } 49 | 50 | // Implement methods for the Cache struct 51 | impl> Cache { 52 | // Create a new cache with a given strategy 53 | pub fn new(strategy: T) -> Self { 54 | Cache { strategy, 55 | // PhantomData is a marker type that captures the type parameters 56 | _marker: PhantomData, 57 | } 58 | } 59 | 60 | // Get a value from the cache by its key 61 | pub fn get(&self, key: &K) -> Option<&V> { 62 | // Delegate to the underlying strategy 63 | self.strategy.get(key) 64 | } 65 | 66 | // Set a value in the cache with a given key 67 | pub fn set(&mut self, key: K, value: V) { 68 | // Delegate to the underlying strategy 69 | self.strategy.set(key, value); 70 | } 71 | } -------------------------------------------------------------------------------- /Module05/cachecomponent/src/main.rs: -------------------------------------------------------------------------------- 1 | pub mod cache_component; 2 | 3 | use cache_component::{Cache, InMemoryCache}; 4 | 5 | 6 | fn main() { 7 | let mut cache = Cache::new(InMemoryCache::new()); 8 | 9 | cache.set("key1".to_string(), 51); 10 | cache.set("key2".to_string(), 71); 11 | 12 | if let Some(value) = cache.get(&"key1".to_string()) 13 | { 14 | println!("Cached Value: {}", value); 15 | } else { 16 | println!("No value found in cache"); 17 | } 18 | 19 | // println!("Value for key1: {:?}", cache.get(&"key1".to_string())); 20 | // println!("Value for key2: {:?}", cache.get(&"key2".to_string())); 21 | // println!("Value for key3: {:?}", cache.get(&"key3".to_string())); 22 | 23 | 24 | } -------------------------------------------------------------------------------- /Module05/consolelog/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "component_logger" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /Module05/consolelog/Readme.md: -------------------------------------------------------------------------------- 1 | The modular logging system can be used in various scenarios where different logging strategies might be required. For example: 2 | 3 | Console Logging: As shown in the example, logging messages to the console. 4 | File Logging: You can create another struct that implements LogStrategy to log messages to a file. 5 | Remote Logging: Another implementation could send logs to a remote server. 6 | 7 | 8 | 9 | // Different File logging Example 10 | `` 11 | use std::fs::OpenOptions; 12 | use std::io::Write; 13 | 14 | pub struct FileLog { 15 | file_path: String, 16 | } 17 | 18 | impl FileLog { 19 | pub fn new(file_path: String) -> Self { 20 | FileLog { file_path } 21 | } 22 | } 23 | 24 | impl LogStrategy for FileLog { 25 | fn log(&self, message: &str) { 26 | let mut file = OpenOptions::new() 27 | .create(true) 28 | .append(true) 29 | .open(&self.file_path) 30 | .unwrap(); 31 | writeln!(file, "{}", message).unwrap(); 32 | } 33 | }`` -------------------------------------------------------------------------------- /Module05/consolelog/src/main.rs: -------------------------------------------------------------------------------- 1 | // include the structs only 2 | pub mod utility; 3 | 4 | use utility::{Logger, ConsoleLog}; 5 | 6 | fn main() { 7 | let console_logger = ConsoleLog; 8 | let logging = Logger::new(console_logger); 9 | 10 | logging.log("This is a message for logging"); 11 | logging.log("42"); 12 | } 13 | -------------------------------------------------------------------------------- /Module05/consolelog/src/utility.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | // Step 1: Define a Contract (Trait) 4 | pub trait LogStrategy { 5 | fn log(&self, message: &str); 6 | } 7 | 8 | // Step 2: Create a Concrete Implementation 9 | pub struct ConsoleLog; 10 | 11 | impl LogStrategy for ConsoleLog { 12 | fn log(&self, message: &str) { 13 | println!("{}", message); 14 | } 15 | } 16 | 17 | // Step 3: Define a Generic Logger 18 | pub struct Logger { 19 | strategy: T, 20 | } 21 | 22 | // Step 4: Implement Logger Methods 23 | impl Logger { 24 | pub fn new(strategy: T) -> Self { 25 | Logger { strategy } 26 | } 27 | 28 | pub fn log(&self, message: M) { 29 | self.strategy.log(&format!("{}", message)); 30 | } 31 | } -------------------------------------------------------------------------------- /Module07/btreemap/src/btree.rs: -------------------------------------------------------------------------------- 1 | use crate::node::Node; 2 | 3 | pub struct BTree { 4 | root: Node, 5 | degree: usize, 6 | } 7 | 8 | impl BTree { 9 | pub fn new(degree: usize) -> Self { 10 | assert!(degree >= 2, "Degree must be at least 2"); 11 | Self { 12 | root: Node::new(true), 13 | degree, 14 | } 15 | } 16 | 17 | pub fn insert(&mut self, key: K, value: V) { 18 | if self.root.keys_len() == 2 * self.degree - 1 { 19 | let mut new_root = Node::new(false); 20 | let mut old_root = std::mem::replace(&mut self.root, Node::new(true)); 21 | let (median_key, right_child) = old_root.split(); 22 | new_root.keys.push(median_key); 23 | new_root.children = Some(vec![Box::new(old_root), right_child]); 24 | self.root = new_root; 25 | } 26 | self.root.insert(key, value, self.degree - 1); 27 | } 28 | 29 | pub fn search<'a>(&'a self, key: &K) -> Option<&'a V> { 30 | self.root.search(key) 31 | } 32 | } -------------------------------------------------------------------------------- /Module07/btreemap/src/config.rs: -------------------------------------------------------------------------------- 1 | pub struct Config { 2 | pub degree: usize, 3 | } 4 | 5 | impl Config { 6 | pub fn load() -> Self { 7 | Self { 8 | degree: 4, // Example value; adjust as needed 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Module07/btreemap/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod btree; 2 | pub mod node; 3 | pub mod util; 4 | pub mod config; 5 | -------------------------------------------------------------------------------- /Module07/btreemap/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | 3 | pub struct DataStorage { 4 | store: BTreeMap, 5 | } 6 | 7 | impl DataStorage { 8 | pub fn new() -> Self { 9 | DataStore { 10 | store: BTreeMap::new(), 11 | } 12 | } 13 | 14 | pub fn insert(&mut self, key: K, value: V) { 15 | self.store.insert(key, value); 16 | } 17 | 18 | pub fn get(&self, key: &K) -> Option<&V> { 19 | self.store.get(key) 20 | } 21 | } 22 | 23 | fn main() { 24 | // Create a new DataStorage instance for storing i32 keys and String values 25 | let mut storage = DataStorage::::new(); 26 | 27 | // Insert some data 28 | storage.insert(1, "One".to_string()); 29 | storage.insert(2, "Two".to_string()); 30 | storage.insert(3, "Three".to_string()); 31 | 32 | // Retrieve and print data 33 | if let Some(value) = storage.get(&2) { 34 | println!("Value for key 2: {}", value); 35 | } 36 | 37 | // Try to get a non-existent key 38 | if let Some(value) = storage.get(&4) { 39 | println!("Value for key 4: {}", value); 40 | } else { 41 | println!("No value found for key 4"); 42 | } 43 | } -------------------------------------------------------------------------------- /Module07/btreemap/src/node.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ord; 2 | 3 | pub struct Node { 4 | pub keys: Vec, 5 | pub values: Option>, // Only for leaf nodes 6 | pub children: Option>>>, // Only for internal nodes 7 | } 8 | 9 | impl Node { 10 | pub fn new(is_leaf: bool) -> Self { 11 | Self { 12 | keys: Vec::new(), 13 | values: if is_leaf { Some(Vec::new()) } else { None }, 14 | children: if !is_leaf { Some(Vec::new()) } else { None }, 15 | } 16 | } 17 | 18 | pub fn keys_len(&self) -> usize { 19 | self.keys.len() 20 | } 21 | 22 | pub fn split(&mut self) -> (K, Box>) { 23 | let mid = self.keys.len() / 2; 24 | let median_key = self.keys[mid].clone(); 25 | 26 | let mut right_child = Box::new(Node::new(self.is_leaf())); 27 | right_child.keys = self.keys.split_off(mid + 1); 28 | 29 | if let Some(ref mut v) = self.values { 30 | right_child.values = Some(v.split_off(mid + 1)); 31 | } 32 | 33 | if let Some(ref mut c) = self.children { 34 | right_child.children = Some(c.split_off(mid + 1)); 35 | } 36 | 37 | self.keys.pop(); // Remove the median key from the left node 38 | 39 | (median_key, right_child) 40 | } 41 | 42 | pub fn insert(&mut self, key: K, value: V, degree: usize) { 43 | let pos = self.keys.binary_search(&key).unwrap_or_else(|e| e); 44 | 45 | if self.is_leaf() { 46 | self.keys.insert(pos, key); 47 | self.values.as_mut().unwrap().insert(pos, value); 48 | } else { 49 | let child = &mut self.children.as_mut().unwrap()[pos]; 50 | child.insert(key, value, degree); 51 | 52 | if child.keys_len() > degree { 53 | let (median_key, right_child) = child.split(); 54 | self.keys.insert(pos, median_key); 55 | self.children.as_mut().unwrap().insert(pos + 1, right_child); 56 | } 57 | } 58 | } 59 | 60 | pub fn search<'a>(&'a self, key: &K) -> Option<&'a V> { 61 | let pos = self.keys.binary_search(key).unwrap_or_else(|e| e); 62 | 63 | if pos < self.keys.len() && &self.keys[pos] == key { 64 | self.values.as_ref().unwrap().get(pos) 65 | } else if self.is_leaf() { 66 | None 67 | } else { 68 | self.children.as_ref().unwrap()[pos].search(key) 69 | } 70 | } 71 | 72 | pub fn is_leaf(&self) -> bool { 73 | self.children.is_none() 74 | } 75 | } -------------------------------------------------------------------------------- /Module07/btreemap/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use super::*; 4 | use std::time::Instant; 5 | 6 | #[test] 7 | fn test_insertion() { 8 | let mut btree = BTree::new(3); 9 | btree.insert(10, "ten"); 10 | btree.insert(20, "twenty"); 11 | assert_eq!(btree.search(10), Some(&"ten")); 12 | } 13 | 14 | #[test] 15 | fn test_deletion() { 16 | let mut btree = BTree::new(3); 17 | btree.insert(10, "ten"); 18 | btree.insert(20, "twenty"); 19 | btree.delete(10); 20 | assert_eq!(btree.search(10), None); 21 | } 22 | 23 | #[test] 24 | fn test_performance() { 25 | let mut btree = BTree::new(4); 26 | let start = Instant::now(); 27 | 28 | for i in 0..10000 { 29 | btree.insert(i, i.to_string()); 30 | } 31 | 32 | let duration = start.elapsed(); 33 | println!("Insertion took {:?}", duration); 34 | 35 | assert!(duration.as_secs_f32() < 2.0); // Check performance threshold 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Module07/btreemap/src/util.rs: -------------------------------------------------------------------------------- 1 | // src/utils.rs 2 | /* 3 | optimize_memory_usage: Converts a Vec to a VecDeque for more efficient insertions and deletions if those operations are frequent. 4 | reuse_buffers: Resizes existing buffers instead of creating new ones, reducing allocation overhead. 5 | handle_large_data: Processes large datasets in chunks to avoid high memory usage from large allocations. 6 | 7 | */ 8 | use std::collections::VecDeque; 9 | 10 | // Optimizes memory usage by using a memory-efficient data structure 11 | pub fn optimize_memory_usage(data: Vec) -> VecDeque { 12 | let mut optimized_data = VecDeque::with_capacity(data.len()); 13 | for item in data { 14 | optimized_data.push_back(item); 15 | } 16 | optimized_data 17 | } 18 | 19 | // Function to avoid excessive allocations by reusing existing buffers 20 | pub fn reuse_buffers(existing: &mut Vec, new_capacity: usize) { 21 | if existing.capacity() < new_capacity { 22 | existing.reserve(new_capacity - existing.len()); 23 | } 24 | } 25 | 26 | // Efficiently handle large data by using slices 27 | pub fn handle_large_data(data: &[T]) { 28 | // Example operation: Process slices of data to avoid large allocations 29 | for _chunk in data.chunks(1024) { 30 | // Process each chunk of data 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Module07/valuetree/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "btreemap" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [profile.release] 7 | debug = true 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /Module07/valuetree/Readme.md: -------------------------------------------------------------------------------- 1 | # ValueTree 2 | 3 | A simple and efficient key-value storage implementation in Rust using `BTreeMap`. This project provides a straightforward way to store, retrieve, and remove key-value pairs while maintaining order. 4 | 5 | ## Table of Contents 6 | 7 | - [Features](#features) 8 | - [Installation](#installation) 9 | - [Usage](#usage) 10 | - [API Reference](#api-reference) 11 | - [Unit Tests](#unit-tests) 12 | - [Contributing](#contributing) 13 | - [License](#license) 14 | 15 | ## Features 16 | 17 | - **Ordered Storage**: Utilizes `BTreeMap` to maintain the order of keys. 18 | - **Basic Operations**: Supports insertion, retrieval, and deletion of key-value pairs. 19 | - **Type Safety**: Generic implementation allows for any types that implement the `Ord` trait for keys. 20 | 21 | ## Installation 22 | 23 | To use this library, ensure you have Rust installed. You can install Rust using [rustup](https://rustup.rs/). 24 | 25 | 26 | ## Unit Tests 27 | 28 | The project includes a comprehensive suite of unit tests to ensure the correctness and performance of the `DataStorage` implementation. These tests cover various aspects of the data structure's functionality: 29 | 30 | 1. **Insertion Test**: Verifies that elements can be correctly inserted and retrieved. 31 | 2. **Deletion Test**: Ensures that elements can be properly removed from the storage. 32 | 3. **Deletion of Non-existent Key**: Checks the behavior when attempting to remove a key that doesn't exist. 33 | 4. **Insertion Overwrite**: Confirms that inserting a value with an existing key overwrites the previous value. 34 | 5. **Empty Storage Test**: Validates the behavior of an empty storage structure. 35 | 6. **Performance Test**: Measures the insertion time for a large number of elements to ensure efficiency. 36 | 7. **Multiple Insertions Test**: Verifies the correctness of multiple insertions and retrievals. 37 | 8. **Removal of All Elements**: Ensures that all elements can be removed correctly. 38 | 39 | These tests help maintain the reliability and efficiency of the `DataStorage` implementation. They can be run using the command `cargo test` in the project directory. 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Module07/valuetree/src/ast.rs: -------------------------------------------------------------------------------- 1 | extern crate syn; 2 | extern crate quote; 3 | 4 | use syn::{File, Item}; 5 | use quote::ToTokens; 6 | 7 | fn main() { 8 | let code = r#" 9 | pub struct DataStorage { 10 | store: BTreeMap, 11 | } 12 | impl DataStorage { 13 | pub fn new() -> Self { 14 | DataStorage { 15 | store: BTreeMap::new(), 16 | } 17 | } 18 | 19 | pub fn insert(&mut self, key: K, value: V) { 20 | self.store.insert(key, value); 21 | } 22 | 23 | pub fn get(&self, key: &K) -> Option<&V> { 24 | self.store.get(key) 25 | } 26 | 27 | pub fn remove(&mut self, key: &K) -> Option { 28 | self.store.remove(key) 29 | } 30 | } 31 | fn main() { 32 | let mut storage = DataStorage::::new(); 33 | storage.insert(1, "One".to_string()); 34 | storage.insert(2, "Two".to_string()); 35 | storage.insert(3, "Three".to_string()); 36 | 37 | if let Some(value) = storage.get(&2) { 38 | println!("Value for key 2: {}", value); 39 | } 40 | 41 | if let Some(value) = storage.get(&12) { 42 | println!("Value for key 12 : {}", value); 43 | } else { 44 | println!("No value found for key 4"); 45 | } 46 | } 47 | "#; 48 | 49 | let syntax_tree: File = syn::parse_str(code).expect("Unable to parse code"); 50 | 51 | for item in syntax_tree.items { 52 | match item { 53 | Item::Struct(item_struct) => { 54 | println!("Struct: {}", item_struct.ident); 55 | for field in item_struct.fields { 56 | println!(" Field: {:?}", field); 57 | } 58 | } 59 | Item::Impl(item_impl) => { 60 | println!("Impl: {:?}", item_impl.self_ty); 61 | for item in item_impl.items { 62 | match item { 63 | syn::ImplItem::Method(method) => { 64 | println!(" Method: {}", method.sig.ident); 65 | } 66 | _ => {} 67 | } 68 | } 69 | } 70 | Item::Fn(item_fn) => { 71 | println!("Function: {}", item_fn.sig.ident); 72 | } 73 | _ => {} 74 | } 75 | } 76 | } 77 | = -------------------------------------------------------------------------------- /Module07/valuetree/src/btree.rs: -------------------------------------------------------------------------------- 1 | use crate::node::Node; 2 | 3 | pub struct BTree { 4 | root: Node, 5 | degree: usize, 6 | } 7 | 8 | impl BTree { 9 | pub fn new(degree: usize) -> Self { 10 | assert!(degree >= 2, "Degree must be at least 2"); 11 | Self { 12 | root: Node::new(true), 13 | degree, 14 | } 15 | } 16 | 17 | pub fn insert(&mut self, key: K, value: V) { 18 | if self.root.keys_len() == 2 * self.degree - 1 { 19 | let mut new_root = Node::new(false); 20 | let mut old_root = std::mem::replace(&mut self.root, Node::new(true)); 21 | let (median_key, right_child) = old_root.split(); 22 | new_root.keys.push(median_key); 23 | new_root.children = Some(vec![Box::new(old_root), right_child]); 24 | self.root = new_root; 25 | } 26 | self.root.insert(key, value, self.degree - 1); 27 | } 28 | 29 | pub fn search<'a>(&'a self, key: &K) -> Option<&'a V> { 30 | self.root.search(key) 31 | } 32 | } -------------------------------------------------------------------------------- /Module07/valuetree/src/config.rs: -------------------------------------------------------------------------------- 1 | pub struct Config { 2 | pub degree: usize, 3 | } 4 | 5 | impl Config { 6 | pub fn load() -> Self { 7 | Self { 8 | degree: 4, // Example value; adjust as needed 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Module07/valuetree/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod btree; 2 | pub mod node; 3 | pub mod util; 4 | pub mod config; 5 | -------------------------------------------------------------------------------- /Module07/valuetree/src/node.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ord; 2 | 3 | pub struct Node { 4 | pub keys: Vec, 5 | pub values: Option>, // Only for leaf nodes 6 | pub children: Option>>>, // Only for internal nodes 7 | } 8 | 9 | impl Node { 10 | pub fn new(is_leaf: bool) -> Self { 11 | Self { 12 | keys: Vec::new(), 13 | values: if is_leaf { Some(Vec::new()) } else { None }, 14 | children: if !is_leaf { Some(Vec::new()) } else { None }, 15 | } 16 | } 17 | 18 | pub fn keys_len(&self) -> usize { 19 | self.keys.len() 20 | } 21 | 22 | pub fn split(&mut self) -> (K, Box>) { 23 | let mid = self.keys.len() / 2; 24 | let median_key = self.keys[mid].clone(); 25 | 26 | let mut right_child = Box::new(Node::new(self.is_leaf())); 27 | right_child.keys = self.keys.split_off(mid + 1); 28 | 29 | if let Some(ref mut v) = self.values { 30 | right_child.values = Some(v.split_off(mid + 1)); 31 | } 32 | 33 | if let Some(ref mut c) = self.children { 34 | right_child.children = Some(c.split_off(mid + 1)); 35 | } 36 | 37 | self.keys.pop(); // Remove the median key from the left node 38 | 39 | (median_key, right_child) 40 | } 41 | 42 | pub fn insert(&mut self, key: K, value: V, degree: usize) { 43 | let pos = self.keys.binary_search(&key).unwrap_or_else(|e| e); 44 | 45 | if self.is_leaf() { 46 | self.keys.insert(pos, key); 47 | self.values.as_mut().unwrap().insert(pos, value); 48 | } else { 49 | let child = &mut self.children.as_mut().unwrap()[pos]; 50 | child.insert(key, value, degree); 51 | 52 | if child.keys_len() > degree { 53 | let (median_key, right_child) = child.split(); 54 | self.keys.insert(pos, median_key); 55 | self.children.as_mut().unwrap().insert(pos + 1, right_child); 56 | } 57 | } 58 | } 59 | 60 | pub fn search<'a>(&'a self, key: &K) -> Option<&'a V> { 61 | let pos = self.keys.binary_search(key).unwrap_or_else(|e| e); 62 | 63 | if pos < self.keys.len() && &self.keys[pos] == key { 64 | self.values.as_ref().unwrap().get(pos) 65 | } else if self.is_leaf() { 66 | None 67 | } else { 68 | self.children.as_ref().unwrap()[pos].search(key) 69 | } 70 | } 71 | 72 | pub fn is_leaf(&self) -> bool { 73 | self.children.is_none() 74 | } 75 | } -------------------------------------------------------------------------------- /Module07/valuetree/src/util.rs: -------------------------------------------------------------------------------- 1 | // src/utils.rs 2 | /* 3 | optimize_memory_usage: Converts a Vec to a VecDeque for more efficient insertions and deletions if those operations are frequent. 4 | reuse_buffers: Resizes existing buffers instead of creating new ones, reducing allocation overhead. 5 | handle_large_data: Processes large datasets in chunks to avoid high memory usage from large allocations. 6 | 7 | */ 8 | use std::collections::VecDeque; 9 | 10 | // Optimizes memory usage by using a memory-efficient data structure 11 | pub fn optimize_memory_usage(data: Vec) -> VecDeque { 12 | let mut optimized_data = VecDeque::with_capacity(data.len()); 13 | for item in data { 14 | optimized_data.push_back(item); 15 | } 16 | optimized_data 17 | } 18 | 19 | // Function to avoid excessive allocations by reusing existing buffers 20 | pub fn reuse_buffers(existing: &mut Vec, new_capacity: usize) { 21 | if existing.capacity() < new_capacity { 22 | existing.reserve(new_capacity - existing.len()); 23 | } 24 | } 25 | 26 | // Efficiently handle large data by using slices 27 | pub fn handle_large_data(data: &[T]) { 28 | // Example operation: Process slices of data to avoid large allocations 29 | for _chunk in data.chunks(1024) { 30 | // Process each chunk of data 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Module08/banking/.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgres://abir1203:sadface@localhost/database_name -------------------------------------------------------------------------------- /Module08/banking/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "banking" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | axum = "0.7.7" 8 | dotenv = "0.15.0" 9 | serde = "1.0.215" 10 | serde_json = "1.0.132" 11 | sqlx = "0.8.2" 12 | tokio = "1.41.1" 13 | tracing = "0.1.40" 14 | tracing-subscriber = "0.3.18" 15 | -------------------------------------------------------------------------------- /Module08/banking/src/config.rs: -------------------------------------------------------------------------------- 1 | use dotenv::dotenv; 2 | use std::env; 3 | 4 | pub struct Config { 5 | pub database_url: String, 6 | } 7 | 8 | impl Config { 9 | pub async fn from_env() -> Self { 10 | dotenv().ok(); 11 | let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 12 | Config {database_url} 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Module08/banking/src/db/account.rs: -------------------------------------------------------------------------------- 1 | use crate::models::Account; 2 | use crate::errors::AppError; 3 | use sqlx::{PgPool, query_as}; 4 | use bigdecimal::BigDecimal; 5 | 6 | pub async fn create_account(pool: &PgPool, name: &str) -> Result { 7 | query_as!( 8 | Account, 9 | "INSERT INTO accounts (name, balance) VALUES ($1, 0.0) RETURNING id, name, balance", 10 | name 11 | ) 12 | .fetch_one(pool) 13 | .await 14 | .map_err(AppError::DatabaseError) 15 | } -------------------------------------------------------------------------------- /Module08/banking/src/db/mod.rs: -------------------------------------------------------------------------------- 1 | use sqlx::{PgPool, Pool, Postgres}; 2 | use crate::config::Config; 3 | 4 | pub async fn create_pool(config: &Config) -> PgPool { 5 | PgPool::connect(&config.database_url) 6 | .await 7 | .expect("Failed to create database pool") 8 | } -------------------------------------------------------------------------------- /Module08/banking/src/db/transaction.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module08/banking/src/db/transaction.rs -------------------------------------------------------------------------------- /Module08/banking/src/errors.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | use axum::{http::StatusCode, response::IntoResponse}; 3 | use serde_json::json; 4 | 5 | #[derive(Error, Debug)] 6 | pub enum AppError { 7 | #[error("Database error: {0}")] 8 | DatabaseError(#[from] sqlx::Error), 9 | #[error("Account not found")] 10 | AccountNotFound, 11 | #[error("Insufficient funds")] 12 | InsufficientFunds, 13 | } 14 | 15 | impl IntoResponse for AppError { 16 | fn into_response(self) -> axum::response::Response { 17 | let (status, error_message) = match self { 18 | AppError::DatabaseError(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Database error"), 19 | AppError::AccountNotFound => (StatusCode::NOT_FOUND, "Account not found"), 20 | AppError::InsufficientFunds => (StatusCode::BAD_REQUEST, "Insufficient funds"), 21 | }; 22 | 23 | (status, axum::Json(json!({ "error": error_message }))).into_response() 24 | } 25 | } -------------------------------------------------------------------------------- /Module08/banking/src/main.rs: -------------------------------------------------------------------------------- 1 | use banking::config::get_config; 2 | use banking::routes::create_routes; 3 | 4 | #[tokio::main] 5 | async fn main() { 6 | let config = get_config().await; 7 | let pool = config.create_db_pool().await.unwrap(); 8 | let app = create_routes(pool); 9 | let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 10 | dotenv().ok(); // Load environment variables from .env file 11 | 12 | axum::Server::bind(&config.server_address) 13 | .serve(app.into_make_service()) 14 | .await 15 | .unwrap(); 16 | } -------------------------------------------------------------------------------- /Module08/banking/src/models/account.rs: -------------------------------------------------------------------------------- 1 | // src/models/account.rs 2 | use serde::{Deserialize, Serialize}; 3 | use bigdecimal::BigDecimal; 4 | use sqlx::FromRow; 5 | 6 | #[derive(Debug, Serialize, Deserialize, FromRow)] 7 | pub struct Account { 8 | pub id: i32, 9 | pub name: String, 10 | pub balance: BigDecimal, 11 | } 12 | 13 | #[derive(Debug, Serialize, Deserialize)] 14 | pub struct NewAccount { 15 | pub name: String, 16 | } 17 | -------------------------------------------------------------------------------- /Module08/banking/src/models/transaction.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use bigdecimal::BigDecimal; 3 | use sqlx::FromRow; 4 | use chrono::{DateTime, Utc}; 5 | 6 | #[derive(Debug, Serialize, Deserialize, FromRow)] 7 | pub struct Transaction { 8 | pub id: i32, 9 | pub from_account_id: Option, 10 | pub to_account_id: Option, 11 | pub amount: BigDecimal, 12 | pub transaction_type: String, 13 | pub created_at: DateTime, 14 | } -------------------------------------------------------------------------------- /Module08/banking/src/routes/account.rs: -------------------------------------------------------------------------------- 1 | use axum::{extract::State, Json}; 2 | use crate::{db::account, models::NewAccount, AppError}; 3 | use crate::db::create_account; 4 | use crate::db::Account; 5 | 6 | pub async fn create_account_handler( 7 | State(pool): State, 8 | Json(payload): Json, 9 | ) -> Result, AppError> { 10 | let account = account::create_account(&pool, &payload.name).await?; 11 | Ok(Json(account)) 12 | } -------------------------------------------------------------------------------- /Module08/banking/src/routes/mod.rs: -------------------------------------------------------------------------------- 1 | use axum::{Router, routing::post}; 2 | use crate::db::DbPool; 3 | use std::sync::Arc; 4 | 5 | pub fn create_routes(pool: Arc) -> Router { 6 | Router::new() 7 | .route("/accounts", post(create_account_handler)) 8 | .route("/accounts/:id/deposit", post(deposit_handler)) 9 | .layer(axum::extract::Extension(pool)) 10 | } -------------------------------------------------------------------------------- /Module08/banking/src/services/account_service.rs: -------------------------------------------------------------------------------- 1 | use crate::db::account; 2 | use crate::errors::AppError; 3 | use sqlx::PgPool; 4 | 5 | pub async fn create_account_service(pool: &PgPool, name: &str) -> Result { 6 | account::create_account(pool, name).await 7 | } -------------------------------------------------------------------------------- /Module09/.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgres://user:password@localhost/dbname 2 | JWT_SECRET=abir 3 | JWT_EXPIRATION=86400 4 | HOST=127.0.0.1 5 | PORT=8080 -------------------------------------------------------------------------------- /Module09/AmortizedCostAdvanced.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/AmortizedCostAdvanced.mp4 -------------------------------------------------------------------------------- /Module09/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust::1.68 as builder 2 | 3 | WORKDIR /usr/src/backend 4 | COPY . . 5 | 6 | RUN cargo build --release 7 | 8 | FROM debian::buster-slim 9 | 10 | RUN apt-get update && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/* 11 | 12 | COPY --from=builder /usr/src/backend/target/release/backend /usr/local/bin/backend 13 | 14 | CMD ["backend"] -------------------------------------------------------------------------------- /Module09/media/texts/02b8865db121f075.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Module09/media/texts/067e47c63ddd3127.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Module09/media/texts/38a2fbd3333e2b51.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Module09/media/texts/64cb41458ffa7112.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Module09/media/texts/7f33a0ccd2a76713.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Module09/media/texts/a4b94c96deb9ef21.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Module09/media/texts/ba31d1ef370d0d29.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Module09/media/texts/e8497c8cd8465f40.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/AmortizedCostAdvanced.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/AmortizedCostAdvanced.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/AmortizedCostRefined.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/AmortizedCostRefined.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1000529315_2516712950.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1000529315_2516712950.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1342615424_1257065805.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1342615424_1257065805.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1570874046_2323842036.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1570874046_2323842036.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1600594787_3800533162.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1600594787_3800533162.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1644675564_718189330.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1644675564_718189330.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_189541869_3613570100.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_189541869_3613570100.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2215745579_163205416.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2215745579_163205416.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2595125285_1304643872.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2595125285_1304643872.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2646125366_258853677.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2646125366_258853677.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2793458955_1425216704.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2793458955_1425216704.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2876327323_2864915012.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2876327323_2864915012.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2894392248_1180209270.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2894392248_1180209270.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2919340033_3490668070.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2919340033_3490668070.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_3068668600_921797842.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_3068668600_921797842.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_320231996_1535447459.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_320231996_1535447459.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_3891874688_4099317236.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_3891874688_4099317236.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_4129878736_1584757070.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_4129878736_1584757070.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_4150750034_2345848816.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_4150750034_2345848816.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_533474223_1796147278.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_533474223_1796147278.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_556781075_2280001411.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_556781075_2280001411.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_66812978_1041101844.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_66812978_1041101844.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_737070546_2881160873.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_737070546_2881160873.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_784179552_1872585525.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_784179552_1872585525.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_800706528_1010095989.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_800706528_1010095989.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3529212410_1760247645_2142691362.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3529212410_1760247645_2142691362.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/partial_movie_file_list.txt: -------------------------------------------------------------------------------- 1 | # This file is used internally by FFMPEG. 2 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3529212410_1760247645_2142691362.mp4' 3 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2876327323_2864915012.mp4' 4 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_3068668600_921797842.mp4' 5 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1570874046_2323842036.mp4' 6 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2595125285_1304643872.mp4' 7 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1644675564_718189330.mp4' 8 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_556781075_2280001411.mp4' 9 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_66812978_1041101844.mp4' 10 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2919340033_3490668070.mp4' 11 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2793458955_1425216704.mp4' 12 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_4150750034_2345848816.mp4' 13 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_189541869_3613570100.mp4' 14 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_533474223_1796147278.mp4' 15 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_800706528_1010095989.mp4' 16 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1600594787_3800533162.mp4' 17 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2215745579_163205416.mp4' 18 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2894392248_1180209270.mp4' 19 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_4129878736_1584757070.mp4' 20 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_2646125366_258853677.mp4' 21 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_320231996_1535447459.mp4' 22 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1342615424_1257065805.mp4' 23 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_1000529315_2516712950.mp4' 24 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_784179552_1872585525.mp4' 25 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_737070546_2881160873.mp4' 26 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostAdvanced/3040924799_3891874688_4099317236.mp4' 27 | -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1047548945_2225697842.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1047548945_2225697842.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1115191695_1609054424.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1115191695_1609054424.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1178597654_3936940076.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1178597654_3936940076.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1187074030_921797842.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1187074030_921797842.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_163472557_3934050777.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_163472557_3934050777.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1840646158_4000590238.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1840646158_4000590238.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1912175879_1803578682.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1912175879_1803578682.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1976618423_1455043070.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1976618423_1455043070.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2023230840_3095364569.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2023230840_3095364569.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_213720279_742841984.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_213720279_742841984.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2158552800_2215161034.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2158552800_2215161034.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2215745579_902315314.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2215745579_902315314.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2876327323_2864915012.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2876327323_2864915012.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2919340033_612882166.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2919340033_612882166.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3054095095_567640343.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3054095095_567640343.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3388956070_3416479938.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3388956070_3416479938.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_348530885_3153408772.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_348530885_3153408772.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3574089711_658649037.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3574089711_658649037.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3795840722_1437417951.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3795840722_1437417951.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3891874688_1846330621.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3891874688_1846330621.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_4259308663_658649037.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_4259308663_658649037.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_737070546_1068583945.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_737070546_1068583945.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_784179552_2918718511.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_784179552_2918718511.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_831676087_897214138.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_831676087_897214138.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_933458367_4063910195.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_933458367_4063910195.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_998441320_2982120678.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_998441320_2982120678.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3529212410_3514323760_2142691362.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3529212410_3514323760_2142691362.mp4 -------------------------------------------------------------------------------- /Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/partial_movie_file_list.txt: -------------------------------------------------------------------------------- 1 | # This file is used internally by FFMPEG. 2 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3529212410_3514323760_2142691362.mp4' 3 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2876327323_2864915012.mp4' 4 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1187074030_921797842.mp4' 5 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1047548945_2225697842.mp4' 6 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1178597654_3936940076.mp4' 7 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1912175879_1803578682.mp4' 8 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1115191695_1609054424.mp4' 9 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2023230840_3095364569.mp4' 10 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2919340033_612882166.mp4' 11 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_831676087_897214138.mp4' 12 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2158552800_2215161034.mp4' 13 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1840646158_4000590238.mp4' 14 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_933458367_4063910195.mp4' 15 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_213720279_742841984.mp4' 16 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3795840722_1437417951.mp4' 17 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3574089711_658649037.mp4' 18 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_4259308663_658649037.mp4' 19 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_2215745579_902315314.mp4' 20 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_1976618423_1455043070.mp4' 21 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3054095095_567640343.mp4' 22 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_348530885_3153408772.mp4' 23 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3388956070_3416479938.mp4' 24 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_998441320_2982120678.mp4' 25 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_163472557_3934050777.mp4' 26 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_784179552_2918718511.mp4' 27 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_737070546_1068583945.mp4' 28 | file 'file:/mnt/c/Users/mabba/Downloads/Rust_Modular/Module09/media/videos/a/1080p60/partial_movie_files/AmortizedCostRefined/3040924799_3891874688_1846330621.mp4' 29 | -------------------------------------------------------------------------------- /Module09/rust_backend/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_backend" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | actix-web = "4.9.0" 8 | bcrypt = "0.15.1" 9 | chrono = "0.4.38" 10 | config = "0.14.0" 11 | dotenv = "0.15.0" 12 | env_logger = "0.11.5" 13 | jsonwebtoken = "9.3.0" 14 | log = "0.4.22" 15 | serde = "1.0.210" 16 | serde_json = "1.0.128" 17 | sqlx = "0.8.2" 18 | thiserror = "1.0.64" 19 | tokio = "1.40.0" 20 | uuid = "1.10.0" 21 | 22 | 23 | 24 | [dev-dependencies] 25 | actix-rt = "2.8" 26 | -------------------------------------------------------------------------------- /Module09/rust_backend/src/'db/create_users_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE users ( 2 | id UUID PRIMARY KEY, 3 | username VARCHAR(50) UNIQUE NOT NULL, 4 | email VARCHAR(255) UNIQUE NOT NULL, 5 | password_hash VARCHAR(255) NOT NULL, 6 | created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP 7 | ); -------------------------------------------------------------------------------- /Module09/rust_backend/src/config.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use config::{Config, ConfigError, File}; 3 | 4 | #[derive(Debug, Deserialize)] 5 | pub struct Settings { 6 | pub host: String, 7 | pub port: u16, 8 | pub database_url: String, 9 | pub jwt_secret: String, 10 | pub jwt_expiration: i64, 11 | } 12 | 13 | pub fn load_config() -> Result { 14 | let mut s = Config::default(); 15 | 16 | s.merge(File::with_name("config/default"))?; 17 | s.merge(Environment::with_prefix("APP"))?; 18 | 19 | s.try_into() 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Module09/rust_backend/src/errors.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{HttpResponse, ResponseError}; 2 | use thiserror::Error; 3 | 4 | #[derive(Error, Debug)] 5 | pub enum AppError { 6 | #[error("Internal Server Error")] 7 | InternalServerError, 8 | #[error("Bad Request")] 9 | BadRequest, 10 | #[error("Unauthorized")] 11 | Unauthorized, 12 | #[error("Not Found")] 13 | NotFound, 14 | } 15 | 16 | impl ResponseError for AppError { 17 | fn error_response(&self) -> HttpResponse { 18 | match self { 19 | AppError::InternalServerError => { 20 | HttpResponse::InternalServerError().json("Internal Server Error") 21 | } 22 | AppError::BadRequest(ref message) => HttpResponse::BadRequest().json(message), 23 | AppError::Unauthorized => HttpResponse::Unauthorized().json("Unauthorized"), 24 | 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Module09/rust_backend/src/handlers/auth.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{web, HttpResponse, Responder}; 2 | use crate::models::user::{CreateUser, LoginUser}; 3 | use crate::services::auth; 4 | use crate::errors::AppError; 5 | 6 | pub async fn register(user: web::Json, pool: web::Data) -> Result { 7 | let user = auth::register_user(user.into_inner(), &pool).await?; 8 | Ok(HttpResponse::Ok().json(user)) 9 | } 10 | 11 | pub async fn login(creds: web::Json, pool: web::Data) -> Result { 12 | let token = auth::login_user(creds.into_inner(), &pool).await?; 13 | Ok(HttpResponse::Ok().json(json!({ "token": token }))) 14 | } -------------------------------------------------------------------------------- /Module09/rust_backend/src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{web, App, HttpServer}; 2 | use sqlx::postgres::PgPoolOptions; 3 | use dotenv::dotenv; 4 | 5 | 6 | mod config; 7 | mod errors; 8 | mod models; 9 | mod handlers; 10 | mod middleware; 11 | mod db; 12 | mod services; 13 | 14 | #[actix_web::main] 15 | async fn main() -> std::io::Result<()> { 16 | dotenv().ok(); 17 | env_logger::init(); 18 | 19 | let config = config::load_config().expect("Failed to load configuration"); 20 | let pool = PgPoolOptions::new() 21 | .max_connections(5) 22 | .connect(&config.database_url) 23 | .await 24 | .expect("Failed to create pool"); 25 | 26 | log::info!("Starting server at http://{}:{}", config.host, config.port); 27 | 28 | HttpServer::new(move || { 29 | App::new() 30 | .app_data(web::Data::new(pool.clone())) 31 | .wrap(middleware::auth::Authentication) 32 | .service( 33 | web::scope("/api") 34 | .service(handlers::health::health_check) 35 | .service(handlers::auth::login) 36 | .service(handlers::auth::register) 37 | ) 38 | }) 39 | .bind(format!("{}:{}", config.host, config.port))? 40 | .run() 41 | .await 42 | } -------------------------------------------------------------------------------- /Module09/rust_backend/src/middleware/auth.rs: -------------------------------------------------------------------------------- 1 | use actix_web::dev::{ServiceRequest, ServiceResponse}; 2 | use actix_web::Error; 3 | use actix_web::error::ErrorUnauthorized; 4 | use actix_web::http::header::{HeaderName, HeaderValue}; 5 | use actix_web::web::Data; 6 | use futures::future::{ok, Ready}; 7 | use jsonwebtoken::{decode, DecodingKey, Validation}; 8 | 9 | use crate::config::Settings; 10 | 11 | pub struct Authentication; 12 | 13 | impl Transform for Authentication 14 | where 15 | S: Service, Error = Error>, 16 | S::Future: 'static, 17 | B: 'static, 18 | { 19 | type Request = ServiceRequest; 20 | type Response = ServiceResponse; 21 | type Error = Error; 22 | type InitError = (); 23 | type Transform = AuthenticationMiddleware; 24 | type Future = Ready>; 25 | 26 | fn new_transform(&self, service: S) -> Self::Future { 27 | ok(AuthenticationMiddleware { service }) 28 | } 29 | } 30 | 31 | pub struct AuthenticationMiddleware { 32 | service: S, 33 | } 34 | 35 | impl Service for AuthenticationMiddleware 36 | where 37 | S: Service, Error = Error>, 38 | S::Future: 'static, 39 | B: 'static, 40 | { 41 | type Request = ServiceRequest; 42 | type Response = ServiceResponse; 43 | type Error = Error; 44 | type Future = Pin>>>; 45 | 46 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { 47 | self.service.poll_ready(cx) 48 | } 49 | 50 | fn call(&mut self, req: ServiceRequest) -> Self::Future { 51 | let auth_header = req.headers().get("Authorization"); 52 | let config = req.app_data::>().unwrap(); 53 | 54 | match auth_header { 55 | Some(auth_header) => { 56 | let auth_token = auth_header.to_str().unwrap().split("Bearer ").collect::>()[1]; 57 | let token_data = match decode::( 58 | &auth_token, 59 | &DecodingKey::from_secret(config.jwt_secret.as_ref()), 60 | &Validation::default(), 61 | ) { 62 | Ok(c) => c, 63 | Err(_) => return Box::pin(async move { Err(ErrorUnauthorized("Invalid token")) }), 64 | }; 65 | 66 | req.extensions_mut().insert(token_data.claims); 67 | 68 | let fut = self.service.call(req); 69 | Box::pin(async move { 70 | let res = fut.await?; 71 | Ok(res) 72 | }) 73 | } 74 | None => Box::pin(async move { Err(ErrorUnauthorized("Authorization header missing")) }), 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Module09/rust_backend/src/models/user.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use sqlx::FromRow; 3 | use uuid::Uuid; 4 | 5 | #[derive(Debug, Serialize, Deserialize, FromRow)] 6 | pub struct User { 7 | pub id: Uuid, 8 | pub username: String, 9 | pub email: String, 10 | pub password_hash: String, 11 | } 12 | 13 | #[derive(Debug, Serialize, Deserialize)] 14 | pub struct CreateUser { 15 | pub username: String, 16 | pub email: String, 17 | pub password: String, 18 | } 19 | 20 | 21 | #[derive(Debug, Serialize, Deserialize)] 22 | pub struct LoginUser { 23 | pub username: String, 24 | pub password: String, 25 | } -------------------------------------------------------------------------------- /Module09/rust_backend/src/nginx/backend.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name example.com; 4 | 5 | location / { 6 | proxy_pass http://127.0.0.1:8080; 7 | proxy_http_version 1.1; 8 | proxy_set_header Upgrade $http_upgrade; 9 | proxy_set_header Connection 'upgrade'; 10 | proxy_set_header Host $host; 11 | proxy_cache_bypass $http_upgrade; 12 | proxy_set_header X-Real-IP $remote_addr; 13 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 14 | proxy_set_header X-Forwarded-Proto $scheme; 15 | } 16 | 17 | # Security headers 18 | add_header X-Frame-Options "SAMEORIGIN" always; 19 | add_header X-XSS-Protection "1; mode=block" always; 20 | add_header X-Content-Type-Options "nosniff" always; 21 | add_header Referrer-Policy "no-referrer-when-downgrade" always; 22 | add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; 23 | add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; 24 | 25 | # SSL configuration (after obtaining SSL certificate) 26 | # listen 443 ssl http2; 27 | # ssl_certificate /path/to/fullchain.pem; 28 | # ssl_certificate_key /path/to/privkey.pem; 29 | # include /path/to/options-ssl-nginx.conf; 30 | } -------------------------------------------------------------------------------- /Module09/rust_backend/tests/auth.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/rust_backend/tests/auth.rs -------------------------------------------------------------------------------- /Module09/rust_backend/tests/healthcheck.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module09/rust_backend/tests/healthcheck.rs -------------------------------------------------------------------------------- /Module09/tokenize/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mon" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | regex = "1.11.0" 8 | -------------------------------------------------------------------------------- /Module10/generic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generic" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /Module10/generic/src/advanced_trait.rs: -------------------------------------------------------------------------------- 1 | pub trait Area { 2 | fn area(&self) -> f64; 3 | } 4 | 5 | pub trait Perimeter { 6 | fn perimeter(&self) -> f64; 7 | } 8 | 9 | pub struct Rectangle { 10 | pub width: f64, 11 | pub height: f64, 12 | } 13 | 14 | impl Area for Rectangle { 15 | fn area(&self) -> f64 { 16 | self.width * self.height 17 | } 18 | } 19 | 20 | impl Perimeter for Rectangle { 21 | fn perimeter(&self) -> f64 { 22 | 2.0 * (self.width + self.height) 23 | } 24 | } 25 | 26 | pub fn calculate_shape_properties(shape: &T) 27 | where 28 | T: Area + Perimeter, 29 | { 30 | println!( 31 | "Area: {}, Perimeter: {}", 32 | shape.area(), 33 | shape.perimeter() 34 | ); 35 | } 36 | 37 | pub fn run_example() { 38 | let rect = Rectangle { width: 5.0, height: 3.0 }; 39 | calculate_shape_properties(&rect); 40 | } 41 | -------------------------------------------------------------------------------- /Module10/generic/src/associated_types.rs: -------------------------------------------------------------------------------- 1 | pub trait Calculator { 2 | type Operand; 3 | type Result; 4 | 5 | fn calculate(&self, a: Self::Operand, b: Self::Operand) -> Self::Result; 6 | fn square(&self, a: Self::Operand) -> Self::Result; 7 | } 8 | 9 | pub struct Adder; 10 | 11 | impl Calculator for Adder { 12 | type Operand = i32; 13 | type Result = i32; 14 | 15 | fn calculate(&self, a: i32, b: i32) -> i32 { 16 | a + b 17 | } 18 | 19 | fn square(&self, a: i32) -> i32 { 20 | a * a 21 | } 22 | } 23 | 24 | pub fn run_example() { 25 | let adder = Adder; 26 | let sum = adder.calculate(3, 4); 27 | println!("3 + 4 = {}", sum); // Prints: 3 + 4 = 7 28 | 29 | let square = adder.square(5); 30 | println!("5 squared = {}", square); // Prints: 5 squared = 25 31 | } 32 | -------------------------------------------------------------------------------- /Module10/generic/src/higher_kind.rs: -------------------------------------------------------------------------------- 1 | /// The `Wrapper` struct is a custom generic type that takes another type `T`. 2 | /// It works with types that are `Option`, or other similar type constructors. 3 | 4 | pub struct Wrapper { 5 | value: Option, 6 | } 7 | 8 | impl Wrapper { 9 | /// Creates a new `Wrapper` with an initial value. 10 | /// 11 | /// # Arguments 12 | /// 13 | /// * `value` - An option that holds the value of type `T`. 14 | /// 15 | /// # Returns 16 | /// 17 | /// A new `Wrapper` instance containing the `Option`. 18 | pub fn new(value: Option) -> Self { 19 | Wrapper { value } 20 | } 21 | 22 | /// Maps the value inside the `Option` to a new value of type `U`, 23 | /// applying the function `f` on the current value. 24 | /// 25 | /// # Arguments 26 | /// 27 | /// * `f` - A closure that transforms `T` into `U`. 28 | /// 29 | /// # Returns 30 | /// 31 | /// A new `Wrapper` containing the transformed value. 32 | pub fn map(self, f: F) -> Wrapper 33 | where 34 | F: FnOnce(T) -> U, 35 | { 36 | Wrapper { 37 | value: self.value.map(f), 38 | } 39 | } 40 | 41 | /// Unwraps the value inside the `Wrapper` or returns a default value if `None`. 42 | /// 43 | /// # Arguments 44 | /// 45 | /// * `default` - The value to return in case the `Option` is `None`. 46 | /// 47 | /// # Returns 48 | /// 49 | /// The value inside the `Wrapper` or the `default` if `None`. 50 | pub fn unwrap_or(self, default: T) -> T { 51 | self.value.unwrap_or(default) 52 | } 53 | 54 | /// Checks if the `Wrapper` contains a value. 55 | /// 56 | /// # Returns 57 | /// 58 | /// `true` if the `Wrapper` contains `Some(T)`, `false` if `None`. 59 | pub fn is_some(&self) -> bool { 60 | self.value.is_some() 61 | } 62 | 63 | /// Retrieves the inner value, panicking if the value is `None`. 64 | /// 65 | /// # Panics 66 | /// 67 | /// This method will panic if the `Wrapper` contains `None`. 68 | pub fn unwrap(self) -> T { 69 | self.value.unwrap() 70 | } 71 | } 72 | 73 | impl Wrapper 74 | where 75 | T: std::fmt::Debug, 76 | { 77 | /// Prints the wrapped value. 78 | pub fn print(&self) { 79 | match &self.value { 80 | Some(val) => println!("{:?}", val), 81 | None => println!("None"), 82 | } 83 | } 84 | } 85 | 86 | /// The `run_example` function demonstrates how `Wrapper` works with higher-kinded types. 87 | pub fn run_example() { 88 | println!("--- Example 1: Basic mapping ---"); 89 | let wrapper = Wrapper::new(Some(10)); 90 | let mapped = wrapper.map(|x| x * 2); // Map `10` to `20` 91 | mapped.print(); // Prints: 20 92 | 93 | println!("--- Example 2: Unwrap or default ---"); 94 | let wrapper_none = Wrapper::new(None); 95 | let default_value = wrapper_none.unwrap_or(42); // Use default value `42` 96 | println!("Unwrapped or default: {}", default_value); // Prints: 42 97 | 98 | println!("--- Example 3: Check if some ---"); 99 | let wrapper_some = Wrapper::new(Some(5)); 100 | println!("Is Some? {}", wrapper_some.is_some()); // Prints: true 101 | 102 | println!("--- Example 4: Panic on unwrap ---"); 103 | // Uncomment to see panic: 104 | //let wrapper_none = Wrapper::new(None); 105 | //let panicked_value = wrapper_none.unwrap(); // Will panic: "called `Option::unwrap()` on a `None` value" 106 | } 107 | -------------------------------------------------------------------------------- /Module10/generic/src/main.rs: -------------------------------------------------------------------------------- 1 | mod where_syntax; 2 | mod sized_and_unsized; 3 | mod associated_types; 4 | mod operator_overloading; 5 | mod higher_kind; 6 | 7 | fn main() { 8 | println!("Rust Generics Playground:"); 9 | 10 | println!("\nRunning Where Clause Example:"); 11 | where_syntax::run_example(); 12 | 13 | println!("\nRunning Dynamically Sized Types Example:"); 14 | sized_and_unsized::run_example(); 15 | 16 | println!("\nRunning Associated Types Example:"); 17 | associated_types::run_example(); 18 | 19 | println!("\nRunning Operator Overloading Example:"); 20 | operator_overloading::run_example(); 21 | 22 | println!("\nRunning Higher-Kinded Types Example:"); 23 | higher_kind::run_example(); 24 | } 25 | -------------------------------------------------------------------------------- /Module10/generic/src/operator_overloading.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Add, Sub}; 2 | 3 | #[derive(Debug, PartialEq)] 4 | pub struct Vector2D { 5 | pub x: i32, 6 | pub y: i32, 7 | } 8 | 9 | impl Add for Vector2D { 10 | type Output = Self; 11 | 12 | fn add(self, other: Self) -> Self { 13 | Self { 14 | x: self.x + other.x, 15 | y: self.y + other.y, 16 | } 17 | } 18 | } 19 | 20 | impl Sub for Vector2D { 21 | type Output = Self; 22 | 23 | fn sub(self, other: Self) -> Self { 24 | Self { 25 | x: self.x - other.x, 26 | y: self.y - other.y, 27 | } 28 | } 29 | } 30 | 31 | pub fn run_example() { 32 | let v1 = Vector2D { x: 1, y: 2 }; 33 | let v2 = Vector2D { x: 3, y: 4 }; 34 | 35 | let sum = v1 + v2; 36 | println!("Sum: {:?}", sum); // Prints: Sum: Vector2D { x: 4, y: 6 } 37 | 38 | let v3 = Vector2D { x: 10, y: 20 }; 39 | let v4 = Vector2D { x: 5, y: 15 }; 40 | 41 | let diff = v3 - v4; 42 | println!("Difference: {:?}", diff); // Prints: Difference: Vector2D { x: 5, y: 5 } 43 | } 44 | -------------------------------------------------------------------------------- /Module10/generic/src/sized_and_unsized.rs: -------------------------------------------------------------------------------- 1 | pub fn print_message(message: &T) { 2 | println!("{}", message); 3 | } 4 | 5 | pub fn run_example() { 6 | let msg_str: &str = "Hello, world!"; 7 | let msg_string: String = String::from("Hello, Rust!"); 8 | 9 | print_message(msg_str); // Prints: Hello, world! 10 | print_message(&msg_string); // Prints: Hello, Rust! 11 | 12 | // Dynamically sized type via Box 13 | let boxed_str: Box = Box::new("Dynamically Sized Type"); 14 | print_message(&*boxed_str); // Prints: Dynamically Sized Type 15 | } 16 | -------------------------------------------------------------------------------- /Module10/generic/src/where_syntax.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | use std::fmt::Debug; 3 | 4 | pub struct DataProcessor 5 | where 6 | T: Clone + Debug, 7 | { 8 | data: Vec, 9 | } 10 | 11 | impl DataProcessor 12 | where 13 | T: Clone + Debug, 14 | { 15 | pub fn new(data: Vec) -> Self { 16 | Self { data } 17 | } 18 | 19 | pub fn process_data(&self, op: F) 20 | where 21 | F: Fn(&T), 22 | { 23 | for item in &self.data { 24 | op(item); 25 | } 26 | } 27 | 28 | pub fn map_data(&self, f: F) -> Vec 29 | where 30 | F: Fn(&T) -> U, 31 | { 32 | self.data.iter().map(f).collect() 33 | } 34 | 35 | pub fn aggregate(&self, f: F) -> Option 36 | where 37 | F: Fn(&T, &T) -> T, 38 | { 39 | if self.data.is_empty() { 40 | return None; 41 | } 42 | let mut result = self.data[0].clone(); 43 | for item in &self.data[1..] { 44 | result = f(&result, item); 45 | } 46 | Some(result) 47 | } 48 | 49 | pub fn time_process_data(&self, op: F) 50 | where 51 | F: Fn(&T), 52 | { 53 | let start = Instant::now(); 54 | self.process_data(op); 55 | let duration = start.elapsed(); 56 | println!("Processing took: {:?}", duration); 57 | } 58 | 59 | pub fn time_map_data(&self, f: F) -> Vec 60 | where 61 | F: Fn(&T) -> U, 62 | { 63 | let start = Instant::now(); 64 | let result = self.map_data(f); 65 | let duration = start.elapsed(); 66 | println!("Mapping took: {:?}", duration); 67 | result 68 | } 69 | } 70 | 71 | pub fn run_example() { 72 | let processor = DataProcessor::new(vec![1, 2, 3]); 73 | 74 | // Processing data 75 | processor.time_process_data(|item| println!("{:?}", item)); 76 | 77 | // Mapping data 78 | let mapped = processor.time_map_data(|x| x * 2); 79 | println!("Mapped Data: {:?}", mapped); 80 | 81 | // Aggregating data (sum) 82 | let sum = processor.aggregate(|a, b| a + b); 83 | println!("Sum of Data: {:?}", sum); 84 | 85 | // Edge case: Aggregating empty data 86 | let empty_processor: DataProcessor = DataProcessor::new(vec![]); 87 | let empty_sum = empty_processor.aggregate(|a, b| a + b); 88 | println!("Sum of Empty Data: {:?}", empty_sum); 89 | } 90 | -------------------------------------------------------------------------------- /Module10/performanceCheck/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "performanceCheck" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | criterion = { version = "0.5", features = ["html_reports"] } 10 | 11 | lazy_static = "1.5.0" 12 | rand = "0.8.5" 13 | 14 | [[bench]] 15 | name = "fibonacci_benchmark" 16 | harness = false 17 | -------------------------------------------------------------------------------- /Module10/performanceCheck/Readme.md: -------------------------------------------------------------------------------- 1 | # Performance Benchmarking with Criterion 2 | 3 | This project benchmarks various Fibonacci implementations and sorting algorithms using the Criterion library in Rust. The goal is to evaluate the performance of different algorithms and provide insights into their efficiency. 4 | 5 | ## Table of Contents 6 | 7 | - [Features](#features) 8 | - [Getting Started](#getting-started) 9 | - [Benchmarking](#benchmarking) 10 | - [Fibonacci Implementations](#fibonacci-implementations) 11 | - [Sorting Algorithms](#sorting-algorithms) 12 | - [Dependencies](#dependencies) 13 | - [License](#license) 14 | 15 | ## Features 16 | 17 | - Benchmarking of multiple Fibonacci algorithms: 18 | - Recursive 19 | - Iterative 20 | - Memoized 21 | - Matrix Exponentiation 22 | - Benchmarking of sorting algorithms: 23 | - Bubble Sort 24 | - Quick Sort 25 | - Random data generation for testing 26 | 27 | ## Getting Started 28 | 29 | To get started with this project, follow these steps: 30 | 31 | 1. **Clone the repository**: 32 | ```bash 33 | git clone https://github.com/yourusername/yourproject.git 34 | cd yourproject 35 | ``` 36 | 37 | 2. **Install Rust**: If you haven't already, install Rust by following the instructions at [rust-lang.org](https://www.rust-lang.org/tools/install). 38 | 39 | 3. **Add dependencies**: Ensure that the following dependencies are included in your `Cargo.toml` file: 40 | ```toml 41 | [dependencies] 42 | criterion = "0.3" 43 | lazy_static = "1.4" 44 | rand = "0.8" # or the latest version 45 | ``` 46 | 47 | ## Benchmarking 48 | 49 | To run the benchmarks, use the following command: 50 | 51 | ```bash 52 | cargo bench 53 | ``` 54 | 55 | This command will execute the benchmarks defined in the `benches` directory and provide detailed output on the performance of each algorithm. 56 | 57 | ## Fibonacci Implementations 58 | 59 | The project includes several implementations of the Fibonacci sequence: 60 | 61 | - **Recursive**: A straightforward recursive approach. 62 | - **Iterative**: An iterative method that uses a loop. 63 | - **Memoized**: A version that caches results to improve performance. 64 | - **Matrix Exponentiation**: A mathematical approach using matrix multiplication. 65 | 66 | ## Sorting Algorithms 67 | 68 | The project benchmarks the following sorting algorithms: 69 | 70 | - **Bubble Sort**: A simple comparison-based sorting algorithm. 71 | - **Quick Sort**: A more efficient, divide-and-conquer sorting algorithm. 72 | 73 | ## Dependencies 74 | 75 | This project relies on the following Rust crates: 76 | 77 | - `criterion`: For benchmarking. 78 | - `lazy_static`: For creating static variables that require initialization. 79 | - `rand`: For generating random data for testing. 80 | 81 | ## License 82 | 83 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details. 84 | -------------------------------------------------------------------------------- /Module10/performanceCheck/benches/fibonacci_benchmark.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | use criterion::{black_box, criterion_group, criterion_main, Criterion}; 3 | use lazy_static::lazy_static; 4 | use std::sync::RwLock; 5 | 6 | pub fn fib_recursive(n: u64) -> u64 { 7 | match n { 8 | 0 => 1, 9 | 1 => 1, 10 | n => fib_recursive(n - 1) + fib_recursive(n - 2), 11 | } 12 | } 13 | 14 | // Iterative Fibonacci 15 | pub fn fib_iterative(n: u64) -> u64 { 16 | let mut a = 1; 17 | let mut b = 1; 18 | for _ in 2..=n { 19 | let temp = a + b; 20 | a = b; 21 | b = temp; 22 | } 23 | b 24 | } 25 | // Memoized Fibonacci 26 | lazy_static! { 27 | static ref FIB_CACHE: RwLock> = RwLock::new(vec![1, 1]); 28 | } 29 | 30 | // Matrix Exponentiation Fibonacci 31 | pub fn fib_matrix(n: u64) -> u64 { 32 | if n == 0 { 33 | return 1; 34 | } 35 | let mut m = ((1, 1), (1, 0)); 36 | let mut result = ((1, 0), (0, 1)); // Identity matrix 37 | let mut power = n - 1; 38 | while power > 0 { 39 | if power % 2 == 1 { 40 | result = multiply(result, m); 41 | } 42 | m = multiply(m, m); 43 | power /= 2; 44 | } 45 | result.0 .0 46 | } 47 | 48 | fn multiply(a: ((u64, u64), (u64, u64)), b: ((u64, u64), (u64, u64))) -> ((u64, u64), (u64, u64)) { 49 | ( 50 | (a.0 .0 * b.0 .0 + a.0 .1 * b.1 .0, a.0 .0 * b.0 .1 + a.0 .1 * b.1 .1), 51 | (a.1 .0 * b.0 .0 + a.1 .1 * b.1 .0, a.1 .0 * b.0 .1 + a.1 .1 * b.1 .1), 52 | ) 53 | } 54 | 55 | fn fibonacci(n: u64) -> u64 { 56 | let mut a = 0; 57 | let mut b = 1; 58 | match n { 59 | 0 => b, 60 | _ => { 61 | for _ in 0..n { 62 | let c = a + b; 63 | a = b; 64 | b = c; 65 | } 66 | b 67 | } 68 | } 69 | } 70 | // Benchmarking setup 71 | fn bench_fib(c: &mut Criterion) { 72 | c.bench_function("fib_recursive 20", |b| b.iter(|| fib_recursive(black_box(10)))); 73 | c.bench_function("fib_iterative 20", |b| b.iter(|| fib_iterative(black_box(10)))); 74 | c.bench_function("fib_matrix 20", |b| b.iter(|| fib_matrix(black_box(10)))); 75 | } 76 | 77 | criterion_group!(benches, bench_fib); 78 | criterion_main!(benches); -------------------------------------------------------------------------------- /Module10/performanceCheck/benches/sort_bench.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | use criterion::{black_box, criterion_group, criterion_main, Criterion}; 3 | use rand::Rng; 4 | // Real life algorithms 5 | 6 | fn bubble_sort(arr: &mut [i32]) { 7 | let len = arr.len(); 8 | for i in 0..len { 9 | for j in 0..len - i - 1 { 10 | if arr[j] > arr[j + 1] { 11 | arr.swap(j, j + 1); 12 | } 13 | } 14 | } 15 | } 16 | 17 | fn quick_sort(arr: &mut [i32]) { 18 | if arr.len() <= 1 { 19 | return; 20 | } 21 | let pivot = arr.len() / 2; 22 | let (left, right) = arr.split_at_mut(pivot); 23 | quick_sort(left); 24 | quick_sort(right); 25 | } 26 | 27 | 28 | fn generate_large_data(size: usize) -> Vec { 29 | let mut rng = rand::thread_rng(); 30 | (0..size).map(|_| rng.gen_range(0..1000)).collect() 31 | } 32 | 33 | // Benchmark setup 34 | fn bench_sorting(c: &mut Criterion) { 35 | let mut arr1 = vec![5, 2, 9, 1, 5, 6, 3, 8, 7, 4]; 36 | let mut arr2 = vec![5, 2, 9, 1, 5, 6, 3, 8, 7, 4,3,2,1, -1, 100 , -200, 2, 34, 45 , 71];; 37 | 38 | c.bench_function("bubble_sort", |b| b.iter(|| bubble_sort(&mut arr1))); 39 | c.bench_function("quick_sort", |b| { 40 | let mut data = generate_large_data(10); // Ensure this generates a sufficiently large dataset 41 | b.iter(|| quick_sort(black_box(&mut data))); 42 | }); 43 | } 44 | 45 | 46 | criterion_group!(benches, bench_sorting); 47 | criterion_main!(benches); -------------------------------------------------------------------------------- /Module10/performanceCheck/src/lib.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdabir1203/Modular-Rust-Learning/b4c751ec5be8f608ec9e3aa7ab14b119bd262fdc/Module10/performanceCheck/src/lib.rs -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust Project-Based Learning Application 2 | ![Rust](https://github.com/user-attachments/assets/2f2412bf-9ff9-4656-b64c-4f99521c59a8) 3 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fmdabir1203%2FModular-Rust-Learning.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fmdabir1203%2FModular-Rust-Learning?ref=badge_shield) 4 | 5 | 6 | 7 | This repository represents various Modular Projects based on Rust Programming Language. The goal is to learn various programming concepts of Rust through building Projects. The idea is inspired from @JohnCrickett Challenge. 8 | 9 | [![CI](https://github.com/mdabir1203/Modular-Rust-Learning/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/mdabir1203/Modular-Rust-Learning/actions/workflows/CI.yml) 10 | 11 | # WHY \ What \ How 12 | 13 | ### Progressive Learning Path 14 | By creating a repository of modular projects, one can learn in start with simple concepts and gradually build up to more complex Rust features and patterns. This approach allows anyone to learn at their own pace and revisit earlier projects as understanding grows. 15 | ### Hands-on Experience 16 | Building actual projects provides practical, hands-on experience with Rust. This method of learning by doing helps reinforce concepts more effectively than passive learning alone. One will encounter real-world challenges and learn how to apply Rust's features to solve them. 17 | 18 | ### Modular Approach Benefits 19 | Breaking down learning into modular projects offers several advantages: 20 | 21 | - Focus on specific concepts or features in each project 22 | - Easier to manage and understand smaller, self-contained codebases 23 | - Flexibility to explore different areas of Rust (e.g., systems programming, web development, game development) 24 | - Ability to combine modules later for more complex applications 25 | 26 | ### Portfolio Development 27 | As one build their repository, one can simultaneously create a portfolio of Rust projects. This can be valuable when: 28 | 29 | - Seeking Rust-related job opportunities 30 | - Contributing to open-source projects 31 | - Demonstrating your skills to the Rust community 32 | 33 | ### Community Engagement 34 | A public repository of Rust projects can: 35 | 36 | - Attract feedback and contributions from other Rust enthusiasts 37 | - Serve as a resource for other learners 38 | - Encourage collaboration and knowledge sharing within the Rust ecosystem 39 | 40 | By building a repository of modular Rust projects, you create a personalized, practical, and engaging learning experience that not only enhances your skills but also contributes to your professional development and community involvement.Last edited just now 41 | 42 | ## Getting Started 43 | 44 | To get started with this project, ensure you have Rust and Cargo installed on your system. You can install both by following the instructions on the [official Rust website](https://www.rust-lang.org/tools/install). 45 | 46 | Once Rust is installed, you can clone this repository to your local machine: 47 | 48 | ```bash 49 | git clone https://github.com/mdabir1203/InventRust.git 50 | ``` 51 | 52 | Navigate into the project directory: 53 | 54 | To run the application, execute: ``` cargo build --release ``` 55 | 56 | ## Usage 57 | 58 | Various Projects have various usecases. The github readme in each folder will give you what the project is about. 59 | 60 | ## Contributing 61 | 62 | Contributions to this project are welcome! Whether it's submitting bug reports, suggesting enhancements, or contributing code, all forms of collaboration are appreciated. 63 | 64 | Check writings here : https://www.medium.com/@md.abir1203 65 | 66 | 67 | ## License 68 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fmdabir1203%2FModular-Rust-Learning.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fmdabir1203%2FModular-Rust-Learning?ref=badge_large) 69 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | We maintain security updates for the following versions of Rust Modular Projects: 6 | 7 | | Version | Supported | Notes | 8 | |---------|-------------------|-------| 9 | | 1.2.x | :white_check_mark: | Current stable release | 10 | | 1.1.x | :white_check_mark: | Extended support | 11 | | 1.0.x | :x: | End of life | 12 | | < 1.0 | :x: | Development versions | 13 | 14 | ## Security Updates 15 | 16 | - Patches for security vulnerabilities are provided for all supported versions 17 | - Critical updates are released as soon as possible 18 | - Non-critical updates are bundled with regular releases 19 | 20 | ## Reporting a Vulnerability 21 | 22 | We take security vulnerabilities seriously. Please follow these steps to report a vulnerability: 23 | 24 | ### Reporting Process 25 | 26 | 1. **DO NOT** create a public GitHub issue for security vulnerabilities 27 | 2. Email your findings to [md.abir1203@gmail.com] 28 | 3. Encrypt sensitive information using our [PGP key](link-to-pgp-key) 29 | 30 | ### What to Include 31 | 32 | - Detailed description of the vulnerability 33 | - Steps to reproduce 34 | - Potential impact 35 | - Suggested fix (if available) 36 | 37 | ### Response Timeline 38 | 39 | You can expect: 40 | 41 | 1. **Initial Response**: Within 48 hours 42 | 2. **Status Update**: Within 5 business days 43 | 3. **Vulnerability Assessment**: Within 10 business days 44 | 4. **Fix Implementation**: Timeline provided based on severity 45 | 46 | ### Severity Levels 47 | 48 | We classify vulnerabilities according to the following criteria: 49 | 50 | | Severity | Description | Response Time | 51 | |----------|-------------|---------------| 52 | | Critical | Remote code execution, data breach | 24-48 hours | 53 | | High | Authentication bypass, data corruption | 3-5 days | 54 | | Medium | Information disclosure, DoS | 7-14 days | 55 | | Low | Minor issues, edge cases | Next release cycle | 56 | 57 | ## Security Best Practices 58 | 59 | ### For Contributors 60 | 61 | 1. **Code Security** 62 | - Use safe Rust practices 63 | - Avoid `unsafe` blocks unless absolutely necessary 64 | - Follow OWASP secure coding guidelines 65 | 66 | 2. **Dependency Management** 67 | - Regular `cargo audit` checks 68 | - Keep dependencies updated 69 | - Use version pinning for critical dependencies 70 | 71 | 3. **Testing Requirements** 72 | - Security test coverage 73 | - Fuzz testing for parsing operations 74 | - Regular penetration testing 75 | 76 | ### For Users 77 | 78 | 1. **Installation Security** 79 | - Verify package signatures 80 | - Use official release channels 81 | - Check SHA-256 hashes 82 | 83 | 2. **Configuration Security** 84 | - Follow principle of least privilege 85 | - Use secure defaults 86 | - Regular security audits 87 | 88 | ## Disclosure Policy 89 | 90 | 1. **Private Disclosure** 91 | - Security issues are handled privately 92 | - CVE assignments when applicable 93 | - Coordinated disclosure with affected parties 94 | 95 | 2. **Public Disclosure** 96 | - After patch release 97 | - Full disclosure in security advisory 98 | - Credit to reporters (if desired) 99 | 100 | ## Security Features 101 | 102 | Our security features include: 103 | 104 | - Memory safety through Rust's ownership system 105 | - Safe concurrent programming practices 106 | - Input validation and sanitization 107 | - Secure cryptographic implementations 108 | - Regular security audits 109 | 110 | ## Compliance 111 | 112 | This project adheres to: 113 | 114 | - OWASP Secure Coding Practices 115 | - NIST Cybersecurity Framework 116 | - Rust Security Working Group guidelines 117 | 118 | ## Bug Bounty Program 119 | 120 | We currently do not maintain a bug bounty program. However, we appreciate and acknowledge security researchers who responsibly disclose vulnerabilities. 121 | 122 | ## Security Updates and Notifications 123 | 124 | - Subscribe to our security mailing list 125 | - Watch our GitHub repository 126 | - Follow our security advisory RSS feed 127 | 128 | ## Contact 129 | 130 | Security Team: 131 | - Email: [md.abir1203@gmail.com] 132 | - PGP Key: [Add your PGP key fingerprint] 133 | - Emergency Contact: [Add emergency contact if available] 134 | 135 | ## Attribution 136 | 137 | We appreciate the security research community. Researchers who report vulnerabilities will be acknowledged in our security advisories (unless they prefer to remain anonymous). 138 | 139 | ## Changes to This Policy 140 | 141 | This policy may be updated or revised. All changes will be documented in our changelog. 142 | 143 | --- 144 | 145 | Last updated: February 6, 2025 146 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Find all directories containing Cargo.toml files 4 | directories=$(find . -name "Cargo.toml" -exec dirname {} \; | sort -u) 5 | 6 | # Loop through each directory and run the commands 7 | for dir in $directories; do 8 | ( 9 | cd "$dir" || exit 10 | cargo clean 11 | rm -f Cargo.lock 12 | ) 13 | done --------------------------------------------------------------------------------