map_trait/map.rs
1use std::borrow::Borrow;
2use std::hash::Hash;
3use std::ops::Deref;
4
5/// A generic Map trait
6///
7/// # Examples
8///
9/// This is a toy example of a map which reexposes an inner map and stores the
10/// most recent key and value to be inserted. Because the LastInsertMap implements
11/// Map, it can be seamlessly used as a replacement for other maps.
12/// ```
13/// use std::borrow::Borrow;
14/// use std::hash::Hash;
15/// use std::collections::HashMap;
16///
17/// use map_trait::map::Map;
18/// struct LastInsertMap<M, K, V> {
19/// inner_map: M,
20/// last_key: K,
21/// last_value: V,
22/// }
23///
24/// impl<'m, K, V, M> LastInsertMap<M, K, V>
25/// where
26/// K: Copy,
27/// V: 'm + Copy,
28/// M: Map<'m, K, V>,
29/// {
30/// fn new(mut map: M, key: K, value: V) -> Self {
31/// map.insert(key, value);
32/// LastInsertMap {
33/// inner_map: map,
34/// last_key: key,
35/// last_value: value,
36/// }
37/// }
38///
39/// fn get_last_insert(&self) -> (&K, &V) {
40/// (&self.last_key, &self.last_value)
41/// }
42/// }
43///
44/// impl<'m, K, V, M> Map<'m, K, V> for LastInsertMap<M, K, V>
45/// where
46/// K: Copy,
47/// V: 'm + Copy,
48/// M: Map<'m, K, V>,
49/// {
50/// type GetGuard<'a> = M::GetGuard<'a> where Self: 'a;
51///
52/// #[inline]
53/// fn get<'a, Q: ?Sized>(&'a self, k: &Q) -> Option<Self::GetGuard<'a>>
54/// where
55/// K: Borrow<Q>,
56/// Q: Hash + Eq + Ord,
57/// {
58/// self.inner_map.get(k)
59/// }
60///
61/// #[inline]
62/// fn insert(&mut self, k: K, v: V) -> Option<V> {
63/// self.last_key = k;
64/// self.last_value = v;
65/// self.inner_map.insert(k, v)
66/// }
67/// }
68///
69/// # fn main() {
70/// let mut map = LastInsertMap::new(HashMap::new(), 0, 1);
71/// assert_eq!(map.get_last_insert(), (&0, &1));
72/// assert_eq!(map.get(&0), Some(&1));
73/// assert_eq!(map.insert(1, 2), None);
74/// assert_eq!(map.get(&1), Some(&2));
75/// assert_eq!(map.get_last_insert(), (&1, &2));
76/// # }
77/// ```
78pub trait Map<'m, K, V: 'm> {
79 type GetGuard<'a>: Deref<Target = V>
80 where
81 Self: 'a;
82
83 fn get<'a, Q: ?Sized>(&'a self, k: &Q) -> Option<Self::GetGuard<'a>>
84 where
85 K: Borrow<Q>,
86 Q: Hash + Eq + Ord;
87 fn insert(&mut self, k: K, v: V) -> Option<V>;
88}
89
90impl<'m, K, V, S> Map<'m, K, V> for std::collections::HashMap<K, V, S>
91where
92 K: Hash + Eq,
93 V: 'm,
94 S: std::hash::BuildHasher,
95{
96 type GetGuard<'a> = &'a V where Self: 'a;
97
98 #[inline]
99 fn get<'a, Q: ?Sized>(&'a self, k: &Q) -> Option<Self::GetGuard<'a>>
100 where
101 K: Borrow<Q>,
102 Q: Hash + Eq,
103 {
104 std::collections::HashMap::get(self, k)
105 }
106
107 #[inline]
108 fn insert(&mut self, k: K, v: V) -> Option<V> {
109 std::collections::HashMap::insert(self, k, v)
110 }
111}
112
113impl<'m, K, V> Map<'m, K, V> for std::collections::BTreeMap<K, V>
114where
115 K: Ord,
116 V: 'm,
117{
118 type GetGuard<'a> = &'a V where Self: 'a;
119
120 #[inline]
121 fn get<'a, Q: ?Sized>(&'a self, k: &Q) -> Option<Self::GetGuard<'a>>
122 where
123 K: Borrow<Q>,
124 Q: Ord,
125 {
126 std::collections::BTreeMap::get(self, k)
127 }
128
129 #[inline]
130 fn insert(&mut self, k: K, v: V) -> Option<V> {
131 std::collections::BTreeMap::insert(self, k, v)
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 use std::fmt::Debug;
140
141 fn assert_map_get<'m, K, V>(map: &impl Map<'m, K, V>, k: K, v: V)
142 where
143 K: Hash + Eq + Ord,
144 V: 'm + Clone + Eq + Debug,
145 {
146 assert_eq!(map.get(&k).unwrap().clone(), v);
147 }
148
149 fn assert_map_insert<'m, K, V>(map: &mut impl Map<'m, K, V>, k: K, v: V, o: Option<V>)
150 where
151 K: Hash + Eq,
152 V: 'm + Eq + Debug,
153 {
154 assert_eq!(map.insert(k, v), o);
155 }
156
157 #[test]
158 fn test_hash_map() {
159 let mut map = std::collections::HashMap::new();
160
161 assert_map_insert(&mut map, 1, 2, None);
162 assert_map_get(&map, 1, 2);
163 }
164
165 #[test]
166 fn test_btree_map() {
167 let mut map = std::collections::BTreeMap::new();
168
169 assert_map_insert(&mut map, 1, 2, None);
170 assert_map_get(&map, 1, 2);
171 }
172}