use std::{iter, ops::Add}; use crate::message::{self, Message}; pub fn encrypt_message(message: &mut Message, circle_length: &usize) -> Vec { encode_circles( &mut triples_into_circles(&message.to_triples(), circle_length), &mut message.parts.start_shift, ) } fn caesar_shift(char: char, shift: u8) -> char { shift.wrapping_add(char as u8) as char } pub type Circle = Vec; pub fn circle_to_points(circle: Circle) -> Vec { circle.iter().flat_map(|triple| { vec![ triple.first as u8 as f64, triple.second as u8 as f64, triple.third as u8 as f64 ] }).collect() } 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() }