0

How can i push this

["a", "bb", "c", "dd", "e", "ff", "g", "hh"] //type is Vec<String>

to this

fn list_codes() -> BiMap<char, &'static str> 
{
    let letters = BiMap::<char, &str>::new();
    [('a',"cl01"),
     ('b',"cl02"),
     ('c',"cl03"),
     ('d',"cl04")]
        .into_iter()
        .collect()
}

That should be like this

fn list_codes() -> BiMap<char, &'static str> 
{
     [('a',"cl01"),
     ('b',"cl02"),
     ('c',"cl03"),
     ('d',"cl04"),
     ('a',"bb"),
     ('c',"dd"),
     ('e',"ff"),
     ('g',"hh")]
        .into_iter()
        .collect()
}

Actually the logic is simple. It will take a list from csv file and import to a BiMap. After the importion of bimap, the program will use this BiMap to encode/decode the texts.

EXTRAS:

The rest of code is here:

//-------------------------//
#![allow(non_snake_case)]
//-------------------------//
#![allow(dead_code)]
//-------------------------//
#![allow(unused_variables)]
//-------------------------//
#![allow(unused_imports)]
//-------------------------//
// #![allow(inactive_code)]
//-------------------------//

use std::error::Error as stdErr;
use std::io::Error as ioErr;
use std::net::ToSocketAddrs;
use std::process;
use std::env;
use std::fs;
use std::array;
use std::io;
use std::slice::SliceIndex;

use csv::Error as csvErr;
use csv::Reader;
use csv::StringRecord;
use bimap::BiMap;
use directories::ProjectDirs;
use serde::Deserialize;

//#[cfg(doc)] #[doc = include_str!("../Changelog.md")] pub mod _changelog{}
#[derive(Deserialize, Debug)]
struct Config {
    seperator: String,
    list_file_path: String,
}

#[derive(Debug, Deserialize)]
struct Record <'a> {
    letter: char,
    code: &'a str,
}

fn find_and_read_config_file() -> Result<String, ioErr>
{
    if let Some(proj_dirs) = ProjectDirs::from
    (
        "dev",
        "rusty-bois",
        "test-config-parser",
    ) 
    {
        let config_file_name = "settings.toml"; 

        let config_path = proj_dirs.config_dir();

        let config_file = fs::read_to_string(config_path.join(config_file_name),);
        config_file
    }
    else 
    {
        Err(ioErr::new(io::ErrorKind::NotFound, "no"))
    }
}

fn parse_toml() -> String 
{
    let config_file = find_and_read_config_file();
    let config: Config = match config_file
        {
            Ok(file) => toml::from_str(&file).unwrap(),
            Err(_) => Config 
            {
                seperator: "x".to_string(),
                list_file_path: "rdl".to_string(),
            },
        };
    let result = format!("{}\n{}",config.list_file_path, config.seperator);
    return result;
}

fn reformat_parse_toml() -> Vec<String>
{
    let mut vec_values = Vec::new();
    let mut i = 0;
    for values in parse_toml().split("\n")
    {
        vec_values.insert(i,values.to_string());
        i += 1;
    }
    vec_values
}

fn read_and_parse_csv() -> Result<Vec<StringRecord>, csvErr>
{
    let config_vars = reformat_parse_toml();
    let csv_file_path = &config_vars[0];

    let mut rdr = Reader::from_path(csv_file_path)?;
    rdr.records().collect()
}

fn reformat_read_and_parse_csv() -> Vec<String>
{
    let csv_records = read_and_parse_csv();
    let mut csv_records_as_list = Vec::new();
    let mut i = 0;

    for a in csv_records.iter()
    {
        for b in a 
        {
            for c in b 
            {
                csv_records_as_list.insert(i, c.to_string());
                i += 1 
            }
        }
    }
    csv_records_as_list
}

fn input() -> String 
{
    let mut input = String::new();
    match io::stdin().read_line(&mut input) {
        Ok(_) => {
                return input.to_string();
            },
        Err(e) => {
            return e.to_string();
        }
    }
}

fn list_codes() -> BiMap<char, &'static str> 
{
    let letters = BiMap::<char, &str>::new();
    [('a',"cl01"),
    ('b',"cl02"),
    ('c',"cl03"),
    ('d',"cl04")]
        .into_iter()
        .collect()
}

fn coder(flag: &str) -> String 
{
    let letters = list_codes();
    let mut result_raw = String::new();
    let result = String::new();
    let config_vars = reformat_parse_toml();
    let split_char = &config_vars[1];

    if flag == "e"
    {
        println!("Enter the text that you want to encrypt:");
        let ipt = input().trim_end().to_string();
        let ipt_char = ipt.chars();
        for letter in ipt_char
        {
            result_raw = format!("{}{}{}",result_raw,split_char,letters.get_by_left(&letter).unwrap());
        }
        let result = &result_raw[1..];
        return result.to_string();
    }
    else if flag == "d"
    {
        println!("Enter the text that you want to decrypt:");
        let ipt = input().trim_end().to_string();
        let ipt_char = ipt.chars();
        for code in ipt.split(split_char) 
        {
            result_raw = format!("{} {}", result_raw, letters.get_by_right(code).unwrap());
        }
        let decoded = result_raw;
        return decoded;
    }
    else
    {  
        return "Error while decode/encode the input".to_string();
    }
}

fn coder_from_file(flag: &str, path: &str) -> String 
{
    let letters = list_codes();
    let mut result_raw = String::new();
    let result = String::new();
    let contents = fs::read_to_string(path)
    .expect("Something went wrong reading the file");
    let config_vars = reformat_parse_toml();
    let split_char = &config_vars[1];


    if flag == "ef"
    {
        for letter in contents.chars()
        {
            result_raw = format!("{}{}{}",result_raw,split_char,letters.get_by_left(&letter).unwrap());
        }
        let result = &result_raw[1..];
        return result.to_string();
    }
    else if flag == "df" 
    {
        for code in contents.replace("\n", "xpl01").split(split_char) 
        {
            // You might want to have a look at the `String.push_str()` function to avoid creating a new string every time
            result_raw = format!("{}{}", result_raw, letters.get_by_right(code).unwrap());
        }
        let result = result_raw;
        return result;        
    }    
    else
    {  
        return "Error while decode/encode the input".to_string();
    }
}

fn coder_options() -> String
{
    let args: Vec<String> = env::args().collect();
    let mode = &args[1];
    let config_vars = reformat_parse_toml();
    let split_char = &config_vars[1];
   
    let mut m_opt = String::new();

    if mode == "-d"
    {  
        m_opt = coder(&"d");
    }
    else if mode == "-e"
    {
        m_opt = coder(&"e");
    }
    else if mode == "-ef" 
    {
        let filename = &args[2];
        m_opt = coder_from_file(&"ef",&filename);
    }
    else if mode == "-df" 
    {
        let filename = &args[2];
        m_opt = coder_from_file(&"df",&filename);
    }
    else
    {
        println!("You picked wrong flag. Please select a vaild one.")
    }

    return m_opt;

}

fn main () 
{
    let coder_options = coder_options();
    println!("{}", coder_options)
}

Here is Cargo.toml

[package]
name = "Coder"
version = "0.1.0"
edition = "2021"
authors = ["Huso112"]
license= "GPL-3.0"
description = "This program encrypt your datas with special codes."
repository=""

[[bin]]
path = "src/Coder.rs"
name = "Coder"

[dependencies]
bimap = "~0.6.1"
directories = "~4.0.1"
serde = {version="~1.0.133", features=["derive"]}
toml = "~0.5.8"
csv = "~1.1.6"

Here is settings.toml file

seperator = "z"
list_file_path = "/home/hoovy/.config/test-config-parser/lang-table.csv"

Here is lang-table.csv file

letter,code
a,bb
c,dd
e,ff
g,hh

1 Answers1

0

Boring way:

let mut i = 0;
while i < vec_values.len() - 1 {
    let key_str = &vec_values[i];
    let value = &vec_values[i + 1].clone();

    let key = match key_str.chars().nth(0) {
        Some(key) => key,
        None => {
            println!("error: empty key");
            break;
        }
    };

    letters.insert(key, value);
    i += 2;
}

A version without clone() if you don't need vec_values after this, and can tear it apart:

if vec_values.len() % 2 != 0 {
    println!("error: missing a last value");
    return;
}

while !vec_values.is_empty() {
    // Note: ok to unwrap, because we are sure that vec_values has an even number of values
    let value = vec_values.pop().unwrap();
    let key_str = vec_values.pop().unwrap();

    let key = match key_str.chars().nth(0) {
        Some(key) => key,
        None => {
            println!("error: empty key");
            break;
        }
    };

    letters.insert(key, value);
}

There's also a "smart" way using Iterator methods, but I'll refrain from advising it here.

battlmonstr
  • 5,841
  • 1
  • 23
  • 33