use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
pub fn parse_config(
mut args: Vec<String>,
) -> Result<HashMap<String, String>, Box<dyn std::error::Error>> {
let mut ret = HashMap::<String, String>::new();
let suffix = "_FILE";
let mut appendage = args
.iter()
.cloned()
.map(|mut key| {
key.push_str(suffix);
key
})
.collect::<Vec<String>>();
args.append(&mut appendage);
for arg in args {
let key: String = arg.trim_end_matches(suffix).into();
if arg.ends_with(suffix) {
let path;
if let Ok(val) = env::var(arg) {
path = val;
} else {
continue;
};
let f = File::open(path.clone())
.expect(&format!("Could not open: {}", path));
let bufread = BufReader::new(f);
for line in bufread.lines() {
match line {
Ok(line) if !line.is_empty() => {
ret.insert(key.clone(), line);
}
Err(err) => return Err(err.into()),
_ => continue,
}
}
} else {
match env::var(arg) {
Ok(val) => {
ret.insert(key, val);
}
Err(_) => {
continue
}
}
}
}
Ok(ret)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn env_var_pass() -> Result<(), Box<dyn std::error::Error>> {
let args = vec!["SOME_VALUE".into()];
let map = parse_config(args)?;
if Some(&"123".into()) == map.get("SOME_VALUE") {
Ok(())
} else {
Err("".into())
}
}
#[test]
fn env_var_fail() -> Result<(), Box<dyn std::error::Error>> {
let args = vec!["DOES_NOT_EXIST".into()];
let map = parse_config(args);
if map.is_err() {
Ok(())
} else {
Err("".into())
}
}
#[test]
fn env_var_empty() -> Result<(), Box<dyn std::error::Error>> {
let args = vec![];
let map = parse_config(args)?;
if None == map.get("SOME_VALUE") {
Ok(())
} else {
Err("".into())
}
}
#[test]
fn env_var_file_pass() -> Result<(), Box<dyn std::error::Error>> {
let args = vec!["SOME_VALUE_FILE".into()];
let map = parse_config(args)?;
if Some(&"123".into()) == map.get("SOME_VALUE") {
Ok(())
} else {
Err("".into())
}
}
#[test]
fn env_var_file_fail() -> Result<(), Box<dyn std::error::Error>> {
let args = vec!["DOES_NOT_EXIST".into()];
let map = parse_config(args);
if map.is_err() {
Ok(())
} else {
Err("".into())
}
}
#[test]
fn env_var_file_empty() -> Result<(), Box<dyn std::error::Error>> {
let args = vec![];
let map = parse_config(args)?;
if None == map.get("SOME_VALUE") {
Ok(())
} else {
Err("".into())
}
}
}