#![crate_name = "bruteforce"]
#![feature(
const_fn,
test,
generators,
generator_trait,
const_if_match,
const_panic,
proc_macro_hygiene
)]
#![cfg_attr(not(feature = "std"), no_std)]
extern crate test;
#[cfg(not(feature = "std"))]
extern crate no_std_compat as std;
#[cfg(feature = "bruteforce-macros")]
extern crate bruteforce_macros;
pub mod charset;
#[cfg(feature = "generators")]
use std::ops::{Generator, GeneratorState};
#[cfg(feature = "generators")]
use std::pin::Pin;
use std::prelude::v1::*;
use charset::Charset;
#[cfg(test)]
mod tests {
#[macro_use]
use super::*;
use test::Bencher;
const BENCH_CHARS: Charset = Charset::new(&[
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
'2', '3', '4', '5', '6', '7', '8', '9', '!', '\"', '\'', '?', '\\', '#', '$', '§', '%',
'&', '/', '(', ')', '=', '[', ']', '{', '}', '´', '`', '<', '>', '€', ',', '.', '-', '_',
]);
#[bench]
fn bench_raw_next(b: &mut Bencher) {
let mut brute_forcer = BruteForce::new(BENCH_CHARS);
b.iter(|| {
brute_forcer.raw_next();
});
}
#[bench]
fn bench_next(b: &mut Bencher) {
let mut brute_forcer = BruteForce::new(BENCH_CHARS);
b.iter(|| brute_forcer.next());
}
#[bench]
fn bench_new(b: &mut Bencher) {
b.iter(|| BruteForce::new(BENCH_CHARS));
}
#[bench]
fn bench_charset_new(b: &mut Bencher) {
b.iter(|| {
Charset::new(&[
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '\"',
'\'', '?', '\\', '#', '$', '§', '%', '&', '/', '(', ')', '=', '[', ']', '{', '}',
'´', '`', '<', '>', '€', ',', '.', '-', '_',
])
});
}
#[bench]
fn bench_charset_new_by_str(b: &mut Bencher) {
b.iter(|| Charset::new_by_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"\'?\\$§%&/()=[]{}´`<>€,.-_"));
}
#[bench]
fn bench_charset_concat(b: &mut Bencher) {
let c1 = Charset::new_by_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
let c2 = Charset::new_by_str("abcdefghijklmnopqrstuvwxyz0123456789");
b.iter(|| c1.concat(&c2));
}
#[bench]
fn bench_charset_by_range(b: &mut Bencher) {
b.iter(|| Charset::by_char_range('a'..='z'));
}
#[bench]
fn bench_charset_to_string(b: &mut Bencher) {
b.iter(|| BENCH_CHARS.to_string());
}
}
#[derive(Debug, Clone)]
pub struct BruteForce<'a> {
pub chars: Charset<'a>,
pub current: String,
raw_current: Vec<usize>,
}
impl<'a> BruteForce<'a> {
pub fn new(charset: Charset) -> BruteForce {
BruteForce {
chars: charset,
current: String::default(),
raw_current: vec![],
}
}
pub fn new_at(charset: Charset, start: usize) -> BruteForce {
BruteForce {
chars: charset,
current: String::default(),
raw_current: (0..start).map(|_| 0).collect::<Vec<usize>>(),
}
}
pub fn new_by_start_string(charset: Charset, start_string: String) -> BruteForce {
BruteForce {
current: String::default(),
raw_current: start_string
.chars()
.rev()
.map(|c1| charset.iter().position(|&c2| c1 == c2))
.collect::<Option<Vec<usize>>>()
.expect("characters in start_string must exist in charset"),
chars: charset,
}
}
pub fn raw_next(&mut self) -> &str {
let mut temp = String::default();
std::mem::swap(&mut self.current, &mut temp);
temp.clear();
temp.extend(self.raw_current.iter().rev().map(|&i| {
assert!(i < self.chars.len(), "Bug: Invalid character index");
self.chars[i]
}));
self.current = temp;
let mut carryover = true;
for i in self.raw_current.iter_mut() {
*i += 1;
if *i == self.chars.len() {
*i = 0;
} else {
carryover = false;
break;
}
}
if carryover {
self.raw_current.push(0);
}
&self.current
}
}
impl<'a> Iterator for BruteForce<'a> {
type Item = String;
fn next(&mut self) -> Option<String> {
Some(self.raw_next().to_string())
}
}
#[cfg(feature = "generators")]
impl Generator for Pin<&mut BruteForce<'_>> {
type Yield = String;
type Return = ();
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
GeneratorState::Yielded(self.get_mut().raw_next().to_string())
}
}