rot26/
lib.rs

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/// Encrypts the input using rot26.
10#[inline(always)]
11pub fn encrypt(input: &str) -> String {
12    encrypt_any(input, 26)
13}
14
15/// Decrypts the input using rot26.
16#[inline(always)]
17pub fn decrypt(input: &str) -> String {
18    decrypt_any(input, 26)
19}
20
21/// Encrypts the input using rot13.
22/// Warning: Security researchers have managed to crack rot13.
23/// New users are recommended to use rot26 for the best security.
24#[inline(always)]
25pub fn encrypt_rot13(input: &str) -> String {
26    encrypt_any(input, 13)
27}
28
29/// Decrypts the input using rot13.
30/// Warning: Security researchers have managed to crack rot13.
31/// New users are recommended to use rot26 for the best security.
32#[inline(always)]
33pub fn decrypt_rot13(input: &str) -> String {
34    decrypt_any(input, 13)
35}
36
37/// Encrypt using any amount.
38/// Warning: Please carefully choose the right amount.
39/// New users are recommended to use rot26 for the best security.
40pub 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
56/// Decrypt using any amount.
57/// Warning: Please carefully choose the right amount.
58/// New users are recommended to use rot26 for the best security.
59pub 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}