From eb7909f607d31d00d2925992d3ee26fa163aa74b Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Tue, 24 Jan 2017 02:03:44 -0800 Subject: Add merge API with initial File Source --- src/source.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/source.rs (limited to 'src/source.rs') diff --git a/src/source.rs b/src/source.rs new file mode 100644 index 0000000..bb3efd6 --- /dev/null +++ b/src/source.rs @@ -0,0 +1,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, Box>; +} + +#[derive(Default)] +pub struct File { + // Basename of configuration file + name: String, + + // Namespace to restrict configuration from the file + namespace: Option, + + // 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, table: &toml::Table, prefix: Option) { + 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, Box> { + // 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) + } +} -- cgit v1.2.3