Skip to main content

cipher_salad/cipher/
atbash.rs

1use crate::{Alphabet, ForeignGraphemesPolicy};
2use unicode_segmentation::UnicodeSegmentation;
3
4pub struct Atbash {
5    foreign_policy: ForeignGraphemesPolicy,
6    alphabet: Alphabet,
7}
8
9impl Atbash {
10    #[must_use]
11    pub fn new(alphabet: Alphabet, foreign_policy: ForeignGraphemesPolicy) -> Self {
12        Self {
13            foreign_policy,
14            alphabet,
15        }
16    }
17
18    fn cipher(&self, contents: &str) -> String {
19        contents
20            .graphemes(true)
21            .map(|grapheme| (grapheme, self.alphabet.index_of(grapheme)))
22            .filter_map(|(grapheme, index)| match index {
23                Some(grapheme_index) => {
24                    let ciphered_index = -(grapheme_index as isize + 1);
25                    let ciphered_index = ciphered_index.rem_euclid(self.alphabet.length() as isize);
26                    self.alphabet.grapheme_at(ciphered_index as usize).cloned()
27                }
28                None => match self.foreign_policy {
29                    ForeignGraphemesPolicy::Include => Some(grapheme.to_string()),
30                    ForeignGraphemesPolicy::Exclude => Some(String::new()),
31                },
32            })
33            .collect()
34    }
35
36    #[must_use]
37    pub fn encrypt(&self, contents: &str) -> String {
38        self.cipher(contents)
39    }
40
41    #[must_use]
42    pub fn decrypt(&self, ciphertext: &str) -> String {
43        self.cipher(ciphertext)
44    }
45}