1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
extern crate toml;

use std::fs::File;
use std::fs::OpenOptions;
use std::io::prelude::*;
use toml::Value;

#[derive(Debug)]
pub struct Config {
    config: String,
    env_file: String,
    prefix: String,
    upper_case: bool,
}

impl Config {
    pub fn new(config: &str, env_file: &str, upper_case: bool, prefix: &str) -> Config {
        Config {
            config: String::from(config),
            env_file: String::from(env_file),
            prefix: String::from(prefix),
            upper_case,
        }
    }

    pub fn config(&self) -> &String {
        &self.config
    }

    pub fn env_file(&self) -> &String {
        &self.env_file
    }

    pub fn is_upper_case(&self) -> bool {
        self.upper_case
    }

    pub fn prefix(&self) -> String {
        self.prefix.clone()
    }
}

pub fn run(conf: Config) {
    let mut file = File::open(conf.config()).unwrap();

    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    let value = contents.parse::<Value>().unwrap();

    let mut envs = String::new();
    iter_table(&value, &mut envs, &conf, "");
    let mut env_file = OpenOptions::new()
        .create(true)
        .write(true)
        .open(&conf.env_file)
        .unwrap();
    if let Err(_) = env_file.write(envs.as_bytes()) {
        eprintln!("Write content to {} failed!", &conf.env_file);
    }
}

fn iter_table(value: &Value, envs: &mut String, conf: &Config, t: &str) {
    if let Some(table) = value.as_table() {
        for (k, v) in table {
            if v.is_table() {
                iter_table(v, envs, conf, k);
            } else {
                let line;
                let key;
                let mid;
                let mut prefix = String::new();
                if conf.is_upper_case() {
                    key = k.as_str().to_uppercase().to_string();
                    mid = if t != "" {
                        t.to_uppercase().to_string() + "_"
                    } else {
                        "".to_string()
                    }
                } else {
                    key = k.clone();
                    mid = if t != "" {
                        t.to_string() + "_"
                    } else {
                        "".to_string()
                    }
                }

                if conf.prefix() != prefix {
                    prefix = conf.prefix();
                }

                if v.is_str() {
                    line = String::from(format!(
                        "{}{}{}={}\n",
                        prefix,
                        mid,
                        key,
                        v.as_str().unwrap().trim_matches('"')
                    ));
                } else {
                    line = String::from(format!("{}{}{}={}\n", prefix, mid, key, v));
                }
                envs.push_str(&line);
            }
        }
    }
}