From a6fb2f92dc8d53660c1d2d066f146ef261052330 Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Thu, 26 Jan 2017 00:09:41 -0800 Subject: Add some examples --- src/file.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/file.rs (limited to 'src/file.rs') diff --git a/src/file.rs b/src/file.rs new file mode 100644 index 0000000..2ffc836 --- /dev/null +++ b/src/file.rs @@ -0,0 +1,143 @@ +use std::fs; +use std::env; +use std::error::Error; +use std::io::Read; +use std::collections::HashMap; + +use toml; + +use value::Value; +use source::Source; + +#[derive(Default)] +pub struct File { + /// Basename of configuration file + name: String, + + /// Directory where configuration file is found + /// When not specified, the current working directory (CWD) is considered + path: Option, + + /// 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 path(&mut self, path: &str) -> &mut File { + self.path = Some(path.into()); + self + } + + 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 toml_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) => toml_collect(content, table, Some(key)), + + toml::Value::String(ref value) => { + content.insert(key, value.clone().into()); + } + + toml::Value::Integer(value) => { + content.insert(key, value.into()); + } + + toml::Value::Float(value) => { + content.insert(key, value.into()); + } + + toml::Value::Boolean(value) => { + content.insert(key, value.into()); + } + + _ => { + // Unhandled + } + } + } +} + +impl Source for File { + fn build(&mut self) -> Result, Box> { + let mut content = HashMap::new(); + + // Find file + // TODO: Use a nearest algorithm rather than strictly CWD + let cwd = match env::current_dir() { + Ok(cwd) => cwd, + Err(err) => { + if self.required { + return Err(From::from(err)); + } else { + return Ok(content); + } + } + }; + + let filename = cwd.join(self.name.clone() + ".toml"); + + // Read contents from file + let mut file = match fs::File::open(filename) { + Ok(file) => file, + Err(err) => { + if self.required { + return Err(From::from(err)); + } else { + return Ok(content); + } + } + }; + + let mut buffer = String::new(); + let res = file.read_to_string(&mut buffer); + if res.is_err() { + if self.required { + return Err(From::from(res.err().unwrap())); + } else { + return Ok(content); + } + } + + // 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 + toml_collect(&mut content, &document, None); + + Ok(content) + } +} -- cgit v1.2.3