use crate::{input, Cipher, CipherResult, TABULA_RECTA};
pub struct Vigenere {
key: String,
}
impl Vigenere {
pub fn new(key: &str) -> Self {
input::is_alpha(key).expect("`key` must be alphabetic");
Self {
key: key.to_ascii_uppercase(),
}
}
}
impl Cipher for Vigenere {
fn encipher(&self, ptext: &str) -> CipherResult {
input::is_alpha(ptext)?;
let ptext = ptext.to_ascii_uppercase();
let key = self.key.as_bytes();
let ctext = ptext
.bytes()
.enumerate()
.map(move |(i, c)| {
let y = key[i % key.len()] as usize - 65;
let x = c as usize - 65;
TABULA_RECTA[y][x]
})
.collect();
Ok(String::from_utf8(ctext).unwrap())
}
fn decipher(&self, ctext: &str) -> CipherResult {
input::is_alpha(ctext)?;
let ctext = ctext.to_ascii_uppercase();
let key = self.key.as_bytes();
let ptext = ctext
.bytes()
.enumerate()
.map(move |(i, c)| {
let y = key[i % key.len()] as usize - 65;
TABULA_RECTA[y].iter().position(|&j| j == c).unwrap() as u8 + 65
})
.collect();
Ok(String::from_utf8(ptext).unwrap())
}
}