use std::io::Read;
fn parse_dotenv_string(content: &str) -> Result<std::collections::HashMap<String, String>, Box<dyn std::error::Error>> {
let mut dotenv = std::collections::HashMap::new();
let lines = content.split("\n");
for line in lines {
let line = line.trim();
if line.len() == 0 {
continue;
}
if line.starts_with("#") {
continue;
}
let tokens: Vec<&str> = line.split("=").collect();
if tokens.len() != 2 {
continue;
}
let key = tokens[0].trim().to_string();
let value = tokens[1].trim().to_string();
dotenv.insert(key, value);
}
return Ok(dotenv);
}
fn read_text_file(file: &str) -> Result<String, Box<dyn std::error::Error>> {
let mut file = std::fs::File::open(file)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
return Ok(buffer);
}
fn is_file_existing(file: &str) -> bool {
let path = std::path::Path::new(file);
return path.exists();
}
fn read_file_if_exists(file: &str) -> Result<String, Box<dyn std::error::Error>> {
if !is_file_existing(file) {
return Ok("".into());
}
let content = read_text_file(file)?;
return Ok(content);
}
fn read_dotenv_file_if_exists(path: &str) -> Result<std::collections::HashMap<String, String>, Box<dyn std::error::Error>> {
let content = read_file_if_exists(path)?;
let map = parse_dotenv_string(&content)?;
return Ok(map);
}
fn read_dotenv_file_from_stdin() -> Result<std::collections::HashMap<String, String>, Box<dyn std::error::Error>> {
let content = read_whole_lines_from_stdin()?;
let map = parse_dotenv_string(&content)?;
return Ok(map);
}
fn read_dotenv_file(path: &str) -> Result<std::collections::HashMap<String, String>, Box<dyn std::error::Error>> {
let content = read_text_file(path)?;
let map = parse_dotenv_string(&content)?;
return Ok(map);
}
pub struct DotenvFile {
pub map: std::collections::HashMap<String, String>,
}
impl DotenvFile {
pub fn configure(use_stdin: bool, file: Option<String>) -> Result<DotenvFile, Box<dyn std::error::Error>> {
if use_stdin {
let vars = read_dotenv_file_from_stdin()?;
let instance = Self { map: vars };
return Ok(instance);
} else if file.is_none() {
let vars = read_dotenv_file_if_exists(".env")?;
let instance = Self { map: vars };
return Ok(instance);
} else {
let file = file.unwrap();
let vars = read_dotenv_file(&file)?;
let instance = Self { map: vars };
return Ok(instance);
}
}
pub fn get_inner_map(&self) -> &std::collections::HashMap<String, String> {
return &self.map;
}
}
fn read_whole_lines_from_stdin() -> Result<String, Box<dyn std::error::Error>> {
let stdin = std::io::stdin();
let mut handle = stdin.lock();
let mut buffer = String::new();
let _size_read = handle.read_to_string(&mut buffer)?;
return Ok(buffer);
}