use crate::{input, Cipher, CipherInputError, CipherResult, TABULA_RECTA};
pub struct RunningKey {
key: String,
}
impl RunningKey {
pub fn new(key: &str) -> Self {
input::is_alpha(key).expect("`key` must be alphabetic");
Self {
key: key.to_ascii_uppercase(),
}
}
}
impl Cipher for RunningKey {
fn encipher(&self, ptext: &str) -> CipherResult {
if self.key.len() < ptext.len() {
return Err(CipherInputError::BadInput(String::from(
"`ptext` cannot be longer than the key",
)));
}
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] 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 {
if self.key.len() < ctext.len() {
return Err(CipherInputError::BadInput(String::from(
"`ctext` cannot be longer than the key",
)));
}
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] as usize - 65;
TABULA_RECTA[y].iter().position(|&j| j == c).unwrap() as u8 + 65
})
.collect();
Ok(String::from_utf8(ptext).unwrap())
}
}