1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
macro_rules! map { ($treeimport:path) => { use $treeimport::{Tree, Iter}; use std::fmt::Debug; use std::borrow::Borrow; /// This Map uses a similar strategy to BTreeMap to ensure cache /// efficient performance on modern hardware while still providing /// log(N) get, insert, and remove operations. /// # Examples /// ``` /// use std::string::String; /// use self::immutable_chunkmap::rc::map::Map; /// /// let m = /// Map::new() /// .insert(&String::from("1"), &1) /// .insert(&String::from("2"), &2) /// .insert(&String::from("3"), &3); /// /// assert_eq!(m.get("1"), Option::Some(&1)); /// assert_eq!(m.get("2"), Option::Some(&2)); /// assert_eq!(m.get("3"), Option::Some(&3)); /// assert_eq!(m.get("4"), Option::None); /// /// for (k, v) in &m { /// println!("key {}, val: {}", k, v) /// } /// ``` #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Map<K: Ord + Clone + Debug, V: Clone + Debug> { len: usize, root: Tree<K, V> } impl<'a,K,V> IntoIterator for &'a Map<K,V> where K: 'a + Ord + Clone + Debug, V: 'a + Clone + Debug { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.root.into_iter() } } impl<K,V> Map<K,V> where K: Ord + Clone + Debug, V: Clone + Debug { /// Create a new empty map pub fn new() -> Self { Map { len: 0, root: Tree::new() } } /// This method of insertion can be orders of magnitude faster than inserting elements one by /// one. Assuming you are inserting a large number of elements relative to the size of the /// map (1/10 +). Assuming your elements are already sorted, or nearly sorted. /// /// A word of warning however. If you're inserting small chunks (< 1/10) relative to the size /// of the map, or your chunks are not sorted, this method will still work, but it may be /// significantly slower than adding each element one by one. /// /// Regardless of whether the input is sorted or not, and regardless of it's size relative to /// the size of the map, this method runs in log(N) time where N is the size of the map. /// #Examples /// ``` /// use self::immutable_chunkmap::rc::map::Map; /// /// let v = vec![(1, 3), (10, 1), (-12, 2), (44, 0), (50, -1)]; /// let mut refs: Vec<(&i64, &i64)> = v.iter().map(|&(ref k, ref v)| (k, v)).collect(); /// refs.sort_unstable_by_key(|&(k, _)| k); /// /// let m = Map::new().insert_sorted(&refs); /// /// for &(ref k, ref v) in &v { /// assert_eq!(m.get(k), Option::Some(v)) /// } /// ``` pub fn insert_sorted(&self, elts: &[(&K, &V)]) -> Self { let (t, len) = self.root.insert_sorted(self.len, elts); Map { len: len, root: t } } /// return a new map with (k, v) inserted into it. If k already exists in the old map, the /// new map will contain the new binding, not the old. This method runs in log(N) time, where /// N is the size of the map. pub fn insert(&self, k: &K, v: &V) -> Self { let (t, len) = self.root.insert(self.len, k, v); Map { len: len, root: t } } /// lookup the mapping for k. If it doesn't exist return None. Runs in log(N) time where N is /// the size of the map. pub fn get<'a, Q: ?Sized + Ord + Debug>(&'a self, k: &Q) -> Option<&'a V> where K: Borrow<Q> { self.root.get(k) } /// return a new map with the mapping under k removed. Runs in log(N) time, where N is the /// size of the map pub fn remove<Q: Sized + Ord>(&self, k: &Q) -> Self where K: Borrow<Q> { let (t, len) = self.root.remove(self.len, k); Map {root: t, len: len} } /// get the number of elements in the map O(1) pub fn length(&self) -> usize { self.len } #[allow(dead_code)] pub(crate) fn invariant(&self) -> () { self.root.invariant(self.len) } } }; }