Compare commits
	
		
			2 Commits
		
	
	
		
			7a841eac8f
			...
			b4ba730818
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b4ba730818 | |||
| 01da4a6c39 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
/target
 | 
			
		||||
							
								
								
									
										45
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
{
 | 
			
		||||
    // Use IntelliSense to learn about possible attributes.
 | 
			
		||||
    // Hover to view descriptions of existing attributes.
 | 
			
		||||
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 | 
			
		||||
    "version": "0.2.0",
 | 
			
		||||
    "configurations": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "lldb",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "name": "Debug executable 'all_the_passwords'",
 | 
			
		||||
            "cargo": {
 | 
			
		||||
                "args": [
 | 
			
		||||
                    "build",
 | 
			
		||||
                    "--bin=all_the_passwords",
 | 
			
		||||
                    "--package=all_the_passwords"
 | 
			
		||||
                ],
 | 
			
		||||
                "filter": {
 | 
			
		||||
                    "name": "all_the_passwords",
 | 
			
		||||
                    "kind": "bin"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "args": [],
 | 
			
		||||
            "cwd": "${workspaceFolder}"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "type": "lldb",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "name": "Debug unit tests in executable 'all_the_passwords'",
 | 
			
		||||
            "cargo": {
 | 
			
		||||
                "args": [
 | 
			
		||||
                    "test",
 | 
			
		||||
                    "--no-run",
 | 
			
		||||
                    "--bin=all_the_passwords",
 | 
			
		||||
                    "--package=all_the_passwords"
 | 
			
		||||
                ],
 | 
			
		||||
                "filter": {
 | 
			
		||||
                    "name": "all_the_passwords",
 | 
			
		||||
                    "kind": "bin"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "args": [],
 | 
			
		||||
            "cwd": "${workspaceFolder}"
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
# This file is automatically @generated by Cargo.
 | 
			
		||||
# It is not intended for manual editing.
 | 
			
		||||
version = 3
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "all_the_passwords"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "num-format",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "arrayvec"
 | 
			
		||||
version = "0.7.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "itoa"
 | 
			
		||||
version = "1.0.10"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "num-format"
 | 
			
		||||
version = "0.4.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "arrayvec",
 | 
			
		||||
 "itoa",
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										10
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "all_the_passwords"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
 | 
			
		||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
num-format = "0.4.4"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										117
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
use std::io::{stderr, Write};
 | 
			
		||||
use std::thread::{self, sleep};
 | 
			
		||||
use std::time::{Duration, Instant};
 | 
			
		||||
 | 
			
		||||
use num_format::{Locale, ToFormattedString};
 | 
			
		||||
 | 
			
		||||
const ALL_CHARS: &'static str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.<>/?;':\"[]{}\\|-=_+`~!@#$%^&*()";
 | 
			
		||||
const LEN: usize = 4;
 | 
			
		||||
 | 
			
		||||
static mut SOFAR: u128 = 0;
 | 
			
		||||
static mut TOTAL: usize = 0;
 | 
			
		||||
 | 
			
		||||
/// Pseudo main 
 | 
			
		||||
/// 
 | 
			
		||||
/// Starts the number crunching (blocking on main thread!) and the
 | 
			
		||||
/// timer thread which watches the main thread while
 | 
			
		||||
/// reporting statistics about it. 
 | 
			
		||||
fn start(char_list: &str, output_len: usize) {
 | 
			
		||||
    /// Flag to communicate between main (combination crunching) and
 | 
			
		||||
    /// timer threads.
 | 
			
		||||
    static mut IS_DONE: bool = false;
 | 
			
		||||
 | 
			
		||||
    let start = Instant::now();
 | 
			
		||||
 | 
			
		||||
    // Just to report stats
 | 
			
		||||
    let timer = thread::spawn(move || {
 | 
			
		||||
        let mut out = stderr();
 | 
			
		||||
 | 
			
		||||
        while unsafe { !IS_DONE } {
 | 
			
		||||
            let mut elapsed = start.elapsed().as_secs() as u128;
 | 
			
		||||
            // prevent div by zero err
 | 
			
		||||
            if elapsed == 0 { elapsed = 1; }
 | 
			
		||||
 | 
			
		||||
            let sofar = unsafe {SOFAR};
 | 
			
		||||
            // output P/s
 | 
			
		||||
            let _ = out.write(
 | 
			
		||||
                format!("\rCalculated {} possibilities thus far, at {} p/s",
 | 
			
		||||
                    sofar.to_formatted_string(&Locale::en_NA),
 | 
			
		||||
                    (sofar / elapsed).to_formatted_string(&Locale::en_NA),
 | 
			
		||||
                ).as_bytes());
 | 
			
		||||
            let _ = out.flush();
 | 
			
		||||
            sleep(Duration::from_secs(1));
 | 
			
		||||
            
 | 
			
		||||
            /*
 | 
			
		||||
            // output remaining time
 | 
			
		||||
            // I haven't tested to see if this timer is somewhat accurate...
 | 
			
		||||
            // This is code I stole of reddit... what am I doing?
 | 
			
		||||
            let remaining = unsafe { TOTAL as u128 / (sofar / elapsed) };
 | 
			
		||||
            let sec = remaining % 60;
 | 
			
		||||
            let min = (remaining / 60) % 60;
 | 
			
		||||
            let hrs = (remaining / 60) / 60;
 | 
			
		||||
            
 | 
			
		||||
            let _ = out.write(
 | 
			
		||||
            // TODO clear the whole line, don't just put cursor to the begining...
 | 
			
		||||
                format!("\r{}%, {}h:{}m:{}s remaining                       ",
 | 
			
		||||
                    unsafe { sofar / TOTAL as u128 },
 | 
			
		||||
                    hrs, min, sec
 | 
			
		||||
            ).as_bytes());
 | 
			
		||||
            let _ = out.flush();
 | 
			
		||||
            sleep(Duration::from_secs(1));
 | 
			
		||||
            */
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // starting with the blank string is important
 | 
			
		||||
    calc(char_list, &"", output_len);
 | 
			
		||||
 | 
			
		||||
    unsafe { IS_DONE = true; }
 | 
			
		||||
    timer.join().unwrap();
 | 
			
		||||
 | 
			
		||||
    eprintln!("\r{}ms to calculate the permutations (p) for {} chars (n) across {} slots (r).", start.elapsed().as_millis().to_formatted_string(&Locale::en_NA), char_list.len(), output_len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    // All the status messages are printed on stderr
 | 
			
		||||
    // This way you can pipe the actual permutations into
 | 
			
		||||
    // a file whilst still getting debug messages. 
 | 
			
		||||
    let t = (ALL_CHARS.len() as u128).pow(LEN.try_into().unwrap());
 | 
			
		||||
    unsafe { TOTAL = t as usize };
 | 
			
		||||
    eprintln!(
 | 
			
		||||
        "Calculating {} combinations...\n(Number may be trunkated if too large)\n",
 | 
			
		||||
        unsafe { TOTAL }.to_formatted_string(&Locale::en_NA)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    start(ALL_CHARS, LEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Recurseively create and print every combination of
 | 
			
		||||
/// `choices` chars inside a string of `len` length.
 | 
			
		||||
/// 
 | 
			
		||||
/// 
 | 
			
		||||
/// * `choices` string containing all the chars you wish
 | 
			
		||||
/// to build random strings with. 
 | 
			
		||||
/// 
 | 
			
		||||
/// * `prefix` should be a blank string `""` unless you
 | 
			
		||||
/// actually want a prefix on every output. This variable is
 | 
			
		||||
/// mainly used within the recursive nature of the funciton.
 | 
			
		||||
/// 
 | 
			
		||||
/// * `len` the size that all the output strings wil be.
 | 
			
		||||
fn calc(choices: &str, prefix: &str, len: usize) {
 | 
			
		||||
    let need_to_fill = len - prefix.len();
 | 
			
		||||
    match need_to_fill {
 | 
			
		||||
        // the last char in the sequence, time to print
 | 
			
		||||
        1 => {
 | 
			
		||||
            for i in choices.chars() {
 | 
			
		||||
                println!("{}{}", prefix, i);
 | 
			
		||||
                unsafe { SOFAR = SOFAR + 1 };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // need to recurse farther into the sequence
 | 
			
		||||
        _ => {
 | 
			
		||||
            for i in choices.chars() {
 | 
			
		||||
                calc(choices, &(prefix.to_string() + &i.to_string()), len);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user