circle-cipher/src/encoding.rs

70 lines
2.1 KiB
Rust

use std::{iter, ops::Add};
use crate::message::{self, Message};
pub fn encrypt_message(message: &mut Message, circle_length: &usize) -> Vec<Circle> {
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<message::Triple>;
pub fn circle_to_points(circle: Circle) -> Vec<f64> {
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<message::Triple>, circle_length: &usize) -> Vec<Circle> {
triples.chunks(*circle_length)
.map(|chunk| {
chunk.to_vec()
}).collect()
}
fn encode_circles(circles: &mut Vec<Circle>, shift: &mut u8) -> Vec<Circle> {
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::<Circle>();
let new_circle = match count {
0 => {
let mut vec = vec![circle[0].clone()];
vec.extend(new_circle);
return vec;
},
_ => new_circle,
};
new_circle
}).collect()
}