vec_entry/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5use core::{ops::{IndexMut}, mem::{replace, forget}};
6
7use alloc::{vec::Vec, collections::VecDeque};
8
9
10
11/// A view into a single entry which may either be vacant or occupied.
12///
13/// This `enum` is constructed from the [`entry`] method on [`EntryExt`].
14///
15pub enum Entry<'a, C: ?Sized> {
16    /// An occupied entry.
17    Occupied(OccupiedEntry<'a, C>),
18
19    /// A vacant entry.
20    Vacant(VacantEntry<'a, C>),
21}
22
23pub struct OccupiedEntry<'a, C: ?Sized>{
24    index: usize,
25    container: &'a mut C,
26}
27
28pub struct VacantEntry<'a, C: ?Sized>{
29    index: usize,
30    container: &'a mut C,
31}
32
33impl<'a, C: 'a+Entriable> OccupiedEntry<'a, C> {
34    /// Gets a reference to the index of the entry.
35    pub fn key(&self) -> &usize {
36        &self.index
37    }
38
39    /// Take the ownership of the index and value from the container.
40    pub fn remove_entry(self) -> (usize, C::T) {
41        debug_assert!(self.index < self.container.len());
42        (self.index, self.remove())
43    }
44
45    /// Gets a reference to the value in the entry.
46    pub fn get(&self) -> &C::T {
47        debug_assert!(self.index < self.container.len());
48        &self.container[self.index]
49    }
50
51    /// Gets a mutable reference to the value in the entry.
52    ///
53    /// If you need a reference to the `OccupiedEntry` which may outlive the
54    /// destruction of the `Entry` value, see [`into_mut`].
55    ///
56    /// [`into_mut`]: #method.into_mut
57    pub fn get_mut(&mut self) -> &mut C::T {
58        debug_assert!(self.index < self.container.len());
59        &mut self.container[self.index]
60    }
61
62    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
63    /// with a lifetime bound to the map itself.
64    ///
65    /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
66    ///
67    /// [`get_mut`]: #method.get_mut
68    pub fn into_mut(self) -> &'a mut C::T {
69        debug_assert!(self.index < self.container.len());
70        &mut self.container[self.index]
71    }
72
73    /// Sets the value of the entry, and returns the entry’s old value.
74    pub fn insert(&mut self, value: C::T) -> C::T {
75        replace(self.get_mut(), value)
76    }
77
78    /// Takes the value out of the entry, and returns it. Keeps the allocated memory for reuse.
79    pub fn remove(self) -> C::T {
80        debug_assert!(self.index < self.container.len());
81        self.container.remove(self.index)
82    }
83
84    /// Replaces the entry, returning the index and value.
85    pub fn replace_entry(mut self, value: C::T) -> (usize, C::T) {
86        (self.index, self.insert(value))
87    }
88
89    /// Provides shared access to the key and owned access to the value of the
90    /// entry and allows to replace or remove it based on the value of the
91    /// returned option.
92    pub fn replace_entry_with<F, R>(mut self, f: F) -> (Entry<'a, C>, R)
93    where F: FnOnce(&usize, C::T) -> (Option<C::T>, R) {
94        struct RemoveDropHandler<'b, 'a, C: 'a+Entriable>(&'b mut OccupiedEntry<'a, C>);
95        impl<'b, 'a, C: 'a+Entriable> Drop for RemoveDropHandler<'b, 'a, C> {
96            fn drop(&mut self) {
97                forget(self.0.container.remove(self.0.index));
98            }
99        }
100
101        // get the pointer before we construct the handler to minimize the chance
102        // of panic-drop-leaking
103        let index = self.index;
104        let ptr: *mut _ = self.get_mut();
105        let handler = RemoveDropHandler(&mut self);
106        // This is safe because we either write over it or forget it
107        let v = unsafe { core::ptr::read(ptr) };
108
109        match f(&index, v) {
110            (None, r) => {
111                // Go ahead and forgetfully remove the entry
112                drop(handler);
113                let entry = if self.container.len() <= self.index {
114                    Entry::Vacant(VacantEntry{index: self.index, container: self.container})
115                } else {
116                    Entry::Occupied(self)
117                };
118                (entry, r)
119            }
120            (Some(v), val) => {
121                // Don't remove the entry, just overwrite it forgetfully
122                forget(handler);
123                unsafe { core::ptr::write(ptr, v) };
124
125                (Entry::Occupied(self), val)
126            }
127        }
128    }
129    
130}
131
132impl<'a, C : 'a+Entriable> VacantEntry<'a, C> {
133    /// Gets a reference to the index of the entry.
134    pub fn key(&self) -> &usize {
135        &self.index
136    }
137
138    /// Take ownership of the key.
139    pub fn into_key(self) -> usize {
140        self.index
141    }
142
143    /// Set the value of the entry, and return a mutable reference to it.
144    ///
145    /// # Panics
146    ///
147    /// Panics if the entry's index is greater than container's length
148    pub fn insert(self, v: C::T) -> &'a mut C::T {
149        self.container.insert(self.index, v);
150        &mut self.container[self.index]
151    }
152}
153
154pub trait EntryExt {
155    /// Get a key's entry for in-place manipulation.
156    fn entry<'a>(&'a mut self, index: usize) -> Entry<'a, Self>;
157}
158
159pub trait Entriable: IndexMut<usize, Output = Self::T> {
160    type T;
161
162    /// Returns the number of elements in the container.
163    fn len(&self) -> usize;
164
165    /// Inserts an element at `index` within the container, shifting all elements
166    /// with indices greater than or equal to `index` towards the back.
167    ///
168    /// Element at index 0 is the front.
169    ///
170    /// # Panics
171    ///
172    /// Panics if `index` is greater than container's length
173    fn insert(&mut self, index: usize, value: Self::T);
174
175    /// Removes and returns the element at `index` from the container, shifting
176    /// all elements with indices greater than or equal to `index` towards the
177    /// front.
178    /// 
179    /// Element at index 0 is the front of the container.
180    ///
181    /// # Panics
182    ///
183    /// Panics if `index` is out of bounds.
184    fn remove(&mut self, index: usize) -> Self::T;
185}
186
187impl<C: Entriable> EntryExt for C {
188    fn entry<'a>(&'a mut self, index: usize) -> Entry<'a, Self> {
189        if index >= self.len() {
190            Entry::Vacant(VacantEntry{index, container: self})
191        } else {
192            Entry::Occupied(OccupiedEntry{index, container: self})
193        }
194    }
195
196}
197
198impl<T> Entriable for Vec<T> {
199    type T = T;
200
201    fn len(&self) -> usize {
202        Vec::len(self)
203    }
204    fn insert(&mut self, index: usize, value: T) {
205        Vec::insert(self, index, value)
206    }
207    fn remove(&mut self, index: usize) -> T {
208        Vec::remove(self, index)
209    }
210}
211
212impl<T> Entriable for VecDeque<T> {
213    type T = T;
214
215    fn len(&self) -> usize {
216        VecDeque::len(self)
217    }
218    fn insert(&mut self, index: usize, value: T) {
219        VecDeque::insert(self, index, value)
220    }
221    fn remove(&mut self, index: usize) -> T {
222        VecDeque::remove(self, index).unwrap()
223    }
224}
225
226#[cfg(test)]
227mod tests {
228    use core::cell::Cell;
229
230    use alloc::vec;
231
232    use super::*;
233
234    #[test]
235    fn it_works() {
236        let mut v = vec![69u64, 420, 0xDEADBEEF];
237
238        match v.entry(1) {
239            Entry::Vacant(_) => unreachable!(),
240            Entry::Occupied(mut o) => {
241                assert_eq!(*o.get(), 420);
242                assert_eq!(*o.get_mut(), 420);
243
244                o.replace_entry_with(|k, v|{
245                    assert_eq!(*k, 1);
246                    assert_eq!(v, 420);
247                    (None, ())
248                });
249
250            },
251        }
252
253        assert_eq!(v, [69, 0xDEADBEEF])
254    }
255
256    #[test]
257    fn drop_count() {
258        struct DropCounter<'a>(&'a Cell<usize>);
259        impl<'a> Drop for DropCounter<'a> {
260            fn drop(&mut self) {
261                self.0.set(self.0.get() + 1)
262            }
263        }
264
265        let c = Cell::new(0);
266        let mut v = vec![DropCounter(&c), DropCounter(&c), DropCounter(&c), DropCounter(&c)];
267
268        let entry = match v.entry(1) {
269            Entry::Vacant(_) => unreachable!(),
270            Entry::Occupied(o) => {
271                assert_eq!(c.get(), 0);
272                let (entry, ()) = o.replace_entry_with(|k, v|{
273                    assert_eq!(*k, 1);
274                    assert_eq!(c.get(), 0);
275                    drop(v);
276                    assert_eq!(c.get(), 1);
277                    (None, ())
278                });
279                assert_eq!(c.get(), 1);
280                entry
281            },
282        };
283
284        match entry {
285            Entry::Vacant(_) => unreachable!(),
286            Entry::Occupied(o) => {
287                assert_eq!(c.get(), 1);
288                o.replace_entry_with(|k, v|{
289                    assert_eq!(*k, 1);
290                    assert_eq!(c.get(), 1);
291                    drop(v);
292                    assert_eq!(c.get(), 2);
293                    (Some(DropCounter(&c)), ())
294                });
295                assert_eq!(c.get(), 2);
296                
297            }
298        }
299        drop(v);
300        assert_eq!(c.get(), 5);
301
302    }
303}