iddqd/id_hash_map/
trait_defs.rs

1use alloc::{boxed::Box, rc::Rc, sync::Arc};
2use core::hash::Hash;
3
4/// An element stored in an [`IdHashMap`].
5///
6/// This trait is used to define the key type for the map.
7///
8/// # Examples
9///
10/// ```
11/// # #[cfg(feature = "default-hasher")] {
12/// use iddqd::{IdHashItem, IdHashMap, id_upcast};
13///
14/// // Define a struct with a key.
15/// #[derive(Debug, PartialEq, Eq, Hash)]
16/// struct MyItem {
17///     id: String,
18///     value: u32,
19/// }
20///
21/// // Implement IdHashItem for the struct.
22/// impl IdHashItem for MyItem {
23///     // Keys can borrow from the item.
24///     type Key<'a> = &'a str;
25///
26///     fn key(&self) -> Self::Key<'_> {
27///         &self.id
28///     }
29///
30///     id_upcast!();
31/// }
32///
33/// // Create an IdHashMap and insert items.
34/// let mut map = IdHashMap::new();
35/// map.insert_unique(MyItem { id: "foo".to_string(), value: 42 }).unwrap();
36/// map.insert_unique(MyItem { id: "bar".to_string(), value: 20 }).unwrap();
37/// # }
38/// ```
39///
40/// [`IdHashMap`]: crate::IdHashMap
41pub trait IdHashItem {
42    /// The key type.
43    type Key<'a>: Eq + Hash
44    where
45        Self: 'a;
46
47    /// Retrieves the key.
48    fn key(&self) -> Self::Key<'_>;
49
50    /// Upcasts the key to a shorter lifetime, in effect asserting that the
51    /// lifetime `'a` on [`IdHashItem::Key`] is covariant.
52    ///
53    /// Typically implemented via the [`id_upcast`] macro.
54    fn upcast_key<'short, 'long: 'short>(
55        long: Self::Key<'long>,
56    ) -> Self::Key<'short>;
57}
58
59macro_rules! impl_for_ref {
60    ($type:ty) => {
61        impl<'b, T: 'b + ?Sized + IdHashItem> IdHashItem for $type {
62            type Key<'a>
63                = T::Key<'a>
64            where
65                Self: 'a;
66
67            fn key(&self) -> Self::Key<'_> {
68                (**self).key()
69            }
70
71            fn upcast_key<'short, 'long: 'short>(
72                long: Self::Key<'long>,
73            ) -> Self::Key<'short>
74            where
75                Self: 'long,
76            {
77                T::upcast_key(long)
78            }
79        }
80    };
81}
82
83impl_for_ref!(&'b T);
84impl_for_ref!(&'b mut T);
85
86macro_rules! impl_for_box {
87    ($type:ty) => {
88        impl<T: ?Sized + IdHashItem> IdHashItem for $type {
89            type Key<'a>
90                = T::Key<'a>
91            where
92                Self: 'a;
93
94            fn key(&self) -> Self::Key<'_> {
95                (**self).key()
96            }
97
98            fn upcast_key<'short, 'long: 'short>(
99                long: Self::Key<'long>,
100            ) -> Self::Key<'short> {
101                T::upcast_key(long)
102            }
103        }
104    };
105}
106
107impl_for_box!(Box<T>);
108impl_for_box!(Rc<T>);
109impl_for_box!(Arc<T>);