iddqd/bi_hash_map/trait_defs.rs
1//! Trait definitions for `BiHashMap`.
2
3use alloc::{boxed::Box, rc::Rc, sync::Arc};
4use core::hash::Hash;
5
6/// An item in a [`BiHashMap`].
7///
8/// This trait is used to define the keys.
9///
10/// # Examples
11///
12/// ```
13/// # #[cfg(feature = "default-hasher")] {
14/// use iddqd::{BiHashItem, BiHashMap, bi_upcast};
15///
16/// // Define a struct with two keys.
17/// #[derive(Debug, PartialEq, Eq, Hash)]
18/// struct MyPair {
19/// id: u32,
20/// name: String,
21/// }
22///
23/// // Implement BiHashItem for the struct.
24/// impl BiHashItem for MyPair {
25/// type K1<'a> = u32;
26/// type K2<'a> = &'a str;
27///
28/// fn key1(&self) -> Self::K1<'_> {
29/// self.id
30/// }
31///
32/// fn key2(&self) -> Self::K2<'_> {
33/// &self.name
34/// }
35///
36/// bi_upcast!();
37/// }
38///
39/// // Create a BiHashMap and insert items.
40/// let mut map = BiHashMap::new();
41/// map.insert_unique(MyPair { id: 1, name: "Alice".to_string() }).unwrap();
42/// map.insert_unique(MyPair { id: 2, name: "Bob".to_string() }).unwrap();
43/// # }
44/// ```
45///
46/// [`BiHashMap`]: crate::BiHashMap
47pub trait BiHashItem {
48 /// The first key type.
49 type K1<'a>: Eq + Hash
50 where
51 Self: 'a;
52
53 /// The second key type.
54 type K2<'a>: Eq + Hash
55 where
56 Self: 'a;
57
58 /// Retrieves the first key.
59 fn key1(&self) -> Self::K1<'_>;
60
61 /// Retrieves the second key.
62 fn key2(&self) -> Self::K2<'_>;
63
64 /// Upcasts the first key to a shorter lifetime, in effect asserting that
65 /// the lifetime `'a` on [`BiHashItem::K1`] is covariant.
66 ///
67 /// Typically implemented via the [`bi_upcast`] macro.
68 ///
69 /// [`bi_upcast`]: crate::bi_upcast
70 fn upcast_key1<'short, 'long: 'short>(
71 long: Self::K1<'long>,
72 ) -> Self::K1<'short>;
73
74 /// Upcasts the second key to a shorter lifetime, in effect asserting that
75 /// the lifetime `'a` on [`BiHashItem::K2`] is covariant.
76 ///
77 /// Typically implemented via the [`bi_upcast`] macro.
78 ///
79 /// [`bi_upcast`]: crate::bi_upcast
80 fn upcast_key2<'short, 'long: 'short>(
81 long: Self::K2<'long>,
82 ) -> Self::K2<'short>;
83}
84
85macro_rules! impl_for_ref {
86 ($type:ty) => {
87 impl<'b, T: 'b + ?Sized + BiHashItem> BiHashItem for $type {
88 type K1<'a>
89 = T::K1<'a>
90 where
91 Self: 'a;
92 type K2<'a>
93 = T::K2<'a>
94 where
95 Self: 'a;
96
97 fn key1(&self) -> Self::K1<'_> {
98 (**self).key1()
99 }
100
101 fn key2(&self) -> Self::K2<'_> {
102 (**self).key2()
103 }
104
105 fn upcast_key1<'short, 'long: 'short>(
106 long: Self::K1<'long>,
107 ) -> Self::K1<'short>
108 where
109 Self: 'long,
110 {
111 T::upcast_key1(long)
112 }
113
114 fn upcast_key2<'short, 'long: 'short>(
115 long: Self::K2<'long>,
116 ) -> Self::K2<'short>
117 where
118 Self: 'long,
119 {
120 T::upcast_key2(long)
121 }
122 }
123 };
124}
125
126impl_for_ref!(&'b T);
127impl_for_ref!(&'b mut T);
128
129macro_rules! impl_for_box {
130 ($type:ty) => {
131 impl<T: ?Sized + BiHashItem> BiHashItem for $type {
132 type K1<'a>
133 = T::K1<'a>
134 where
135 Self: 'a;
136
137 type K2<'a>
138 = T::K2<'a>
139 where
140 Self: 'a;
141
142 fn key1(&self) -> Self::K1<'_> {
143 (**self).key1()
144 }
145
146 fn key2(&self) -> Self::K2<'_> {
147 (**self).key2()
148 }
149
150 fn upcast_key1<'short, 'long: 'short>(
151 long: Self::K1<'long>,
152 ) -> Self::K1<'short> {
153 T::upcast_key1(long)
154 }
155
156 fn upcast_key2<'short, 'long: 'short>(
157 long: Self::K2<'long>,
158 ) -> Self::K2<'short> {
159 T::upcast_key2(long)
160 }
161 }
162 };
163}
164
165impl_for_box!(Box<T>);
166impl_for_box!(Rc<T>);
167impl_for_box!(Arc<T>);