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>);