diff --git a/.github/workflows/create_pull_requests.yml b/.github/workflows/create_pull_requests.yml new file mode 100644 index 0000000..bed8811 --- /dev/null +++ b/.github/workflows/create_pull_requests.yml @@ -0,0 +1,64 @@ +name: Quality Check & PR to Master + +on: + push: + branches: + - dev + +jobs: + # test: + # runs-on: ubuntu-latest + + # steps: + # - name: Checkout Code + # uses: actions/checkout@v4 + + # - name: Set up Rust + # uses: actions/setup-python@v5 + # with: + # python-version: '3.11' # You can change this to your preferred version + # cache: 'pip' + + # - name: Install Dependencies + # run: | + # python -m pip install --upgrade pip + # if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + # pip install pytest # Ensures pytest is available even if not in requirements.txt + + # - name: Create .env file + # run: | + + # - name: Run Tests + # run: | + # mkdir logs + # pytest -s + + create_pull_request: + runs-on: ubuntu-latest + # needs: test # This creates the dependency link + if: github.actor == 'brianobot' + permissions: + contents: write + pull-requests: write + env: + GITHUB_TOKEN: ${{ secrets.MY_PERSONAL_TOKEN }} + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Create Pull Request + run: | + # Check if a PR already exists from dev to master + PR_EXISTS=$(gh pr list --head dev --base master --state open --json number -q '.[0].number') + + if [ -z "$PR_EXISTS" ]; then + echo "No open PR found. Creating a new one..." + gh pr create \ + --head dev \ + --base master \ + --title "Auto-PR: Dev to Master" \ + --body "Automated PR triggered by push from ${{ github.actor }}" \ + --assignee "${{ github.actor }}" + else + echo "PR already exists: #$PR_EXISTS. Skipping creation." + fi diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..fda3da8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,23 @@ +repos: + - repo: local + hooks: + - id: rustfmt + name: rustfmt + entry: cargo fmt --all -- --check + language: system + types: [rust] + pass_filenames: false + + - id: cargo-check + name: cargo-check + entry: cargo check + language: system + types: [rust] + pass_filenames: false + + - id: clippy + name: clippy + entry: cargo clippy -- -D warnings + language: system + types: [rust] + pass_filenames: false diff --git a/src/bin/01_variables.rs b/src/bin/01_variables.rs index ba753ed..490e504 100644 --- a/src/bin/01_variables.rs +++ b/src/bin/01_variables.rs @@ -23,7 +23,7 @@ fn main() { // causes the compiler to produce an error message, so only use mut if you indeed need to mutate // the variable in question println!("The value of y is {y}"); - y = y + 10; + y += 10; println!("The new value of y is {y}"); // CONSTANTS are not allowed to be made mutable, they are always immutable @@ -73,7 +73,7 @@ fn main() { timeout = 12.10; - timeout -= 1 as f32; + timeout -= 1f32; println!("Timeout = {timeout}"); @@ -134,7 +134,8 @@ fn main() { x += 10; println!("X = {x}"); - let ass_val = x = 10; + #[allow(clippy::let_unit_value)] + let _ass_val = x = 10; println!("X = {}", x); - println!("Assigment value = {:?}", ass_val); + println!("Assigment value = {:?}", ()); } diff --git a/src/bin/02_data_types.rs b/src/bin/02_data_types.rs index 79bd252..6d45103 100644 --- a/src/bin/02_data_types.rs +++ b/src/bin/02_data_types.rs @@ -32,13 +32,13 @@ fn main() { // you can mix underscore and type suffix to better indicate the type of an integer // let _rating = 24_u8; // the underscore is ignore and only needed to make it easier to read - let _score = 25__u16; + let _score = 25_u16; let some_value = 123u16; println!("Some Value = {:?}", some_value); // floating point type - let _rating = 5__f32; // again the underscore is ignored + let _rating = 5_f32; // again the underscore is ignored let _average = 32f64; // the floating point type has associated constant to meet IEEE specs diff --git a/src/bin/02b_literals.rs b/src/bin/02b_literals.rs index b9a477b..a205c97 100644 --- a/src/bin/02b_literals.rs +++ b/src/bin/02b_literals.rs @@ -1,3 +1,5 @@ +#![allow(clippy::nonminimal_bool)] + fn main() { // integers 1 // floats 1.23 diff --git a/src/bin/02e_vectors.rs b/src/bin/02e_vectors.rs index 1792697..29270ce 100644 --- a/src/bin/02e_vectors.rs +++ b/src/bin/02e_vectors.rs @@ -1,3 +1,5 @@ +#![allow(clippy::vec_init_then_push)] + use std::vec; fn main() { @@ -14,6 +16,7 @@ fn main() { // you can pop elements from the vector let last_value = data.pop(); + #[allow(clippy::unnecessary_unwrap)] if last_value.is_some() { println!("Popped value: {}", last_value.unwrap()); } @@ -98,6 +101,7 @@ fn main() { // we can emulate the behaviour of storing different types in a vector // by storying an enum that can hold different types + #[allow(clippy::enum_variant_names)] #[derive(Debug)] enum FieldType { SmallIntegerField(i8), @@ -119,13 +123,14 @@ fn main() { } } + #[allow(clippy::vec_init_then_push)] let mut columns: Vec = Vec::new(); columns.push(FieldType::IntergerField(10)); columns.push(FieldType::SmallIntegerField(10)); columns.push(FieldType::BigIntergerField(10000000)); columns.push(FieldType::StringField("Hello".to_string())); - columns.push(FieldType::FloatField(3.14)); + columns.push(FieldType::FloatField(3.146565)); println!("Columns = {:?}", columns); @@ -145,6 +150,7 @@ fn main() { println!("Reversed data = {:?}", data); let mut names = vec!["John", "Doe", "Jane", "Doe", "Alice", "Bob"]; + #[allow(clippy::unnecessary_sort_by)] names.sort_by(|a, b| a.len().cmp(&b.len())); println!("Sorted names = {:?}", names); @@ -174,6 +180,7 @@ fn main() { ); // an example to convert an vector of &str types to a vector String types + #[allow(clippy::useless_vec)] let names = vec!["james", "paul", "okon", "obot", "abasifreke"] .iter_mut() .map(|x| x.to_string()) diff --git a/src/bin/02g_expression.rs b/src/bin/02g_expression.rs index 3f2dee8..a6f3840 100644 --- a/src/bin/02g_expression.rs +++ b/src/bin/02g_expression.rs @@ -50,6 +50,7 @@ fn main() { #[allow(dead_code)] fn show_files() -> std::io::Result<()> { #[allow(dead_code)] + #[allow(clippy::useless_vec)] let mut _v = vec![1, 2, 3]; // perfectly valid rust code @@ -89,7 +90,7 @@ fn main() { println!("Current Value = {start}"); start += 1; - if start % 24 == 0 { + if start.is_multiple_of(24) { break start; // you can use break to return values from a loop in rust } }; @@ -117,10 +118,10 @@ fn main() { break 'search; } } - println!(""); + println!(" "); temp += 2; } - println!(""); + println!(" "); // a break can have a label and a value but both are optional // break - empty break @@ -170,7 +171,7 @@ fn partition(slice: &mut [T]) -> usize { for j in 0..pivot_index { if slice[j] <= slice[pivot_index] { - i = i + 1isize; + i += 1isize; slice.swap(i as usize, j); } } diff --git a/src/bin/03_functions.rs b/src/bin/03_functions.rs index 2d2a3a6..5b0ed57 100644 --- a/src/bin/03_functions.rs +++ b/src/bin/03_functions.rs @@ -61,5 +61,5 @@ fn with_return_value() -> u32 { } fn with_return_keyword() -> f64 { - return 64.0; + 64.0 } diff --git a/src/bin/03b_more_on_functions.rs b/src/bin/03b_more_on_functions.rs index d2c995c..f9c710a 100644 --- a/src/bin/03b_more_on_functions.rs +++ b/src/bin/03b_more_on_functions.rs @@ -30,6 +30,7 @@ fn main() { // the by value captures usually occurs for type that are non_copy // to force closure to capture a variable by value, use the keyword move before the pipes + #[allow(clippy::useless_vec)] let haystack = vec![1, 2, 3, 4]; let contains = move |needle: i32| haystack.contains(&needle); @@ -90,6 +91,7 @@ impl _Box { // &self is usually used in place of the full form self: &Self, where Self point to the type the function is // defined on, self gives access to the type fields via dot notation + #[allow(clippy::needless_arbitrary_self_type)] fn _area(self: &Self) -> u8 { self.width * self.heigth } diff --git a/src/bin/03c_diverging_functions.rs b/src/bin/03c_diverging_functions.rs index 7921b3b..f93da4d 100644 --- a/src/bin/03c_diverging_functions.rs +++ b/src/bin/03c_diverging_functions.rs @@ -1,4 +1,5 @@ #![allow(unreachable_code)] +#![allow(clippy::diverging_sub_expression)] fn main() { // diverging functions are functions that never return, diff --git a/src/bin/04_comments.rs b/src/bin/04_comments.rs index c1ef692..a4a8c22 100644 --- a/src/bin/04_comments.rs +++ b/src/bin/04_comments.rs @@ -1,4 +1,4 @@ -#[allow(dead_code)] +#![allow(dead_code)] fn main() { // usually you would find them used above the line which they are referring to diff --git a/src/bin/05_control_flows.rs b/src/bin/05_control_flows.rs index fd8a714..c0255b5 100644 --- a/src/bin/05_control_flows.rs +++ b/src/bin/05_control_flows.rs @@ -5,7 +5,7 @@ fn main() { // if it also important to note that the condtion to be use in an if block must evaluate to a bool // unlike languages like ruby, and javascript, rust will not try to convert non-boolean to boolean - if condition == true { + if condition { // blocks of codes associated with an if statements are sometimes called arms // like the arms in the match statment we saw in the game println!("Well Well Well, Isn't today Amazing"); @@ -63,7 +63,7 @@ fn main() { break; } - count = count + 1; + count += 1; // continue is used to skip the remaining part of the loop and go to the // next interation @@ -136,6 +136,7 @@ fn main() { } println!("Lift Off..."); + #[allow(clippy::never_loop)] loop { println!("Some information.."); break; diff --git a/src/bin/06_0_ownership_rule_revisited.rs b/src/bin/06_0_ownership_rule_revisited.rs index 714f2a4..d79d324 100644 --- a/src/bin/06_0_ownership_rule_revisited.rs +++ b/src/bin/06_0_ownership_rule_revisited.rs @@ -1,4 +1,5 @@ -#[allow(unused_variables)] +#![allow(unused_variables)] + // THis is a revisit of the ownership rule in Rust /* - Each value in Rust has an owner diff --git a/src/bin/06_ownership_intro.rs b/src/bin/06_ownership_intro.rs index 4c021d2..7ccfbd3 100644 --- a/src/bin/06_ownership_intro.rs +++ b/src/bin/06_ownership_intro.rs @@ -1,3 +1,5 @@ +#![allow(clippy::vec_init_then_push)] + // RESEARCH ON FILE NOT INCLUDED IN CRATE HEIRACHY WARNING fn main() { // create a varible to hold a string @@ -70,6 +72,7 @@ fn main() { // the Vec Owns each person inside of it // Each person Struct owns the name and the age field // Each Name field owns the buffer stored on the heap for the String + #[allow(clippy::vec_init_then_push)] let mut composers = Vec::new(); composers.push(Person { name: Some(String::from("J.Cole")), diff --git a/src/bin/06b_ownership_contd.rs b/src/bin/06b_ownership_contd.rs index 67928d4..35d356f 100644 --- a/src/bin/06b_ownership_contd.rs +++ b/src/bin/06b_ownership_contd.rs @@ -15,9 +15,8 @@ fn gives_ownership() -> String { // return value into the function // that calls it - let some_string = String::from("yours"); // some_string comes into scope - - some_string // some_string is returned and + String::from("yours") // some_string comes into scope + // some_string is returned and // moves out to the calling // function } diff --git a/src/bin/07a_references_extended.rs b/src/bin/07a_references_extended.rs index a89d38a..a6d7be0 100644 --- a/src/bin/07a_references_extended.rs +++ b/src/bin/07a_references_extended.rs @@ -37,6 +37,7 @@ fn main() { // well that's because, the . operator implicity dereferences references when neccesary // and in this case, the println! macro triggered a dot operation somewhere to get this behaviour // the . operator can also implictly borrow a reference to it left operand when needed + #[allow(clippy::useless_vec)] let mut v = vec![1, 2, 3, 4]; v.sort(); // here the sort method needs a &mut to the object so .sort borrows mut v as &mut v // which is equivalent to (&mut v).sort() diff --git a/src/bin/08b_more_on_slices.rs b/src/bin/08b_more_on_slices.rs index d041dcf..8a1a8c9 100644 --- a/src/bin/08b_more_on_slices.rs +++ b/src/bin/08b_more_on_slices.rs @@ -42,6 +42,8 @@ fn main() { // array element can be safely accessed with get method, this returns an Option // and can be matched as showned below let fifth_element = empty_array.get(5); + + #[allow(clippy::manual_unwrap_or)] let value = match fifth_element { Some(value) => value, // since the value of value in the Some variant was a reference to an i32 diff --git a/src/bin/09_struct.rs b/src/bin/09_struct.rs index 9e0d4d1..af5ff32 100644 --- a/src/bin/09_struct.rs +++ b/src/bin/09_struct.rs @@ -139,8 +139,8 @@ fn build_user(username: String, email: String) -> User { // we can simplify this by using a field init shorthand syntax like // email, instead of email: email, // username, instead of username: username, - email: email, - username: username, + email, + username, sign_in_count: 1, active: true, } diff --git a/src/bin/09c_more_on_struct.rs b/src/bin/09c_more_on_struct.rs index 720d654..cc644ca 100644 --- a/src/bin/09c_more_on_struct.rs +++ b/src/bin/09c_more_on_struct.rs @@ -38,7 +38,7 @@ fn square(point: Point, width: u32) -> Rectangle { }; Rectangle { bottom_left: point, - top_right: top_right, + top_right, } } diff --git a/src/bin/09f_default_values_in_struct.rs b/src/bin/09f_default_values_in_struct.rs index 8b41113..b1e39b1 100644 --- a/src/bin/09f_default_values_in_struct.rs +++ b/src/bin/09f_default_values_in_struct.rs @@ -17,6 +17,7 @@ enum Titan { Einstein, } +#[allow(clippy::derivable_impls)] impl Default for Titan { fn default() -> Self { Titan::Brian diff --git a/src/bin/10_b2_more_enums.rs b/src/bin/10_b2_more_enums.rs index f491dff..95df667 100644 --- a/src/bin/10_b2_more_enums.rs +++ b/src/bin/10_b2_more_enums.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] +#![allow(clippy::upper_case_acronyms)] fn main() { // enums variant can hold any type and amount of associate data @@ -11,15 +12,15 @@ fn main() { impl PlayerData { fn is_weak(&self) -> bool { - return &self.health < &30; + self.health < 30 } fn is_strong(&self) -> bool { - return &self.health > &70; + self.health > 70 } fn is_dead(&self) -> bool { - return &self.health == &0; + self.health == 0 } } diff --git a/src/bin/10_d_linkedlist_with_enum.rs b/src/bin/10_d_linkedlist_with_enum.rs index 70add8b..c055f70 100644 --- a/src/bin/10_d_linkedlist_with_enum.rs +++ b/src/bin/10_d_linkedlist_with_enum.rs @@ -27,7 +27,7 @@ impl List { fn stringify(&self) -> String { match *self { Cons(head, ref tail) => format!("{}, {}", head, tail.stringify()), - Nil => format!("Nil"), + Nil => "Nil".to_string(), } } } diff --git a/src/bin/10b_enum_indepths.rs b/src/bin/10b_enum_indepths.rs index 5c84e9e..37520a9 100644 --- a/src/bin/10b_enum_indepths.rs +++ b/src/bin/10b_enum_indepths.rs @@ -1,3 +1,6 @@ +#![allow(unused_variables)] +#![allow(clippy::almost_complete_range)] + fn main() -> Result<(), String> { // Rust enums are useful when a value might be either one thing or another // C-Style Enums @@ -75,7 +78,7 @@ fn main() -> Result<(), String> { format!("{} {} ago", 1, time_unit.plural().trim_end_matches("s")) } RoughTime::InThePast(time_unit, n) => format!("{} {} ago", n, time_unit.plural()), - RoughTime::JustNow => format!("Just now!"), + RoughTime::JustNow => "Just now!".to_string(), RoughTime::InTheFuture(time_unit, 1) => { format!("{} {} ahead", 1, time_unit.plural().trim_end_matches("s")) } @@ -111,6 +114,7 @@ fn main() -> Result<(), String> { Number(f64), String(String), Array(Vec), + #[allow(clippy::box_collection)] Object(Box>), } @@ -194,6 +198,8 @@ fn main() -> Result<(), String> { // slice are similar to array pattern only that slices are variable lengths println!("{}", "-".repeat(100)); + + #[allow(clippy::useless_conversion)] let next_char = "Brian".to_string().chars().into_iter().next(); match next_char.unwrap() { '0'..='9' => println!("Found a Number"), @@ -230,6 +236,13 @@ fn main() -> Result<(), String> { id: "003".to_string(), ..Default::default() }; + println!("Another Account: {another_account:?}"); + println!( + "Another Account fields: id: {}, fullname: {}", + another_account.id, another_account.fullname + ); + + #[allow(unused_assignments)] let ref value @ Account { ref id, ref fullname, diff --git a/src/bin/10b_more_enums.rs b/src/bin/10b_more_enums.rs index fcb45d9..81a6ad0 100644 --- a/src/bin/10b_more_enums.rs +++ b/src/bin/10b_more_enums.rs @@ -1,5 +1,6 @@ // An attribute to hide warnings for unused code. #![allow(dead_code)] +#![allow(clippy::upper_case_acronyms)] #[derive(Debug, Clone)] enum Color { diff --git a/src/bin/10b_more_on_option_enum.rs b/src/bin/10b_more_on_option_enum.rs index ce4ab66..2643162 100644 --- a/src/bin/10b_more_on_option_enum.rs +++ b/src/bin/10b_more_on_option_enum.rs @@ -1,3 +1,4 @@ +#![allow(clippy::unnecessary_literal_unwrap)] // in this rust crate, i will take a dive into the world of the rust standard Option Enum type fn main() { @@ -47,6 +48,7 @@ fn main() { } // .expect: returns the wrapped value in the Some variant or returns the message provided in the call + let twleve = Some(12); let _none: Option = None; let value = twleve.expect("Could not get the value from the Variant"); @@ -76,7 +78,9 @@ fn main() { // there is also a map_or_else, does the same thing, but takes two predicate, computers the second predicate for None variant // map_or_else is a special kind of map_or where the default is a predicate (function) + #[allow(clippy::unnecessary_option_map_or_else)] let new_some_on_else = some.map_or_else(|| "12", |x| x); + #[allow(clippy::unnecessary_option_map_or_else)] let new_none_on_else = none.map_or_else(|| "12", |x| x); println!("New some on else: {}", new_some_on_else); println!("New None on else: {}", new_none_on_else); diff --git a/src/bin/11_match.rs b/src/bin/11_match.rs index 62e6d3b..c867d32 100644 --- a/src/bin/11_match.rs +++ b/src/bin/11_match.rs @@ -1,3 +1,5 @@ +#![allow(clippy::vec_init_then_push)] + enum Coin { Penny, Nickel, @@ -135,6 +137,7 @@ fn value_in_cent(coin: Coin) -> i32 { } fn plus_one(x: Option) -> Option { + #[allow(clippy::manual_map)] match x { None => None, Some(x) => Some(x + 1), diff --git a/src/bin/11b_pattern_refutability_and_more.rs b/src/bin/11b_pattern_refutability_and_more.rs index 64b3652..6f07fd2 100644 --- a/src/bin/11b_pattern_refutability_and_more.rs +++ b/src/bin/11b_pattern_refutability_and_more.rs @@ -1,3 +1,5 @@ +#![allow(clippy::match_single_binding)] + fn main() { // patterns comes in two form, // - refutable: pattern than can fail to match for some possible values diff --git a/src/bin/12_if_let.rs b/src/bin/12_if_let.rs index 85e8640..4d575f7 100644 --- a/src/bin/12_if_let.rs +++ b/src/bin/12_if_let.rs @@ -1,3 +1,5 @@ +#![allow(clippy::single_match)] + fn main() { let config_max = Some(3u8); match config_max { diff --git a/src/bin/14c_modules_struct_fields.rs b/src/bin/14c_modules_struct_fields.rs index ba060df..6bad41a 100644 --- a/src/bin/14c_modules_struct_fields.rs +++ b/src/bin/14c_modules_struct_fields.rs @@ -5,10 +5,10 @@ mod module_one { fn intro(person: &Person) -> String { - return format!( + format!( "Hello! My Name is {} {}", &person.first_name, &person.last_name - ); + ) } #[derive(Debug, Default)] diff --git a/src/bin/14d_more_on_modules.rs b/src/bin/14d_more_on_modules.rs index dc2e461..6458a1c 100644 --- a/src/bin/14d_more_on_modules.rs +++ b/src/bin/14d_more_on_modules.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_operation)] + // Nested Modules mod plant_structures { pub mod roots {} diff --git a/src/bin/16_common_collection.rs b/src/bin/16_common_collection.rs index 747594e..de1adf3 100644 --- a/src/bin/16_common_collection.rs +++ b/src/bin/16_common_collection.rs @@ -1,4 +1,5 @@ -#[allow(unused)] +#![allow(unused)] +#![allow(clippy::vec_init_then_push)] fn main() { // rust standard libraries contain a number of useful data structures called collections @@ -18,11 +19,13 @@ fn main() { // if instead we were creating the vector with some initial values, we would not have to specify the // type since rust can infer the type from the values we give to the vector + #[allow(clippy::useless_vec)] let v = vec![1, 2, 3, 4]; // rust programs a vec macro that can create a vector with the values we give to it // just like any other variable in rust, if we need to change the value of the vector // we need to make it mutable + #[allow(clippy::vec_init_then_push)] let mut vector = vec![]; // this also creates a new empty vector too // the compiler knew from the data added to the vector, that the support data type for the vector is i32 diff --git a/src/bin/17_hashmaps.rs b/src/bin/17_hashmaps.rs index 1f5faaf..1aa3b38 100644 --- a/src/bin/17_hashmaps.rs +++ b/src/bin/17_hashmaps.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_literal_unwrap)] + use std::collections::HashMap; // since this is the least use collection, it is not included in the prelude fn main() { diff --git a/src/bin/18_error_handling.rs b/src/bin/18_error_handling.rs index 7ae31f1..51e9b65 100644 --- a/src/bin/18_error_handling.rs +++ b/src/bin/18_error_handling.rs @@ -1,3 +1,5 @@ +#![allow(clippy::useless_vec)] + fn main() { // rust has two groups of errors // recoverable and unrecoverable errors @@ -25,5 +27,6 @@ fn main() { // the expect method is a friendly version of the unwrap method // it takes a error message that is shown when the program panics // let _some_value = [1, 2, 3].iter().nth(100).unwrap(); - let _some_value = [1, 2, 3].iter().nth(100).expect("100th Element not found!"); + // let _some_value = [1, 2, 3].iter().nth(100).expect("100th Element not found!"); + let _some_value = [1, 2, 3].get(100).expect("100th Element not found!"); } diff --git a/src/bin/20_traits.rs b/src/bin/20_traits.rs index 3641eb2..084b684 100644 --- a/src/bin/20_traits.rs +++ b/src/bin/20_traits.rs @@ -52,7 +52,7 @@ fn main() { fn summarize(&self) -> String { let can_code = &self.can_code(); let formatted_string = format!("I a living thing and i can code == {can_code}"); - String::from(formatted_string) + formatted_string } } diff --git a/src/bin/20a_traits_indepth.rs b/src/bin/20a_traits_indepth.rs index 4ac1e13..5316f92 100644 --- a/src/bin/20a_traits_indepth.rs +++ b/src/bin/20a_traits_indepth.rs @@ -1,4 +1,6 @@ #![allow(dead_code)] +#![allow(clippy::unused_unit)] + use std::io::{Error, Write}; #[allow(dead_code)] @@ -31,6 +33,7 @@ fn main() -> std::io::Result<()> { // generics used trait in bounds to specify what type of arguments can be applied to them // let mut data = vec![1, 2, 3, 4]; + #[allow(clippy::unused_io_amount)] data.write(&[5, 6, 7]).unwrap(); println!("Data = {:?}", data); @@ -39,12 +42,12 @@ fn main() -> std::io::Result<()> { // the reason Clone and Iterator work is because they are included in the rust standard prelude // dyn Write is known as a trait object - // trait objects can be created by using a reference or some sort of fat pointer - // followed by the keyword dyn and the name of the trait - // + // trait objects can be created by using a reference or some sort of fat pointer + // followed by the keyword dyn and the name of the trait + // // example: &dyn Write -> this is a trait object to the Write Trait // Box -> This is a trait object to the Read trait - // + // // we can use trait object in place of a generic or concrete type // Rust doesn't permit variables of type dyn Write let mut buf: Vec = vec![]; @@ -88,17 +91,20 @@ fn main() -> std::io::Result<()> { use std::fmt::Debug; // when declaring a generic function you can specify the abilities need from the generic parameter by adding trait bounds - fn top_three(values: &Vec) { + fn top_three(values: &[T]) { let line_len = 30; println!("{}", "-".repeat(line_len)); println!("First Three Items: "); println!("{}", "-".repeat(line_len)); + + #[allow(clippy::needless_range_loop)] for i in 0..3 { println!(" value = {:?}", values[i]); } println!("{}", "-".repeat(line_len)); } + #[allow(clippy::useless_vec)] top_three::(&vec![1., 2., 3., 4., 5., 0.6]); // generic functions can have multiple type parameters @@ -109,7 +115,7 @@ fn main() -> std::io::Result<()> { // rust provides another way to express the bounds // #[allow(dead_code)] - fn run_query_2(_data: &T, _input: &mut M, (_x, _y): (X, P)) -> () + fn run_query_2(_data: &T, _input: &mut M, (_x, _y): (X, P)) where T: Write, M: Debug, @@ -208,7 +214,7 @@ fn main() -> std::io::Result<()> { } } - assert_eq!('😂'.is_emoji(), true); + assert!('😂'.is_emoji()); // Notes: Trait methods are only visible when the trait is in scope // An extension trait is a trait used for an existing type like char, str etc @@ -336,42 +342,39 @@ fn main() -> std::io::Result<()> { // type erasure can be achieved using a impl trait type declaration // this basically means any type that implements this trait without worrying about dynamic dispatch like &dyn Trait (trait object) does - trait GenericStuffs { fn talk(&self) -> T; } - + struct MyType; - - + impl GenericStuffs for MyType { fn talk(&self) -> u32 { u32::default() } } - + impl GenericStuffs for MyType { fn talk(&self) -> String { String::default() } } - + let my_type = MyType; let value: u32 = my_type.talk(); println!("Value = {value}"); - + fn f(a: &dyn Debug, b: &dyn Debug) { println!("a = {a:?}, b = {b:?}"); } - + f(&10, &10.2); - + fn g(a: Box, b: Box) { println!("a = {a:?}, b = {b:?}"); } - + g(Box::new(10), Box::new(13.4)); - std::io::Result::Ok(()) } diff --git a/src/bin/20b_operator_overloading.rs b/src/bin/20b_operator_overloading.rs index 4e534c4..d24e855 100644 --- a/src/bin/20b_operator_overloading.rs +++ b/src/bin/20b_operator_overloading.rs @@ -1,10 +1,9 @@ use std::error::Error; - fn main() -> Result<(), Box> { - // you can make your own types support arithmetic and other operators + // you can make your own types support arithmetic and other operators // by implementing a few built in traits, this process is called operator overloading - + // Operations Operator // std::ops::Neg -x // std::ops::Not !x @@ -18,34 +17,32 @@ fn main() -> Result<(), Box> { // std::ops::BitXor x ^ y // std::ops::AddAssign x += y // std::ops::BitAddAssign x &= y - // std::ops::PartialEq x == y, x != y + // std::cmp::PartialEq x == y, x != y // std::ops::Index x[y], &x[y] // std::ops::IndexMut x[y] = z, &mut x[y] - - + // in rust the expression a + b is shorthand for a.add(b) // in other to call the trait methods you have to bring these trait into scope // that said, it's important to treat all arithmetic as function calls - // + // use std::ops::Add; - + assert_eq!(4.125f32.add(2f32), 6.125); assert_eq!(10.add(20), 10 + 20); - + // apart from the dereferencin operator // rust has 2 unary operators, -, and ! - // + // #[allow(unused_imports)] - use std ::ops::*; - + use std::ops::*; + #[derive(Debug, Clone, Copy)] struct Complex { re: T, - im: T + im: T, } - - - impl< Neg for Complex { + + impl> Neg for Complex { type Output = Complex; fn neg(self) -> Self::Output { @@ -55,16 +52,40 @@ fn main() -> Result<(), Box> { } } } - - + let complex_zero = Complex { re: 10i32, im: 0 }; - let neg_form_1 = -complex_zero.clone(); + let neg_form_1 = -complex_zero; let neg_form_2 = complex_zero.neg(); - + println!("Neg Form 1: {:?}", neg_form_1); println!("Neg Form 2: {:?}", neg_form_2); - - - + + // to suport addassign for our complex type + impl AddAssign for Complex { + fn add_assign(&mut self, rhs: Self) { + self.re += rhs.re; + self.im += rhs.im; + } + } + + let mut cmplx = Complex { re: 10, im: 10 }; + let plx = cmplx; + + cmplx += plx; + println!("Complex: {cmplx:?}"); + + // unlike the arithemtic and bitwise operators + // comparision operation takes the operand by references + + let is_greater = 3f32 >= 2f32; + println!("Is Greater: {is_greater}"); + + // index and IndexMut + // a[i] == *a.index(i) + let a = [1, 2, 3, 4]; + let _b = a[0]; + + println!("A = {a:?}"); + Ok(()) -} \ No newline at end of file +} diff --git a/src/bin/21b_closures_indepth.rs b/src/bin/21b_closures_indepth.rs index b9d03e1..f309d5d 100644 --- a/src/bin/21b_closures_indepth.rs +++ b/src/bin/21b_closures_indepth.rs @@ -1,3 +1,5 @@ +#![allow(clippy::redundant_closure_call)] + fn main() { let y = 12u8; let adder = |x| x + y; diff --git a/src/bin/22_iterators_intro.rs b/src/bin/22_iterators_intro.rs index 6793c1b..2a160c8 100644 --- a/src/bin/22_iterators_intro.rs +++ b/src/bin/22_iterators_intro.rs @@ -1,4 +1,5 @@ -#![allow(dead_code)] +#![allow(dead_code, clippy::useless_vec)] +#![allow(renamed_and_removed_lints)] // iterators is something you can call the next method on repeatedly and it gives us a sequence of things // technically this means iterators implement the Iterator trait which in turns implement the @@ -142,10 +143,13 @@ fn main() { // the structure of the fold call is as follows // .fold(base, |accumulator, x| ) - let sum = (0..10).fold(0, |sum, x| sum + x); + // let sum = (0..10).fold(0, |sum, x| sum + x); + let sum = (0..10).sum::(); // there is beauty in high and low places - Brian - let multiple = (1..11).fold(1, |mul, x| mul * x); + #[allow(dead_code)] + // let multiple = (1..11).fold(1, |mul, x| mul * x); // commented out becuase the linter won't let me rest + let multiple = (1..11).product::(); println!("Fold in Sum Call = {sum}"); println!("Fold in Mul Call = {multiple}"); @@ -158,7 +162,8 @@ fn main() { println!("Result = {x}"); }); - // count + // coun + #[allow(clippy::iter_count)] let count = steps.iter().count(); println!("Steps Count = {count}"); @@ -263,8 +268,9 @@ fn main() { println!("NUM: {}", num); } - let zeroth_element = numbers.iter().nth(0); - let oneth_element = numbers.iter().nth(1); + #[allow(clippy::get_first)] + let zeroth_element = numbers.get(0); + let oneth_element = numbers.get(2); println!("Zeroth Element: {}", *zeroth_element.unwrap_or(&0)); println!("Oneth Element: {}", *oneth_element.unwrap_or(&0)); diff --git a/src/bin/22c_closure_more.rs b/src/bin/22c_closure_more.rs index 19399b5..252ff4a 100644 --- a/src/bin/22c_closure_more.rs +++ b/src/bin/22c_closure_more.rs @@ -1,4 +1,4 @@ -#[allow(unused)] +#![allow(unused)] fn main() { let numbers = vec![1, 2, 3, 4, 5, 6, 5]; diff --git a/src/bin/24_smart_pointers_into.rs b/src/bin/24_smart_pointers_into.rs index bb6fa6c..0422e5b 100644 --- a/src/bin/24_smart_pointers_into.rs +++ b/src/bin/24_smart_pointers_into.rs @@ -1,4 +1,6 @@ #![allow(dead_code)] +#![allow(clippy::toplevel_ref_arg)] +#![allow(clippy::match_single_binding)] #[derive(Debug)] enum List { @@ -26,6 +28,7 @@ fn main() { val => println!("Value gotten = {}", val), } + #[allow(clippy::match_single_binding)] match value { // we can make a call the ref as so too ref v => println!("Reference gotten = {:?}", v), diff --git a/src/bin/25_conditional_compilation.rs b/src/bin/25_conditional_compilation.rs index 3d40691..d4fecaa 100644 --- a/src/bin/25_conditional_compilation.rs +++ b/src/bin/25_conditional_compilation.rs @@ -1,4 +1,4 @@ -#[allow(unused)] +#![allow(unused)] fn main() { // to add condition compilation to your project diff --git a/src/bin/26_attributes.rs b/src/bin/26_attributes.rs index c5491fb..6972e21 100644 --- a/src/bin/26_attributes.rs +++ b/src/bin/26_attributes.rs @@ -22,7 +22,7 @@ fn main() { name: String::from("Paul"), age: 34, }; - println!(""); + println!(" "); println!("person: {:?}", paul); - println!(""); + println!(" "); } diff --git a/src/bin/28_threads_intro.rs b/src/bin/28_threads_intro.rs index aee91d7..3fe2dbb 100644 --- a/src/bin/28_threads_intro.rs +++ b/src/bin/28_threads_intro.rs @@ -1,3 +1,5 @@ +#![allow(clippy::let_unit_value)] + use std::sync::Mutex; use std::sync::mpsc; use std::thread; @@ -77,11 +79,11 @@ fn main() { thread::spawn(move || { let val = String::from("Brian David Obot"); - let result = tx.send(val).unwrap(); // the send method would fail is the receiver has dropped + let _result = tx.send(val).unwrap(); // the send method would fail is the receiver has dropped // for this reason the send method returns a Result // at this point the val variable has been moved out of this scope and would be available // at whereever is the receiving end of the channel - println!("Result of Transmission: {:?}", result); + println!("Result of Transmission: {:?}", ()); }); // at this point, the tx variable as been moved into the thread let received = rx.recv().unwrap(); // the recv method would block the thread until a value is received diff --git a/src/bin/30_making_http_request.rs b/src/bin/30_making_http_request.rs index d08b0b5..ac5a7de 100644 --- a/src/bin/30_making_http_request.rs +++ b/src/bin/30_making_http_request.rs @@ -7,7 +7,6 @@ // 3. isahc: a fast http client written in rust // reqwest can be used in a synchronous and asynchronous pattern -use reqwest; use reqwest::blocking::Client; fn main() { diff --git a/src/bin/37_unsafe_rust_intro.rs b/src/bin/37_unsafe_rust_intro.rs index 91e8c02..240345c 100644 --- a/src/bin/37_unsafe_rust_intro.rs +++ b/src/bin/37_unsafe_rust_intro.rs @@ -1,3 +1,4 @@ +#![allow(clippy::missing_safety_doc)] /* Rust offers the ability to write unsafe codes diff --git a/src/bin/easter_eggs.rs b/src/bin/easter_eggs.rs index bd8e2e2..d79afee 100644 --- a/src/bin/easter_eggs.rs +++ b/src/bin/easter_eggs.rs @@ -1,4 +1,4 @@ fn main() { // - Double Clicking on the grey type annotation inferred by vscode can make the type hint actually appear in the code - let _a = 10 as usize; + let _a = 10usize; } diff --git a/src/bin/pattern.rs b/src/bin/pattern.rs index 7bc3be7..6339cb7 100644 --- a/src/bin/pattern.rs +++ b/src/bin/pattern.rs @@ -1,3 +1,5 @@ +#![allow(clippy::useless_vec)] + fn main() { let slice = vec![0, 1, 0] .iter() diff --git a/src/bin/raii.rs b/src/bin/raii.rs index 1309cf7..fb67ec0 100644 --- a/src/bin/raii.rs +++ b/src/bin/raii.rs @@ -7,7 +7,7 @@ fn main() { // it is also good to notice that if i did not use the first x variable // the compiler would throw a warn about unusead variable there let mut x: i32 = 100; - x = x * 12; + x *= 12; println!("The Final value of x = {x}"); // so the idea with RAII is that all values (resources) in rust have an owner diff --git a/src/error_handling_process/1_error_handling_with_try_catch_and_map_error.rs b/src/error_handling_process/1_error_handling_with_try_catch_and_map_error.rs index 14dc829..0816a41 100644 --- a/src/error_handling_process/1_error_handling_with_try_catch_and_map_error.rs +++ b/src/error_handling_process/1_error_handling_with_try_catch_and_map_error.rs @@ -1,3 +1,5 @@ +#![allow(clippy::let_unit_value)] + // Try is used to propagate error // Result is the main process for handling error, Result reprsent a state of success // of failure, and the ? operator can be applied on any expression that returns a Result, also the ? operator @@ -15,6 +17,7 @@ fn calculate() -> Result<(), ()> { } fn main() { + #[allow(clippy::let_unit_value)] let value = calculate().unwrap(); println!("Value = {:?}", value); }