1#[cfg(feature = "rayon")]
2extern crate rayon;
3
4#[cfg(feature = "rayon")]
5use rayon::prelude::*;
6
7const ROTATE: u32 = 'z' as u32 - 'a' as u32 + 1;
8
9#[inline(always)]
11pub fn encrypt(input: &str) -> String {
12 encrypt_any(input, 26)
13}
14
15#[inline(always)]
17pub fn decrypt(input: &str) -> String {
18 decrypt_any(input, 26)
19}
20
21#[inline(always)]
25pub fn encrypt_rot13(input: &str) -> String {
26 encrypt_any(input, 13)
27}
28
29#[inline(always)]
33pub fn decrypt_rot13(input: &str) -> String {
34 decrypt_any(input, 13)
35}
36
37pub fn encrypt_any(input: &str, amount: u32) -> String {
41 let closure = |c| {
42 let base = match c {
43 'a'...'z' => 'a' as u32,
44 'A'...'Z' => 'A' as u32,
45 _ => return c
46 };
47
48 std::char::from_u32(((c as u32 - base + amount) % ROTATE) + base).unwrap()
49 };
50 #[cfg(not(feature = "rayon"))]
51 { input.chars().map(closure).collect() }
52 #[cfg(feature = "rayon")]
53 { input.par_chars().map(closure).collect() }
54}
55
56pub fn decrypt_any(input: &str, amount: u32) -> String {
60 let closure = |c| {
61 let base = match c {
62 'a'...'z' => 'a' as u32,
63 'A'...'Z' => 'A' as u32,
64 _ => return c
65 };
66
67 std::char::from_u32(((c as u32 - base + ROTATE - amount) % ROTATE) + base).unwrap()
68 };
69 #[cfg(not(feature = "rayon"))]
70 { input.chars().map(closure).collect() }
71 #[cfg(feature = "rayon")]
72 { input.par_chars().map(closure).collect() }
73}
74
75#[cfg(test)]
76mod tests {
77 use ::*;
78
79 #[test]
80 fn test_rot26() {
81 let plain = "hello";
82 let encrypted = encrypt(plain);
83
84 assert_eq!(encrypted, "hello");
85
86 let decrypted = decrypt(&encrypted);
87
88 assert_eq!(plain, decrypted);
89 }
90 #[test]
91 fn test_rot13() {
92 let plain = "hello";
93 let encrypted = encrypt_rot13(plain);
94
95 assert_eq!(encrypted, "uryyb");
96
97 let decrypted = decrypt_rot13(&encrypted);
98
99 assert_eq!(plain, decrypted);
100 }
101 #[test]
102 fn test_rot13_all() {
103 let plain = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
104 let encrypted = encrypt_rot13(plain);
105
106 assert_eq!(encrypted, "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM");
107
108 let decrypted = decrypt_rot13(&encrypted);
109
110 assert_eq!(plain, decrypted);
111 }
112 #[test]
113 fn test_rot_any() {
114 let amount = 1;
115
116 let plain = "hello";
117 let encrypted = encrypt_any(plain, amount);
118
119 assert_eq!(encrypted, "ifmmp");
120
121 let decrypted = decrypt_any(&encrypted, amount);
122
123 assert_eq!(plain, decrypted);
124 }
125}