AIT/src/controller/model_utils/hamming_code_seven_four.rs

124 lines
4.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::collections::HashMap;
use std::sync::LazyLock;
use crate::{
controller::view_utils::{hamming_code_input_utils::*, input_utils::*},
model::{models::*, Result},
};
static SYNDROMES: LazyLock<HashMap<usize, (bool, bool, bool)>> = LazyLock::new(|| {
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)),
])
});
pub fn hamming(raw_input: String, mode: HammingMode) -> Result<String> {
let length_of_code: usize = mode.clone() as usize;
let prepared_input: String = processing_input(&raw_input);
let (first_condition, second_condition): (bool, bool) =
check_correct_binary_code(&raw_input, &prepared_input, length_of_code);
if raw_input.is_empty() {
Err("Введите код.".into())
} else if !first_condition || !second_condition {
Err("Проверьте корректность ввода.".into())
} else {
let prepared_data: Vec<u8> = from_string_to_vec_bits(prepared_input);
match mode {
HammingMode::Encrypt => Ok(hamming_encrypt_data(&prepared_data, length_of_code)),
HammingMode::Decrypt => Ok(hamming_decrypt_data(&prepared_data, length_of_code)),
}
}
}
pub fn hamming_encrypt_data(data: &Vec<u8>, 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<u8>, result_string: &mut String, length_of_code: usize) {
let mut general_length: usize = length_of_code;
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::<Vec<u8>>()
.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.is_empty() {
if errors.is_empty() {
result_string.push_str("Все коды корректны.");
} else {
result_string.push_str(errors.as_str());
}
} else {
result_string.push_str("Введите код для проверки.")
}
}