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
|
use std::fs;
use std::env;
use std::error::Error;
use std::io::Read;
use std::collections::HashMap;
use toml;
use value::Value;
pub trait Source {
fn build(&mut self) -> Result<HashMap<String, Value>, Box<Error>>;
}
#[derive(Default)]
pub struct File {
// Basename of configuration file
name: String,
// Namespace to restrict configuration from the file
namespace: Option<String>,
// A required File will error if it cannot be found
required: bool,
}
impl File {
pub fn with_name(name: &str) -> File {
File {
name: name.into(),
required: true,
..Default::default()
}
}
pub fn namespace(&mut self, namespace: &str) -> &mut File {
self.namespace = Some(namespace.into());
self
}
pub fn required(&mut self, required: bool) -> &mut File {
self.required = required;
self
}
}
fn collect(content: &mut HashMap<String, Value>, table: &toml::Table, prefix: Option<String>) {
for (key, value) in table {
// Construct full key from prefix
let key = if let Some(ref prefix) = prefix {
prefix.clone() + "." + key
} else {
key.clone()
};
match *value {
// Recurse into nested table
toml::Value::Table(ref table) => collect(content, table, Some(key)),
toml::Value::String(ref value) => {
content.insert(key, value.clone().into());
}
_ => {
// Unhandled
}
}
}
}
impl Source for File {
fn build(&mut self) -> Result<HashMap<String, Value>, Box<Error>> {
// Find file
// TODO: Use a nearest algorithm rather than strictly CWD
let cwd = env::current_dir()?;
let filename = cwd.join(self.name.clone() + ".toml");
// Read contents from file
let mut file = fs::File::open(filename)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
// Parse
let mut parser = toml::Parser::new(&buffer);
// TODO: Get a solution to make this return an Error-able
let document = parser.parse().unwrap();
// Iterate through document and fill content
let mut content = HashMap::new();
collect(&mut content, &document, None);
Ok(content)
}
}
|