iddqd/tri_hash_map/
trait_defs.rs

1//! Trait definitions for `TriHashMap`.
2
3use alloc::{boxed::Box, rc::Rc, sync::Arc};
4use core::hash::Hash;
5
6/// An item in a [`TriHashMap`].
7///
8/// This trait is used to define the keys.
9///
10/// # Examples
11///
12/// ```
13/// # #[cfg(feature = "default-hasher")] {
14/// use iddqd::{TriHashItem, TriHashMap, tri_upcast};
15///
16/// // Define a struct with three keys.
17/// #[derive(Debug, PartialEq, Eq, Hash)]
18/// struct Person {
19///     id: u32,
20///     name: String,
21///     email: String,
22/// }
23///
24/// // Implement TriHashItem for the struct.
25/// impl TriHashItem for Person {
26///     type K1<'a> = u32;
27///     type K2<'a> = &'a str;
28///     type K3<'a> = &'a str;
29///
30///     fn key1(&self) -> Self::K1<'_> {
31///         self.id
32///     }
33///
34///     fn key2(&self) -> Self::K2<'_> {
35///         &self.name
36///     }
37///
38///     fn key3(&self) -> Self::K3<'_> {
39///         &self.email
40///     }
41///
42///     tri_upcast!();
43/// }
44///
45/// // Create a TriHashMap and insert items.
46/// let mut map = TriHashMap::new();
47/// map.insert_unique(Person {
48///     id: 1,
49///     name: "Alice".to_string(),
50///     email: "alice@example.com".to_string(),
51/// })
52/// .unwrap();
53/// map.insert_unique(Person {
54///     id: 2,
55///     name: "Bob".to_string(),
56///     email: "bob@example.com".to_string(),
57/// })
58/// .unwrap();
59/// # }
60/// ```
61///
62/// [`TriHashMap`]: crate::TriHashMap
63pub trait TriHashItem {
64    /// The first key type.
65    type K1<'a>: Eq + Hash
66    where
67        Self: 'a;
68
69    /// The second key type.
70    type K2<'a>: Eq + Hash
71    where
72        Self: 'a;
73
74    /// The third key type.
75    type K3<'a>: Eq + Hash
76    where
77        Self: 'a;
78
79    /// Retrieves the first key.
80    fn key1(&self) -> Self::K1<'_>;
81
82    /// Retrieves the second key.
83    fn key2(&self) -> Self::K2<'_>;
84
85    /// Retrieves the third key.
86    fn key3(&self) -> Self::K3<'_>;
87
88    /// Upcasts the first key to a shorter lifetime, in effect asserting that
89    /// the lifetime `'a` on [`TriHashItem::K1`] is covariant.
90    ///
91    /// Typically implemented via the [`tri_upcast`] macro.
92    ///
93    /// [`tri_upcast`]: crate::tri_upcast
94    fn upcast_key1<'short, 'long: 'short>(
95        long: Self::K1<'long>,
96    ) -> Self::K1<'short>;
97
98    /// Upcasts the second key to a shorter lifetime, in effect asserting that
99    /// the lifetime `'a` on [`TriHashItem::K2`] is covariant.
100    ///
101    /// Typically implemented via the [`tri_upcast`] macro.
102    ///
103    /// [`tri_upcast`]: crate::tri_upcast
104    fn upcast_key2<'short, 'long: 'short>(
105        long: Self::K2<'long>,
106    ) -> Self::K2<'short>;
107
108    /// Upcasts the third key to a shorter lifetime, in effect asserting that
109    /// the lifetime `'a` on [`TriHashItem::K3`] is covariant.
110    ///
111    /// Typically implemented via the [`tri_upcast`] macro.
112    ///
113    /// [`tri_upcast`]: crate::tri_upcast
114    fn upcast_key3<'short, 'long: 'short>(
115        long: Self::K3<'long>,
116    ) -> Self::K3<'short>;
117}
118
119macro_rules! impl_for_ref {
120    ($type:ty) => {
121        impl<'b, T: 'b + ?Sized + TriHashItem> TriHashItem for $type {
122            type K1<'a>
123                = T::K1<'a>
124            where
125                Self: 'a;
126            type K2<'a>
127                = T::K2<'a>
128            where
129                Self: 'a;
130            type K3<'a>
131                = T::K3<'a>
132            where
133                Self: 'a;
134
135            fn key1(&self) -> Self::K1<'_> {
136                (**self).key1()
137            }
138
139            fn key2(&self) -> Self::K2<'_> {
140                (**self).key2()
141            }
142
143            fn key3(&self) -> Self::K3<'_> {
144                (**self).key3()
145            }
146
147            fn upcast_key1<'short, 'long: 'short>(
148                long: Self::K1<'long>,
149            ) -> Self::K1<'short>
150            where
151                Self: 'long,
152            {
153                T::upcast_key1(long)
154            }
155
156            fn upcast_key2<'short, 'long: 'short>(
157                long: Self::K2<'long>,
158            ) -> Self::K2<'short>
159            where
160                Self: 'long,
161            {
162                T::upcast_key2(long)
163            }
164
165            fn upcast_key3<'short, 'long: 'short>(
166                long: Self::K3<'long>,
167            ) -> Self::K3<'short>
168            where
169                Self: 'long,
170            {
171                T::upcast_key3(long)
172            }
173        }
174    };
175}
176
177impl_for_ref!(&'b T);
178impl_for_ref!(&'b mut T);
179
180macro_rules! impl_for_box {
181    ($type:ty) => {
182        impl<T: ?Sized + TriHashItem> TriHashItem for $type {
183            type K1<'a>
184                = T::K1<'a>
185            where
186                Self: 'a;
187
188            type K2<'a>
189                = T::K2<'a>
190            where
191                Self: 'a;
192
193            type K3<'a>
194                = T::K3<'a>
195            where
196                Self: 'a;
197
198            fn key1(&self) -> Self::K1<'_> {
199                (**self).key1()
200            }
201
202            fn key2(&self) -> Self::K2<'_> {
203                (**self).key2()
204            }
205
206            fn key3(&self) -> Self::K3<'_> {
207                (**self).key3()
208            }
209
210            fn upcast_key1<'short, 'long: 'short>(
211                long: Self::K1<'long>,
212            ) -> Self::K1<'short> {
213                T::upcast_key1(long)
214            }
215
216            fn upcast_key2<'short, 'long: 'short>(
217                long: Self::K2<'long>,
218            ) -> Self::K2<'short> {
219                T::upcast_key2(long)
220            }
221
222            fn upcast_key3<'short, 'long: 'short>(
223                long: Self::K3<'long>,
224            ) -> Self::K3<'short> {
225                T::upcast_key3(long)
226            }
227        }
228    };
229}
230
231impl_for_box!(Box<T>);
232impl_for_box!(Rc<T>);
233impl_for_box!(Arc<T>);