Skip to content

Instantly share code, notes, and snippets.

@Lokathor
Created August 20, 2017 04:06
Show Gist options
  • Save Lokathor/4ef461296f02ab32eee025e4bf09198b to your computer and use it in GitHub Desktop.
Save Lokathor/4ef461296f02ab32eee025e4bf09198b to your computer and use it in GitHub Desktop.
//! A module for creating collections of mutable references from collection
//! objects. This allows you to edit more than one location within a collection
//! at the same time. This is totally safe to do as long as you don't re-shape
//! the collection while you do it (which the lifetimes ensure). It's basically
//! a generalization of the `split_at_mut` concept.
use std::cell::RefCell;
use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::Hash;
/// A structure that holds a mutable reference to a HashMap as well as a
/// collection of mutable references to values within that HashMap.
#[derive(Debug)]
pub struct MultiMutHashMap<'source, K: 'source, V: 'source>
where
K: Hash + Eq,
{
source: &'source mut HashMap<K, V>,
results_cell: RefCell<HashMap<K, &'source mut V>>,
}
impl<'source, K: 'source, V: 'source> MultiMutHashMap<'source, K, V>
where
K: Hash + Eq,
{
/// Constructs a new MultiMutHashMap from a HashMap to borrow against and a
/// set of targets to try and acquire.
pub fn new(src: &'source mut HashMap<K, V>, targets: HashSet<K>) -> Self {
let mut ref_results = HashMap::new();
for target in targets.into_iter() {
let opt_pointer: Option<*mut V> = {
src.get_mut(&target).map(|v| v as *mut V)
};
opt_pointer.map(|p| unsafe {
ref_results.insert(target, p.as_mut().unwrap());
});
}
MultiMutHashMap {
source: src,
results_cell: RefCell::new(ref_results),
}
}
/// Grabs a mutable reference out of this MultiMutHashMap. You can only
/// extract each mutable reference once, and it is not guaranteed that every
/// target you asked for was acquired in the first place.
pub fn extract_reference(&self, key: &K) -> Option<&'source mut V> {
let mut results = self.results_cell.borrow_mut();
results.remove(key)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment