diff --git a/Cargo.toml b/Cargo.toml index d206a7c..109a5a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,4 +19,5 @@ clap = { version = "4.5.4", features = ["derive"] } fast32 = "1.0.2" libpt = { version = "0.5.1", features = ["bintols"], default-features = false } num = "0.4.3" +rand = "0.8.5" diff --git a/src/format.rs b/src/format.rs index ebc59d1..6bc0ae3 100644 --- a/src/format.rs +++ b/src/format.rs @@ -86,6 +86,16 @@ pub struct FormatOptions { #[arg(short = 's', long)] /// format to base64 base64: bool, + #[arg(short = 'r', long, default_value_t = 0, value_parser=numf_parser::)] + /// output random numbers + /// + /// Add a user defined amount of cryptographically pseudorandom numbers to the number list. + rand: NumberType, + #[arg(long, default_value_t = NumberType::MAX, value_parser=numf_parser::)] + /// max for the random numbers + /// + /// Generated numbers will not be lower than this. Only has an effect with --rand set. + rand_max: NumberType, #[arg(short = 'z', long)] /// format to base32 base32: bool, @@ -183,6 +193,26 @@ impl FormatOptions { pub fn push_number(&mut self, value: NumberType) { self.numbers.push(value) } + + /// get rand + pub fn rand(&self) -> NumberType { + self.rand + } + + /// set amount of extra random numbers manually + pub fn set_rand(&mut self, rand: NumberType) { + self.rand = rand; + } + + /// get highes allowed random value + pub fn rand_max(&self) -> NumberType { + self.rand_max + } + + /// set highes allowed random value + pub fn set_rand_max(&mut self, rand_max: NumberType) { + self.rand_max = rand_max; + } } impl Default for FormatOptions { @@ -197,6 +227,8 @@ impl Default for FormatOptions { base64: false, dec: false, numbers: vec![], + rand: 0, + rand_max: NumberType::MAX, } } } diff --git a/src/main.rs b/src/main.rs index ca7e5ab..a8eabaa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ mod format; use format::*; use numf::format::numf_parser; -fn main() { +fn main() -> anyhow::Result<()> { // try to read from stdin first, appending the numbers we read to the FormatOptions let mut options = FormatOptions::parse(); let mut stdin_nums = Vec::new(); @@ -23,6 +23,7 @@ fn main() { let whole: String = match String::from_utf8(stdin_nums) { Ok(r) => r, Err(e) => { + eprintln!("{}", FormatOptions::command().render_usage()); eprintln!("stdin for this program only accepts text: {e:#?}"); exit(1); } @@ -32,6 +33,7 @@ fn main() { let number = match numf_parser(s) { Ok(n) => n, Err(e) => { + eprintln!("{}", FormatOptions::command().render_usage()); eprintln!("could not parse number from stdin: {e:#?}"); exit(2); } @@ -40,14 +42,24 @@ fn main() { } } Err(e) => { + eprintln!("{}", FormatOptions::command().render_usage()); eprintln!("could not read from stdin: {e:#?}"); exit(2); } }; } + if options.rand() > 0 { + use rand::prelude::*; + let mut rand = rand::rngs::OsRng; + for _i in 0..options.rand() { + options.push_number(rand.gen_range(0..options.rand_max())); + } + } + if options.numbers().is_empty() { - format!("{}", FormatOptions::command().render_usage()); + eprintln!("{}", FormatOptions::command().render_usage()); + eprintln!("no numbers have been provided"); exit(1); } @@ -59,4 +71,5 @@ fn main() { for o in out { println!("{o}") } + Ok(()) }