diff options
| -rw-r--r-- | src/lib.rs | 148 | 
1 files changed, 148 insertions, 0 deletions
| @@ -206,6 +206,62 @@ impl Value {          Some(cur_value)      } + +    /// Lookups for mutable value at specified path. +    /// +    /// Uses '.' as a path separator. +    /// +    /// Note: arrays have zero-based indexes. +    /// +    /// Note: empty path returns self. +    /// +    /// ``` +    /// # #![allow(unstable)] +    /// let toml = r#" +    ///      [test] +    ///      foo = "bar" +    /// +    ///      [[values]] +    ///      foo = "baz" +    /// +    ///      [[values]] +    ///      foo = "qux" +    /// "#; +    /// let mut value: toml::Value = toml.parse().unwrap(); +    /// { +    ///    let string = value.lookup_mut("test.foo").unwrap(); +    ///    assert_eq!(string, &mut toml::Value::String(String::from("bar"))); +    ///    *string = toml::Value::String(String::from("foo")); +    /// } +    /// let result = value.lookup_mut("test.foo").unwrap(); +    /// assert_eq!(result.as_str().unwrap(), "foo"); +    /// ``` +    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::<usize>().ok() { +                        Some(idx) if idx < v.len() => cur = &mut v[idx], +                        _ => return None +                    } +                } +                _ => return None +           } +        } +        Some(cur) +    }  }  impl FromStr for Value { @@ -224,6 +280,98 @@ mod tests {      use super::Value;      #[test] +    fn lookup_mut_change() { +        let toml = r#" +              [test] +              foo = "bar" + +              [[values]] +              foo = "baz" + +              [[values]] +              foo = "qux" +        "#; + +        let mut value: Value = toml.parse().unwrap(); +        { +          let foo = value.lookup_mut("values.0.foo").unwrap(); +          *foo = Value::String(String::from("bar")); +        } +        let foo = value.lookup("values.0.foo").unwrap(); +        assert_eq!(foo.as_str().unwrap(), "bar"); +    } + +    #[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#"                [test] |