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

/// enigma module
use super::{ SubstitutionTable, ALPHABETS };

/// utility module
use utility::{ GetIndex, IndexResult };

pub enum Digit {
    Up,
    NoChange
}

pub struct Router {
    pub position: usize,
    pub substitution_table: SubstitutionTable
}

pub trait RouterProtocol {
    fn increment(&mut self) -> Digit;
    fn encrypt(&self, character: &char) -> char;
    fn reverse(&self, character: &char) -> char;
}

impl RouterProtocol for Router {
    fn increment(&mut self) -> Digit {
        self.position += 1;
        let digit     = self.get_digit();
        self.position = self.position % self.get_length();

        return digit
    }

    fn encrypt(&self, character: &char) -> char {

        let characters = ALPHABETS.to_vec();
        let length     = self.get_length();

        match characters.get_index(character) {
            IndexResult::Exist(index) => return self.substitution_table.characters[(index + self.position) % length],
            IndexResult::None         => *character
        }
    }

    fn reverse(&self, character: &char) -> char {

        let characters = ALPHABETS.to_vec();
        let length     = self.get_length();

        match self.substitution_table.characters.get_index(character) {
            IndexResult::Exist(index) => characters[(length + index - self.position) % length],
            IndexResult::None         => *character
        }
    }
}

impl Router {

    pub fn new(substitution_table: SubstitutionTable) -> Self {
        Router {
            position: 0,
            substitution_table
        }
    }

    pub fn set_position(&mut self, position: &char) {
        self.position = match ALPHABETS.to_vec().get_index(position) {
            IndexResult::Exist(index) => index,
            IndexResult::None         => 0
        }
    }

    fn get_length(&self) -> usize {
        self.substitution_table.characters.len()
    }

    fn get_digit(&self) -> Digit {
        match self.position == self.substitution_table.characters.len() {
            true  => Digit::Up,
            false => Digit::NoChange
        }
    }
}