1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Exposing encryption methods.
pub mod base64;
pub mod vigenere;
pub mod xor;

// Importing the encryption methods.
pub use base64::Base64;
pub use vigenere::Vigenere;
pub use xor::Xor;

// Bringing crate's prelude to scope.
use crate::prelude::*;

// Using standard library's traits.
use std::default::Default;

// Other exports.
use std::sync::Arc;
use async_trait::async_trait;

// Definition of the alphabet used on some encryption methods.
pub static ALPHABET: [char; 26] = [
    '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',
];

// Setting States for the PasswordBuilder
#[derive(Default, Clone, Debug)]
pub struct NoUnique;
#[derive(Clone, Debug)]
pub struct Unique(Arc<str>);
#[derive(Default, Clone, Debug)]
pub struct NoVariable;
#[derive(Clone, Debug)]
pub struct Variable(Arc<str>);

/// Definines the password builder that implements default values and can be cloned.
#[derive(Clone, Default, Debug)]
pub struct PasswordBuilder<U, V> {
    unique: U,
    variable: V,
    repeat: Option<u8>,
}

/// Defines method encryption trait.
#[async_trait]
pub trait Method: std::fmt::Debug {
    async fn encrypt(&self, uw: Arc<str>, vw: Arc<str>) -> Result<String>;
}

/// Implementation of PasswordBuilder when nothing is set yet.
impl PasswordBuilder<NoUnique, NoVariable> {
    pub fn new() -> Self {
        Default::default()
    }
}

/// Implementation of PasswordBuilder when it is already instantiated.
impl<U, V> PasswordBuilder<U, V> {
    /// Sets the unique word to build the passoword.
    pub fn unique(self, word: impl Into<String>) -> PasswordBuilder<Unique, V> {
        PasswordBuilder {
            unique: Unique(Arc::from(word.into())),
            variable: self.variable,
            repeat: self.repeat,
        }
    }

    /// Sets the variable word to build the password.
    pub fn variable(self, word: impl Into<String>) -> PasswordBuilder<U, Variable> {
        PasswordBuilder {
            unique: self.unique,
            variable: Variable(Arc::from(word.into())),
            repeat: self.repeat,
        }
    }
}

/// Implementation of PasswordBuilder when "unique" and "variable" fields are set.
impl PasswordBuilder<Unique, Variable> {
    /// Sets a number of repetitions to use on the following specified method.
    pub fn repeat(self, number: impl Into<u8>) -> Self {
        PasswordBuilder {
            repeat: Some(number.into()),
            ..self
        }
    }

    /// Generates a password based on a method. Can be chained with multiple methods.
    pub async fn method<T: Method + Default + PartialEq + Clone>(self, method: T) -> Result<Self> {
        let vw = self.variable.0.clone();

        let mut repeat = self.repeat.unwrap_or(1);
        if repeat == 0 {
            repeat = 1_u8;
        }

        let mut pass = self.unique.0.clone();
        for _ in 0..repeat {
            let new_pass = method.encrypt(pass, vw.clone()).await?;

            pass = Arc::from(new_pass);
        }

        Ok(PasswordBuilder {
            unique: Unique(pass),
            repeat: None,
            ..self
        })
    }

    /// Generates a password based on a method from a pointer. Can be chained with multiple methods.
    pub async fn method_ptr(self, method: Arc<dyn Method + Sync + Send>) -> Result<Self> {
        let vw = self.variable.0.clone();

        let mut repeat = self.repeat.unwrap_or(1);
        if repeat == 0 {
            repeat = 1_u8;
        }

        let mut pass = self.unique.0.clone();
        for _ in 0..repeat {
            let new_pass = method.encrypt(pass, vw.clone()).await?;

            pass = Arc::from(new_pass);
        }

        Ok(PasswordBuilder {
            unique: Unique(pass),
            repeat: None,
            ..self
        })
    }

    pub fn build(self) -> String {
        self.unique.0.to_string()
    }
}