use crate::util; pub struct CaesarCipher { alphabet: Vec, offset: i64, } impl CaesarCipher { pub fn new(alphabet: &str, offset: i64) -> anyhow::Result { let alphabet = alphabet.chars().collect::>(); let offset = offset % alphabet.len() as i64; util::verify_alphabet(&alphabet)?; Ok(Self { alphabet, offset }) } pub fn encode(&self, input: &str) -> anyhow::Result { let mut output = String::with_capacity(input.len()); for c in input.chars() { let index = self.get_index(c, self.offset)?; output.push(self.alphabet[index]) } Ok(output) } pub fn decode(&self, input: &str) -> anyhow::Result { let mut output = String::with_capacity(input.len()); for c in input.chars() { let index = self.get_index(c, -self.offset)?; output.push(self.alphabet[index]) } Ok(output) } fn get_index(&self, c: char, offset: i64) -> anyhow::Result { let mut index = self.alphabet .iter() .position(|&x| x == c) .ok_or(anyhow::anyhow!("cannot encode character {:?}", c))? as i64 + offset; while index < 0 { index += self.alphabet.len() as i64; } index %= self.alphabet.len() as i64; Ok(index as usize) } }