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
use crate::crypto_systems::mono_alphabet::{MonoError, Monosubstitution};
use crate::Traits::Decrypt;
impl Decrypt<MonoError, String, String> for Monosubstitution {
/// Decrypts a string using the Monosubstitution cipher.
///
/// This function replaces each character in the input string with its corresponding character in the dictionary.
/// Non-alphabetic characters are left unchanged.
///
/// # Arguments
///
/// * `input` - A `String` that holds the text to be decrypted.
///
/// # Returns
///
/// * A `Result<String, MonoError>` which is `Ok` if the decryption is successful, and `Err` otherwise.
/// The `Ok` variant contains the decrypted text, and the `Err` variant contains an error type.
///
/// # Example
///
/// ```
/// # use ferric_crypto_lib::crypto_systems::mono_alphabet::{MonoError, Monosubstitution};
/// # use ferric_crypto_lib::Traits::Decrypt;
/// # use std::collections::HashMap;
///
/// let dict: HashMap<char, char> = [('d', 'a'), ('e', 'b'), ('f', 'c')].iter().cloned().collect();
/// let mono = Monosubstitution::from(dict);
/// let result = mono.decrypt("def".to_string()).unwrap();
/// assert_eq!(result, "abc");
/// ```
fn decrypt(&self, input: String) -> Result<String, MonoError> {
let mut decrypted = String::new();
for c in input.to_lowercase().chars() {
if self.dict.keys().any(|&k| k == c) {
// Find the corresponding key for the value in the dictionary
for (key, value) in &self.dict {
if *key == c {
decrypted.push(*value);
}
}
} else {
return Err(MonoError::InvalidCharacter(c));
}
}
Ok(decrypted)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Traits::Decrypt;
//use crate::crypto_systems::mono_alphabet::MonoError;
use std::collections::HashMap;
#[test]
fn decrypts_lowercase_letters() {
let dict: HashMap<char, char> = [('d', 'a'), ('e', 'b'), ('f', 'c')]
.iter()
.cloned()
.collect();
#[cfg(feature = "debug")]
{
// print all keys
for (key, value) in &dict {
dbg!(&key);
dbg!(&value);
}
}
let mono = Monosubstitution::from(dict);
let result = mono.decrypt("def".to_string()).unwrap();
assert_eq!(result, "abc");
}
#[test]
fn decrypts_uppercase_letters() {
let dict: HashMap<char, char> = [('d', 'a'), ('e', 'b'), ('f', 'c')]
.iter()
.cloned()
.collect();
let mono = Monosubstitution::from(dict);
let result = mono.decrypt("DEF".to_string()).unwrap();
assert_eq!(result, "abc");
}
#[test]
fn decrypts_mixed_case() {
let dict: HashMap<char, char> = [('d', 'a'), ('e', 'b'), ('f', 'c')]
.iter()
.cloned()
.collect();
let mono = Monosubstitution::from(dict);
let result = mono.decrypt("DeF".to_string()).unwrap();
assert_eq!(result, "abc");
}
#[test]
fn decrypts_empty_string() {
let mono = Monosubstitution::new();
let result = mono.decrypt("".to_string()).unwrap();
assert_eq!(result, "");
}
#[test]
fn decrypts_non_alphabetic_characters() {
let mono = Monosubstitution::new();
let result = mono.decrypt("123!@#".to_string()).unwrap_err();
assert_eq!(result, MonoError::InvalidCharacter('1'));
}
}