====== Solution chiffre de Vigenère en Rust ====== Solution à ce [[nsi:tds:cryptographie:chiffre_vigenere|problème]]. // src/lib.rs fn shift_letter(letter:char, s:u8) -> char { if !is_maj(letter) { return letter; } let c = letter as u8; let a = 65u8; // ASCII de A (a + (c - a + s) % 26) as char } fn is_maj(letter:char) -> bool { letter >= 'A' && letter <= 'Z' } fn str_to_vec(text:&str) -> Vec { let mut v:Vec = Vec::new(); for c in text.chars() { if is_maj(c) { v.push((c as u8) - 65); } } v } pub fn cypher(message:&str, key:&str) -> String { let k = str_to_vec(key); let n = k.len(); if n == 0 { return String::from(message); } let mut s = String::new(); let mut i = 0; for c in message.chars() { if !is_maj(c) { s.push(c); continue; } s.push(shift_letter(c, k[i])); i = (i + 1)%n; } s } pub fn decypher(message:&str, key:&str) -> String { let k = str_to_vec(key); let n = k.len(); if n == 0 { return String::from(message); } let mut s = String::new(); let mut i = 0; for c in message.chars() { if !is_maj(c) { s.push(c); continue; } s.push(shift_letter(c, 26 - k[i])); i = (i + 1)%n; } s } #[cfg(test)] mod tests { #[test] fn shift_test() { assert_eq!(crate::shift_letter('A', 2), 'C'); assert_eq!(crate::shift_letter('Z', 5), 'E'); assert_eq!(crate::shift_letter('i', 5), 'i'); assert_eq!(crate::shift_letter(' ', 15), ' '); } #[test] fn is_maj_test() { assert_eq!(crate::is_maj('A'), true); assert_eq!(crate::is_maj('e'), false); assert_eq!(crate::is_maj(' '), false); } #[test] fn vec_test() { assert_eq!(crate::str_to_vec("AB C"), [0u8, 1u8, 2u8]); } #[test] fn cypher_test() { assert_eq!(crate::cypher("BONJOUR AMI", "AB C"), String::from("BPPJPWR BOI")); } #[test] fn decypher_test() { assert_eq!(crate::decypher("BPPJPWR BOI", "AB C"), String::from("BONJOUR AMI")); } } // src/main.rs use std::env; use std::fs; // file system use vigenere::{cypher, decypher}; fn main() { let args: Vec = env::args().collect(); if args.len() < 3 { panic!("Usage : {} source key [-cypher ou -decypher] [cible]", args[0]); } let filename = &args[1]; let message = fs::read_to_string(filename) .expect("Impossible d'ouvrir le fichier."); let key = &args[2]; let sens = if args.len() >= 4 { &args[3] } else { "-cypher" }; let s = if sens == "-cypher" { cypher(&message, &key) } else { decypher(&message, &key) }; if args.len() >= 5 { let cible = &args[4]; fs::write(cible, s).expect("Impossible d'écrire le fichier."); } else { print!("{}", s); } }