# multi_mut
A bunch of extension methods on `HashMap` and `BTreeMap` that provide a safe API for getting multiple mutable references to values contained in them.
Runtime checks are done to prevent mutable aliasing.
## How to use
Add to Cargo.toml::
```
[dependencies]
multi_mut = "0.1"
```
Bring the extension trait to the scope in your code:
```
use multi_mut::HashMapMultiMut;
```
or
```
use multi_mut::BTreeMapMultiMut;
```
You can now have more than one mutable reference to your `HashMap` or `BTreeMap` safely!
```
let (one, two) = map.get_pair_mut("key_one", "key_two").unwrap();
assert_eq!(one, "value_one");
assert_eq!(two, "value_two");
one.push_str("_edited");
two.push_str("_edited");
assert_eq!(one, "value_one_edited");
assert_eq!(two, "value_two_edited");
```
Quick & dirty list of available functions:
* `get_pair_mut(key, key)` Returns a pair of mutable references wrapped in `Option`
* `pair_mut(key, key)` Returns a pair of mutable references and panics if the keys don't exist.
* `get_triple_mut(key, key, key)`Returns a triple of mutable references wrapped in `Option`
* `triple_mut(key, key, key)` Returns a triple of mutable references and panics if the keys don't exist.
* `multi_mut()` and `iter_multi_mut()` return arbitrary number of mutable references. Check out the example below.
To prevent mutable aliasing, all functions will panic if the input keys aren't unique. None of the functions allocate.
`multi_mut()` and `iter_multi_mut()` perform a linear search over a buffer of pointers every time a mutable reference
is pulled out of the `HashMap`/`BTreeMap`. In practice, this is fast enough.
### How to use `multi_mut()` and `iter_multi_mut()`
`multi_mut()` and `iter_multi_mut()` need a mutable buffer to keep track of existing references to prevent mutable aliasing.
See the line `let mut buffer = [std::ptr::null(); 3];` in the example. The size of the buffer determines how many values you can
pull out of the underlying `HashMap`/`BTreeMap`.
The difference between the two methods is that `multi_mut()` returns a wrapper which can be used to fetch mutable references
from `HashMap`/`BTreeMap` using the `get_mut(&K) -> Option<&mut V>` or `mut_ref(&K) -> &mut V` (this panics if the key doesn't exist) methods,
whereas `iter_multi_mut()` requires a list of keys up front, and then returns an iterator that spews out mutable references.
An example of `multi_mut()`:
```
let mut buffer = [std::ptr::null(); 3];
let mut wrapper = map.multi_mut(&mut buffer);
let one = wrapper.get_mut("key_one").unwrap();
let two = wrapper.get_mut("key_two").unwrap();
let three = wrapper.get_mut("key_three").unwrap();
assert_eq!(one, "value_one");
assert_eq!(two, "value_two");
assert_eq!(three, "value_three");
one.push_str("_edited");
two.push_str("_edited");
three.push_str("_edited");
assert_eq!(one, "value_one_edited");
assert_eq!(two, "value_two_edited");
assert_eq!(three, "value_three_edited");
```
An example of `iter_multi_mut()`:
```
let mut buffer = [std::ptr::null(); 3];
let keys = ["key_one", "key_two", "key_three"];
let mut wrapper = map.iter_multi_mut(&keys, &mut buffer);
let one = wrapper.next().unwrap();
let two = wrapper.next().unwrap();
let three = wrapper.next().unwrap();
assert_eq!(one, "value_one");
assert_eq!(two, "value_two");
assert_eq!(three, "value_three");
one.push_str("_edited");
two.push_str("_edited");
three.push_str("_edited");
assert_eq!(one, "value_one_edited");
assert_eq!(two, "value_two_edited");
assert_eq!(three, "value_three_edited");
```