use std::{iter, ops::Add}; use crate::message::{self, Message}; pub fn encrypt_message(message: &mut Message, circle_length: &usize) -> Vec { fill_circles( &mut encode_circles( &mut triples_into_circles(&message.to_triples(), circle_length), &mut message.parts.start_shift, ), circle_length ) } fn caesar_shift(char: char, shift: u8) -> char { (char as u8 + shift) as char } type Circle = Vec; fn triples_into_circles(triples: &Vec, circle_length: &usize) -> Vec { triples.chunks(*circle_length) .map(|chunk| { chunk.to_vec() }).collect() } fn encode_circles(circles: &mut Vec, shift: &mut u8) -> Vec { circles.iter_mut().enumerate().map(|(count, circle)| { let shift_delta = match count { count if count % 2 == 0 => count.add(1) as i8, _ => -(count.add(1) as i8) }; let circle_iter = circle.iter_mut(); let new_circle = match count { 0 => circle_iter.skip(1), _ => circle_iter.skip(0), }.map(|triple| { triple.first = caesar_shift(triple.first, *shift); *shift = shift.wrapping_add_signed(shift_delta); triple.second = caesar_shift(triple.second, *shift); *shift = shift.wrapping_add_signed(shift_delta); triple.second = caesar_shift(triple.third, *shift); *shift = shift.wrapping_add_signed(shift_delta); triple.clone() }).collect::(); let new_circle = match count { 0 => { let mut vec = vec![circle[0].clone()]; vec.extend(new_circle); return vec; }, _ => new_circle, }; new_circle }).collect() } fn fill_circles(circles: &mut Vec, circle_length: &usize) -> Vec { circles.iter_mut().map(|circle| { circle.extend(iter::repeat(message::Triple::filler()) .take( circle_length - circle.len() ) ); circle.clone() }).collect() }