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}