non_empty_collections/index_map/
entry.rs

1use super::Index;
2use std::hash::{BuildHasher, Hash};
3use std::mem;
4use std::ops::{Deref, DerefMut};
5use {Error, NonEmptyIndexMap};
6
7/// An occupied entry.
8pub struct Occupied<'a, K: 'a, V: 'a, S: 'a> {
9    pub(super) key: K,
10    pub(super) index: Index,
11    pub(super) map: &'a mut NonEmptyIndexMap<K, V, S>,
12}
13
14/// A vacant (empty) entry.
15pub struct Vacant<'a, K: 'a, V: 'a, S: 'a> {
16    pub(super) key: K,
17    pub(super) map: &'a mut NonEmptyIndexMap<K, V, S>,
18}
19
20/// A map's entry.
21pub enum Entry<'a, K: 'a, V: 'a, S: 'a> {
22    /// An occupied entry.
23    Occupied(Occupied<'a, K, V, S>),
24    /// A vacant (empty) entry.
25    Vacant(Vacant<'a, K, V, S>),
26}
27
28impl<'a, K: 'a, V: 'a, S: 'a> Deref for Occupied<'a, K, V, S>
29where
30    K: Eq + Hash,
31    S: BuildHasher,
32{
33    type Target = V;
34
35    fn deref(&self) -> &V {
36        self.map.get_entry(self.index)
37    }
38}
39
40impl<'a, K: 'a, V: 'a, S: 'a> DerefMut for Occupied<'a, K, V, S>
41where
42    K: Eq + Hash,
43    S: BuildHasher,
44{
45    fn deref_mut(&mut self) -> &mut V {
46        self.map.get_entry_mut(self.index)
47    }
48}
49
50impl<'a, K: 'a, V: 'a, S: 'a> Occupied<'a, K, V, S>
51where
52    K: Eq + Hash,
53    S: BuildHasher,
54{
55    /// Removes the entry from the map.
56    ///
57    /// Will fail on an attempt to remove the last element from the map.
58    pub fn remove_entry(self) -> Result<(K, V), Error> {
59        let key = self.key;
60        let map = self.map;
61        map.remove_entry(&key)
62            .map(|x| x.expect("The entry exists for sure"))
63    }
64
65    /// Replace the entry's value with a given one, returning the old one.
66    pub fn replace(&mut self, new_value: V) -> V {
67        let old = self.map.get_entry_mut(self.index);
68        mem::replace(old, new_value)
69    }
70
71    pub fn into_value(self) -> &'a mut V {
72        let idx = self.index;
73        self.map.get_entry_mut(idx)
74    }
75}
76
77impl<'a, K: 'a, V: 'a, S: 'a> Vacant<'a, K, V, S>
78where
79    K: Eq + Hash,
80    S: BuildHasher,
81{
82    pub fn insert(self, value: V) -> &'a mut V {
83        let map = self.map;
84        let key = self.key;
85        match map.get_rest_mut().entry(key) {
86            ::indexmap::map::Entry::Occupied(_) => panic!("The entry exists for sure"),
87            ::indexmap::map::Entry::Vacant(entry) => entry.insert(value),
88        }
89    }
90}
91
92impl<'a, K: 'a, V: 'a, S: 'a> Entry<'a, K, V, S>
93where
94    K: Eq + Hash,
95    S: BuildHasher,
96{
97    /// Returns a mutable reference to a value if the entry exists, or creates a new entry using a
98    /// given closure if it doesn't exist yet and returns a reference to a newly created entry's
99    /// value.
100    pub fn or_insert(self, value: V) -> &'a mut V {
101        match self {
102            Entry::Occupied(x) => x.into_value(),
103            Entry::Vacant(v) => v.insert(value),
104        }
105    }
106
107    /// Returns a mutable reference to a value if the entry exists, or creates a new entry with a
108    /// given value if it doesn't exist yet and returns a reference to a newly created entry's
109    /// value.
110    pub fn or_insert_with<F>(self, f: F) -> &'a mut V
111    where
112        F: FnOnce() -> V,
113    {
114        match self {
115            Entry::Occupied(x) => x.into_value(),
116            Entry::Vacant(v) => v.insert(f()),
117        }
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    #[test]
126    fn test_occupied_one() {
127        let mut map = NonEmptyIndexMap::new(1, 2);
128        let entry = map.entry(1);
129        let occupied = match entry {
130            Entry::Occupied(x) => x,
131            Entry::Vacant(_) => panic!("Expected an occupied entry"),
132        };
133        assert_eq!(Err(Error::EmptyCollection), occupied.remove_entry());
134    }
135
136    #[test]
137    fn test_occupied() {
138        let mut map = NonEmptyIndexMap::from_item_and_iterator(1, 2, vec![(3, 4), (5, 6), (7, 8)]);
139        {
140            let entry = map.entry(1);
141            let occupied = match entry {
142                Entry::Occupied(x) => x,
143                Entry::Vacant(_) => panic!("Expected an occupied entry"),
144            };
145            assert_eq!(Ok((1, 2)), occupied.remove_entry());
146        }
147        assert_eq!(3, map.len());
148        {
149            let entry = map.entry(5);
150            match entry {
151                Entry::Occupied(x) => x,
152                Entry::Vacant(_) => panic!("Expected an occupied entry"),
153            };
154        }
155        assert_eq!(3, map.len());
156    }
157
158    #[test]
159    fn test_vacant() {
160        let mut map = NonEmptyIndexMap::new(1, 2);
161        {
162            let entry = map.entry(2);
163            let vacant = match entry {
164                Entry::Vacant(x) => x,
165                Entry::Occupied(_) => panic!("Expected a vacant entry"),
166            };
167            assert_eq!(&3, vacant.insert(3));
168        }
169        assert_eq!(Some(&3), map.get(&2));
170    }
171
172    #[test]
173    fn test_or_insert() {
174        let mut map = NonEmptyIndexMap::new(1, 2);
175        {
176            let entry = map.entry(1);
177            assert_eq!(&2, entry.or_insert(3));
178        }
179        assert_eq!(Some(&2), map.get(&1));
180        assert_eq!(1, map.len());
181        {
182            let entry = map.entry(2);
183            assert_eq!(&3, entry.or_insert(3));
184        }
185        assert_eq!(Some(&3), map.get(&2));
186        assert_eq!(2, map.len());
187    }
188
189    #[test]
190    fn test_or_insert_with() {
191        let mut map = NonEmptyIndexMap::new(1, 2);
192        {
193            let entry = map.entry(1);
194            assert_eq!(&2, entry.or_insert_with(|| 3));
195        }
196        assert_eq!(Some(&2), map.get(&1));
197        assert_eq!(1, map.len());
198        {
199            let entry = map.entry(2);
200            assert_eq!(&3, entry.or_insert_with(|| 3));
201        }
202        assert_eq!(Some(&3), map.get(&2));
203        assert_eq!(2, map.len());
204    }
205}