From 457a5ab2441cf535d77dcc6f1c3cc45d9369b6b1 Mon Sep 17 00:00:00 2001 From: Oakchris1955 <80592203+Oakchris1955@users.noreply.github.com> Date: Sun, 18 Jun 2023 13:35:24 +0300 Subject: [PATCH] Split project into library and binary --- Cargo.toml | 13 ++-- bin/Cargo.toml | 9 +++ bin/src/main.rs | 94 ++++++++++++++++++++++++++ lib/Cargo.toml | 7 ++ lib/src/lib.rs | 76 +++++++++++++++++++++ src/main.rs | 171 ------------------------------------------------ 6 files changed, 191 insertions(+), 179 deletions(-) create mode 100644 bin/Cargo.toml create mode 100644 bin/src/main.rs create mode 100644 lib/Cargo.toml create mode 100644 lib/src/lib.rs delete mode 100644 src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 4ea6a07..e82a217 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,6 @@ -[package] -name = "win95-keygen" -version = "0.1.0" -edition = "2021" -publish = false +[workspace] -[dependencies] -clap = { version = "4.3.4", features = [ "derive" ] } -rand = "0.8.5" +members = [ + "bin", + "lib" +] \ No newline at end of file diff --git a/bin/Cargo.toml b/bin/Cargo.toml new file mode 100644 index 0000000..06793ab --- /dev/null +++ b/bin/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "win95-keygen-bin" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +clap = { version = "4.3.4", features = [ "derive" ] } +win95-keygen = { path = "../lib" } diff --git a/bin/src/main.rs b/bin/src/main.rs new file mode 100644 index 0000000..dfc207a --- /dev/null +++ b/bin/src/main.rs @@ -0,0 +1,94 @@ +use clap::{Parser, ValueEnum}; +use std::{fmt, io}; + +use win95_keygen as keygen; + +#[derive(ValueEnum, Debug, Clone)] +#[clap(rename_all = "kebab_case")] +enum KeyType { + CDNormal, + CDLong, + OEM, +} + +impl fmt::Display for KeyType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + Self::CDNormal => "normal CD", + Self::CDLong => "long (11-digit) CD", + Self::OEM => "OEM", + } + ) + } +} + +#[derive(Parser)] +#[command( + author, + version, + about, + long_about = "A key generation utility to generate valid product key for the Win95 and Win98" +)] +struct Args { + #[arg(value_enum)] + keytype: Option, +} + +fn read_line(msg: S) -> String +where + S: Into, +{ + let msg = msg.into(); + let mut temp_string = String::new(); + + println!("{}: ", msg); + + while io::stdin().read_line(&mut temp_string).is_err() { + eprintln!("Error while reading from line, please try again."); + temp_string.clear(); + println!("{}: ", msg); + } + + temp_string.trim().to_string() +} + +fn main() { + let mut args = Args::parse(); + + while args.keytype.is_none() { + args.keytype = KeyType::from_str( + &read_line(format!( + "No key type provided by user. Please enter one (available options: {:?})", + KeyType::value_variants() + .iter() + .map(|variant| KeyType::to_possible_value(variant) + .unwrap() + .get_name() + .to_string()) + .collect::>() + )), + true, + ) + .ok(); + + if args.keytype.is_none() { + eprintln!("Invalid value provided, please try again") + } + } + + let keytype = args.keytype.unwrap(); + + println!("Generating {} key...", keytype); + + println!( + "{}", + match keytype { + KeyType::CDNormal => keygen::cd_normal(), + KeyType::CDLong => keygen::cd_long(), + KeyType::OEM => keygen::oem(), + } + ) +} diff --git a/lib/Cargo.toml b/lib/Cargo.toml new file mode 100644 index 0000000..01981e2 --- /dev/null +++ b/lib/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "win95-keygen" +version = "0.1.0" +edition = "2021" + +[dependencies] +rand = "0.8.5" diff --git a/lib/src/lib.rs b/lib/src/lib.rs new file mode 100644 index 0000000..edf2b46 --- /dev/null +++ b/lib/src/lib.rs @@ -0,0 +1,76 @@ +use rand::Rng; + +fn random_within_range(start: usize, end: usize) -> usize { + rand::thread_rng().gen_range(start..end) +} + +fn seven_div_generator(length: usize) -> String { + let mut num_array: Vec = Vec::with_capacity(length); + + for _ in 0..length - 1 { + num_array.push(random_within_range(0, 9)); + } + + num_array.push(random_within_range(1, 7)); + + while num_array.iter().sum::() % 7 != 0 { + num_array[random_within_range(0, length - 1)] = random_within_range(0, 9) + } + + num_array + .iter() + .map(|num| num.to_string()) + .collect::() +} + +pub fn cd_normal() -> String { + let first_digits: usize; + + loop { + let temp_num = random_within_range(0, 998); + match temp_num { + 333 | 444 | 555 | 666 | 777 | 888 => (), + _ => { + first_digits = temp_num; + break; + } + } + } + + format!("{:0>3}-{}", first_digits, seven_div_generator(7)) +} + +pub fn cd_long() -> String { + let first_digits: usize = random_within_range(0, 999); + let mut check_digit = first_digits % 10 + 1; + if check_digit > 9 { + check_digit = 0 + } + + format!( + "{:0>3}{}-{}", + first_digits, + check_digit.to_string(), + seven_div_generator(7) + ) +} + +pub fn oem() -> String { + let date = random_within_range(1, 366); + + let year = if rand::thread_rng().gen_bool((5.0 / 2.0) / 3.0) { + random_within_range(95, 99) + } else { + random_within_range(0, 2) + }; + + let seven_digits = seven_div_generator(6); + + format!( + "{:0>3}{:0>2}-OEM-0{}-{:0>5}", + date, + year, + seven_digits, + random_within_range(0, 99999) + ) +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 806676a..0000000 --- a/src/main.rs +++ /dev/null @@ -1,171 +0,0 @@ -use clap::{Parser, ValueEnum}; -use std::{fmt, io}; - -#[derive(ValueEnum, Debug, Clone)] // ArgEnum here -#[clap(rename_all = "kebab_case")] -enum KeyType { - CDNormal, - CDLong, - OEM, -} - -impl fmt::Display for KeyType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - match self { - Self::CDNormal => "normal CD", - Self::CDLong => "long (11-digit) CD", - Self::OEM => "OEM", - } - ) - } -} - -#[derive(Parser)] -#[command( - author, - version, - about, - long_about = "A key generation utility to generate valid product key for the Win95 and Win98" -)] -struct Args { - #[arg(value_enum)] - keytype: Option, -} - -mod key_generators { - use rand::Rng; - - fn random_within_range(start: usize, end: usize) -> usize { - rand::thread_rng().gen_range(start..end) - } - - fn seven_div_generator(length: usize) -> String { - let mut num_array: Vec = Vec::with_capacity(length); - - for _ in 0..length - 1 { - num_array.push(random_within_range(0, 9)); - } - - num_array.push(random_within_range(1, 7)); - - while num_array.iter().sum::() % 7 != 0 { - num_array[random_within_range(0, length - 1)] = random_within_range(0, 9) - } - - num_array - .iter() - .map(|num| num.to_string()) - .collect::() - } - - pub fn cd_normal() -> String { - let first_digits: usize; - - loop { - let temp_num = random_within_range(0, 998); - match temp_num { - 333 | 444 | 555 | 666 | 777 | 888 => (), - _ => { - first_digits = temp_num; - break; - } - } - } - - format!("{:0>3}-{}", first_digits, seven_div_generator(7)) - } - - pub fn cd_long() -> String { - let first_digits: usize = random_within_range(0, 999); - let mut check_digit = first_digits % 10 + 1; - if check_digit > 9 { - check_digit = 0 - } - - format!( - "{:0>3}{}-{}", - first_digits, - check_digit.to_string(), - seven_div_generator(7) - ) - } - - pub fn oem() -> String { - let date = random_within_range(1, 366); - - let year = if rand::thread_rng().gen_bool((5.0 / 2.0) / 3.0) { - random_within_range(95, 99) - } else { - random_within_range(0, 2) - }; - - let seven_digits = seven_div_generator(6); - - format!( - "{:0>3}{:0>2}-OEM-0{}-{:0>5}", - date, - year, - seven_digits, - random_within_range(0, 99999) - ) - } -} - -fn read_line(msg: S) -> String -where - S: Into, -{ - let msg = msg.into(); - let mut temp_string = String::new(); - - println!("{}: ", msg); - - while io::stdin().read_line(&mut temp_string).is_err() { - eprintln!("Error while reading from line, please try again."); - temp_string.clear(); - println!("{}: ", msg); - } - - temp_string.trim().to_string() -} - -fn main() { - let mut args = Args::parse(); - - while args.keytype.is_none() { - args.keytype = KeyType::from_str( - &read_line(format!( - "No key type provided by user. Please enter one (available options: {:?})", - KeyType::value_variants() - .iter() - .map(|variant| KeyType::to_possible_value(variant) - .unwrap() - .get_name() - .to_string()) - .collect::>() - )), - true, - ) - .ok(); - - if args.keytype.is_none() { - eprintln!("Invalid value provided, please try again") - } - } - - let keytype = args.keytype.unwrap(); - - println!("Generating {} key...", keytype); - - println!( - "{}", - match keytype { - KeyType::CDNormal => key_generators::cd_normal(), - KeyType::CDLong => key_generators::cd_long(), - KeyType::OEM => key_generators::oem(), - } - ) -}