summaryrefslogtreecommitdiffstats
path: root/src/config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs132
1 files changed, 128 insertions, 4 deletions
diff --git a/src/config.rs b/src/config.rs
index 126d31b..6c81244 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,5 +1,6 @@
use value::Value;
use source::{Source, SourceBuilder};
+use path;
use std::error::Error;
use std::fmt;
@@ -213,8 +214,55 @@ impl Config {
Ok(())
}
- pub fn get<'a>(&'a self, key: &str) -> Option<&'a Value> {
- self.cache.get(key)
+ // Child ( Child ( Identifier( "x" ), "y" ), "z" )
+ fn path_get<'a, 'b>(&'a self, expr: path::Expression) -> Option<&'a Value> {
+ match expr {
+ path::Expression::Identifier(text) => {
+ self.cache.get(&text)
+ }
+
+ path::Expression::Child(expr, member) => {
+ match self.path_get(*expr) {
+ Some(&Value::Table(ref table)) => {
+ table.get(&member)
+ }
+
+ _ => None
+ }
+ }
+
+ path::Expression::Subscript(expr, mut index) => {
+ match self.path_get(*expr) {
+ Some(&Value::Array(ref array)) => {
+ let len = array.len() as i32;
+
+ if index < 0 {
+ index = len + index;
+ }
+
+ if index < 0 || index >= len {
+ None
+ } else {
+ Some(&array[index as usize])
+ }
+ }
+
+ _ => None
+ }
+ }
+ }
+ }
+
+ pub fn get<'a>(&'a self, key_path: &str) -> Option<&'a Value> {
+ let key_expr: path::Expression = match key_path.parse() {
+ Ok(expr) => expr,
+ Err(_) => {
+ // TODO: Log warning here
+ return None;
+ }
+ };
+
+ self.path_get(key_expr)
}
pub fn get_str<'a>(&'a self, key: &str) -> Option<Cow<'a, str>> {
@@ -236,6 +284,10 @@ impl Config {
pub fn get_map<'a>(&'a self, key: &str) -> Option<&'a HashMap<String, Value>> {
self.get(key).and_then(Value::as_map)
}
+
+ pub fn get_slice<'a>(&'a self, key: &str) -> Option<&'a [Value]> {
+ self.get(key).and_then(Value::as_slice)
+ }
}
#[cfg(test)]
@@ -392,9 +444,41 @@ mod test {
assert_eq!(c.get_bool("key_11"), None);
}
- // Deep merge of tables
#[test]
- fn test_merge() {
+ fn test_slice() {
+ let mut c = Config::new();
+
+ c.set("values", vec![
+ Value::Integer(10),
+ Value::Integer(325),
+ Value::Integer(12),
+ ]).unwrap();
+
+ let values = c.get_slice("values").unwrap();
+
+ assert_eq!(values.len(), 3);
+ assert_eq!(values[1].as_int(), Some(325));
+ }
+
+ #[test]
+ fn test_slice_into() {
+ let mut c = Config::new();
+
+ c.set("values", vec![
+ 10,
+ 325,
+ 12,
+ ]).unwrap();
+
+ let values = c.get_slice("values").unwrap();
+
+ assert_eq!(values.len(), 3);
+ assert_eq!(values[1].as_int(), Some(325));
+
+ }
+
+ #[test]
+ fn test_map() {
let mut c = Config::new();
{
@@ -428,4 +512,44 @@ mod test {
assert_eq!(m.get("db").unwrap().as_str().unwrap(), "1");
}
}
+
+ #[test]
+ fn test_path() {
+ use file::{File, FileFormat};
+
+ let mut c = Config::new();
+
+ c.merge(File::from_str(r#"
+ [redis]
+ address = "localhost:6379"
+
+ [[databases]]
+ name = "test_db"
+ options = { trace = true }
+ "#, FileFormat::Toml)).unwrap();
+
+ assert_eq!(c.get_str("redis.address").unwrap(), "localhost:6379");
+ assert_eq!(c.get_str("databases[0].name").unwrap(), "test_db");
+ assert_eq!(c.get_str("databases[0].options.trace").unwrap(), "true");
+ }
+
+ #[test]
+ fn test_map_into() {
+ let mut c = Config::new();
+
+ {
+ let mut m = HashMap::new();
+ m.insert("port".into(), 6379);
+ m.insert("db".into(), 2);
+
+ c.set("redis", m).unwrap();
+ }
+
+ {
+ let m = c.get_map("redis").unwrap();
+
+ assert_eq!(m.get("port").unwrap().as_int().unwrap(), 6379);
+ assert_eq!(m.get("db").unwrap().as_int().unwrap(), 2);
+ }
+ }
}