envmap 0.0.2

Small crate to read environment variables into a hashmap
Documentation
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())
        }
    }
}