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
11pub enum Entry<'a, C: ?Sized> {
16 Occupied(OccupiedEntry<'a, C>),
18
19 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 pub fn key(&self) -> &usize {
36 &self.index
37 }
38
39 pub fn remove_entry(self) -> (usize, C::T) {
41 debug_assert!(self.index < self.container.len());
42 (self.index, self.remove())
43 }
44
45 pub fn get(&self) -> &C::T {
47 debug_assert!(self.index < self.container.len());
48 &self.container[self.index]
49 }
50
51 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 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 pub fn insert(&mut self, value: C::T) -> C::T {
75 replace(self.get_mut(), value)
76 }
77
78 pub fn remove(self) -> C::T {
80 debug_assert!(self.index < self.container.len());
81 self.container.remove(self.index)
82 }
83
84 pub fn replace_entry(mut self, value: C::T) -> (usize, C::T) {
86 (self.index, self.insert(value))
87 }
88
89 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 let index = self.index;
104 let ptr: *mut _ = self.get_mut();
105 let handler = RemoveDropHandler(&mut self);
106 let v = unsafe { core::ptr::read(ptr) };
108
109 match f(&index, v) {
110 (None, r) => {
111 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 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 pub fn key(&self) -> &usize {
135 &self.index
136 }
137
138 pub fn into_key(self) -> usize {
140 self.index
141 }
142
143 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 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 fn len(&self) -> usize;
164
165 fn insert(&mut self, index: usize, value: Self::T);
174
175 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}