#![crate_name = "bruteforce"]
#![feature(test, coroutines, proc_macro_hygiene)]
#![cfg_attr(not(feature = "std"), no_std)]
#[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;
#[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 cur = &mut self.current;
let chars = &self.chars;
cur.clear();
cur.extend(self.raw_current.iter().rev().map(|&i| {
assert!(i < chars.len(), "Bug: Invalid character index");
chars[i]
}));
let mut carryover = true;
let chars_len_m = self.chars.len() - 1;
for i in self.raw_current.iter_mut() {
if *i == chars_len_m {
*i = 0;
} else {
*i += 1;
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())
}
}