iddqd/id_ord_map/trait_defs.rs
1//! Trait definitions for `IdOrdMap`.
2
3use alloc::{boxed::Box, rc::Rc, sync::Arc};
4
5/// An element stored in an [`IdOrdMap`].
6///
7/// This trait is used to define the key type for the map.
8///
9/// # Examples
10///
11/// ```
12/// use iddqd::{IdOrdItem, IdOrdMap, id_upcast};
13///
14/// // Define a struct with a key.
15/// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
16/// struct MyItem {
17/// id: String,
18/// value: u32,
19/// }
20///
21/// // Implement IdOrdItem for the struct.
22/// impl IdOrdItem 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 IdOrdMap and insert items.
34/// let mut map = IdOrdMap::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/// [`IdOrdMap`]: crate::IdOrdMap
40pub trait IdOrdItem {
41 /// The key type.
42 type Key<'a>: Ord
43 where
44 Self: 'a;
45
46 /// Retrieves the key.
47 fn key(&self) -> Self::Key<'_>;
48
49 /// Upcasts the key to a shorter lifetime, in effect asserting that the
50 /// lifetime `'a` on [`IdOrdItem::Key`] is covariant.
51 ///
52 /// Typically implemented via the [`id_upcast`] macro.
53 ///
54 /// [`id_upcast`]: crate::id_upcast
55 fn upcast_key<'short, 'long: 'short>(
56 long: Self::Key<'long>,
57 ) -> Self::Key<'short>;
58}
59
60macro_rules! impl_for_ref {
61 ($type:ty) => {
62 impl<'b, T: 'b + ?Sized + IdOrdItem> IdOrdItem for $type {
63 type Key<'a>
64 = T::Key<'a>
65 where
66 Self: 'a;
67
68 fn key(&self) -> Self::Key<'_> {
69 (**self).key()
70 }
71
72 fn upcast_key<'short, 'long: 'short>(
73 long: Self::Key<'long>,
74 ) -> Self::Key<'short>
75 where
76 Self: 'long,
77 {
78 T::upcast_key(long)
79 }
80 }
81 };
82}
83
84impl_for_ref!(&'b T);
85impl_for_ref!(&'b mut T);
86
87macro_rules! impl_for_box {
88 ($type:ty) => {
89 impl<T: ?Sized + IdOrdItem> IdOrdItem for $type {
90 type Key<'a>
91 = T::Key<'a>
92 where
93 Self: 'a;
94
95 fn key(&self) -> Self::Key<'_> {
96 (**self).key()
97 }
98
99 fn upcast_key<'short, 'long: 'short>(
100 long: Self::Key<'long>,
101 ) -> Self::Key<'short> {
102 T::upcast_key(long)
103 }
104 }
105 };
106}
107
108impl_for_box!(Box<T>);
109impl_for_box!(Rc<T>);
110impl_for_box!(Arc<T>);