Skip to content

Commit

Permalink
Refactor condensed multiple bools to Checks struct
Browse files Browse the repository at this point in the history
  • Loading branch information
atamakahere-git committed Mar 1, 2024
1 parent 90f4350 commit 4d2eab5
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 68 deletions.
21 changes: 10 additions & 11 deletions src/add/curseforge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crate::{
upgrade::mod_downloadable,
};

use super::Checks;

fn project_exist(profile: &Profile, project: &furse::structures::mod_structs::Mod) -> bool {
profile.mods.iter().any(|mod_| {
mod_.name.to_lowercase() == project.name.to_lowercase()
Expand Down Expand Up @@ -40,9 +42,7 @@ pub async fn curseforge(
curseforge: &furse::Furse,
project_id: i32,
profile: &mut Profile,
perform_checks: bool,
check_game_version: bool,
check_mod_loader: bool,
checks: &Checks,
) -> super::Result<String> {
let project = curseforge.get_mod(project_id).await?;

Expand All @@ -62,19 +62,18 @@ pub async fn curseforge(
}

// Check if the project is compatible
if perform_checks
&& !is_project_compatible(curseforge, &project, profile, check_game_version).await?
if checks.perform_checks()
&& !is_project_compatible(curseforge, &project, profile, checks.game_version()).await?
{
return Err(super::Error::Incompatible);
}

// Add it to the profile
profile.mods.push(Mod {
name: project.name.trim().to_string(),
identifier: ModIdentifier::CurseForgeProject(project.id),
check_game_version,
check_mod_loader,
});
profile.mods.push(Mod::new(
project.name.trim(),
ModIdentifier::CurseForgeProject(project.id),
checks,
));

Ok(project.name)
}
18 changes: 9 additions & 9 deletions src/add/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::{
upgrade::mod_downloadable,
};

use super::Checks;

fn project_exist(profile: &Profile, repo: &Repository, repo_name: &(String, String)) -> bool {
profile.mods.iter().any(|mod_| {
mod_.name.to_lowercase() == repo.name.to_lowercase()
Expand Down Expand Up @@ -40,8 +42,7 @@ pub async fn github(
repo_handler: &octocrab::repos::RepoHandler<'_>,
profile: &mut Profile,
perform_checks: bool,
check_game_version: bool,
check_mod_loader: bool,
checks: &Checks,
) -> super::Result<String> {
let repo = repo_handler.get().await?;
let repo_name = (
Expand All @@ -66,18 +67,17 @@ pub async fn github(
}

// Check if the repo is compatible
if !is_project_compatible(profile, &releases, check_game_version).await? {
if !is_project_compatible(profile, &releases, checks.game_version()).await? {
return Err(super::Error::Incompatible);
}
}

// Add it to the profile
profile.mods.push(Mod {
name: repo.name.trim().to_string(),
identifier: ModIdentifier::GitHubRepository(repo_name),
check_game_version,
check_mod_loader,
});
profile.mods.push(Mod::new(
repo.name.trim(),
ModIdentifier::GitHubRepository(repo_name),
checks,
));

Ok(repo.name)
}
156 changes: 127 additions & 29 deletions src/add/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cell::Cell;

use crate::config::structs::Profile;
use reqwest::StatusCode;

Expand Down Expand Up @@ -31,6 +33,88 @@ pub enum Error {

pub type Result<T> = std::result::Result<T, Error>;

/// Single sturct to condense check flags for game version, mod loader and to-check
/// Saves space, reduce complexity in fn args and is fast
///
/// Bit mappings (LTR: [7,6,5,4,3,2,1,0]):
/// 0: flag for "perform checks"
/// 1: flag for "game version"
/// 2: flag for "mod loader"
#[derive(Default)]
pub struct Checks(Cell<u8>);

impl Checks {
/// Generates new [Checks] will all values set to [true]
pub fn new_all_set() -> Self {
Self(Cell::new(0b00000111))
}

/// Generates [Checks] from given predicate
pub fn from(checks: bool, game_version: bool, mod_loader: bool) -> Self {
let ret = Self::default();
if checks {
ret.set_perform_check();
}
if game_version {
ret.set_game_version();
}
if mod_loader {
ret.set_mod_loader();
}
ret
}

/// Set "perform_checks" bit to true
pub fn set_perform_check(&self) {
self.0.set(self.0.get() | 1 << 0);
}

/// Set "game_version" bit to true
pub fn set_game_version(&self) {
self.0.set(self.0.get() | 1 << 1);
}

/// Set "mod_loader" bit to true
pub fn set_mod_loader(&self) {
self.0.set(self.0.get() | 1 << 2);
}

/// Set "perform_checks" bit to false
pub fn unset_perform_check(&self) {
self.0.set(self.0.get() & 1 << 0);
}

/// Set "game_version" bit to false
pub fn unset_game_version(&self) {
self.0.set(self.0.get() & 1 << 1);
}

/// Set "mod_loader" bit to true
pub fn unset_mod_loader(&self) {
self.0.set(self.0.get() & 1 << 2);
}

/// Return "perform_checks" bit status
pub fn perform_checks(&self) -> bool {
self.0.get() & 1 != 0
}

/// Return "game_version" bit status
pub fn game_version(&self) -> bool {
self.0.get() & (1 << 1) != 0
}

/// Return "mod_loader" bit status
pub fn mod_loader(&self) -> bool {
self.0.get() & (1 << 2) != 0
}

/// Reset all bits to 0 (all flags to false)
pub fn reset(&self) {
self.0.set(0);
}
}

impl From<furse::Error> for Error {
fn from(err: furse::Error) -> Self {
if let furse::Error::ReqwestError(source) = &err {
Expand Down Expand Up @@ -87,9 +171,7 @@ pub async fn add_multiple(
github,
profile,
&identifier,
true,
true,
true,
&Checks::new_all_set(),
)
.await
{
Expand All @@ -107,47 +189,63 @@ pub async fn add_multiple(
(success_names, failures)
}

#[allow(clippy::too_many_arguments)]
pub async fn add_single(
modrinth: &ferinth::Ferinth,
curseforge: &furse::Furse,
github: &octocrab::Octocrab,
profile: &mut Profile,
identifier: &str,
perform_checks: bool,
check_game_version: bool,
check_mod_loader: bool,
checks: &Checks,
) -> Result<String> {
if let Ok(project_id) = identifier.parse() {
curseforge::curseforge(
curseforge,
project_id,
profile,
perform_checks,
check_game_version,
check_mod_loader,
)
.await
curseforge::curseforge(curseforge, project_id, profile, checks).await
} else if identifier.matches('/').count() == 1 {
let split = identifier.split('/').collect::<Vec<_>>();
github::github(
&github.repos(split[0], split[1]),
profile,
perform_checks,
check_game_version,
check_mod_loader,
checks.perform_checks(),
checks,
)
.await
} else {
modrinth::modrinth(
modrinth,
identifier,
profile,
perform_checks,
check_game_version,
check_mod_loader,
)
.await
.map(|o| o.0)
modrinth::modrinth(modrinth, identifier, profile, checks)
.await
.map(|o| o.0)
}
}

#[cfg(test)]
mod test {
use super::Checks;

#[test]
fn check_bit_set_unset() {
let check = Checks::default();

// seting bits
check.set_perform_check();
check.set_mod_loader();
check.set_game_version();

assert!(check.perform_checks() && check.game_version() && check.mod_loader());

// Unset after set
check.unset_perform_check();
check.unset_mod_loader();
check.unset_game_version();

assert!(!(check.perform_checks() && check.game_version() && check.mod_loader()));

// Unset after Unset
check.unset_mod_loader();

assert!(!check.mod_loader());

// set after set
check.set_game_version();
check.set_game_version();

assert!(check.game_version());
}
}
31 changes: 12 additions & 19 deletions src/add/modrinth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::{
upgrade::check::{game_version_check, mod_loader_check},
};

use super::Checks;

fn project_exist(profile: &Profile, project: &Project) -> bool {
profile.mods.iter().any(|mod_| {
mod_.name.to_lowercase() == project.title.to_lowercase()
Expand All @@ -26,16 +28,11 @@ fn check_mod_loader_fabric_backwards_compatible(
&& mod_loader_check(Some(ModLoader::Fabric), &project.loaders))
}

fn project_comatible(
profile: &Profile,
project: &Project,
check_game_version: bool,
check_mod_loader: bool,
) -> bool {
fn project_comatible(profile: &Profile, project: &Project, checks: &Checks) -> bool {
game_version_check(
profile.get_version(check_game_version),
profile.get_version(checks.game_version()),
&project.game_versions,
) && check_mod_loader_fabric_backwards_compatible(profile, project, check_mod_loader)
) && check_mod_loader_fabric_backwards_compatible(profile, project, checks.mod_loader())
}

/// Check if the project of `project_id` exists, is a mod, and is compatible with `profile`.
Expand All @@ -46,9 +43,7 @@ pub async fn modrinth(
modrinth: &ferinth::Ferinth,
project_id: &str,
profile: &mut Profile,
perform_checks: bool,
check_game_version: bool,
check_mod_loader: bool,
checks: &Checks,
) -> super::Result<(String, Vec<DonationLink>)> {
let project = modrinth.get_project(project_id).await?;

Expand All @@ -60,17 +55,15 @@ pub async fn modrinth(
return Err(super::Error::NotAMod);
}

if perform_checks && !project_comatible(profile, &project, check_game_version, check_mod_loader)
{
if checks.perform_checks() && !project_comatible(profile, &project, checks) {
return Err(super::Error::Incompatible);
}

profile.mods.push(Mod {
name: project.title.trim().to_string(),
identifier: ModIdentifier::ModrinthProject(project.id),
check_game_version,
check_mod_loader,
});
profile.mods.push(Mod::new(
project.title.trim(),
ModIdentifier::ModrinthProject(project.id),
checks,
));

Ok((project.title, project.donation_urls))
}
13 changes: 13 additions & 0 deletions src/config/structs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize};
use std::{path::PathBuf, str::FromStr};

use crate::add::Checks;

#[derive(Deserialize, Serialize, Debug, Default, Clone)]
pub struct Config {
/// The index of the active profile
Expand Down Expand Up @@ -90,6 +92,17 @@ pub struct Mod {
pub check_mod_loader: bool,
}

impl Mod {
pub fn new(name: &str, identifier: ModIdentifier, checks: &Checks) -> Self {
Self {
name: name.into(),
identifier,
check_game_version: checks.game_version(),
check_mod_loader: checks.mod_loader(),
}
}
}

fn is_true(b: &bool) -> bool {
*b
}
Expand Down

0 comments on commit 4d2eab5

Please sign in to comment.