json_syntax/object/
index_map.rs

1use super::{Entry, Key};
2use core::hash::{BuildHasher, Hash};
3use hashbrown::hash_map::DefaultHashBuilder;
4use hashbrown::raw::RawTable;
5
6pub trait Equivalent<K: ?Sized> {
7	fn equivalent(&self, key: &K) -> bool;
8}
9
10impl<Q: ?Sized + Eq, K: ?Sized> Equivalent<K> for Q
11where
12	K: std::borrow::Borrow<Q>,
13{
14	fn equivalent(&self, key: &K) -> bool {
15		self == key.borrow()
16	}
17}
18
19fn equivalent_key<'a, Q>(entries: &'a [Entry], k: &'a Q) -> impl 'a + Fn(&Indexes) -> bool
20where
21	Q: ?Sized + Equivalent<Key>,
22{
23	move |indexes| k.equivalent(&entries[indexes.rep].key)
24}
25
26fn make_hasher<'a, S>(entries: &'a [Entry], hash_builder: &'a S) -> impl 'a + Fn(&Indexes) -> u64
27where
28	S: BuildHasher,
29{
30	move |indexes| hash_builder.hash_one(&entries[indexes.rep].key)
31}
32
33#[derive(Clone, Debug, PartialEq, Eq)]
34pub struct Indexes {
35	/// Index of the first entry with the considered key (the representative).
36	rep: usize,
37
38	/// Other indexes with this key.
39	other: Vec<usize>,
40}
41
42impl Indexes {
43	fn new(rep: usize) -> Self {
44		Self {
45			rep,
46			other: Vec::new(),
47		}
48	}
49
50	pub fn len(&self) -> usize {
51		1 + self.other.len()
52	}
53
54	pub fn first(&self) -> usize {
55		self.rep
56	}
57
58	pub fn is_redundant(&self) -> bool {
59		!self.other.is_empty()
60	}
61
62	pub fn redundant(&self) -> Option<usize> {
63		self.other.first().cloned()
64	}
65
66	pub fn redundants(&self) -> &[usize] {
67		&self.other
68	}
69
70	fn insert(&mut self, mut index: usize) {
71		if index != self.rep {
72			if index < self.rep {
73				core::mem::swap(&mut index, &mut self.rep);
74			}
75
76			if let Err(i) = self.other.binary_search(&index) {
77				self.other.insert(i, index)
78			}
79		}
80	}
81
82	/// Removes the given index, unless it is the last remaining index.
83	///
84	/// Returns `true` if the index has been removed or not in the list,
85	/// and `false` if it was the last index (and hence not removed).
86	fn remove(&mut self, index: usize) -> bool {
87		if self.rep == index {
88			if self.other.is_empty() {
89				false
90			} else {
91				self.rep = self.other.remove(0);
92				true
93			}
94		} else {
95			if let Ok(i) = self.other.binary_search(&index) {
96				self.other.remove(i);
97			}
98
99			true
100		}
101	}
102
103	/// Decreases all index greater than `index` by one.
104	pub fn shift_down(&mut self, index: usize) {
105		if self.rep > index {
106			self.rep -= 1
107		}
108
109		for i in &mut self.other {
110			if *i > index {
111				*i -= 1
112			}
113		}
114	}
115
116	/// Increases all index greater than or equal to `index` by one.
117	pub fn shift_up(&mut self, index: usize) {
118		if self.rep >= index {
119			self.rep += 1
120		}
121
122		for i in &mut self.other {
123			if *i >= index {
124				*i += 1
125			}
126		}
127	}
128
129	pub fn iter(&self) -> super::Indexes {
130		super::Indexes::Some {
131			first: Some(self.rep),
132			other: self.other.iter(),
133		}
134	}
135}
136
137impl<'a> IntoIterator for &'a Indexes {
138	type Item = usize;
139	type IntoIter = super::Indexes<'a>;
140
141	fn into_iter(self) -> Self::IntoIter {
142		self.iter()
143	}
144}
145
146#[derive(Clone)]
147pub struct IndexMap<S = DefaultHashBuilder> {
148	hash_builder: S,
149	table: RawTable<Indexes>,
150}
151
152impl<S: Default> IndexMap<S> {
153	fn default() -> Self {
154		Self {
155			hash_builder: S::default(),
156			table: RawTable::default(),
157		}
158	}
159}
160
161impl<S> IndexMap<S> {
162	pub fn new() -> Self
163	where
164		S: Default,
165	{
166		Self::default()
167	}
168
169	pub fn contains_duplicate_keys(&self) -> bool {
170		unsafe {
171			for bucket in self.table.iter() {
172				if bucket.as_ref().is_redundant() {
173					return true;
174				}
175			}
176		}
177
178		false
179	}
180}
181
182impl<S: BuildHasher> IndexMap<S> {
183	pub fn get<Q>(&self, entries: &[Entry], key: &Q) -> Option<&Indexes>
184	where
185		Q: ?Sized + Hash + Equivalent<Key>,
186	{
187		let hash = self.hash_builder.hash_one(key);
188		self.table.get(hash, equivalent_key(entries, key))
189	}
190
191	/// Associates the given `key` to `index`.
192	///
193	/// Returns `true` if no index was already associated to the key.
194	pub fn insert(&mut self, entries: &[Entry], index: usize) -> bool {
195		let key = &entries[index].key;
196		let hash = self.hash_builder.hash_one(key);
197		match self.table.get_mut(hash, equivalent_key(entries, key)) {
198			Some(indexes) => {
199				indexes.insert(index);
200				false
201			}
202			None => {
203				self.table.insert(
204					hash,
205					Indexes::new(index),
206					make_hasher::<S>(entries, &self.hash_builder),
207				);
208				true
209			}
210		}
211	}
212
213	/// Removes the association between the given key and index.
214	pub fn remove(&mut self, entries: &[Entry], index: usize) {
215		let key = &entries[index].key;
216		let hash = self.hash_builder.hash_one(key);
217		if let Some(bucket) = self.table.find(hash, equivalent_key(entries, key)) {
218			let indexes = unsafe { bucket.as_mut() };
219
220			if !indexes.remove(index) {
221				unsafe { self.table.remove(bucket) };
222			}
223		}
224	}
225
226	/// Decreases all index greater than `index` by one everywhere in the table.
227	pub fn shift_down(&mut self, index: usize) {
228		unsafe {
229			for bucket in self.table.iter() {
230				let indexes = bucket.as_mut();
231				indexes.shift_down(index)
232			}
233		}
234	}
235
236	/// Increases all index greater than or equal to `index` by one everywhere in the table.
237	pub fn shift_up(&mut self, index: usize) {
238		unsafe {
239			for bucket in self.table.iter() {
240				let indexes = bucket.as_mut();
241				indexes.shift_up(index)
242			}
243		}
244	}
245
246	pub fn clear(&mut self) {
247		self.table.clear()
248	}
249}
250
251#[cfg(test)]
252mod tests {
253	use super::*;
254	use crate::Value;
255
256	#[test]
257	fn insert() {
258		let entries = [
259			Entry::new("a".into(), Value::Null),
260			Entry::new("b".into(), Value::Null),
261			Entry::new("a".into(), Value::Null),
262		];
263
264		let mut indexes: IndexMap = IndexMap::default();
265		indexes.insert(&entries, 2);
266		indexes.insert(&entries, 1);
267		indexes.insert(&entries, 0);
268
269		let mut a = indexes.get(&entries, "a").unwrap().iter();
270		let mut b = indexes.get(&entries, "b").unwrap().iter();
271
272		assert_eq!(a.next(), Some(0));
273		assert_eq!(a.next(), Some(2));
274		assert_eq!(a.next(), None);
275		assert_eq!(b.next(), Some(1));
276		assert_eq!(b.next(), None);
277		assert_eq!(indexes.get(&entries, "c"), None)
278	}
279
280	#[test]
281	fn remove1() {
282		let entries = [
283			Entry::new("a".into(), Value::Null),
284			Entry::new("b".into(), Value::Null),
285			Entry::new("a".into(), Value::Null),
286		];
287
288		let mut indexes: IndexMap = IndexMap::default();
289		indexes.insert(&entries, 2);
290		indexes.insert(&entries, 1);
291		indexes.insert(&entries, 0);
292
293		indexes.remove(&entries, 1);
294		indexes.remove(&entries, 0);
295
296		let mut a = indexes.get(&entries, "a").unwrap().iter();
297
298		assert_eq!(a.next(), Some(2));
299		assert_eq!(a.next(), None);
300		assert_eq!(indexes.get(&entries, "b"), None)
301	}
302
303	#[test]
304	fn remove2() {
305		let entries = [
306			Entry::new("a".into(), Value::Null),
307			Entry::new("b".into(), Value::Null),
308			Entry::new("a".into(), Value::Null),
309		];
310
311		let mut indexes: IndexMap = IndexMap::default();
312		indexes.insert(&entries, 2);
313		indexes.insert(&entries, 1);
314		indexes.insert(&entries, 0);
315
316		indexes.remove(&entries, 0);
317		indexes.remove(&entries, 1);
318		indexes.remove(&entries, 2);
319
320		assert_eq!(indexes.get(&entries, "a"), None);
321		assert_eq!(indexes.get(&entries, "b"), None)
322	}
323}