use std::{borrow::Borrow, collections::HashMap}; use crate::{ model::model::*, controller::view_utils::input_utils::*, }; /// **Синдромы** /// /// ошибочная позиция 1 false true true. /// /// ошибочная позиция 2 false false true. /// /// ошибочная позиция 3 true false true. /// /// ошибочная позиция 4 false true false. /// /// ошибочная позиция 5 true true false. /// /// ошибочная позиция 6 true false false. /// /// ошибочная позиция 7 false false false. pub fn hamming(raw_input: String, mode: HammingMode) -> Result{ let length_of_code : usize = mode.clone() as usize; let prepared_input : String = processing_input(&raw_input); let (fc, sc) = check_correct_input(&raw_input, &prepared_input, length_of_code); if !fc || !sc { Err("Ошибка. Проверьте корректность ввода.".to_string()) } else { let mut data : String = String::new(); let prepared_data: Vec = from_string_to_vec_bits(prepared_input); match mode { HammingMode::Encrypt => hamming_encrypt_data(&prepared_data, &mut data, length_of_code), HammingMode::Decrypt => hamming_decrypt_data(&prepared_data, &mut data, length_of_code), } return Ok(data); } } pub fn hamming_encrypt_data( data: &Vec, result_string: &mut String, length_of_code: usize ) { let mut i : usize = length_of_code; while i <= data.len(){ let data_bits = &data[i - length_of_code..i]; let (check_bit_1, check_bit_2, check_bit_3) = ( data_bits[0] ^ data_bits[1] ^ data_bits[3], data_bits[0] ^ data_bits[2] ^ data_bits[3], data_bits[1] ^ data_bits[2] ^ data_bits[3] ); result_string.push_str(&*format!("{check_bit_1}{}{check_bit_2}{}{check_bit_3}{}{} ", data_bits[0], data_bits[1], data_bits[2], data_bits[3])); i += length_of_code; } } pub fn hamming_decrypt_data( data: &Vec, result_string: &mut String, length_of_code: usize ) { let mut i : usize = length_of_code; let syndromes : HashMap = HashMap::from( [ (1, (false, true, true)), (2, (false, false, true)), (3, (true, false, true)), (4, (false, true, false)), (5, (true, true, false)), (6, (true, false, false)), (7, (false, false, false)), ] ); let mut errors : String = String::new(); while i <= data.len(){ let mut data_bits = &data[i - length_of_code..i]; let checked_bits : (bool, bool, bool) = ( (data_bits[1] ^ data_bits[3] ^ data_bits[6]) == data_bits[0], (data_bits[1] ^ data_bits[5] ^ data_bits[6]) == data_bits[2], (data_bits[3] ^ data_bits[5] ^ data_bits[6]) == data_bits[4] ); match checked_bits { (true, true, true) => { i += length_of_code; continue; }, _ => { let error_position = syndromes .iter() .find(move |&(&error_position, &error)| error == checked_bits). unwrap().0; let correctly_code : Vec = data_bits .iter() .enumerate() .map(|(index, bit)| { if index == error_position - 1 { if *bit == 1u8 { 0u8 } else { 1u8 } } else { *bit } }).collect(); let error = format!("Ошибка в коде {} {:?}, позиция ошибки {}, корректный код: {:?}; \n", i / 7, &data_bits, error_position, correctly_code ); errors.push_str(error.as_str()); i += length_of_code; } } } if errors.len() == 0 { result_string.push_str("Все коды корректны."); } else { result_string.push_str(errors.as_str()) } }