forked from TheAlgorithms/Rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vigenere.rs
86 lines (75 loc) · 2.23 KB
/
vigenere.rs
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
//! Vigenère Cipher
//!
//! # Algorithm
//!
//! Rotate each ascii character by the offset of the corresponding key character.
//! When we reach the last key character, we start over from the first one.
//! This implementation does not rotate unicode characters.
/// Vigenère cipher to rotate plain_text text by key and return an owned String.
pub fn vigenere(plain_text: &str, key: &str) -> String {
// Remove all unicode and non-ascii characters from key
let key: String = key.chars().filter(|&c| c.is_ascii_alphabetic()).collect();
let key = key.to_ascii_lowercase();
let key_len = key.len();
if key_len == 0 {
return String::from(plain_text);
}
let mut index = 0;
plain_text
.chars()
.map(|c| {
if c.is_ascii_alphabetic() {
let first = if c.is_ascii_lowercase() { b'a' } else { b'A' };
let shift = key.as_bytes()[index % key_len] - b'a';
index += 1;
// modulo the distance to keep character range
(first + (c as u8 + shift - first) % 26) as char
} else {
c
}
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty() {
assert_eq!(vigenere("", "test"), "");
}
#[test]
fn vigenere_base() {
assert_eq!(
vigenere("LoremIpsumDolorSitAmet", "base"),
"MojinIhwvmVsmojWjtSqft"
);
}
#[test]
fn vigenere_with_spaces() {
assert_eq!(
vigenere(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"spaces"
),
"Ddrgq ahhuo hgddr uml sbev, ggfheexwljr chahxsemfy tlkx."
);
}
#[test]
fn vigenere_unicode_and_numbers() {
assert_eq!(
vigenere("1 Lorem ⏳ ipsum dolor sit amet Ѡ", "unicode"),
"1 Fbzga ⏳ ltmhu fcosl fqv opin Ѡ"
);
}
#[test]
fn vigenere_unicode_key() {
assert_eq!(
vigenere("Lorem ipsum dolor sit amet", "😉 key!"),
"Vspoq gzwsw hmvsp cmr kqcd"
);
}
#[test]
fn vigenere_empty_key() {
assert_eq!(vigenere("Lorem ipsum", ""), "Lorem ipsum");
}
}