handy/typed.rs
1//! This module provides [`TypedHandleMap`][typed::TypedHandleMap] and
2//! [`TypedHandle`][typed::TypedHandle]. These are wrappers around of
3//! [`HandleMap`] and [`Handle`] which statically prevent trying to use a
4//! `Handle` returned from a `HandleMap<T>` to get a value out of a
5//! `HandleMap<U>`, instead of allowing it to fail at runtime, as it will with
6//! `HandleMap`.
7//!
8//! For most use cases, this is probably not worth the extra trouble, but it's
9//! provided for completeness, and because the definition of `TypedHandle` has
10//! some subtle gotchas.
11//!
12//! These abstractions are thin. Methods exist to go bidirectionally to and from
13//! both `TypedHandleMap<T>` to `HandleMap<T>` and `TypedHandle<T>` to `Handle`.
14//! You shouldn't need to do this, but restricting it seems needless.
15
16use crate::{Handle, HandleMap};
17use core::marker::PhantomData;
18
19/// A `TypedHandleMap` is a wrapper around a [`HandleMap`] which gives you some
20/// additional type safety, should you desire.
21///
22/// It accepts and returns [`TypedHandle`]s, and you can only pass a
23/// `TypedHandle<T>` to a `TypedHandleMap<T>` -- attempting to pass it to a
24/// `TypedHandleMap<U>` will be statically detected.
25///
26/// Beyond this, it still can detect use of a handle that came from another map.
27///
28/// You use it with `TypedHandle`s, which only will accept handles of the
29/// correct type. This could be useful if you have several handle maps in your
30/// program, and find
31///
32/// `TypedHandle<T>` is Copy + Send + Sync (and several others) regardless of
33/// `T`, which is not true for a naïve implementation of this, so it's provided
34/// even though I don't think it's that helpful for most usage (handle maps
35/// already detect this at runtime).
36#[derive(Clone, Debug)]
37pub struct TypedHandleMap<T>(HandleMap<T>);
38
39impl<T> TypedHandleMap<T> {
40 /// Create a new typed handle map.
41 ///
42 /// ## Example
43 /// ```
44 /// # use handy::typed::TypedHandleMap;
45 /// let m: TypedHandleMap<u32> = TypedHandleMap::new();
46 /// // No allocation is performed by default.
47 /// assert_eq!(m.capacity(), 0);
48 /// ```
49 #[inline]
50 pub fn new() -> Self {
51 Self(HandleMap::new())
52 }
53
54 /// Create a typed handle map from one which accepts untyped handles.
55 ///
56 /// ## Example
57 /// ```
58 /// # use handy::HandleMap;
59 /// # use handy::typed::{TypedHandleMap, TypedHandle};
60 /// let mut m: HandleMap<u32> = HandleMap::new();
61 /// let h = m.insert(10u32);
62 /// let tm = TypedHandleMap::from_untyped(m);
63 /// assert_eq!(tm[TypedHandle::from_handle(h)], 10u32);
64 /// ```
65 #[inline]
66 pub fn from_untyped(h: HandleMap<T>) -> Self {
67 Self(h)
68 }
69
70 /// Convert this map into it's wrapped [`HandleMap`]. See also
71 /// [`TypedHandleMap::as_untyped_map`] and [`TypedHandleMap::as_mut_untyped_map`].
72 ///
73 /// ## Example
74 /// ```
75 /// # use handy::HandleMap;
76 /// # use handy::typed::TypedHandleMap;
77 /// let mut tm: TypedHandleMap<u32> = TypedHandleMap::new();
78 /// let th = tm.insert(10u32);
79 /// let m = tm.into_untyped();
80 /// assert_eq!(m[th.handle()], 10);
81 /// ```
82 #[inline]
83 pub fn into_untyped(self) -> HandleMap<T> {
84 self.0
85 }
86
87 /// Create a new typed handle map with the specified capacity.
88 ///
89 /// ## Example
90 /// ```
91 /// # use handy::typed::TypedHandleMap;
92 /// let m: TypedHandleMap<u32> = TypedHandleMap::with_capacity(10);
93 /// // Note that we don't guarantee the capacity will be exact.
94 /// // (though in practice it will so long as the requested
95 /// // capacity is >= 8)
96 /// assert!(m.capacity() >= 10);
97 /// ```
98 #[inline]
99 pub fn with_capacity(c: usize) -> Self {
100 Self::from_untyped(HandleMap::with_capacity(c))
101 }
102
103 /// Get the number of entries we can hold before reallocation.
104 ///
105 /// This just calls [`HandleMap::capacity`] on our wrapped map.
106 ///
107 /// ## Example
108 /// ```
109 /// # use handy::typed::TypedHandleMap;
110 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
111 /// m.insert(10);
112 /// assert!(m.capacity() >= 1);
113 /// ```
114 #[inline]
115 pub fn capacity(&self) -> usize {
116 self.0.capacity()
117 }
118
119 /// Get the number of occupied entries.
120 ///
121 /// This just calls [`HandleMap::len`] on our wrapped map.
122 /// ## Example
123 /// ```
124 /// # use handy::typed::TypedHandleMap;
125 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
126 /// assert_eq!(m.len(), 0);
127 /// m.insert(10u32);
128 /// assert_eq!(m.len(), 1);
129 /// ```
130 #[inline]
131 pub fn len(&self) -> usize {
132 self.0.len()
133 }
134
135 /// Returns true if our length is zero.
136 ///
137 /// This just calls [`HandleMap::is_empty`] on our wrapped map.
138 ///
139 /// ## Example
140 /// ```
141 /// # use handy::typed::TypedHandleMap;
142 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
143 /// assert!(m.is_empty());
144 /// ```
145 #[inline]
146 pub fn is_empty(&self) -> bool {
147 self.0.is_empty()
148 }
149
150 /// Get a reference to this map as a [`HandleMap`].
151 ///
152 /// This shouldn't be necessary except in advanced use, but may allow access
153 /// to APIs that aren't mirrored, like most of the `raw` APIs.
154 ///
155 /// ## Example
156 /// ```
157 /// # use handy::HandleMap;
158 /// # use handy::typed::TypedHandleMap;
159 /// let mut tm: TypedHandleMap<u32> = TypedHandleMap::new();
160 /// let th = tm.insert(10u32);
161 /// assert_eq!(tm.as_untyped_map()[th.handle()], 10);
162 /// ```
163 #[inline]
164 pub fn as_untyped_map(&self) -> &HandleMap<T> {
165 &self.0
166 }
167
168 /// Get a mutable reference to this map as a [`HandleMap`].
169 ///
170 /// This shouldn't be necessary except in advanced use, but may allow access
171 /// to APIs that aren't mirrored, like most of the `raw` APIs.
172 ///
173 /// ## Example
174 /// ```
175 /// # use handy::typed::TypedHandleMap;
176 /// let mut tm = TypedHandleMap::new();
177 /// let th = tm.insert(10u32);
178 /// tm.as_mut_untyped_map()[th.handle()] = 5;
179 /// assert_eq!(tm[th], 5);
180 /// ```
181 #[inline]
182 pub fn as_mut_untyped_map(&mut self) -> &mut HandleMap<T> {
183 &mut self.0
184 }
185
186 /// Add a new item, returning a handle to it.
187 ///
188 /// This just calls [`HandleMap::insert`] on our wrapped map.
189 ///
190 /// ## Example
191 /// ```
192 /// # use handy::typed::TypedHandleMap;
193 /// let mut m = TypedHandleMap::new();
194 /// assert_eq!(m.len(), 0);
195 /// m.insert(10u32);
196 /// assert_eq!(m.len(), 1);
197 /// ```
198 #[inline]
199 pub fn insert(&mut self, value: T) -> TypedHandle<T> {
200 TypedHandle::from_handle(self.0.insert(value))
201 }
202
203 /// Remove the value referenced by this handle from the map, returning it.
204 ///
205 /// If the handle doesn't point to an entry in the map we return None. This
206 /// will happen if:
207 ///
208 /// - The handle comes from a different map.
209 /// - The item it referenced has been removed already.
210 /// - It appears corrupt in some other way.
211 ///
212 /// This just calls [`HandleMap::remove`] on our wrapped map.
213 ///
214 /// ## Example
215 /// ```
216 /// # use handy::typed::TypedHandleMap;
217 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
218 /// let h = m.insert(10u32);
219 /// // Present:
220 /// assert_eq!(m.remove(h), Some(10));
221 /// // Not present:
222 /// assert_eq!(m.remove(h), None);
223 /// ```
224 #[inline]
225 pub fn remove(&mut self, handle: TypedHandle<T>) -> Option<T> {
226 self.0.remove(handle.h)
227 }
228
229 /// Remove all entries in this handle map.
230 ///
231 /// This just calls [`HandleMap::clear`] on our wrapped map.
232 ///
233 /// ## Example
234 /// ```
235 /// # use handy::typed::TypedHandleMap;
236 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
237 /// let h = m.insert(10u32);
238 /// m.clear();
239 /// assert_eq!(m.len(), 0);
240 /// assert_eq!(m.get(h), None);
241 /// ```
242 #[inline]
243 pub fn clear(&mut self) {
244 self.0.clear();
245 }
246
247 /// Try and get a reference to the item backed by the handle.
248 ///
249 /// If the handle doesn't point to an entry in the map we return None. This
250 /// will happen if:
251 ///
252 /// - The handle comes from a different map.
253 /// - The item it referenced has been removed already.
254 /// - It appears corrupt in some other way.
255 ///
256 /// This just calls [`HandleMap::get`] on our wrapped map.
257 ///
258 /// ## Example
259 /// ```
260 /// # use handy::typed::TypedHandleMap;
261 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
262 /// let h = m.insert(10u32);
263 /// assert_eq!(m.get(h), Some(&10));
264 /// m.remove(h);
265 /// assert_eq!(m.get(h), None);
266 /// ```
267 #[inline]
268 pub fn get(&self, handle: TypedHandle<T>) -> Option<&T> {
269 self.0.get(handle.h)
270 }
271
272 /// Try and get mutable a reference to the item backed by the handle.
273 ///
274 /// If the handle doesn't point to an entry in the map we return None. This
275 /// will happen if:
276 ///
277 /// - The handle comes from a different map.
278 /// - The item it referenced has been removed already.
279 /// - It appears corrupt in some other way.
280 ///
281 /// This just calls [`HandleMap::get_mut`] on our wrapped map.
282 ///
283 /// ## Example
284 /// ```
285 /// # use handy::typed::TypedHandleMap;
286 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
287 /// let h = m.insert(10u32);
288 /// *m.get_mut(h).unwrap() += 1;
289 /// assert_eq!(m[h], 11);
290 /// // Note: The following is equivalent if you're going to `unwrap` the result of get_mut:
291 /// m[h] += 1;
292 /// assert_eq!(m[h], 12);
293 /// ```
294 #[inline]
295 pub fn get_mut(&mut self, handle: TypedHandle<T>) -> Option<&mut T> {
296 self.0.get_mut(handle.h)
297 }
298
299 /// Returns true if the handle refers to an item present in this map.
300 ///
301 /// This just calls [`HandleMap::contains`] on our wrapped map.
302 ///
303 /// ## Example
304 /// ```
305 /// # use handy::typed::TypedHandleMap;
306 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
307 /// let h = m.insert(10u32);
308 /// assert!(m.contains(h));
309 /// m.remove(h);
310 /// assert!(!m.contains(h));
311 /// ```
312 #[inline]
313 pub fn contains(&self, h: TypedHandle<T>) -> bool {
314 self.0.contains_key(h.h)
315 }
316
317 /// Returns true if the handle refers to an item present in this map.
318 ///
319 /// This just calls [`HandleMap::contains_key`] on our wrapped map.
320 ///
321 /// ## Example
322 /// ```
323 /// # use handy::typed::TypedHandleMap;
324 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
325 /// let h = m.insert(10u32);
326 /// assert!(m.contains_key(h));
327 /// m.remove(h);
328 /// assert!(!m.contains_key(h));
329 /// ```
330 #[inline]
331 pub fn contains_key(&self, h: TypedHandle<T>) -> bool {
332 self.0.contains_key(h.h)
333 }
334
335 /// Search the map for `item`, and if it's found, return a handle to it.
336 ///
337 /// If more than one value compare as equal to `item`, it's not specified
338 /// which we will return.
339 ///
340 /// Note that this is a naive O(n) search, so if you want this often, you
341 /// might want to store the handle as a field on the value.
342 ///
343 /// This just calls [`HandleMap::find_handle`] on our wrapped map and wraps
344 /// the resulting handle.
345 ///
346 /// ## Example
347 /// ```
348 /// # use handy::typed::TypedHandleMap;
349 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
350 /// let h = m.insert(10u32);
351 /// assert_eq!(m.find_handle(&10), Some(h));
352 /// assert_eq!(m.find_handle(&11), None);
353 /// ```
354 #[inline]
355 pub fn find_handle(&self, item: &T) -> Option<TypedHandle<T>>
356 where
357 T: PartialEq,
358 {
359 self.0.find_handle(item).map(TypedHandle::from_handle)
360 }
361
362 /// Reserve space for `sz` additional items.
363 ///
364 /// This just calls [`HandleMap::reserve`] on our wrapped map.
365 ///
366 /// ## Example
367 ///
368 /// ```
369 /// # use handy::typed::TypedHandleMap;
370 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
371 /// assert_eq!(m.capacity(), 0);
372 /// m.reserve(10);
373 /// assert!(m.capacity() >= 10);
374 /// ```
375 pub fn reserve(&mut self, sz: usize) {
376 self.0.reserve(sz)
377 }
378
379 /// Get an iterator over every occupied slot of this map.
380 ///
381 /// See also `iter_with_handles` if you want the handles during
382 /// iteration.
383 ///
384 /// This just calls [`HandleMap::iter`] on our wrapped map.
385 ///
386 /// ## Example
387 ///
388 /// ```
389 /// # use handy::typed::TypedHandleMap;
390 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
391 /// m.insert(10u32);
392 /// assert_eq!(*m.iter().next().unwrap(), 10);
393 /// ```
394 #[inline]
395 pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T> + 'a {
396 self.0.iter()
397 }
398
399 /// Get a mut iterator over every occupied slot of this map.
400 ///
401 /// See also `iter_mut_with_handles` if you want the handles during
402 /// iteration.
403 ///
404 /// This just calls [`HandleMap::iter_mut`] on our wrapped map.
405 ///
406 /// ## Example
407 ///
408 /// ```
409 /// # use handy::typed::TypedHandleMap;
410 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
411 /// let h = m.insert(10u32);
412 /// for v in m.iter_mut() {
413 /// *v += 1;
414 /// }
415 /// assert_eq!(m[h], 11);
416 /// ```
417 #[inline]
418 pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> + 'a {
419 self.0.iter_mut()
420 }
421
422 /// Get an iterator over every occupied slot of this map, as well as a
423 /// handle which can be used to fetch them later.
424 ///
425 /// This just calls [`HandleMap::iter_with_handles`] on our wrapped map and
426 /// wraps the resulting handles.
427 ///
428 /// ## Example
429 /// ```
430 /// # use handy::typed::TypedHandleMap;
431 /// # let m: TypedHandleMap<u32> = TypedHandleMap::new();
432 /// for (h, v) in m.iter_with_handles() {
433 /// println!("{:?} => {}", h, v);
434 /// }
435 /// ```
436 #[inline]
437 pub fn iter_with_handles<'a>(&'a self) -> impl Iterator<Item = (TypedHandle<T>, &'a T)> + 'a {
438 self.0
439 .iter_with_handles()
440 .map(|(h, v)| (TypedHandle::from_handle(h), v))
441 }
442
443 /// Get a mut iterator over every occupied slot of this map, as well as a
444 /// handle which can be used to fetch them later.
445 ///
446 /// This just calls [`HandleMap::iter_mut_with_handles`] on our wrapped map and
447 /// wraps the resulting handles
448 ///
449 /// ## Example
450 /// ```
451 /// # use handy::typed::TypedHandleMap;
452 /// # let mut m = TypedHandleMap::<u32>::new();
453 /// for (h, v) in m.iter_mut_with_handles() {
454 /// *v += 1;
455 /// println!("{:?}", h);
456 /// }
457 /// ```
458 #[inline]
459 pub fn iter_mut_with_handles<'a>(
460 &'a mut self,
461 ) -> impl Iterator<Item = (TypedHandle<T>, &'a mut T)> + 'a {
462 self.0
463 .iter_mut_with_handles()
464 .map(|(h, v)| (TypedHandle::from_handle(h), v))
465 }
466
467 /// If `index` refers to an occupied entry, return a `Handle` to it.
468 /// Otherwise, return None.
469 ///
470 /// This just calls [`HandleMap::handle_for_index`] on our wrapped map and wraps
471 /// the resulting handle.
472 ///
473 /// ## Example
474 /// ```
475 /// # use handy::typed::TypedHandleMap;
476 /// let mut m: TypedHandleMap<u32> = TypedHandleMap::new();
477 /// let h = m.insert(10u32);
478 /// assert_eq!(m.handle_for_index(h.index()), Some(h));
479 /// ```
480 #[inline]
481 pub fn handle_for_index(&self, index: usize) -> Option<TypedHandle<T>> {
482 self.0.handle_for_index(index).map(TypedHandle::from_handle)
483 }
484}
485
486/// A `TypedHandle` is a wrapper around a [`Handle`] which gives you some
487/// additional type safety, should you desire. You use it with a
488/// `TypedHandleMap`, which only will accept handles of the correct type. This
489/// could be useful if you have several handle maps in your program, and find
490///
491/// `TypedHandle<T>` is Copy + Send + Sync (and several others) regardless of
492/// `T`, which is not true for a naïve implementation of this, so it's provided
493/// even though I don't think it's that helpful for most usage (handle maps
494/// already detect this at runtime).
495#[repr(transparent)]
496pub struct TypedHandle<T> {
497 h: Handle,
498 _marker: PhantomData<fn() -> T>,
499}
500
501impl<T> TypedHandle<T> {
502 /// The `TypedHandle` equivalent of [`Handle::EMPTY`].
503 pub const EMPTY: Self = Self::from_handle(Handle::EMPTY);
504
505 /// Construct a typed handle from an untyped [`Handle`].
506 ///
507 /// This typically shouldn't be necessary if you're using typed maps
508 /// exclusively, but could be useful when building abstractions on top of
509 /// handles.
510 #[inline]
511 pub const fn from_handle(h: Handle) -> Self {
512 Self {
513 h,
514 _marker: Self::BOO,
515 }
516 }
517
518 // Rust (as of the current version) doesn't allow using function pointers
519 // (e.g. `fn()`) in const functions. This triggers when constructing a
520 // PhantomData, even though it probably shouldn't. To get around this, we
521 // just instantiate it outside of the const fn, which surprisingly works.
522 const BOO: PhantomData<fn() -> T> = PhantomData;
523
524 /// Access the wrapped untyped handle.
525 ///
526 /// This typically shouldn't be necessary if you're using typed maps
527 /// exclusively, but could be useful when building abstractions on top of
528 /// handles, as well as for accessing the accessors on [`Handle`] which are
529 /// not otherwise directly exposed on `TypedHandle`.
530 #[inline]
531 pub const fn handle(self) -> Handle {
532 self.h
533 }
534
535 /// Construct a handle from the separate parts.
536 ///
537 /// # Warning
538 /// This is a feature intended for advanced usage. An attempt is made to
539 /// cope with dubious handles, but it's almost certainly possible to pierce
540 /// the abstraction veil of the HandleMap if you use this.
541 ///
542 /// However, it should not be possible to cause memory unsafety -- this
543 /// crate has no unsafe code.
544 #[inline]
545 pub const fn from_raw_parts(index: usize, generation: u16, meta: u16) -> Self {
546 Self::from_handle(Handle::from_raw_parts(index, generation, meta))
547 }
548
549 /// Construct a handle from it's internal `u64` value.
550 ///
551 /// See the documentation for [`Handle::from_raw`] for further info.
552 ///
553 /// # Warning
554 ///
555 /// This is a feature intended for advanced usage. An attempt is made to
556 /// cope with dubious handles, but it's almost certainly possible to pierce
557 /// the abstraction veil of the HandleMap if you use this.
558 ///
559 /// However, it should not be possible to cause memory unsafety -- this
560 /// crate has no unsafe code.
561 #[inline]
562 pub const fn from_raw(value: u64) -> Self {
563 Self::from_handle(Handle::from_raw(value))
564 }
565
566 /// Get the internal u64 representation of this handle.
567 ///
568 /// See the documentation for [`Handle::into_raw`] for further info.
569 #[inline]
570 pub const fn into_raw(self) -> u64 {
571 self.h.0
572 }
573
574 /// Returns the index value of this handle.
575 ///
576 /// While a usize is returned, this value is guaranteed to be 32 bits.
577 ///
578 /// See the documentation for [`Handle::index`] for further info.
579 #[inline]
580 pub const fn index(self) -> usize {
581 self.h.index()
582 }
583
584 /// Returns the generation value of this handle.
585 ///
586 /// See the documentation for [`Handle::generation`] for further info.
587 #[inline]
588 pub const fn generation(self) -> u16 {
589 self.h.generation()
590 }
591
592 /// Returns the metadata field of this handle.
593 ///
594 /// See the documentation for [`Handle::meta`] for further info.
595 #[inline]
596 pub const fn meta(self) -> u16 {
597 self.h.meta()
598 }
599
600 /// Returns the metadata field of this handle. This is an alias for
601 /// `map_id`, as in the common case, this is what the metadata field is used
602 /// for.
603 ///
604 /// See [`Handle::meta`] for more info.
605 #[inline]
606 pub const fn map_id(self) -> u16 {
607 self.h.map_id()
608 }
609}
610
611impl<T> core::ops::Index<TypedHandle<T>> for TypedHandleMap<T> {
612 type Output = T;
613 fn index(&self, h: TypedHandle<T>) -> &T {
614 self.get(h).expect("Invalid handle used in index")
615 }
616}
617
618impl<T> core::ops::IndexMut<TypedHandle<T>> for TypedHandleMap<T> {
619 fn index_mut(&mut self, h: TypedHandle<T>) -> &mut T {
620 self.get_mut(h).expect("Invalid handle used in index_mut")
621 }
622}
623
624impl<T> Default for TypedHandleMap<T> {
625 // #[derive()] only works if T is also Default, so open-code this
626 fn default() -> Self { Self::new() }
627}
628
629// The automatically derived trait implementations place a bound on T,
630// which defeats the whole point of using a handle.
631impl<T> Clone for TypedHandle<T> {
632 #[inline]
633 fn clone(&self) -> Self {
634 Self {
635 h: self.h,
636 _marker: PhantomData,
637 }
638 }
639}
640
641impl<T> Copy for TypedHandle<T> {}
642impl<T> Eq for TypedHandle<T> {}
643
644impl<T> PartialEq for TypedHandle<T> {
645 #[inline]
646 fn eq(&self, o: &Self) -> bool {
647 self.h.0 == o.h.0
648 }
649 #[inline]
650 #[allow(clippy::partialeq_ne_impl)] // derive includes it, so so shall I.
651 fn ne(&self, o: &Self) -> bool {
652 self.h.0 != o.h.0
653 }
654}
655
656impl<T> PartialOrd for TypedHandle<T> {
657 #[inline]
658 fn partial_cmp(&self, o: &Self) -> Option<core::cmp::Ordering> {
659 self.h.0.partial_cmp(&o.h.0)
660 }
661 #[inline]
662 fn lt(&self, o: &Self) -> bool {
663 self.h.0 < o.h.0
664 }
665 #[inline]
666 fn le(&self, o: &Self) -> bool {
667 self.h.0 <= o.h.0
668 }
669 #[inline]
670 fn ge(&self, o: &Self) -> bool {
671 self.h.0 >= o.h.0
672 }
673 #[inline]
674 fn gt(&self, o: &Self) -> bool {
675 self.h.0 > o.h.0
676 }
677}
678
679impl<T> IntoIterator for TypedHandleMap<T> {
680 type IntoIter = crate::IntoIter<T>;
681 type Item = T;
682 fn into_iter(self) -> Self::IntoIter {
683 self.0.into_iter()
684 }
685}
686
687impl<T> Ord for TypedHandle<T> {
688 #[inline]
689 fn cmp(&self, o: &Self) -> core::cmp::Ordering {
690 self.h.0.cmp(&o.h.0)
691 }
692}
693
694impl<T> Default for TypedHandle<T> {
695 #[inline]
696 fn default() -> Self {
697 Self {
698 h: Handle::EMPTY,
699 _marker: PhantomData,
700 }
701 }
702}
703
704impl<T> core::hash::Hash for TypedHandle<T> {
705 #[inline]
706 fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
707 core::hash::Hash::hash(&self.h, h)
708 }
709}
710
711impl<T> core::fmt::Debug for TypedHandle<T> {
712 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
713 f.debug_tuple("TypedHandle").field(&self.h).finish()
714 }
715}
716
717#[cfg(test)]
718mod tests {
719 use super::*;
720 #[test]
721 fn test_handle_parts() {
722 let h = TypedHandle::<()>::from_raw_parts(0, 0, 0);
723 assert_eq!(h.index(), 0);
724 assert_eq!(h.generation(), 0);
725 assert_eq!(h.meta(), 0);
726 assert_eq!(h.meta(), h.map_id());
727
728 let h = TypedHandle::<()>::from_raw_parts(!0, 0, 0);
729 assert_eq!(h.index(), (!0u32) as usize);
730 assert_eq!(h.generation(), 0);
731 assert_eq!(h.meta(), 0);
732 assert_eq!(h.meta(), h.map_id());
733
734 assert_eq!(TypedHandle::<()>::from_raw(h.into_raw()), h);
735
736 let h = TypedHandle::<()>::from_raw_parts(0, !0, 0);
737 assert_eq!(h.index(), 0);
738 assert_eq!(h.generation(), !0);
739 assert_eq!(h.meta(), 0);
740 assert_eq!(h.meta(), h.map_id());
741
742 let h = TypedHandle::<()>::from_raw_parts(0, 0, !0);
743 assert_eq!(h.index(), 0);
744 assert_eq!(h.generation(), 0);
745 assert_eq!(h.meta(), !0);
746 assert_eq!(h.meta(), h.map_id());
747
748 let h = TypedHandle::<()>::from_raw_parts(!0, !0, !0);
749 assert_eq!(h.index(), (!0u32) as usize);
750 assert_eq!(h.generation(), !0);
751 assert_eq!(h.meta(), !0);
752 assert_eq!(h.meta(), h.map_id());
753 }
754
755 use crate::tests::Foobar;
756
757 #[test]
758 fn test_correct_value_single() {
759 let mut map = TypedHandleMap::new();
760 let handle = map.insert(Foobar(1234));
761 assert_eq!(map.get(handle).unwrap(), &Foobar(1234));
762 map.remove(handle).unwrap();
763 assert_eq!(map.get(handle), None);
764 let handle = map.as_mut_untyped_map().insert(Foobar(1234));
765 assert_eq!(
766 map.get(TypedHandle::from_handle(handle)).unwrap(),
767 &Foobar(1234)
768 );
769 }
770
771 #[test]
772 fn test_indexing() {
773 let mut map = TypedHandleMap::new();
774 let handle = map.insert(Foobar(5454));
775 assert_eq!(map[handle].0, 5454);
776 map[handle] = Foobar(6767);
777 assert_eq!(map[handle].0, 6767);
778 }
779
780 #[test]
781 fn test_correct_value_multiple() {
782 let mut map = TypedHandleMap::new();
783 let handle1 = map.insert(Foobar(1234));
784 let handle2 = map.insert(Foobar(4321));
785 assert_eq!(map.get(handle1).unwrap(), &Foobar(1234));
786 assert_eq!(map.get(handle2).unwrap(), &Foobar(4321));
787 map.remove(handle1).unwrap();
788 assert_eq!(map.get(handle1), None);
789 assert_eq!(map.get(handle2).unwrap(), &Foobar(4321));
790 }
791
792 #[test]
793 fn test_wrong_map() {
794 let mut map1 = TypedHandleMap::new();
795 let mut map2 = TypedHandleMap::new();
796
797 let handle1 = map1.insert(Foobar(1234));
798 let handle2 = map2.insert(Foobar(1234));
799
800 assert_eq!(map1.get(handle1).unwrap(), &Foobar(1234));
801 assert_eq!(map2.get_mut(handle2).unwrap(), &mut Foobar(1234));
802
803 assert_eq!(map1.get(handle2), None);
804 assert_eq!(map2.get_mut(handle1), None);
805 }
806
807 #[test]
808 fn test_bad_index() {
809 let map: TypedHandleMap<Foobar> = TypedHandleMap::new();
810 assert_eq!(
811 map.get(TypedHandle::<Foobar>::from_raw_parts(
812 100,
813 2,
814 map.as_untyped_map().map_id()
815 )),
816 None
817 );
818 }
819
820 #[test]
821 fn test_reserve() {
822 let mut map = TypedHandleMap::<u32>::with_capacity(10);
823 let cap0 = map.capacity();
824 map.reserve(cap0 + 10);
825 assert!(map.capacity() >= cap0 + 10);
826 }
827
828 #[test]
829 fn test_clear() {
830 let mut map = HandleMap::new();
831 map.insert(5u32);
832 assert!(map.len() == 1);
833 map.clear();
834 assert!(map.is_empty());
835 }
836
837 #[test]
838 fn test_iters() {
839 use alloc::collections::BTreeMap;
840 let (map, handles) = crate::tests::mixed_handlemap();
841 let mut map = TypedHandleMap::from_untyped(map);
842 let handles = handles
843 .into_iter()
844 .map(|(h, v)| (TypedHandle::<Foobar>::from_handle(h), v))
845 .collect::<alloc::vec::Vec<_>>();
846
847 assert_eq!(map.len(), handles.len());
848 let handle_to_foo: BTreeMap<TypedHandle<Foobar>, usize> = handles.iter().copied().collect();
849 let foo_to_handle: BTreeMap<usize, TypedHandle<Foobar>> =
850 handles.iter().copied().map(|t| (t.1, t.0)).collect();
851
852 assert_eq!(handle_to_foo.len(), handles.len());
853 assert_eq!(foo_to_handle.len(), handles.len());
854
855 // iter
856 let mut count = 0;
857 for i in map.iter() {
858 count += 1;
859 assert!(foo_to_handle.contains_key(&i.0));
860 }
861 assert_eq!(count, handles.len());
862
863 // iter_mut
864 let mut count = 0;
865 for i in map.iter_mut() {
866 count += 1;
867 assert!(foo_to_handle.contains_key(&i.0));
868 }
869 assert_eq!(count, handles.len());
870
871 // into_iter
872 let mut count = 0;
873 for i in map.clone() {
874 count += 1;
875 assert!(foo_to_handle.contains_key(&i.0));
876 }
877 assert_eq!(count, handles.len());
878
879 // iter_with_handles
880 let mut count = 0;
881 for (h, i) in map.iter_with_handles() {
882 count += 1;
883 assert!(foo_to_handle.contains_key(&i.0));
884 assert_eq!(handle_to_foo[&h], i.0);
885 }
886 assert_eq!(count, handles.len());
887
888 // iter_mut_with_handles
889 let mut count = 0;
890 for (h, i) in map.iter_mut_with_handles() {
891 count += 1;
892 assert!(foo_to_handle.contains_key(&i.0));
893 assert_eq!(handle_to_foo[&h], i.0);
894 }
895 assert_eq!(count, handles.len());
896 }
897
898 #[test]
899 fn test_find() {
900 let mut m = TypedHandleMap::new();
901 let mut v = alloc::vec![];
902 for i in 0..10usize {
903 v.push(m.insert(i));
904 }
905 for (i, h) in v.iter().enumerate() {
906 assert_eq!(m.find_handle(&i), Some(*h));
907 assert!(m.contains_key(*h));
908 }
909 m.clear();
910 assert!(m.is_empty());
911 for (i, h) in v.iter().enumerate() {
912 assert_eq!(m.find_handle(&i), None);
913 assert!(!m.contains_key(*h));
914 }
915 }
916
917 #[test]
918 fn test_handle_traits() {
919 fn verify<T>()
920 where
921 T: Clone
922 + Copy
923 + PartialEq
924 + PartialOrd
925 + Eq
926 + Ord
927 + core::hash::Hash
928 + Default
929 + Send
930 + Sync,
931 {
932 }
933 verify::<TypedHandle<u32>>();
934 verify::<TypedHandle<*const u32>>();
935 verify::<TypedHandle<core::cell::UnsafeCell<u32>>>();
936 verify::<TypedHandle<alloc::vec::Vec<u32>>>();
937 }
938
939 // Note: fails to compile if we have the variance wrong.
940 #[allow(dead_code, unused_assignments, unused_variables)]
941 fn check_handle_variance<'a, 'b: 'a>(mut x: TypedHandle<&'a u32>, y: TypedHandle<&'b u32>) {
942 // Requires covariance
943 x = y;
944 }
945
946 #[test]
947 // need to actually invoke the clone impl, and I don't feel like splitting this.
948 #[allow(clippy::clone_on_copy, clippy::cognitive_complexity)]
949 fn test_trait_impls() {
950 use core::cmp::Ordering;
951 use core::hash::Hash;
952 type TH = TypedHandle<()>;
953 assert!(TH::from_raw(3) == TH::from_raw(3));
954 assert!(TH::from_raw(3) != TH::from_raw(4));
955
956 assert!(!(TH::from_raw(3) != TH::from_raw(3)));
957 assert!(!(TH::from_raw(3) == TH::from_raw(4)));
958
959 assert!(TH::from_raw(3) < TH::from_raw(4));
960 assert!(TH::from_raw(4) > TH::from_raw(3));
961
962 assert!(!(TH::from_raw(4) < TH::from_raw(4)));
963 assert!(!(TH::from_raw(4) < TH::from_raw(3)));
964
965 assert!(!(TH::from_raw(4) > TH::from_raw(4)));
966 assert!(!(TH::from_raw(3) > TH::from_raw(4)));
967
968 assert!(TH::from_raw(3) <= TH::from_raw(4));
969 assert!(TH::from_raw(3) <= TH::from_raw(3));
970
971 assert!(TH::from_raw(4) >= TH::from_raw(3));
972 assert!(TH::from_raw(4) >= TH::from_raw(4));
973
974 assert!(!(TH::from_raw(5) <= TH::from_raw(4)));
975 assert!(!(TH::from_raw(4) >= TH::from_raw(5)));
976
977 assert_eq!(
978 TH::from_raw(4).partial_cmp(&TH::from_raw(4)),
979 Some(Ordering::Equal)
980 );
981 assert_eq!(
982 TH::from_raw(5).partial_cmp(&TH::from_raw(4)),
983 Some(Ordering::Greater)
984 );
985 assert_eq!(
986 TH::from_raw(5).partial_cmp(&TH::from_raw(6)),
987 Some(Ordering::Less)
988 );
989
990 assert_eq!(TH::from_raw(4).cmp(&TH::from_raw(4)), Ordering::Equal);
991 assert_eq!(TH::from_raw(5).cmp(&TH::from_raw(4)), Ordering::Greater);
992 assert_eq!(TH::from_raw(5).cmp(&TH::from_raw(6)), Ordering::Less);
993
994 assert_eq!(TH::from_raw(5).clone(), TH::from_raw(5));
995
996 let mut h = H_DEFAULT;
997 TH::from_raw(10).hash(&mut h);
998 let mut h2 = H_DEFAULT;
999 Handle::from_raw(10).hash(&mut h2);
1000 assert_eq!(h.0, h2.0);
1001
1002 assert_eq!(
1003 &alloc::format!("{:?}", TH::from_raw_parts(10, 20, 30)),
1004 "TypedHandle(Handle { meta: 30, generation: 20, index: 10 })",
1005 );
1006 }
1007
1008 // Rather than using the deprecated siphash code, just implement a crappy fnv1
1009 struct HashTester(u64);
1010 const H_DEFAULT: HashTester = HashTester(0xcbf2_9ce4_8422_2325);
1011 impl core::hash::Hasher for HashTester {
1012 fn write(&mut self, bytes: &[u8]) {
1013 for b in bytes {
1014 self.0 = self.0.wrapping_mul(0x100_0000_01b3);
1015 self.0 ^= u64::from(*b);
1016 }
1017 }
1018 fn finish(&self) -> u64 {
1019 self.0
1020 }
1021 }
1022}