Repository: toml-rs/toml (language: rust)

Issue:
Table::get_mut?
Thanks for the useful crate!

It looks like Table implements Index and IndexMut, and has an inherent method `Table::get` for getting an optional immutable reference, but there's no easy way to get an optional mutable reference to a key's value. I found myself writing code like this:

```rust
        if table.get(&key).is_some() {
            Some(&mut table[&key])
        } else {
            None
        }
```

It would be useful to expose a get_mut method too.


Discussion / hints:
Hey, thanks!

We can expose `get_mut`, PRs are welcome! :-)

Note, with `IndexMut` API you can get an `Item::None` if the key is not found. So if you're looking for a `Value` (as in key/value pair), you can do `table[&key].as_value_mut()`.

Fix patch:
diff --git a/src/table.rs b/src/table.rs
index 6e5e42d7..34e16bf7 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -177,6 +177,11 @@ impl Table {
         self.items.get(key).map(|kv| &kv.value)
     }
 
+    /// Returns an optional mutable reference to an item given the key.
+    pub fn get_mut<'a>(&'a mut self, key: &str) -> Option<&'a mut Item> {
+        self.items.get_mut(key).map(|kv| &mut kv.value)
+    }
+
     /// If a table has no key/value pairs and implicit, it will not be displayed.
     ///
     /// # Examples
@@ -401,6 +406,8 @@ pub trait TableLike {
     }
     /// Returns an optional reference to an item given the key.
     fn get<'s>(&'s self, key: &str) -> Option<&'s Item>;
+    /// Returns an optional mutable reference to an item given the key.
+    fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item>;
 }
 
 impl TableLike for Table {
@@ -411,6 +418,9 @@ impl TableLike for Table {
     fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
         self.get(key)
     }
+    fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> {
+        self.get_mut(key)
+    }
 }
 
 /// Returns a formatted value.
diff --git a/src/value.rs b/src/value.rs
index 9416f3dc..7a69b0d9 100644
--- a/src/value.rs
+++ b/src/value.rs
@@ -310,6 +310,9 @@ impl TableLike for InlineTable {
     fn get<'s>(&'s self, key: &str) -> Option<&'s Item> {
         self.items.get(key).map(|kv| &kv.value)
     }
+    fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> {
+        self.items.get_mut(key).map(|kv| &mut kv.value)
+    }
 }
 
 /// Downcasting


Test patch:
diff --git a/tests/test_edit.rs b/tests/test_edit.rs
index 7cbb8ce7..83ac64e6 100644
--- a/tests/test_edit.rs
+++ b/tests/test_edit.rs
@@ -617,7 +617,7 @@ fn test_insert_into_inline_table() {
             let a = root.entry("a");
             let a = as_inline_table!(a);
             assert_eq!(a.len(), 2);
-            assert!(a.contains_key("a") && a.get("c").is_some());
+            assert!(a.contains_key("a") && a.get("c").is_some() && a.get_mut("c").is_some());
             a.get_or_insert("b", 42);
             assert_eq!(a.len(), 3);
             a.fmt();