Created
August 20, 2017 04:06
-
-
Save Lokathor/4ef461296f02ab32eee025e4bf09198b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! 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