From ecc4092f14862811d85238d82887be10acb09c69 Mon Sep 17 00:00:00 2001 From: CLog <88345999+CLOG9@users.noreply.github.com> Date: Wed, 24 Jan 2024 01:07:41 +0100 Subject: [PATCH] update (decrytion): creating the decpt - still not fully tested, lib translated --- src/decpt/demapping/demapper.rs | 0 src/encpt/decrypt.rs | 100 +++++++++++++++++++++++----- src/encpt/encrypt.rs | 49 +++++++------- src/encpt/mapping/mapper.rs | 55 ++++++++-------- src/encpt/mapping/switcher.rs | 85 ++++++++++++++++++++++++ src/main.rs | 53 ++------------- src/maps/chars.rs | 111 ++++++++++++++++++++++---------- src/maps/salt.rs | 45 ++++--------- src/shared/parse.rs | 17 +++++ 9 files changed, 332 insertions(+), 183 deletions(-) delete mode 100644 src/decpt/demapping/demapper.rs diff --git a/src/decpt/demapping/demapper.rs b/src/decpt/demapping/demapper.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/encpt/decrypt.rs b/src/encpt/decrypt.rs index e755527..31a5221 100644 --- a/src/encpt/decrypt.rs +++ b/src/encpt/decrypt.rs @@ -1,23 +1,22 @@ use std::{error::Error, i32}; use crate::{ - encpt::math::{matrix::vecs_to_mtrx, process::rem_from_vec}, - mxas_to_chars, + chr_to_mp, chr_to_mxas, + encpt::{ + mapping::switcher::reference_to_origin, + math::{matrix::vecs_to_mtrx, process::rem_from_vec}, + }, + salt_extender, shared::parse::{ - concat_every_n_elements, get_indexes, move_elements, rem_zeros, split_string, - string_vec2_str, Mv_Direction, + concat_every_n_elements, generate_a_string, get_indexes, join_string, move_elements, + pop_elements_from_vector, rem_zeros, split_string, str2_string_vec, string_vec2_str, + Mv_Direction, }, + DirecType, MpType, }; use super::analyse::read::reader; -#[derive(Debug)] -struct EncptInfo { - original_length: usize, - salt_short: usize, // 0 : buffer, 1 : salt - mtrx_n: usize, -} - pub fn ceaser_unswap(indxs: Vec, n: usize) -> Vec { let swp = get_indexes( move_elements(n, Mv_Direction::RIGHT), @@ -29,10 +28,28 @@ pub fn ceaser_unswap(indxs: Vec, n: usize) -> Vec { .map(|c| c.parse::().unwrap()) .collect() } +pub fn ref_to_bfr_vec(salt: String, mx_as_to_char: Vec) -> Vec { + let salt_vec: Vec<&str>; + + let binding = split_string(&salt); + match chr_to_mp( + string_vec2_str(&binding), + MpType::SaltMap, + DirecType::FORWARD, + ) { + Ok(t) => salt_vec = t, + Err(e) => panic!("{}", e), + }; + let bfr_vec: Vec; + match reference_to_origin(salt_vec, string_vec2_str(&mx_as_to_char)) { + Ok(t) => bfr_vec = t, + Err(e) => panic!("{}", e), + }; + bfr_vec +} pub fn df1t_decrypt(buffer: String, salt: String) -> Result> { let parsed_buffer = reader(buffer, "$"); - let info = &parsed_buffer[0]; - let parsed_info = reader(info.to_string(), ";"); + // split each vector let grn = split_string(&parsed_buffer[1]); let rd = split_string(&parsed_buffer[2]); @@ -53,13 +70,64 @@ pub fn df1t_decrypt(buffer: String, salt: String) -> Result; - match mxas_to_chars(string_vec2_str(&restored_mtrx)) { + match chr_to_mxas(string_vec2_str(&restored_mtrx), DirecType::BACKWARD) { Ok(t) => mx_as_to_char = concat_every_n_elements(t, 2), Err(e) => panic!("{}", e), }; - println!("{:?}", mx_as_to_char); - Ok(salt) + + // original length of the buffer before cyph + let orgnl = ceaser_unswap(split_string(&parsed_buffer[0].clone()), 142); + + if orgnl[0] > salt.len() as i32 { + // extending the salt + let virt_str = generate_a_string(orgnl[0] as usize); + let slt_extd: String; + match salt_extender(&salt, &virt_str) { + Ok(t) => slt_extd = t, + Err(e) => panic!("{}", e), + }; + // translating the salt to first level map + let bfr_vec = ref_to_bfr_vec(slt_extd, mx_as_to_char); + println!("{:?}", bfr_vec); + match chr_to_mp( + string_vec2_str(&bfr_vec), + MpType::CharMap, + DirecType::BACKWARD, + ) { + Ok(t) => return Ok(join_string(str2_string_vec(t))), + Err(e) => panic!("{}", e), + }; + // last parse + } else if orgnl[0] < salt.len() as i32 { + // translating the salt to first level map + let mut bfr_vec = ref_to_bfr_vec(salt.clone(), mx_as_to_char); + // pop the extended elements + pop_elements_from_vector(&mut bfr_vec, salt.len() - orgnl[0] as usize); + println!("{:?}", bfr_vec); + + match chr_to_mp( + string_vec2_str(&bfr_vec), + MpType::CharMap, + DirecType::BACKWARD, + ) { + Ok(t) => return Ok(join_string(str2_string_vec(t))), + Err(e) => panic!("{}", e), + }; + } else { + // translating the salt to first level map + let bfr_vec = ref_to_bfr_vec(salt.clone(), mx_as_to_char); + println!("{:?}", bfr_vec); + match chr_to_mp( + string_vec2_str(&bfr_vec), + MpType::CharMap, + DirecType::BACKWARD, + ) { + Ok(t) => return Ok(join_string(str2_string_vec(t))), + Err(e) => panic!("{}", e), + }; + } } // mx version ["652", "165", "314", "671", "113", "422", "103", "923", "314", "194", "113", "389", "314", "422", "652", "923", "113", "194", "103", "422", "652", "389"] diff --git a/src/encpt/encrypt.rs b/src/encpt/encrypt.rs index 8923329..bc2f48e 100644 --- a/src/encpt/encrypt.rs +++ b/src/encpt/encrypt.rs @@ -8,7 +8,7 @@ use crate::shared::parse::{ flatten_vec, get_elements_by_indexes, join_string, move_elements, split_by_n, split_string, str2_string_vec, string_vec2_str, Mv_Direction, }; -use crate::{chr_to_mp, chr_to_mxas, salt_extender, MpType}; +use crate::{chr_to_mp, chr_to_mxas, salt_extender, DirecType, MpType}; #[derive(Debug)] struct ValueError { @@ -21,11 +21,7 @@ impl fmt::Display for ValueError { } impl Error for ValueError {} -#[derive(Debug)] -struct EncptInfo { - original_length: usize, - salt_short: usize, // 0 : buffer, 1 : salt -} + pub fn is_salt_short<'a>(buffer: &'a str, salt: &'a str) -> bool { if buffer.len() > salt.len() { return true; @@ -77,26 +73,41 @@ pub fn df1t_encrypt(buffer: String, salt: String) -> Result = split_string(&buffer); let mut binding2: Vec = split_string(&salt); - let mut shrt = 0; + match is_salt_short(&buffer, &salt) { true => { binding2 = split_string(&extended); - shrt = 1 } // + add the shortest in struct false => binding1 = split_string(&extended), } + match is_salt_short(&buffer, &salt) { + true => { + println!("true") + } // + add the shortest in struct + false => println!("false"), + } let buffer_vec: Vec<&str>; - match chr_to_mp(string_vec2_str(&binding1), MpType::CharMap) { + match chr_to_mp( + string_vec2_str(&binding1), + MpType::CharMap, + DirecType::FORWARD, + ) { Ok(t) => buffer_vec = t, Err(e) => panic!("{}", e), }; let salt_vec: Vec<&str>; - match chr_to_mp(string_vec2_str(&binding2), MpType::SaltMap) { + match chr_to_mp( + string_vec2_str(&binding2), + MpType::SaltMap, + DirecType::FORWARD, + ) { Ok(t) => salt_vec = t, Err(e) => panic!("{}", e), }; + println!("im buffer vec : {:?}", &buffer_vec); + println!("salt vec encpt {:?}", &salt_vec); // Salt and buffer mixing let mixed: Vec; match switch_chars(salt_vec, buffer_vec) { @@ -109,7 +120,7 @@ pub fn df1t_encrypt(buffer: String, salt: String) -> Result; - match chr_to_mxas(string_vec2_str(&binding3)) { + match chr_to_mxas(string_vec2_str(&binding3), DirecType::FORWARD) { Ok(t) => mx_version = t, Err(e) => panic!("{}", e), } @@ -144,18 +155,10 @@ pub fn df1t_encrypt(buffer: String, salt: String) -> Result = parsed_mtrx.into_iter().flatten().collect(); // fulfill info and encrypt it - let info = EncptInfo { - original_length: buffer.len(), - salt_short: shrt, - }; - let orgnl = cyph_info(info.original_length, 0); - let slt_shrt = cyph_info(info.salt_short, 1); - let info_vec = vec![ - join_string(str2_string_vec(orgnl)), - ";".to_string(), - join_string(str2_string_vec(slt_shrt)), - "$".to_string(), - ]; + + let orgnl = cyph_info(buffer.len(), 142); + + let info_vec = vec![join_string(str2_string_vec(orgnl)), "$".to_string()]; println!( "{:?}", join_string(info_vec.to_vec()) + &join_string(flat_mtrx.to_vec()) diff --git a/src/encpt/mapping/mapper.rs b/src/encpt/mapping/mapper.rs index ed8b72e..929fe54 100644 --- a/src/encpt/mapping/mapper.rs +++ b/src/encpt/mapping/mapper.rs @@ -10,18 +10,29 @@ pub enum MpType { SaltMap, } +#[derive(PartialEq)] +pub enum DirecType { + FORWARD, + BACKWARD, +} // map strings to vectors -pub fn chr_to_mp(vc: Vec<&str>, mpt: MpType) -> Result, &str> { +pub fn chr_to_mp(vc: Vec<&str>, mpt: MpType, direc: DirecType) -> Result, &str> { let mut result: Vec<&str> = vec![]; - let mpp: [[&str; 3]; 85]; + let mpp: [[&str; 3]; 62]; + let mut fs: usize = 0; + let mut sc: usize = 1; + if direc == DirecType::BACKWARD { + fs = 1; + sc = 0 + } match mpt { MpType::CharMap => mpp = CHAR_MAP, MpType::SaltMap => mpp = SALT_MAP, } for e in &vc { for s in mpp { - if e == &s[0] { - result.push(s[1]); + if e == &s[fs] { + result.push(s[sc]); } } } @@ -32,30 +43,19 @@ pub fn chr_to_mp(vc: Vec<&str>, mpt: MpType) -> Result, &str> { } } -pub fn chr_to_mxas(vc: Vec<&str>) -> Result, &str> { +pub fn chr_to_mxas(vc: Vec<&str>, direc: DirecType) -> Result, &str> { let mut result: Vec<&str> = vec![]; - - for e in &vc { - for s in CHAR_MAP { - if e == &s[0] { - result.push(s[2]); - } - } - } - if result.len() != vc.len() { - Err("CharError: unrecognized char") - } else { - Ok(result) + let mut fs: usize = 0; + let mut sc: usize = 2; + if direc == DirecType::BACKWARD { + fs = 2; + sc = 0 } -} - -pub fn mxas_to_chars(vc: Vec<&str>) -> Result, &str> { - let mut result: Vec<&str> = vec![]; - for e in &vc { for s in CHAR_MAP { - if e == &s[2] { - result.push(s[0]); + if e == &s[fs] { + println!("{}", e); + result.push(s[sc]); } } } @@ -65,6 +65,7 @@ pub fn mxas_to_chars(vc: Vec<&str>) -> Result, &str> { Ok(result) } } + // extend salt based on string length #[derive(Debug)] struct EmptyValueError; @@ -115,7 +116,7 @@ pub fn salt_extender(salt: &str, password: &str) -> Result( salt_vec: Vec<&'a str>, password_vec: Vec<&'a str>, @@ -47,6 +49,54 @@ pub fn switch_chars<'a>( Ok(result_vector) } +pub fn find_ref_mx(vc: String) -> &'static str { + let mut res: &str = ""; + + for s in REF_CHARS { + if vc.as_str() == s[2] { + res = s[1]; + } + } + + res +} +pub fn reference_to_origin<'a>( + salt_vec: Vec<&'a str>, + mixed_vec: Vec<&'a str>, +) -> Result, Box> { + if salt_vec.len() != mixed_vec.len() { + return Err("Error: not enough args for comparison".into()); + } + let mut result_vector: Vec = Vec::new(); + // Iterate through each pair of elements in the vectors + for (elem1, elem2) in salt_vec.iter().zip(mixed_vec.iter()) { + // Get the first characters of each element + let salt_char1 = elem1.chars().next(); + let salt_char2 = elem1.chars().last(); + // Get the second characters of each element + let mixed_char1 = elem2.chars().next(); + let mixed_char2 = elem2.chars().last(); + // after comparison elements + let mut char1: String = String::from(""); + let mut char2: String = String::from(""); + // Compare the characters + match (salt_char1, salt_char2, mixed_char1, mixed_char2) { + (Some(c1), Some(c2), Some(c3), Some(c4)) => { + if c1 == c4 && c2 == c3 && c1 != c2 && c3 != c4 { + char1 = elem1.chars().collect(); + char2 = "".to_string(); + } else { + char2 = c4.to_string(); + char1 = find_ref_mx(c4.to_string()).to_string(); + } + } + _ => result_vector = vec![], + }; + // Add the modified element to the result vector + result_vector.push(char1 + &char2); + } + Ok(result_vector) +} #[cfg(test)] mod tests { use super::*; @@ -117,4 +167,39 @@ mod tests { Err(err) => panic!("Unexpected error: {}", err), }; } + + #[test] + fn switch_to_original() { + let salt = vec!["vA", "Qb", "Gm", "fd"]; + let original = vec!["He", "pJ", "kF", "rc"]; + let parsed = vec!["ve", "QJ", "GF", "fc"]; + + match reference_to_origin(salt, parsed) { + Ok(res) => assert_eq!(res, original), + Err(err) => panic!("Unexpected error: {}", err), + }; + } + #[test] + fn switch_to_original_equals() { + let salt = vec!["vA", "Qb", "Gm", "yy"]; + let original = vec!["He", "pJ", "Gm", "yy"]; + let parsed = vec!["ve", "QJ", "mG", "yy"]; + + match reference_to_origin(salt, parsed) { + Ok(res) => assert_eq!(res, original), + Err(err) => panic!("Unexpected error: {}", err), + }; + } + + #[test] + fn swtich_to_original_1() { + let original = vec!["p3", "R2", "fd", "m4", "pJ", "rc", "p3", "uO", "pJ", "fd"]; + let salt = vec!["Qb", "sr", "uT", "sr", "Wx", "Qb", "sr", "uT", "sr", "Wx"]; + let parsed = vec!["Q3", "s2", "ud", "s4", "WJ", "Qc", "s3", "uO", "sJ", "Wd"]; + + match reference_to_origin(salt, parsed) { + Ok(res) => assert_eq!(res, original), + Err(err) => panic!("Unexpected error: {}", err), + }; + } } diff --git a/src/main.rs b/src/main.rs index b1d7b0f..3809b02 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,57 +23,12 @@ mod encpt { } fn main() { - let f = "Dr0]DQSrSDD2QG2]DQDQQsGrS3rsGr"; - let d = "NLhdd09DNDL0dd0dDD*Rh9DNZZ"; - println!("grn : {}, ble : {}", f.len(), d.len()); - //Dr0]DQSrSDD2QG2]DQDQQsGrS3rsGr - //NLhdd09DNDL0dd0dDD*Rh9DNZZ - // let _ = chr_to_mp(vec!["A", "B", "C"], MpType::CharMap); - // match salt_extender(String::from("abc"), String::from("dsdfsqdfsqdff")) { - // Ok(result) => println!("Result: {}", result), - // Err(err) => eprintln!("Error: {}", err), - // } - // // DA fR FC - // match switch_chars(vec!["AD", "fR", "Fm"], vec!["AD", "BR", "FC"]) { - // Ok(res) => println!("nested vec {:?}", res), - // Err(err) => println!("hmmmm {}", err), - // }; - // let charvc = vec!["A", "v", "b", "Q", "T", "G"]; - // let res = chr_to_mxas(charvc); - // println!("{:?}", res) - - // let vecs = vec![ - // vec!["785", "535", "789", "987", "123"], - // vec!["543", "528", "693", "285", "147"], - // vec!["753"], - // ]; - // let res = char_to_mtrx(vecs.iter().map(|c| str2_string_vec(c.to_vec())).collect()); - // println!("{:?}", res); - - // let vecs1 = vec![ - // vec![785, 535, 789, 987, 123, 789], - // vec![785, 535, 789, 987, 123, 787], - // vec![785, 535, 789, 987, 123, 456], - // vec![543, 528, 693, 285, 147, 556], - // vec![753, 456, 456, 564, 0, 0], - // vec![0, 0, 0, 0, 0, 0], - // ]; - // // let res1 = fill_mtrx_gaps(6, vecs1); - // // for a in res1 { - // // println!("{:?}", a); - // // } - // // - // let s = mtrx_to_vecs(vecs1); - // for d in s { - // println!("{:?}", d); - // } // Example usage - let salt = "sqdfqdqsdf"; - let password = "radqsfdqsdf"; - let res = df1t_encrypt(password.to_owned(), salt.to_owned()); + let salt = "0hfdf"; + let password = "1sd41"; + let res = df1t_encrypt(password.to_owned(), salt.clone().to_string()); - let saltt = "sqdfqdqsdf"; - let res1 = df1t_decrypt(res.unwrap().to_owned(), saltt.to_owned()); + let res1 = df1t_decrypt(res.unwrap().to_owned(), salt.to_owned()); println!("{}", res1.unwrap()) } diff --git a/src/maps/chars.rs b/src/maps/chars.rs index 71102da..6e0a4a4 100644 --- a/src/maps/chars.rs +++ b/src/maps/chars.rs @@ -1,4 +1,70 @@ -pub const CHAR_MAP: [[&'static str; 3]; 85] = [ +pub const REF_CHARS: [[&'static str; 3]; 62] = [ + ["a", "v", "A"], + ["b", "Q", "b"], + ["c", "G", "m"], + ["d", "f", "d"], + ["e", "H", "e"], + ["f", "p", "J"], + ["g", "k", "F"], + ["h", "r", "c"], + ["i", "M", "g"], + ["j", "O", "B"], + ["k", "Z", "a"], + ["l", "r", "L"], + ["m", "s", "D"], + ["n", "q", "K"], + ["o", "w", "E"], + ["p", "n", "I"], + ["q", "v", "P"], + ["r", "t", "N"], + ["s", "u", "O"], + ["t", "z", "X"], + ["u", "u", "T"], + ["v", "w", "V"], + ["w", "W", "x"], + ["x", "v", "U"], + ["y", "Y", "Y"], + ["z", "S", "S"], + // + ["A", "A", "j"], + ["B", "b", "Q"], + ["C", "T", "G"], + ["D", "d", "f"], + ["E", "e", "H"], + ["F", "J", "p"], + ["G", "F", "k"], + ["H", "s", "R"], + ["I", "g", "M"], + ["J", "I", "o"], + ["K", "a", "Z"], + ["L", "L", "r"], + ["M", "M", "s"], + ["N", "K", "q"], + ["O", "Q", "w"], + ["P", "H", "n"], + ["Q", "P", "l"], + ["R", "N", "C"], + ["S", "O", "h"], + ["T", "Y", "z"], + ["U", "T", "u"], + ["V", "V", "i"], + ["W", "x", "W"], + ["X", "U", "v"], + ["Y", "y", "y"], + ["Z", "S", "t"], + ["0", "g", "9"], + ["1", "j", "8"], + ["2", "G", "6"], + ["3", "f", "7"], + ["4", "m", "4"], + ["5", "d", "5"], + ["6", "p", "3"], + ["7", "R", "1"], + ["8", "R", "2"], + ["9", "o", "0"], +]; + +pub const CHAR_MAP: [[&'static str; 3]; 62] = [ ["a", "vA", "176"], ["b", "Qb", "421"], ["c", "Gm", "342"], @@ -53,39 +119,16 @@ pub const CHAR_MAP: [[&'static str; 3]; 85] = [ ["Y", "yy", "475"], ["Z", "St", "966"], // - ["0", "gv", "667"], - ["1", "jk", "418"], - ["2", "Gt", "779"], - ["3", "fg", "789"], - ["4", "mm", "458"], - ["5", "db", "447"], - ["6", "pd", "396"], - ["7", "Rg", "125"], - ["8", "Rs", "554"], - ["9", "oI", "983"], - ["!", "ab", "632"], - ["@", "cd", "181"], - ["#", "eF", "170"], - ["$", "gH", "280"], - ["%", "iJ", "371"], - ["^", "Kl", "722"], - ["&", "nm", "493"], - ["*", "Po", "704"], - ["(", "Rq", "805"], - [")", "ts", "366"], - ["_", "rt", "527"], - ["+", "ww", "598"], - ["{", "zz", "329"], - ["}", "cD", "999"], - [":", "ef", "508"], - [";", "gh", "977"], - ["<", "mn", "425"], - [">", "op", "114"], - ["?", "qr", "333"], - ["/", "st", "882"], - ["|", "wx", "691"], - ["]", "yz", "940"], - ["}", "cd", "560"], + ["0", "g9", "667"], + ["1", "j8", "418"], + ["2", "G6", "779"], + ["3", "f7", "789"], + ["4", "m4", "458"], + ["5", "d5", "447"], + ["6", "p3", "396"], + ["7", "R1", "125"], + ["8", "R2", "554"], + ["9", "o0", "983"], ]; // char_map // } diff --git a/src/maps/salt.rs b/src/maps/salt.rs index ae717d1..00294eb 100644 --- a/src/maps/salt.rs +++ b/src/maps/salt.rs @@ -1,4 +1,4 @@ -pub const SALT_MAP: [[&'static str; 3]; 85] = [ +pub const SALT_MAP: [[&'static str; 3]; 62] = [ ["a", "tN", "198"], ["b", "uO", "314"], ["c", "zY", "197"], @@ -51,39 +51,16 @@ pub const SALT_MAP: [[&'static str; 3]; 85] = [ ["X", "gH", "280"], ["Y", "gM", "769"], ["Z", "Io", "389"], - ["0", "aZ", "238"], - ["1", "Lr", "537"], - ["2", "Ms", "276"], - ["3", "Kq", "165"], - ["4", "Qw", "194"], - ["5", "Hn", "923"], - ["6", "Pv", "652"], - ["7", "Nt", "891"], - ["8", "Ou", "430"], - ["9", "Yz", "790"], - ["!", "Tu", "311"], - ["@", "VW", "852"], - ["#", "xW", "103"], - ["$", "Uv", "584"], - ["}", "iJ", "371"], - [":", "Kl", "722"], - [";", "nm", "493"], - ["<", "Po", "704"], - [">", "Rq", "805"], - ["?", "ts", "366"], - ["/", "rt", "527"], - ["|", "ww", "598"], - ["]", "zz", "329"], - ["%", "cD", "999"], - ["^", "ef", "508"], - ["&", "gh", "977"], - ["*", "mn", "425"], - ["(", "op", "114"], - [")", "qr", "333"], - ["_", "st", "882"], - ["+", "wx", "691"], - ["{", "yz", "940"], - ["}", "cd", "560"], + ["0", "a9", "238"], + ["1", "L8", "537"], + ["2", "M7", "276"], + ["3", "K6", "165"], + ["4", "Q5", "194"], + ["5", "H4", "923"], + ["6", "P3", "652"], + ["7", "N2", "891"], + ["8", "O1", "430"], + ["9", "Y0", "790"], ]; // char_map // } diff --git a/src/shared/parse.rs b/src/shared/parse.rs index 8a7eaa4..061124e 100644 --- a/src/shared/parse.rs +++ b/src/shared/parse.rs @@ -50,6 +50,23 @@ pub fn concat_every_n_elements(input_vec: Vec<&str>, n: usize) -> Vec { result_vec } + +pub fn generate_a_string(n: usize) -> String { + // Create a string with 'A' repeated n times + let result: String = std::iter::repeat('A').take(n).collect(); + result +} + +pub fn pop_elements_from_vector(vector: &mut Vec, n: usize) { + // Ensure not to pop more elements than the vector has + let num_elements_to_pop = n.min(vector.len()); + + // Calculate the starting index for elements to pop + let start_index = vector.len() - num_elements_to_pop; + + // Truncate the vector to remove the elements + vector.truncate(start_index); +} #[derive(PartialEq)] pub enum Mv_Direction { LEFT,