1 use std::borrow::Borrow; 2 use std::hash::Hash; 3 use std::ops::Index; 4 use std::slice; 5 6 pub(crate) use self::ordered::OrderedMap; 7 pub(crate) use self::unordered::UnorderedMap; 8 pub(crate) use std::collections::hash_map::Entry; 9 10 mod ordered { 11 use super::{Entry, Iter, UnorderedMap}; 12 use std::borrow::Borrow; 13 use std::hash::Hash; 14 use std::mem; 15 16 pub(crate) struct OrderedMap<K, V> { 17 map: UnorderedMap<K, usize>, 18 vec: Vec<(K, V)>, 19 } 20 21 impl<K, V> OrderedMap<K, V> { new() -> Self22 pub(crate) fn new() -> Self { 23 OrderedMap { 24 map: UnorderedMap::new(), 25 vec: Vec::new(), 26 } 27 } 28 iter(&self) -> Iter<K, V>29 pub(crate) fn iter(&self) -> Iter<K, V> { 30 Iter(self.vec.iter()) 31 } 32 33 #[allow(dead_code)] // only used by cxx-build, not cxxbridge-macro keys(&self) -> impl Iterator<Item = &K>34 pub(crate) fn keys(&self) -> impl Iterator<Item = &K> { 35 self.vec.iter().map(|(k, _v)| k) 36 } 37 } 38 39 impl<K, V> OrderedMap<K, V> 40 where 41 K: Copy + Hash + Eq, 42 { insert(&mut self, key: K, value: V) -> Option<V>43 pub(crate) fn insert(&mut self, key: K, value: V) -> Option<V> { 44 match self.map.entry(key) { 45 Entry::Occupied(entry) => { 46 let i = &mut self.vec[*entry.get()]; 47 Some(mem::replace(&mut i.1, value)) 48 } 49 Entry::Vacant(entry) => { 50 entry.insert(self.vec.len()); 51 self.vec.push((key, value)); 52 None 53 } 54 } 55 } 56 contains_key<Q>(&self, key: &Q) -> bool where K: Borrow<Q>, Q: ?Sized + Hash + Eq,57 pub(crate) fn contains_key<Q>(&self, key: &Q) -> bool 58 where 59 K: Borrow<Q>, 60 Q: ?Sized + Hash + Eq, 61 { 62 self.map.contains_key(key) 63 } 64 } 65 66 impl<'a, K, V> IntoIterator for &'a OrderedMap<K, V> { 67 type Item = (&'a K, &'a V); 68 type IntoIter = Iter<'a, K, V>; into_iter(self) -> Self::IntoIter69 fn into_iter(self) -> Self::IntoIter { 70 self.iter() 71 } 72 } 73 } 74 75 mod unordered { 76 use crate::syntax::set::UnorderedSet; 77 use std::borrow::Borrow; 78 use std::collections::hash_map::{Entry, HashMap}; 79 use std::hash::Hash; 80 81 // Wrapper prohibits accidentally introducing iteration over the map, which 82 // could lead to nondeterministic generated code. 83 pub(crate) struct UnorderedMap<K, V>(HashMap<K, V>); 84 85 impl<K, V> UnorderedMap<K, V> { new() -> Self86 pub(crate) fn new() -> Self { 87 UnorderedMap(HashMap::new()) 88 } 89 } 90 91 impl<K, V> UnorderedMap<K, V> 92 where 93 K: Hash + Eq, 94 { insert(&mut self, key: K, value: V) -> Option<V>95 pub(crate) fn insert(&mut self, key: K, value: V) -> Option<V> { 96 self.0.insert(key, value) 97 } 98 contains_key<Q>(&self, key: &Q) -> bool where K: Borrow<Q>, Q: ?Sized + Hash + Eq,99 pub(crate) fn contains_key<Q>(&self, key: &Q) -> bool 100 where 101 K: Borrow<Q>, 102 Q: ?Sized + Hash + Eq, 103 { 104 self.0.contains_key(key) 105 } 106 get<Q>(&self, key: &Q) -> Option<&V> where K: Borrow<Q>, Q: ?Sized + Hash + Eq,107 pub(crate) fn get<Q>(&self, key: &Q) -> Option<&V> 108 where 109 K: Borrow<Q>, 110 Q: ?Sized + Hash + Eq, 111 { 112 self.0.get(key) 113 } 114 entry(&mut self, key: K) -> Entry<K, V>115 pub(crate) fn entry(&mut self, key: K) -> Entry<K, V> { 116 self.0.entry(key) 117 } 118 119 #[allow(dead_code)] // only used by cxx-build, not cxxbridge-macro remove<Q>(&mut self, key: &Q) -> Option<V> where K: Borrow<Q>, Q: ?Sized + Hash + Eq,120 pub(crate) fn remove<Q>(&mut self, key: &Q) -> Option<V> 121 where 122 K: Borrow<Q>, 123 Q: ?Sized + Hash + Eq, 124 { 125 self.0.remove(key) 126 } 127 keys(&self) -> UnorderedSet<K> where K: Copy,128 pub(crate) fn keys(&self) -> UnorderedSet<K> 129 where 130 K: Copy, 131 { 132 let mut set = UnorderedSet::new(); 133 for key in self.0.keys() { 134 set.insert(*key); 135 } 136 set 137 } 138 } 139 } 140 141 pub(crate) struct Iter<'a, K, V>(slice::Iter<'a, (K, V)>); 142 143 impl<'a, K, V> Iterator for Iter<'a, K, V> { 144 type Item = (&'a K, &'a V); 145 next(&mut self) -> Option<Self::Item>146 fn next(&mut self) -> Option<Self::Item> { 147 let (k, v) = self.0.next()?; 148 Some((k, v)) 149 } 150 size_hint(&self) -> (usize, Option<usize>)151 fn size_hint(&self) -> (usize, Option<usize>) { 152 self.0.size_hint() 153 } 154 } 155 156 impl<K, V> Default for UnorderedMap<K, V> { default() -> Self157 fn default() -> Self { 158 UnorderedMap::new() 159 } 160 } 161 162 impl<Q, K, V> Index<&Q> for UnorderedMap<K, V> 163 where 164 K: Borrow<Q> + Hash + Eq, 165 Q: ?Sized + Hash + Eq, 166 { 167 type Output = V; 168 index(&self, key: &Q) -> &V169 fn index(&self, key: &Q) -> &V { 170 self.get(key).unwrap() 171 } 172 } 173