use crate::{input, Cipher, CipherResult};
pub struct Substitution {
key: String,
}
impl Substitution {
pub fn new(key: &str) -> Self {
assert_eq!(key.len(), 26, "`key` must be 26 chars in length");
input::is_alpha(key).expect("`key` must be alphabetic");
input::no_repeated_chars(key).expect("`key` cannot contain repeated chars");
Self {
key: key.to_ascii_uppercase(),
}
}
}
impl Cipher for Substitution {
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().map(move |c| key[(c - 65) as usize]).collect();
Ok(String::from_utf8(ctext).unwrap())
}
fn decipher(&self, ctext: &str) -> CipherResult {
input::is_alpha(ctext)?;
let ctext = ctext.to_ascii_uppercase();
let ptext = ctext
.bytes()
.map(move |c| self.key.find(move |i| i == c as char).unwrap() as u8 + 65)
.collect();
Ok(String::from_utf8(ptext).unwrap())
}
}