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
use crate::crypto_systems::ceasar::Ceasar;
use crate::error::CeasarError;
use crate::prelude::ALPHABET_LEN;
use crate::utils::{decode_digit, encode_char, BaseString, EncodedString, StringType};
use crate::Traits::Encrypt;
use rayon::prelude::*;
impl Encrypt<CeasarError, BaseString, BaseString> for Ceasar {
/// Encrypts a string using the Caesar cipher.
///
/// This function shifts each letter in the input string by a fixed number of positions in the alphabet,
/// wrapping around to the beginning if necessary. Non-alphabetic characters are left unchanged.
/// The shift value is determined by the `shift` field of the `Ceasar` struct.
///
/// # Arguments
///
/// * `input` - A `String` that holds the text to be encrypted.
///
/// # Returns
///
/// * A `Result<String, CeasarError>` which is `Ok` if the encryption is successful, and `Err` otherwise.
/// The `Ok` variant contains the encrypted text, and the `Err` variant contains an error type.
///
/// # Example
///
/// ```
/// # use ferric_crypto_lib::crypto_systems::ceasar::Ceasar;
/// # use ferric_crypto_lib::Traits::Encrypt;
/// let ceasar = Ceasar::new(3);
/// let result = ceasar.encrypt("hello".into()).unwrap();
/// assert_eq!(result, "KHOOR".into());
/// ```
fn encrypt(&self, input: BaseString) -> Result<BaseString, CeasarError> {
let encoded_input = input.encode()?;
// Use par_iter to perform the encryption in parallel, then collect into Vec<usize>
let encrypted_data: Vec<usize> = encoded_input
.par_iter()
.map(|&x| (x + self.shift) % *ALPHABET_LEN)
.collect(); // TODO: would be good if this returned a EncodedString directly!
// Now convert encrypted_data into EncodedString
let encrypted_input = EncodedString::new(encrypted_data, StringType::Standard);
// Code below will be simplified once BaseString is complete
// Finally, decode the encrypted input back into a string
let decoded = encrypted_input.decode()?;
Ok(decoded.to_uppercase())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::error::CharacterParseError::InvalidCharacter;
use crate::Traits::Encrypt;
#[test]
fn encrypts_lowercase() {
let cipher = Ceasar { shift: 3 };
let result = cipher.encrypt("hello".into()).unwrap();
assert_eq!(result, "KHOOR".into());
}
#[test]
fn encrypts_uppercase() {
let cipher = Ceasar { shift: 3 };
let result = cipher.encrypt("HELLO".into()).unwrap();
assert_eq!(result, "KHOOR".into());
}
#[test]
fn encrypts_wrap() {
let cipher = Ceasar { shift: 4 };
let result = cipher.encrypt("zoo".into()).unwrap();
assert_eq!(result, "ASS".into());
}
#[test]
fn encrypts_non_alphabetic_characters() {
let cipher = Ceasar { shift: 3 };
let result = match cipher.encrypt("123!@#".into()) {
Ok(_) => panic!("Should return error"),
Err(e) => e,
};
}
#[test]
fn encrypts_empty_string() {
let cipher = Ceasar { shift: 3 };
let result = cipher.encrypt("".into()).unwrap();
assert_eq!(result, "".into());
}
#[test]
fn encrypts_with_zero_shift() {
let cipher = Ceasar { shift: 0 };
let result = cipher.encrypt("hello".into()).unwrap();
assert_eq!(result, "HELLO".into());
}
#[test]
fn encrypts_with_large_shift() {
let cipher = Ceasar { shift: 100 };
let result = cipher.encrypt("hello".into()).unwrap();
assert_eq!(result, "YUÖÖC".into());
}
#[test]
fn encrypts_mixed_case() {
let cipher = Ceasar { shift: 3 };
let result = cipher.encrypt("HelloVVorld".into()).unwrap();
assert_eq!(result, "KHOORZZRUOG".into());
}
}