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
//! Provided structures to easily configure passphrase generation [schemes](::scheme::Scheme)
//!
//! This module contains various configuration structures that allow easy configuring of a
//! [`Scheme`](::scheme::Scheme) used to define how passphrases are generated.
//!
//! These predefined configuration structures use a predefined set of [components](::component) and
//! support configurability through struct fields. All configuration strucutres have a matching
//! builder to use if you prefer to use the builder pattern.
//!
//! The most basic configuration structure provides is [`BasicConfig`](BasicConfig), see it's
//! documentation for information on how to use it and for some examples.

use component::{
    phrase::BasicPhraseBuilder,
    word::{FixedWordSetProvider, WordCapitalizer},
};
use prelude::*;
use probability::Probability;
use scheme::{Scheme, SchemeBuilder};
use word::{WordList, WordSampler};

use super::{DEFAULT_SEPARATOR, DEFAULT_WORDS};

/// A simple passphrase configuration struct.
///
/// This struct provides basic passphrase generation options for simple passphrases.
/// When the struct is configured, a [`Scheme`](Scheme) may be created based on it to actually
/// generate passphrases.
///
/// # Examples
///
/// Use the default basic configuration, and change the separator. Then build a scheme, and
/// generate a passphrase.
///
/// ```rust
/// extern crate chbs;
/// use chbs::{config::BasicConfig, prelude::*};
///
/// // Define the configuration
/// let mut config = BasicConfig::default();
/// config.separator = "-".into();
///
/// // Build the scheme for generation
/// let mut scheme = config.to_scheme();
///
/// // Generate and output
/// println!("Passphrase: {}", scheme.generate());
/// ```
///
/// Or use the [`BasicConfigBuilder`](BasicConfigBuilder) instead for a builder pattern:
///
/// ```rust
/// // TODO: fix this example
/// // extern crate chbs;
/// // use chbs::{config::*, word::WordSampler};
/// //
/// // let config = BasicConfigBuilder::default()
/// //     .separator("-")
/// //     .build()
/// //     .unwrap();
/// ```
#[derive(Builder, Clone, Debug)]
#[builder(setter(into))]
pub struct BasicConfig<P>
where
    P: WordProvider,
{
    /// The number of words the passphrase will consist of.
    pub words: usize,

    /// A provider random passphrase words can be obtained from.
    pub word_provider: P,

    /// The separator string to use between passphrase words.
    pub separator: String,

    /// Whether to capitalize the first characters of words.
    pub capitalize_first: Probability,

    /// Whether to capitalize whole words.
    pub capitalize_words: Probability,
}

impl Default for BasicConfig<WordSampler> {
    /// Build a default basic configuration instance.
    ///
    /// This configuration uses the defaul wordlist as word provider for generating passphrases.
    fn default() -> BasicConfig<WordSampler> {
        BasicConfig {
            words: DEFAULT_WORDS,
            word_provider: WordList::default().sampler(),
            separator: DEFAULT_SEPARATOR.into(),
            capitalize_first: Probability::half(),
            capitalize_words: Probability::Never,
        }
    }
}

impl<P> ToScheme for BasicConfig<P>
where
    P: WordProvider + 'static,
{
    fn to_scheme(&self) -> Scheme {
        SchemeBuilder::default()
            .word_set_provider(Box::new(FixedWordSetProvider::new(
                self.word_provider.clone(),
                self.words,
            ))).word_stylers(vec![Box::new(WordCapitalizer::new(
                self.capitalize_first,
                self.capitalize_words,
            ))]).phrase_builder(Box::new(BasicPhraseBuilder::new(self.separator.clone())))
            .phrase_stylers(Vec::new())
            .build()
            .unwrap()
    }
}