1use std::collections::HashMap;
2use std::env;
3use std::io::prelude::*;
4use std::io::{BufReader, Lines};
5
6use crate::errors::*;
7use crate::parse;
8
9pub struct Iter<R> {
10 lines: Lines<BufReader<R>>,
11 substitution_data: HashMap<String, Option<String>>,
12}
13
14impl<R: Read> Iter<R> {
15 pub fn new(reader: R) -> Iter<R> {
16 Iter {
17 lines: BufReader::new(reader).lines(),
18 substitution_data: HashMap::new(),
19 }
20 }
21
22 pub fn load(self, prefix: &str) -> Result<()> {
23 for item in self {
24 let (key, value) = item?;
25 if !key.starts_with(prefix) { continue; }
26 if env::var(&key).is_err() {
27 env::set_var(&key, value);
28 }
29 }
30
31 Ok(())
32 }
33
34 pub fn get_vars_base(self, prefix: &str) -> Result<HashMap<String, Option<String>>>{
35 let mut result = HashMap::new();
36
37 for item in self {
38 let (key, value) = item?;
39 if !key.starts_with(prefix) { continue; }
40 result.insert(key.clone(), Some(value.clone()));
41 }
42 Ok(result)
43 }
44
45 pub fn get_vars_with_prefix(self, prefix: &str) -> Result<HashMap<String, Option<String>>> {
46 self.get_vars_base(prefix)
47 }
48
49 pub fn get_vars(self) -> Result<HashMap<String, Option<String>>> {
50 self.get_vars_base(&String::from(""))
51 }
52
53}
54
55impl<R: Read> Iterator for Iter<R> {
56 type Item = Result<(String, String)>;
57
58 fn next(&mut self) -> Option<Self::Item> {
59 loop {
60 let line = match self.lines.next() {
61 Some(Ok(line)) => line,
62 Some(Err(err)) => return Some(Err(Error::Io(err))),
63 None => return None,
64 };
65
66 match parse::parse_line(&line, &mut self.substitution_data) {
67 Ok(Some(result)) => return Some(Ok(result)),
68 Ok(None) => {}
69 Err(err) => return Some(Err(err)),
70 }
71 }
72 }
73}