cxx_gen/syntax/
map.rs

1use std::borrow::Borrow;
2use std::hash::Hash;
3use std::ops::Index;
4use std::slice;
5
6pub(crate) use self::ordered::OrderedMap;
7pub(crate) use self::unordered::UnorderedMap;
8pub(crate) use std::collections::hash_map::Entry;
9
10mod 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> {
22        pub(crate) fn new() -> Self {
23            OrderedMap {
24                map: UnorderedMap::new(),
25                vec: Vec::new(),
26            }
27        }
28
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
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    {
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
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>;
69        fn into_iter(self) -> Self::IntoIter {
70            self.iter()
71        }
72    }
73}
74
75mod 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> {
86        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    {
95        pub(crate) fn insert(&mut self, key: K, value: V) -> Option<V> {
96            self.0.insert(key, value)
97        }
98
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
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
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
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
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
141pub(crate) struct Iter<'a, K, V>(slice::Iter<'a, (K, V)>);
142
143impl<'a, K, V> Iterator for Iter<'a, K, V> {
144    type Item = (&'a K, &'a V);
145
146    fn next(&mut self) -> Option<Self::Item> {
147        let (k, v) = self.0.next()?;
148        Some((k, v))
149    }
150
151    fn size_hint(&self) -> (usize, Option<usize>) {
152        self.0.size_hint()
153    }
154}
155
156impl<K, V> Default for UnorderedMap<K, V> {
157    fn default() -> Self {
158        UnorderedMap::new()
159    }
160}
161
162impl<Q, K, V> Index<&Q> for UnorderedMap<K, V>
163where
164    K: Borrow<Q> + Hash + Eq,
165    Q: ?Sized + Hash + Eq,
166{
167    type Output = V;
168
169    fn index(&self, key: &Q) -> &V {
170        self.get(key).unwrap()
171    }
172}