1use core::{
5 borrow::Borrow,
6 fmt,
7 hash::{Hash, Hasher},
8 iter::FusedIterator,
9 marker::PhantomData,
10 slice::{from_raw_parts, from_raw_parts_mut},
11};
12
13use munge::munge;
14use rancor::{Fallible, Source};
15
16use crate::{
17 collections::{
18 swiss_table::{ArchivedHashTable, HashTableResolver},
19 util::{Entry, EntryAdapter, EntryResolver},
20 },
21 hash::{hash_value, FxHasher64},
22 primitive::{ArchivedUsize, FixedUsize},
23 seal::Seal,
24 ser::{Allocator, Writer, WriterExt as _},
25 Place, Portable, RelPtr, Serialize,
26};
27
28#[derive(Portable)]
30#[cfg_attr(
31 feature = "bytecheck",
32 derive(bytecheck::CheckBytes),
33 bytecheck(verify)
34)]
35#[rkyv(crate)]
36#[repr(C)]
37pub struct ArchivedIndexMap<K, V, H = FxHasher64> {
38 table: ArchivedHashTable<ArchivedUsize>,
39 entries: RelPtr<Entry<K, V>>,
40 _phantom: PhantomData<H>,
41}
42
43impl<K, V, H> ArchivedIndexMap<K, V, H> {
44 fn entries(&self) -> &[Entry<K, V>] {
45 unsafe { from_raw_parts(self.entries.as_ptr(), self.len()) }
46 }
47
48 fn entries_seal(this: Seal<'_, Self>) -> Seal<'_, [Entry<K, V>]> {
49 let len = this.len();
50 munge!(let Self { entries, .. } = this);
51 let slice =
52 unsafe { from_raw_parts_mut(RelPtr::as_mut_ptr(entries), len) };
53 Seal::new(slice)
54 }
55
56 pub const fn is_empty(&self) -> bool {
58 self.len() == 0
59 }
60
61 unsafe fn raw_iter(&self) -> RawIter<'_, K, V> {
62 unsafe { RawIter::new(self.entries.as_ptr().cast(), self.len()) }
63 }
64
65 pub fn iter(&self) -> Iter<'_, K, V> {
67 Iter {
68 inner: unsafe { self.raw_iter() },
69 }
70 }
71
72 pub fn keys(&self) -> Keys<'_, K, V> {
74 Keys {
75 inner: unsafe { self.raw_iter() },
76 }
77 }
78
79 pub const fn len(&self) -> usize {
81 self.table.len()
82 }
83
84 pub fn values(&self) -> Values<'_, K, V> {
86 Values {
87 inner: unsafe { self.raw_iter() },
88 }
89 }
90}
91
92impl<K, V, H: Hasher + Default> ArchivedIndexMap<K, V, H> {
93 pub fn get_full_with<Q, C>(
96 &self,
97 key: &Q,
98 cmp: C,
99 ) -> Option<(usize, &K, &V)>
100 where
101 Q: Hash + Eq + ?Sized,
102 C: Fn(&Q, &K) -> bool,
103 {
104 let index = self.get_index_of_with(key, cmp)?;
105 let entries = self.entries();
106 let entry = &entries[index];
107 Some((index, &entry.key, &entry.value))
108 }
109
110 pub fn get_full<Q>(&self, key: &Q) -> Option<(usize, &K, &V)>
112 where
113 K: Borrow<Q>,
114 Q: Hash + Eq + ?Sized,
115 {
116 self.get_full_with(key, |q, k| q == k.borrow())
117 }
118
119 pub fn get_key_value_with<Q, C>(&self, key: &Q, cmp: C) -> Option<(&K, &V)>
122 where
123 Q: Hash + Eq + ?Sized,
124 C: Fn(&Q, &K) -> bool,
125 {
126 let (_, k, v) = self.get_full_with(key, cmp)?;
127 Some((k, v))
128 }
129
130 pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
132 where
133 K: Borrow<Q>,
134 Q: Hash + Eq + ?Sized,
135 {
136 let (_, k, v) = self.get_full(key)?;
137 Some((k, v))
138 }
139
140 pub fn get_with<Q, C>(&self, key: &Q, cmp: C) -> Option<&V>
143 where
144 Q: Hash + Eq + ?Sized,
145 C: Fn(&Q, &K) -> bool,
146 {
147 Some(self.get_full_with(key, cmp)?.2)
148 }
149
150 pub fn get<Q>(&self, key: &Q) -> Option<&V>
152 where
153 K: Borrow<Q>,
154 Q: Hash + Eq + ?Sized,
155 {
156 Some(self.get_full(key)?.2)
157 }
158
159 pub fn get_full_seal_with<'a, Q, C>(
162 this: Seal<'a, Self>,
163 key: &Q,
164 cmp: C,
165 ) -> Option<(usize, &'a K, Seal<'a, V>)>
166 where
167 Q: Hash + Eq + ?Sized,
168 C: Fn(&Q, &K) -> bool,
169 {
170 let index = this.get_index_of_with(key, cmp)?;
171 let entry = Seal::index(Self::entries_seal(this), index);
172 munge!(let Entry { key, value } = entry);
173 Some((index, key.unseal_ref(), value))
174 }
175
176 pub fn get_full_seal<'a, Q>(
179 this: Seal<'a, Self>,
180 key: &Q,
181 ) -> Option<(usize, &'a K, Seal<'a, V>)>
182 where
183 K: Borrow<Q>,
184 Q: Hash + Eq + ?Sized,
185 {
186 Self::get_full_seal_with(this, key, |q, k| q == k.borrow())
187 }
188
189 pub fn get_key_value_seal_with<'a, Q, C>(
192 this: Seal<'a, Self>,
193 key: &Q,
194 cmp: C,
195 ) -> Option<(&'a K, Seal<'a, V>)>
196 where
197 K: Borrow<Q>,
198 Q: Hash + Eq + ?Sized,
199 C: Fn(&Q, &K) -> bool,
200 {
201 let (_, k, v) = Self::get_full_seal_with(this, key, cmp)?;
202 Some((k, v))
203 }
204
205 pub fn get_key_value_seal<'a, Q>(
207 this: Seal<'a, Self>,
208 key: &Q,
209 ) -> Option<(&'a K, Seal<'a, V>)>
210 where
211 K: Borrow<Q>,
212 Q: Hash + Eq + ?Sized,
213 {
214 let (_, k, v) = Self::get_full_seal(this, key)?;
215 Some((k, v))
216 }
217
218 pub fn get_seal_with<'a, Q, C>(
221 this: Seal<'a, Self>,
222 key: &Q,
223 cmp: C,
224 ) -> Option<Seal<'a, V>>
225 where
226 K: Borrow<Q>,
227 Q: Hash + Eq + ?Sized,
228 C: Fn(&Q, &K) -> bool,
229 {
230 Some(Self::get_full_seal_with(this, key, cmp)?.2)
231 }
232
233 pub fn get_seal<'a, Q>(this: Seal<'a, Self>, key: &Q) -> Option<Seal<'a, V>>
236 where
237 K: Borrow<Q>,
238 Q: Hash + Eq + ?Sized,
239 {
240 Some(Self::get_full_seal(this, key)?.2)
241 }
242
243 pub fn contains_key<Q>(&self, key: &Q) -> bool
245 where
246 K: Borrow<Q>,
247 Q: Hash + Eq + ?Sized,
248 {
249 self.get(key).is_some()
250 }
251
252 pub fn get_index(&self, index: usize) -> Option<(&K, &V)> {
254 if index < self.len() {
255 let entry = &self.entries()[index];
256 Some((&entry.key, &entry.value))
257 } else {
258 None
259 }
260 }
261
262 pub fn get_index_of_with<Q, C>(&self, key: &Q, cmp: C) -> Option<usize>
265 where
266 Q: Hash + Eq + ?Sized,
267 C: Fn(&Q, &K) -> bool,
268 {
269 let entries = self.entries();
270 let index = self.table.get_with(hash_value::<Q, H>(key), |i| {
271 cmp(key, &entries[i.to_native() as usize].key)
272 })?;
273 Some(index.to_native() as usize)
274 }
275
276 pub fn get_index_of<Q>(&self, key: &Q) -> Option<usize>
278 where
279 K: Borrow<Q>,
280 Q: Hash + Eq + ?Sized,
281 {
282 self.get_index_of_with(key, |q, k| q == k.borrow())
283 }
284
285 pub fn resolve_from_len(
287 len: usize,
288 load_factor: (usize, usize),
289 resolver: IndexMapResolver,
290 out: Place<Self>,
291 ) {
292 munge!(let ArchivedIndexMap { table, entries, _phantom: _ } = out);
293 ArchivedHashTable::resolve_from_len(
294 len,
295 load_factor,
296 resolver.table_resolver,
297 table,
298 );
299 RelPtr::emplace(resolver.entries_pos as usize, entries);
300 }
301
302 pub fn serialize_from_iter<I, BKU, BVU, KU, VU, S>(
304 iter: I,
305 load_factor: (usize, usize),
306 serializer: &mut S,
307 ) -> Result<IndexMapResolver, S::Error>
308 where
309 I: Clone + ExactSizeIterator<Item = (BKU, BVU)>,
310 BKU: Borrow<KU>,
311 BVU: Borrow<VU>,
312 KU: Serialize<S, Archived = K> + Hash + Eq,
313 VU: Serialize<S, Archived = V>,
314 S: Fallible + Writer + Allocator + ?Sized,
315 S::Error: Source,
316 {
317 use crate::util::SerVec;
318
319 let table_resolver =
321 ArchivedHashTable::<ArchivedUsize>::serialize_from_iter(
322 0..iter.len(),
323 iter.clone()
324 .map(|(key, _)| hash_value::<KU, H>(key.borrow())),
325 load_factor,
326 serializer,
327 )?;
328
329 SerVec::with_capacity(
331 serializer,
332 iter.len(),
333 |resolvers, serializer| {
334 for (key, value) in iter.clone() {
335 resolvers.push(EntryResolver {
336 key: key.borrow().serialize(serializer)?,
337 value: value.borrow().serialize(serializer)?,
338 });
339 }
340
341 let entries_pos = serializer.align_for::<Entry<K, V>>()?;
342 for ((key, value), resolver) in
343 iter.clone().zip(resolvers.drain())
344 {
345 unsafe {
346 serializer.resolve_aligned(
347 &EntryAdapter::new(key, value),
348 resolver,
349 )?;
350 }
351 }
352
353 Ok(IndexMapResolver {
354 table_resolver,
355 entries_pos: entries_pos as FixedUsize,
356 })
357 },
358 )?
359 }
360}
361
362impl<K, V, H> fmt::Debug for ArchivedIndexMap<K, V, H>
363where
364 K: fmt::Debug,
365 V: fmt::Debug,
366{
367 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368 f.debug_map().entries(self.iter()).finish()
369 }
370}
371
372impl<K, V, H> PartialEq for ArchivedIndexMap<K, V, H>
373where
374 K: PartialEq,
375 V: PartialEq,
376{
377 fn eq(&self, other: &Self) -> bool {
378 self.iter().eq(other.iter())
379 }
380}
381
382impl<K: Eq, V: Eq, H> Eq for ArchivedIndexMap<K, V, H> {}
383
384struct RawIter<'a, K, V> {
385 current: *const Entry<K, V>,
386 remaining: usize,
387 _phantom: PhantomData<(&'a K, &'a V)>,
388}
389
390impl<K, V> RawIter<'_, K, V> {
391 fn new(pairs: *const Entry<K, V>, len: usize) -> Self {
392 Self {
393 current: pairs,
394 remaining: len,
395 _phantom: PhantomData,
396 }
397 }
398}
399
400impl<'a, K, V> Iterator for RawIter<'a, K, V> {
401 type Item = (&'a K, &'a V);
402
403 fn next(&mut self) -> Option<Self::Item> {
404 unsafe {
405 if self.remaining == 0 {
406 None
407 } else {
408 let result = self.current;
409 self.current = self.current.add(1);
410 self.remaining -= 1;
411 let entry = &*result;
412 Some((&entry.key, &entry.value))
413 }
414 }
415 }
416
417 fn size_hint(&self) -> (usize, Option<usize>) {
418 (self.remaining, Some(self.remaining))
419 }
420}
421
422impl<K, V> ExactSizeIterator for RawIter<'_, K, V> {}
423impl<K, V> FusedIterator for RawIter<'_, K, V> {}
424
425#[repr(transparent)]
427pub struct Iter<'a, K, V> {
428 inner: RawIter<'a, K, V>,
429}
430
431impl<'a, K, V> Iterator for Iter<'a, K, V> {
432 type Item = (&'a K, &'a V);
433
434 fn next(&mut self) -> Option<Self::Item> {
435 self.inner.next()
436 }
437
438 fn size_hint(&self) -> (usize, Option<usize>) {
439 self.inner.size_hint()
440 }
441}
442
443impl<K, V> ExactSizeIterator for Iter<'_, K, V> {}
444impl<K, V> FusedIterator for Iter<'_, K, V> {}
445
446#[repr(transparent)]
448pub struct Keys<'a, K, V> {
449 inner: RawIter<'a, K, V>,
450}
451
452impl<'a, K, V> Iterator for Keys<'a, K, V> {
453 type Item = &'a K;
454
455 fn next(&mut self) -> Option<Self::Item> {
456 self.inner.next().map(|(k, _)| k)
457 }
458
459 fn size_hint(&self) -> (usize, Option<usize>) {
460 self.inner.size_hint()
461 }
462}
463
464impl<K, V> ExactSizeIterator for Keys<'_, K, V> {}
465impl<K, V> FusedIterator for Keys<'_, K, V> {}
466
467#[repr(transparent)]
469pub struct Values<'a, K, V> {
470 inner: RawIter<'a, K, V>,
471}
472
473impl<'a, K, V> Iterator for Values<'a, K, V> {
474 type Item = &'a V;
475
476 fn next(&mut self) -> Option<Self::Item> {
477 self.inner.next().map(|(_, v)| v)
478 }
479
480 fn size_hint(&self) -> (usize, Option<usize>) {
481 self.inner.size_hint()
482 }
483}
484
485impl<K, V> ExactSizeIterator for Values<'_, K, V> {}
486impl<K, V> FusedIterator for Values<'_, K, V> {}
487
488pub struct IndexMapResolver {
490 table_resolver: HashTableResolver,
491 entries_pos: FixedUsize,
492}
493
494#[cfg(feature = "bytecheck")]
495mod verify {
496 use bytecheck::{CheckBytes, Verify};
497 use rancor::{Fallible, Source};
498
499 use super::ArchivedIndexMap;
500 use crate::{
501 collections::util::Entry,
502 validation::{ArchiveContext, ArchiveContextExt},
503 };
504
505 unsafe impl<C, K, V, H> Verify<C> for ArchivedIndexMap<K, V, H>
506 where
507 C: Fallible + ArchiveContext + ?Sized,
508 C::Error: Source,
509 K: CheckBytes<C>,
510 V: CheckBytes<C>,
511 {
512 fn verify(
513 &self,
514 context: &mut C,
515 ) -> Result<(), <C as Fallible>::Error> {
516 let ptr = core::ptr::slice_from_raw_parts(
517 self.entries.as_ptr_wrapping(),
518 self.table.len(),
519 );
520
521 context.in_subtree(ptr, |context| {
522 unsafe { <[Entry<K, V>]>::check_bytes(ptr, context) }
525 })
526 }
527 }
528}