#hash-map #extension #btree-map #reference #mutable #mutability #multiple

multi_mut

Methods on HashMap and BTreeMap for safely getting multiple mutable references to the contained values

4 releases

Uses old Rust 2015

0.1.3 Jan 17, 2017
0.1.2 Jan 17, 2017
0.1.1 Jan 17, 2017
0.1.0 Jan 17, 2017

#2024 in Data structures

Download history 4/week @ 2023-12-18 4/week @ 2024-01-08 7/week @ 2024-01-15 6/week @ 2024-02-12 30/week @ 2024-02-19 29/week @ 2024-02-26 21/week @ 2024-03-04 27/week @ 2024-03-11 25/week @ 2024-03-18

108 downloads per month

MIT license

41KB
844 lines

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:

extern crate multi_mut;
use multi_mut::HashMapMultiMut;

or

extern crate multi_mut;
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");

No runtime deps