use std::path::Path; use mini_enigma::components::{ Plugboard, Reflector, Rotor, REFLECTOR_A, REFLECTOR_B, REFLECTOR_B_THIN, REFLECTOR_C, REFLECTOR_C_THIN, ROTOR_BETA, ROTOR_GAMMA, ROTOR_I, ROTOR_II, ROTOR_III, ROTOR_IV, ROTOR_V, ROTOR_VI, ROTOR_VII, ROTOR_VIII, }; use mini_enigma::state_machine::EnigmaSettings; use mini_enigma::utils::Letter; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(untagged)] pub enum RingstellungJSON { Int(Vec), Str(Vec), } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct EnigmaSettingsJSON { pub name: String, pub date: Option, pub rotors: Vec, pub reflector: String, pub ringstellung: RingstellungJSON, pub grundstellung: Vec, pub plugboard: Vec, pub ciphertext: String, pub plaintext: String, } fn get_rotor(name: String) -> Option { match name.as_str() { "I" => Some(ROTOR_I), "II" => Some(ROTOR_II), "III" => Some(ROTOR_III), "IV" => Some(ROTOR_IV), "V" => Some(ROTOR_V), "VI" => Some(ROTOR_VI), "VII" => Some(ROTOR_VII), "VIII" => Some(ROTOR_VIII), "beta" => Some(ROTOR_BETA), "gamma" => Some(ROTOR_GAMMA), _ => None, } } fn get_reflector(name: String) -> Option { match name.as_str() { "A" => Some(REFLECTOR_A), "B" => Some(REFLECTOR_B), "C" => Some(REFLECTOR_C), "B Thin" => Some(REFLECTOR_B_THIN), "C Thin" => Some(REFLECTOR_C_THIN), _ => None, } } pub fn load_enigma_settings

(file_path: P) -> EnigmaSettingsJSON where P: AsRef + std::fmt::Display + Copy, { serde_json::from_str( &std::fs::read_to_string(file_path).expect(&format!("File at {file_path} not found")), ) .expect(&format!("Could not parse file {file_path}")) } impl From for EnigmaSettings { fn from(value: EnigmaSettingsJSON) -> Self { let mut rotors = [ROTOR_I; ROTOR_NUM]; for (i, name) in value.rotors.iter().enumerate() { rotors[i] = get_rotor(name.clone()).expect(format!("Invalid rotor name: {name}").as_str()); } let reflector = get_reflector(value.reflector.clone()) .expect(format!("Invalid reflector name: {}", value.reflector).as_str()); let ringstellung: [u8; ROTOR_NUM] = { let mut rs = [0u8; ROTOR_NUM]; match value.ringstellung { RingstellungJSON::Int(x) => { for (i, &ring) in x.iter().enumerate() { rs[i] = ring } } RingstellungJSON::Str(x) => { for (i, &ring) in x.iter().enumerate() { rs[i] = ring as u8 - 64 } } }; rs }; let grundstellung = { let mut gs = [Letter::A; ROTOR_NUM]; for (i, &ring) in value.grundstellung.iter().enumerate() { gs[i] = Letter::try_from(ring).unwrap(); } gs }; let plugboard = { let pairs = value .plugboard .iter() .map(|x| { ( Letter::try_from(x.as_bytes()[0] as char).unwrap(), Letter::try_from(x.as_bytes()[1] as char).unwrap(), ) }) .collect::>(); Plugboard::new(&pairs) }; EnigmaSettings { rotors, plugboard, reflector, ringstellung, grundstellung, } } }