From 32969ca891a3021587863f0ec0b89ed7151d23b2 Mon Sep 17 00:00:00 2001 From: Bourgond Aries Date: Fri, 25 Mar 2016 17:33:46 +0100 Subject: Implement the non-recursive lookup_mut Also include some tests simply by copying and modifying the other tests for lookup. --- src/lib.rs | 126 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 95 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 21cdf3e..d81b9cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,6 @@ use std::collections::BTreeMap; use std::str::FromStr; -use std::str::Split; pub use parser::{Parser, ParserError}; @@ -208,28 +207,6 @@ impl Value { Some(cur_value) } - fn lookup_mut_recurse<'a>(&'a mut self, matches: &mut Split<'a, char>) -> Option<&'a mut Value> { - if let Some(key) = matches.next() { - match *self { - Value::Table(ref mut hm) => { - match hm.get_mut(key) { - Some(v) => return v.lookup_mut_recurse(matches), - None => return None, - } - }, - Value::Array(ref mut v) => { - match key.parse::().ok() { - Some(idx) if idx < v.len() - => return (&mut v[idx]).lookup_mut_recurse(matches), - _ => return None, - } - }, - _ => return None - } - } - Some(self) - } - /// Lookups for mutable value at specified path. /// /// Uses '.' as a path separator. @@ -259,15 +236,32 @@ impl Value { /// let result = value.lookup_mut("test.foo").unwrap(); /// assert_eq!(result.as_str().unwrap(), "foo"); /// ``` - pub fn lookup_mut<'a>(&'a mut self, path: &'a str) -> Option<&'a mut Value> { - if path.len() == 0 { - return Some(self) - } - - let mut matches = path.split('.'); - self.lookup_mut_recurse(&mut matches) - } + pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> { + let mut cur = self; + if path.len() == 0 { + return Some(cur) + } + for key in path.split('.') { + let tmp = cur; + match *tmp { + Value::Table(ref mut hm) => { + match hm.get_mut(key) { + Some(v) => cur = v, + None => return None + } + } + Value::Array(ref mut v) => { + match key.parse::().ok() { + Some(idx) if idx < v.len() => cur = &mut v[idx], + _ => return None + } + } + _ => return None + } + } + Some(cur) + } } impl FromStr for Value { @@ -285,6 +279,76 @@ impl FromStr for Value { mod tests { use super::Value; + #[test] + fn lookup_mut_valid() { + let toml = r#" + [test] + foo = "bar" + + [[values]] + foo = "baz" + + [[values]] + foo = "qux" + "#; + + let mut value: Value = toml.parse().unwrap(); + + { + let test_foo = value.lookup_mut("test.foo").unwrap(); + assert_eq!(test_foo.as_str().unwrap(), "bar"); + } + + { + let foo1 = value.lookup_mut("values.1.foo").unwrap(); + assert_eq!(foo1.as_str().unwrap(), "qux"); + } + + assert!(value.lookup_mut("test.bar").is_none()); + assert!(value.lookup_mut("test.foo.bar").is_none()); + } + + #[test] + fn lookup_mut_invalid_index() { + let toml = r#" + [[values]] + foo = "baz" + "#; + + let mut value: Value = toml.parse().unwrap(); + + { + let foo = value.lookup_mut("test.foo"); + assert!(foo.is_none()); + } + + { + let foo = value.lookup_mut("values.100.foo"); + assert!(foo.is_none()); + } + + { + let foo = value.lookup_mut("values.str.foo"); + assert!(foo.is_none()); + } + } + + #[test] + fn lookup_mut_self() { + let mut value: Value = r#"foo = "bar""#.parse().unwrap(); + + { + let foo = value.lookup_mut("foo").unwrap(); + assert_eq!(foo.as_str().unwrap(), "bar"); + } + + let foo = value.lookup_mut("").unwrap(); + assert!(foo.as_table().is_some()); + + let baz = foo.lookup_mut("foo").unwrap(); + assert_eq!(baz.as_str().unwrap(), "bar"); + } + #[test] fn lookup_valid() { let toml = r#" -- cgit v1.2.3