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}