use std::collections::HashMap; use crate::{ controller::view_utils::{hamming_code_input_utils::*, input_utils::*}, model::models::*, }; /// **Синдромы** /// /// ошибочная позиция 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): (bool, bool) = check_correct_binary_code(&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: &[u8] = &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 general_length: 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 general_length <= data.len() { let data_bits = &data[general_length - length_of_code..general_length]; 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], ); if let (true, true, true) = checked_bits { general_length += length_of_code; continue; } else { let error_position: &usize = syndromes .iter() .find(move |&(&_error_position, &error)| error == checked_bits) .unwrap() .0; let uncorrect_code: String = from_vec_bits_to_string(&data_bits); let correct_code: String = from_vec_bits_to_string( data_bits .iter() .enumerate() .map(|(index, &bit)| { if index == error_position - 1 { (bit == 0u8).into() } else { bit } }) .collect::>() .as_slice(), ); let error = format!( "Ошибка в коде {} [{uncorrect_code}], позиция ошибки {}, корректный код: [{correct_code}]; \n", general_length / 7, error_position ); errors.push_str(error.as_str()); general_length += length_of_code; } } if data.len() > 0 { if errors.len() == 0 { result_string.push_str("Все коды корректны."); } else { result_string.push_str(errors.as_str()); } } else { result_string.push_str("Введите код для проверки.") } }